rabbitmq-java-client-5.0.0/000077500000000000000000000000001316117667700155275ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/.gitignore000066400000000000000000000002041316117667700175130ustar00rootroot00000000000000*~ .sw? .*.sw? *.beam *.class *.dat *.dump *.iml *.ipr *.iws .DS_Store \#~ /.idea/ /deps/ /target/ /.classpath /.project /.settings rabbitmq-java-client-5.0.0/CODE_OF_CONDUCT.md000066400000000000000000000045051316117667700203320ustar00rootroot00000000000000# Contributor Code of Conduct As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities. We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality. Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery * Personal attacks * Trolling or insulting/derogatory comments * Public or private harassment * Publishing other's private information, such as physical or electronic addresses, without explicit permission * Other unethical or unprofessional conduct Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team. This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting a project maintainer at [info@rabbitmq.com](mailto:info@rabbitmq.com). All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. Maintainers are obligated to maintain confidentiality with regard to the reporter of an incident. This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.3.0, available at [contributor-covenant.org/version/1/3/0/](http://contributor-covenant.org/version/1/3/0/) rabbitmq-java-client-5.0.0/CONTRIBUTING.md000066400000000000000000000032001316117667700177530ustar00rootroot00000000000000## Overview RabbitMQ projects use pull requests to discuss, collaborate on and accept code contributions. Pull requests is the primary place of discussing code changes. ## How to Contribute The process is fairly standard: * Fork the repository or repositories you plan on contributing to * Clone [RabbitMQ umbrella repository](https://github.com/rabbitmq/rabbitmq-public-umbrella) * `cd umbrella`, `make co` * Create a branch with a descriptive name in the relevant repositories * Make your changes, run tests, commit with a [descriptive message](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html), push to your fork * Submit pull requests with an explanation what has been changed and **why** * Submit a filled out and signed [Contributor Agreement](https://github.com/rabbitmq/ca#how-to-submit) if needed (see below) * Be patient. We will get to your pull request eventually If what you are going to work on is a substantial change, please first ask the core team of their opinion on [RabbitMQ mailing list](https://groups.google.com/forum/#!forum/rabbitmq-users). ## Code of Conduct See [CODE_OF_CONDUCT.md](./CODE_OF_CONDUCT.md). ## Contributor Agreement If you want to contribute a non-trivial change, please submit a signed copy of our [Contributor Agreement](https://github.com/rabbitmq/ca#how-to-submit) around the time you submit your pull request. This will make it much easier (in some cases, possible) for the RabbitMQ team at Pivotal to merge your contribution. ## Where to Ask Questions If something isn't clear, feel free to ask on our [mailing list](https://groups.google.com/forum/#!forum/rabbitmq-users). rabbitmq-java-client-5.0.0/LICENSE000066400000000000000000000011761316117667700165410ustar00rootroot00000000000000This package, the RabbitMQ Java client library, is triple-licensed under the Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, please see LICENSE-APACHE2. The RabbitMQ Java client library includes third-party software under the ASL. For this license, please see LICENSE-APACHE2. For attribution of copyright and other details of provenance, please refer to the source code. If you have any questions regarding licensing, please contact us at info@rabbitmq.com. rabbitmq-java-client-5.0.0/LICENSE-APACHE2000066400000000000000000000261361316117667700175450ustar00rootroot00000000000000 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. rabbitmq-java-client-5.0.0/LICENSE-GPL2000066400000000000000000000431031316117667700172370ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. rabbitmq-java-client-5.0.0/LICENSE-MPL-RabbitMQ000066400000000000000000000621161316117667700206270ustar00rootroot00000000000000 MOZILLA PUBLIC LICENSE Version 1.1 --------------- 1. Definitions. 1.0.1. "Commercial Use" means distribution or otherwise making the Covered Code available to a third party. 1.1. "Contributor" means each entity that creates or contributes to the creation of Modifications. 1.2. "Contributor Version" means the combination of the Original Code, prior Modifications used by a Contributor, and the Modifications made by that particular Contributor. 1.3. "Covered Code" means the Original Code or Modifications or the combination of the Original Code and Modifications, in each case including portions thereof. 1.4. "Electronic Distribution Mechanism" means a mechanism generally accepted in the software development community for the electronic transfer of data. 1.5. "Executable" means Covered Code in any form other than Source Code. 1.6. "Initial Developer" means the individual or entity identified as the Initial Developer in the Source Code notice required by Exhibit A. 1.7. "Larger Work" means a work which combines Covered Code or portions thereof with code not governed by the terms of this License. 1.8. "License" means this document. 1.8.1. "Licensable" means having the right to grant, to the maximum extent possible, whether at the time of the initial grant or subsequently acquired, any and all of the rights conveyed herein. 1.9. "Modifications" means any addition to or deletion from the substance or structure of either the Original Code or any previous Modifications. When Covered Code is released as a series of files, a Modification is: A. Any addition to or deletion from the contents of a file containing Original Code or previous Modifications. B. Any new file that contains any part of the Original Code or previous Modifications. 1.10. "Original Code" means Source Code of computer software code which is described in the Source Code notice required by Exhibit A as Original Code, and which, at the time of its release under this License is not already Covered Code governed by this License. 1.10.1. "Patent Claims" means any patent claim(s), now owned or hereafter acquired, including without limitation, method, process, and apparatus claims, in any patent Licensable by grantor. 1.11. "Source Code" means the preferred form of the Covered Code for making modifications to it, including all modules it contains, plus any associated interface definition files, scripts used to control compilation and installation of an Executable, or source code differential comparisons against either the Original Code or another well known, available Covered Code of the Contributor's choice. The Source Code can be in a compressed or archival form, provided the appropriate decompression or de-archiving software is widely available for no charge. 1.12. "You" (or "Your") means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License or a future version of this License issued under Section 6.1. For legal entities, "You" includes any entity which controls, is controlled by, or is under common control with You. For purposes of this definition, "control" means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of more than fifty percent (50%) of the outstanding shares or beneficial ownership of such entity. 2. Source Code License. 2.1. The Initial Developer Grant. The Initial Developer hereby grants You a world-wide, royalty-free, non-exclusive license, subject to third party intellectual property claims: (a) under intellectual property rights (other than patent or trademark) Licensable by Initial Developer to use, reproduce, modify, display, perform, sublicense and distribute the Original Code (or portions thereof) with or without Modifications, and/or as part of a Larger Work; and (b) under Patents Claims infringed by the making, using or selling of Original Code, to make, have made, use, practice, sell, and offer for sale, and/or otherwise dispose of the Original Code (or portions thereof). (c) the licenses granted in this Section 2.1(a) and (b) are effective on the date Initial Developer first distributes Original Code under the terms of this License. (d) Notwithstanding Section 2.1(b) above, no patent license is granted: 1) for code that You delete from the Original Code; 2) separate from the Original Code; or 3) for infringements caused by: i) the modification of the Original Code or ii) the combination of the Original Code with other software or devices. 2.2. Contributor Grant. Subject to third party intellectual property claims, each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license (a) under intellectual property rights (other than patent or trademark) Licensable by Contributor, to use, reproduce, modify, display, perform, sublicense and distribute the Modifications created by such Contributor (or portions thereof) either on an unmodified basis, with other Modifications, as Covered Code and/or as part of a Larger Work; and (b) under Patent Claims infringed by the making, using, or selling of Modifications made by that Contributor either alone and/or in combination with its Contributor Version (or portions of such combination), to make, use, sell, offer for sale, have made, and/or otherwise dispose of: 1) Modifications made by that Contributor (or portions thereof); and 2) the combination of Modifications made by that Contributor with its Contributor Version (or portions of such combination). (c) the licenses granted in Sections 2.2(a) and 2.2(b) are effective on the date Contributor first makes Commercial Use of the Covered Code. (d) Notwithstanding Section 2.2(b) above, no patent license is granted: 1) for any code that Contributor has deleted from the Contributor Version; 2) separate from the Contributor Version; 3) for infringements caused by: i) third party modifications of Contributor Version or ii) the combination of Modifications made by that Contributor with other software (except as part of the Contributor Version) or other devices; or 4) under Patent Claims infringed by Covered Code in the absence of Modifications made by that Contributor. 3. Distribution Obligations. 3.1. Application of License. The Modifications which You create or to which You contribute are governed by the terms of this License, including without limitation Section 2.2. The Source Code version of Covered Code may be distributed only under the terms of this License or a future version of this License released under Section 6.1, and You must include a copy of this License with every copy of the Source Code You distribute. You may not offer or impose any terms on any Source Code version that alters or restricts the applicable version of this License or the recipients' rights hereunder. However, You may include an additional document offering the additional rights described in Section 3.5. 3.2. Availability of Source Code. Any Modification which You create or to which You contribute must be made available in Source Code form under the terms of this License either on the same media as an Executable version or via an accepted Electronic Distribution Mechanism to anyone to whom you made an Executable version available; and if made available via Electronic Distribution Mechanism, must remain available for at least twelve (12) months after the date it initially became available, or at least six (6) months after a subsequent version of that particular Modification has been made available to such recipients. You are responsible for ensuring that the Source Code version remains available even if the Electronic Distribution Mechanism is maintained by a third party. 3.3. Description of Modifications. You must cause all Covered Code to which You contribute to contain a file documenting the changes You made to create that Covered Code and the date of any change. You must include a prominent statement that the Modification is derived, directly or indirectly, from Original Code provided by the Initial Developer and including the name of the Initial Developer in (a) the Source Code, and (b) in any notice in an Executable version or related documentation in which You describe the origin or ownership of the Covered Code. 3.4. Intellectual Property Matters (a) Third Party Claims. If Contributor has knowledge that a license under a third party's intellectual property rights is required to exercise the rights granted by such Contributor under Sections 2.1 or 2.2, Contributor must include a text file with the Source Code distribution titled "LEGAL" which describes the claim and the party making the claim in sufficient detail that a recipient will know whom to contact. If Contributor obtains such knowledge after the Modification is made available as described in Section 3.2, Contributor shall promptly modify the LEGAL file in all copies Contributor makes available thereafter and shall take other steps (such as notifying appropriate mailing lists or newsgroups) reasonably calculated to inform those who received the Covered Code that new knowledge has been obtained. (b) Contributor APIs. If Contributor's Modifications include an application programming interface and Contributor has knowledge of patent licenses which are reasonably necessary to implement that API, Contributor must also include this information in the LEGAL file. (c) Representations. Contributor represents that, except as disclosed pursuant to Section 3.4(a) above, Contributor believes that Contributor's Modifications are Contributor's original creation(s) and/or Contributor has sufficient rights to grant the rights conveyed by this License. 3.5. Required Notices. You must duplicate the notice in Exhibit A in each file of the Source Code. If it is not possible to put such notice in a particular Source Code file due to its structure, then You must include such notice in a location (such as a relevant directory) where a user would be likely to look for such a notice. If You created one or more Modification(s) You may add your name as a Contributor to the notice described in Exhibit A. You must also duplicate this License in any documentation for the Source Code where You describe recipients' rights or ownership rights relating to Covered Code. You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered Code. However, You may do so only on Your own behalf, and not on behalf of the Initial Developer or any Contributor. You must make it absolutely clear than any such warranty, support, indemnity or liability obligation is offered by You alone, and You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of warranty, support, indemnity or liability terms You offer. 3.6. Distribution of Executable Versions. You may distribute Covered Code in Executable form only if the requirements of Section 3.1-3.5 have been met for that Covered Code, and if You include a notice stating that the Source Code version of the Covered Code is available under the terms of this License, including a description of how and where You have fulfilled the obligations of Section 3.2. The notice must be conspicuously included in any notice in an Executable version, related documentation or collateral in which You describe recipients' rights relating to the Covered Code. You may distribute the Executable version of Covered Code or ownership rights under a license of Your choice, which may contain terms different from this License, provided that You are in compliance with the terms of this License and that the license for the Executable version does not attempt to limit or alter the recipient's rights in the Source Code version from the rights set forth in this License. If You distribute the Executable version under a different license You must make it absolutely clear that any terms which differ from this License are offered by You alone, not by the Initial Developer or any Contributor. You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of any such terms You offer. 3.7. Larger Works. You may create a Larger Work by combining Covered Code with other code not governed by the terms of this License and distribute the Larger Work as a single product. In such a case, You must make sure the requirements of this License are fulfilled for the Covered Code. 4. Inability to Comply Due to Statute or Regulation. If it is impossible for You to comply with any of the terms of this License with respect to some or all of the Covered Code due to statute, judicial order, or regulation then You must: (a) comply with the terms of this License to the maximum extent possible; and (b) describe the limitations and the code they affect. Such description must be included in the LEGAL file described in Section 3.4 and must be included with all distributions of the Source Code. Except to the extent prohibited by statute or regulation, such description must be sufficiently detailed for a recipient of ordinary skill to be able to understand it. 5. Application of this License. This License applies to code to which the Initial Developer has attached the notice in Exhibit A and to related Covered Code. 6. Versions of the License. 6.1. New Versions. Netscape Communications Corporation ("Netscape") may publish revised and/or new versions of the License from time to time. Each version will be given a distinguishing version number. 6.2. Effect of New Versions. Once Covered Code has been published under a particular version of the License, You may always continue to use it under the terms of that version. You may also choose to use such Covered Code under the terms of any subsequent version of the License published by Netscape. No one other than Netscape has the right to modify the terms applicable to Covered Code created under this License. 6.3. Derivative Works. If You create or use a modified version of this License (which you may only do in order to apply it to code which is not already Covered Code governed by this License), You must (a) rename Your license so that the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape", "MPL", "NPL" or any confusingly similar phrase do not appear in your license (except to note that your license differs from this License) and (b) otherwise make it clear that Your version of the license contains terms which differ from the Mozilla Public License and Netscape Public License. (Filling in the name of the Initial Developer, Original Code or Contributor in the notice described in Exhibit A shall not of themselves be deemed to be modifications of this License.) 7. DISCLAIMER OF WARRANTY. COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. 8. TERMINATION. 8.1. This License and the rights granted hereunder will terminate automatically if You fail to comply with terms herein and fail to cure such breach within 30 days of becoming aware of the breach. All sublicenses to the Covered Code which are properly granted shall survive any termination of this License. Provisions which, by their nature, must remain in effect beyond the termination of this License shall survive. 8.2. If You initiate litigation by asserting a patent infringement claim (excluding declatory judgment actions) against Initial Developer or a Contributor (the Initial Developer or Contributor against whom You file such action is referred to as "Participant") alleging that: (a) such Participant's Contributor Version directly or indirectly infringes any patent, then any and all rights granted by such Participant to You under Sections 2.1 and/or 2.2 of this License shall, upon 60 days notice from Participant terminate prospectively, unless if within 60 days after receipt of notice You either: (i) agree in writing to pay Participant a mutually agreeable reasonable royalty for Your past and future use of Modifications made by such Participant, or (ii) withdraw Your litigation claim with respect to the Contributor Version against such Participant. If within 60 days of notice, a reasonable royalty and payment arrangement are not mutually agreed upon in writing by the parties or the litigation claim is not withdrawn, the rights granted by Participant to You under Sections 2.1 and/or 2.2 automatically terminate at the expiration of the 60 day notice period specified above. (b) any software, hardware, or device, other than such Participant's Contributor Version, directly or indirectly infringes any patent, then any rights granted to You by such Participant under Sections 2.1(b) and 2.2(b) are revoked effective as of the date You first made, used, sold, distributed, or had made, Modifications made by that Participant. 8.3. If You assert a patent infringement claim against Participant alleging that such Participant's Contributor Version directly or indirectly infringes any patent where such claim is resolved (such as by license or settlement) prior to the initiation of patent infringement litigation, then the reasonable value of the licenses granted by such Participant under Sections 2.1 or 2.2 shall be taken into account in determining the amount or value of any payment or license. 8.4. In the event of termination under Sections 8.1 or 8.2 above, all end user license agreements (excluding distributors and resellers) which have been validly granted by You or any distributor hereunder prior to termination shall survive termination. 9. LIMITATION OF LIABILITY. UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. 10. U.S. GOVERNMENT END USERS. The Covered Code is a "commercial item," as that term is defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer software" and "commercial computer software documentation," as such terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all U.S. Government End Users acquire Covered Code with only those rights set forth herein. 11. MISCELLANEOUS. This License represents the complete agreement concerning subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. This License shall be governed by California law provisions (except to the extent applicable law, if any, provides otherwise), excluding its conflict-of-law provisions. With respect to disputes in which at least one party is a citizen of, or an entity chartered or registered to do business in the United States of America, any litigation relating to this License shall be subject to the jurisdiction of the Federal Courts of the Northern District of California, with venue lying in Santa Clara County, California, with the losing party responsible for costs, including without limitation, court costs and reasonable attorneys' fees and expenses. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not apply to this License. 12. RESPONSIBILITY FOR CLAIMS. As between Initial Developer and the Contributors, each party is responsible for claims and damages arising, directly or indirectly, out of its utilization of rights under this License and You agree to work with Initial Developer and Contributors to distribute such responsibility on an equitable basis. Nothing herein is intended or shall be deemed to constitute any admission of liability. 13. MULTIPLE-LICENSED CODE. Initial Developer may designate portions of the Covered Code as "Multiple-Licensed". "Multiple-Licensed" means that the Initial Developer permits you to utilize portions of the Covered Code under Your choice of the MPL or the alternative licenses, if any, specified by the Initial Developer in the file described in Exhibit A. EXHIBIT A -Mozilla Public License. ``The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. The Original Code is RabbitMQ. The Initial Developer of the Original Code is GoPivotal, Inc. Copyright (c) 2007-2016 Pivotal Software, Inc. All rights reserved. Alternatively, the contents of this file may be used under the terms of the GNU General Public License version 2 (the "GPL2"), or the Apache License version 2 (the "ASL2") in which case the provisions of GPL2 or the ASL2 are applicable instead of those above. If you wish to allow use of your version of this file only under the terms of the GPL2 or the ASL2 and not to allow others to use your version of this file under the MPL, indicate your decision by deleting the provisions above and replace them with the notice and other provisions required by the GPL2 or the ASL2. If you do not delete the provisions above, a recipient may use your version of this file under either the MPL, the GPL2 or the ASL2.'' [NOTE: The text of this Exhibit A may differ slightly from the text of the notices in the Source Code files of the Original Code. You should use the text of this Exhibit A rather than the text found in the Original Code Source Code for Your Modifications.] rabbitmq-java-client-5.0.0/Makefile000066400000000000000000000020431316117667700171660ustar00rootroot00000000000000MVN ?= mvn MVN_FLAGS ?= ifndef DEPS_DIR ifneq ($(wildcard ../../UMBRELLA.md),) DEPS_DIR = .. else DEPS_DIR = deps endif endif MVN_FLAGS += -Ddeps.dir="$(abspath $(DEPS_DIR))" .PHONY: all deps tests clean distclean all: deps $(MVN) $(MVN_FLAGS) compile deps: $(DEPS_DIR)/rabbit @: dist: clean $(MVN) $(MVN_FLAGS) -DskipTests=true -Dmaven.javadoc.failOnError=false package javadoc:javadoc $(DEPS_DIR)/rabbit: git clone https://github.com/rabbitmq/rabbitmq-server.git $@ $(MAKE) -C $@ fetch-deps DEPS_DIR="$(abspath $(DEPS_DIR))" tests: deps $(MVN) $(MVN_FLAGS) verify deploy: $(MVN) $(MVN_FLAGS) deploy clean: $(MVN) $(MVN_FLAGS) clean distclean: clean $(MAKE) -C $(DEPS_DIR)/rabbitmq_codegen clean .PHONY: cluster-other-node cluster-other-node: $(exec_verbose) $(RABBITMQCTL) -n $(OTHER_NODE) stop_app $(verbose) $(RABBITMQCTL) -n $(OTHER_NODE) reset $(verbose) $(RABBITMQCTL) -n $(OTHER_NODE) join_cluster \ $(if $(MAIN_NODE),$(MAIN_NODE),$(RABBITMQ_NODENAME)@$$(hostname -s)) $(verbose) $(RABBITMQCTL) -n $(OTHER_NODE) start_app rabbitmq-java-client-5.0.0/README.in000066400000000000000000000005661316117667700170230ustar00rootroot00000000000000Please see http://www.rabbitmq.com/build-java-client.html for build instructions. For your convenience, a text copy of these instructions is available below. Please be aware that the instructions here may not be as up to date as those at the above URL. See LICENSE for license information. =========================================================================== rabbitmq-java-client-5.0.0/README.md000066400000000000000000000035521316117667700170130ustar00rootroot00000000000000# RabbitMQ Java Client This repository contains source code of the [RabbitMQ Java client](http://www.rabbitmq.com/api-guide.html). The client is maintained by the [RabbitMQ team at Pivotal](http://github.com/rabbitmq/). ## Dependency (Maven Artifact) Maven artifacts are [released to Maven Central](http://search.maven.org/#search%7Cga%7C1%7Cg%3Acom.rabbitmq%20a%3Aamqp-client) via [RabbitMQ Maven repository on Bintray](https://bintray.com/rabbitmq/maven). There's also a [Maven repository with milestone releases](https://bintray.com/rabbitmq/maven-milestones). [Snapshots are available](https://oss.sonatype.org/content/repositories/snapshots/com/rabbitmq/amqp-client/) as well. ### Maven [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.rabbitmq/amqp-client/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.rabbitmq/amqp-client) #### 4.x Series Starting with `4.0`, this client releases are independent from RabbitMQ server releases. These versions can still be used with RabbitMQ server `3.x`. ``` xml com.rabbitmq amqp-client 4.2.0 ``` ### Gradle ``` groovy compile 'com.rabbitmq:amqp-client:4.2.0' ``` #### 3.6.x Series `3.6.x` series are released in concert with RabbitMQ server for historical reasons. ``` xml com.rabbitmq amqp-client 3.6.6 ``` ### Gradle ``` groovy compile 'com.rabbitmq:amqp-client:3.6.6' ``` ## Contributing See [Contributing](./CONTRIBUTING.md) and [How to Run Tests](./RUNNING_TESTS.md). ## License This package, the RabbitMQ Java client library, is triple-licensed under the Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 ("GPL") and the Apache License version 2 ("ASL"). rabbitmq-java-client-5.0.0/RUNNING_TESTS.md000066400000000000000000000131711316117667700201560ustar00rootroot00000000000000## Overview There are multiple test suites in the RabbitMQ Java client library; the source for all of the suites can be found in the [src/test/java](src/test/java) directory. The suites are: * Client tests * Server tests * SSL tests * Functional tests * HA tests All of them assume a RabbitMQ node listening on localhost:5672 (the default settings). SSL tests require a broker listening on the default SSL port. HA tests expect a second node listening on localhost:5673. Connection recovery tests need `rabbitmqctl` to control the running nodes. can control the running node. `mvn verify` will start those nodes with the appropriate configuration. To easily fullfil all those requirements, you can use `make deps` to fetch the dependencies. You can also fetch them yourself and use the same layout: ``` deps |-- rabbitmq_codegen `-- rabbit ``` You then run Maven with the `deps.dir` property set like this: ``` mvn -Ddeps.dir=/path/to/deps verify ``` For details on running specific tests, see below. ## Running a Specific Test Suite To run a specific test suite you should execute one of the following in the top-level directory of the source tree: * To run the client unit tests: ``` mvn -Ddeps.dir=/path/to/deps verify -Dit.test=ClientTests ``` * To run the functional tests: ``` mvn -Ddeps.dir=/path/to/deps verify -Dit.test=FunctionalTests ``` * To run a single test: ``` mvn -Ddeps.dir=/path/to/deps verify -Dit.test=DeadLetterExchange ``` For example, to run the client tests: ``` rabbitmq-java-client$ mvn -Ddeps.dir=/path/to/deps verify -Dit.test=ClientTests [INFO] Scanning for projects... [INFO] Inspecting build with total of 1 modules... [INFO] Installing Nexus Staging features: [INFO] ... total of 1 executions of maven-deploy-plugin replaced with nexus-staging-maven-plugin [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building RabbitMQ Java Client 3.7.0-SNAPSHOT [INFO] ------------------------------------------------------------------------ [INFO] [INFO] --- groovy-maven-plugin:2.0:execute (generate-amqp-sources) @ amqp-client --- [INFO] [INFO] --- build-helper-maven-plugin:1.12:add-source (add-generated-sources-dir) @ amqp-client --- [INFO] Source directory: .../rabbitmq_java_client/target/generated-sources/src/main/java added. [INFO] [INFO] --- maven-resources-plugin:2.5:resources (default-resources) @ amqp-client --- [debug] execute contextualize [INFO] Using 'UTF-8' encoding to copy filtered resources. [INFO] Copying 1 resource [INFO] [INFO] --- maven-compiler-plugin:3.5.1:compile (default-compile) @ amqp-client --- [INFO] Nothing to compile - all classes are up to date [INFO] [INFO] --- groovy-maven-plugin:2.0:execute (remove-old-test-keystores) @ amqp-client --- [INFO] [INFO] --- groovy-maven-plugin:2.0:execute (query-test-tls-certs-dir) @ amqp-client --- [INFO] [INFO] --- keytool-maven-plugin:1.5:importCertificate (generate-test-ca-keystore) @ amqp-client --- [WARNING] Certificate was added to keystore [INFO] [INFO] --- keytool-maven-plugin:1.5:importCertificate (generate-test-empty-keystore) @ amqp-client --- [WARNING] Certificate was added to keystore [INFO] [INFO] --- keytool-maven-plugin:1.5:deleteAlias (generate-test-empty-keystore) @ amqp-client --- [INFO] [INFO] --- maven-resources-plugin:2.5:testResources (default-testResources) @ amqp-client --- [debug] execute contextualize [INFO] Using 'UTF-8' encoding to copy filtered resources. [INFO] Copying 3 resources [INFO] [INFO] --- maven-compiler-plugin:3.5.1:testCompile (default-testCompile) @ amqp-client --- [INFO] Nothing to compile - all classes are up to date [INFO] [INFO] --- maven-surefire-plugin:2.19.1:test (default-test) @ amqp-client --- [INFO] Tests are skipped. [INFO] [INFO] --- maven-jar-plugin:3.0.2:jar (default-jar) @ amqp-client --- [INFO] Building jar: .../rabbitmq_java_client/target/amqp-client-3.7.0-SNAPSHOT.jar [INFO] [INFO] --- groovy-maven-plugin:2.0:execute (start-test-broker-A) @ amqp-client --- [INFO] [INFO] --- groovy-maven-plugin:2.0:execute (start-test-broker-B) @ amqp-client --- [INFO] [INFO] --- groovy-maven-plugin:2.0:execute (create-test-cluster) @ amqp-client --- [INFO] [INFO] --- maven-failsafe-plugin:2.19.1:integration-test (integration-test) @ amqp-client --- ------------------------------------------------------- T E S T S ------------------------------------------------------- Running com.rabbitmq.client.test.ClientTests Tests run: 50, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.732 sec - in com.rabbitmq.client.test.ClientTests Results : Tests run: 50, Failures: 0, Errors: 0, Skipped: 0 [INFO] [INFO] --- groovy-maven-plugin:2.0:execute (stop-test-broker-B) @ amqp-client --- [INFO] [INFO] --- groovy-maven-plugin:2.0:execute (stop-test-broker-A) @ amqp-client --- [INFO] [INFO] --- maven-failsafe-plugin:2.19.1:verify (verify) @ amqp-client --- [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 33.707s [INFO] Finished at: Mon Aug 08 16:22:26 CEST 2016 [INFO] Final Memory: 21M/256M [INFO] ------------------------------------------------------------------------ ``` Test reports can be found in `target/failsafe-reports`. ## Running tests against an externally provided broker or cluster By default, if the RabbitMQ broker sources are available, the testsuite starts automatically a cluster of two RabbitMQ nodes and runs the tests against it. You can also provide your own broker or cluster. To disable the automatic test cluster setup, disable the `setup-test-cluster` Maven profile: ``` mvn verify -P '!setup-test-cluster' ``` rabbitmq-java-client-5.0.0/codegen.py000077500000000000000000000557461316117667700175310ustar00rootroot00000000000000#!/usr/bin/env python ## Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. ## ## This software, the RabbitMQ Java client library, is triple-licensed under the ## Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 ## ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see ## LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, ## please see LICENSE-APACHE2. ## ## This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, ## either express or implied. See the LICENSE file for specific language governing ## rights and limitations of this software. ## ## If you have any questions regarding licensing, please contact us at ## info@rabbitmq.com. from __future__ import nested_scopes from __future__ import print_function import re import sys from amqp_codegen import * class BogusDefaultValue(Exception): def __init__(self, value): self.value = value def __str__(self): return repr(self.value) def java_constant_name(c): return '_'.join(re.split('[- ]', c.upper())) javaTypeMap = { 'octet': 'int', 'shortstr': 'String', 'longstr': 'LongString', 'short': 'int', 'long': 'int', 'longlong': 'long', 'bit': 'boolean', 'table': 'Map', 'timestamp': 'Date' } javaTypesToCheckForNull = set([ 'String', 'LongString', 'Date' ]) # the scalar types in the range of javaTypeMap must be in javaScalarTypes javaScalarTypes = set([ 'int', 'long', 'boolean' ]) # the javaScalarTypes must be in the domain of javaBoxedTypeMap javaBoxedTypeMap = { 'int': 'Integer', 'long': 'Long', 'boolean': 'Boolean' } def java_boxed_type(jtype): if jtype in javaScalarTypes: return javaBoxedTypeMap[jtype] else: return jtype def java_type(spec, domain): return javaTypeMap[spec.resolveDomain(domain)] def java_name(upperNext, name): out = '' for c in name: if not c.isalnum(): upperNext = True elif upperNext: out += c.upper() upperNext = False else: out += c return out def java_class_name(name): return java_name(True, name) def java_getter_name(name): return java_name(False, 'get-' + name) def java_field_name(name): return java_name(False, name) def java_field_type(spec, domain): return javaTypeMap[spec.resolveDomain(domain)] def java_field_default_value(jtype, value): if jtype == 'int': return value elif jtype == 'boolean': return ('%s'% (value)).lower() elif jtype == 'String': return '"%s"' % (value) elif jtype == 'LongString': return 'LongStringHelper.asLongString("%s")' % (value) elif jtype == 'long': return '%sL' % (value) elif jtype == 'Map': return "null" else: raise BogusDefaultValue("JSON provided default value %s for suspicious type %s" % (value, jtype)) def typeNameDefault(spec, a): fieldType = java_field_type(spec, a.domain) defaultVal = java_field_default_value(fieldType, a.defaultvalue) return (fieldType, java_field_name(a.name), defaultVal) def nullCheckedFields(spec, m): fieldsToNullCheck = set([]) for a in m.arguments: (jfType, jfName, jfDefault) = typeNameDefault(spec,a) if jfType in javaTypesToCheckForNull: fieldsToNullCheck.add(jfName) return fieldsToNullCheck #--------------------------------------------------------------------------- def printFileHeader(): print("""// NOTE: This -*- java -*- source code is autogenerated from the AMQP // specification! // // Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. // """) def genJavaApi(spec): def printHeader(): printFileHeader() print("package com.rabbitmq.client;") print() print("import java.io.DataInputStream;") print("import java.io.IOException;") print("import java.util.Collections;") print("import java.util.HashMap;") print("import java.util.Map;") print("import java.util.Date;") print() print("import com.rabbitmq.client.impl.ContentHeaderPropertyWriter;") print("import com.rabbitmq.client.impl.ContentHeaderPropertyReader;") print("import com.rabbitmq.client.impl.LongStringHelper;") def printProtocolClass(): print() print(" public static class PROTOCOL {") print(" public static final int MAJOR = %i;" % spec.major) print(" public static final int MINOR = %i;" % spec.minor) print(" public static final int REVISION = %i;" % spec.revision) print(" public static final int PORT = %i;" % spec.port) print(" }") def printConstants(): print() for (c,v,cls) in spec.constants: print(" public static final int %s = %i;" % (java_constant_name(c), v)) def builder(c,m): def ctorCall(c,m): ctor_call = "com.rabbitmq.client.impl.AMQImpl.%s.%s" % (java_class_name(c.name),java_class_name(m.name)) ctor_arg_list = [ java_field_name(a.name) for a in m.arguments ] print(" return new %s(%s);" % (ctor_call, ", ".join(ctor_arg_list))) def genFields(spec, m): for a in m.arguments: (jfType, jfName, jfDefault) = typeNameDefault(spec, a) if a.defaultvalue != None: print(" private %s %s = %s;" % (jfType, jfName, jfDefault)) else: print(" private %s %s;" % (jfType, jfName)) def genArgMethods(spec, m): for a in m.arguments: (jfType, jfName, jfDefault) = typeNameDefault(spec, a) print(" public Builder %s(%s %s)" % (jfName, jfType, jfName)) print(" { this.%s = %s; return this; }" % (jfName, jfName)) if jfType == "boolean": print(" public Builder %s()" % (jfName)) print(" { return this.%s(true); }" % (jfName)) elif jfType == "LongString": print(" public Builder %s(String %s)" % (jfName, jfName)) print(" { return this.%s(LongStringHelper.asLongString(%s)); }" % (jfName, jfName)) def genBuildMethod(c,m): print(" public %s build() {" % (java_class_name(m.name))) ctorCall(c,m) print(" }") print() print(" // Builder for instances of %s.%s" % (java_class_name(c.name), java_class_name(m.name))) print(" public static final class Builder") print(" {") genFields(spec, m) print() print(" public Builder() { }") print() genArgMethods(spec, m) genBuildMethod(c,m) print(" }") def printClassInterfaces(): for c in spec.classes: print() print(" public static class %s {" % (java_class_name(c.name))) for m in c.allMethods(): print(" public interface %s extends Method {" % ((java_class_name(m.name)))) for a in m.arguments: print(" %s %s();" % (java_field_type(spec, a.domain), java_getter_name(a.name))) builder(c,m) print(" }") print(" }") def printReadProperties(c): if c.fields: for f in c.fields: print(" boolean %s_present = reader.readPresence();" % (java_field_name(f.name))) print() print(" reader.finishPresence();") if c.fields: print() for f in c.fields: (jfName, jfClass) = (java_field_name(f.name), java_class_name(f.domain)) print(" this.%s = %s_present ? reader.read%s() : null;" % (jfName, jfName, jfClass)) def printWritePropertiesTo(c): print() print(" public void writePropertiesTo(ContentHeaderPropertyWriter writer)") print(" throws IOException") print(" {") if c.fields: for f in c.fields: print(" writer.writePresence(this.%s != null);" % (java_field_name(f.name))) print() print(" writer.finishPresence();") if c.fields: print() for f in c.fields: (jfName, jfClass) = (java_field_name(f.name), java_class_name(f.domain)) print(" if (this.%s != null) writer.write%s(this.%s);" % (jfName, jfClass, jfName)) print(" }") def printAppendPropertyDebugStringTo(c): appendList = [ "%s=\")\n .append(this.%s)\n .append(\"" % (f.name, java_field_name(f.name)) for f in c.fields ] print() print(" public void appendPropertyDebugStringTo(StringBuilder acc) {") print(" acc.append(\"(%s)\");" % (", ".join(appendList))) print(" }") def printPropertiesBuilderClass(c): def printBuilderSetter(fieldType, fieldName): print(" public Builder %s(%s %s)" % (fieldName, java_boxed_type(fieldType), fieldName)) print(" { this.%s = %s; return this; }" % (fieldName, fieldName)) if fieldType == "boolean": print(" public Builder %s()" % (fieldName)) print(" { return this.%s(true); }" % (fieldName)) elif fieldType == "LongString": print(" public Builder %s(String %s)" % (fieldName, fieldName)) print(" { return this.%s(LongStringHelper.asLongString(%s)); }" % (fieldName, fieldName)) print() print(" public static final class Builder {") # fields for f in c.fields: (fType, fName) = (java_field_type(spec, f.domain), java_field_name(f.name)) print(" private %s %s;" % (java_boxed_type(fType), fName)) # ctor print() print(" public Builder() {};") # setters print() for f in c.fields: printBuilderSetter(java_field_type(spec, f.domain), java_field_name(f.name)) print() jClassName = java_class_name(c.name) # build() objName = "%sProperties" % (jClassName) ctor_parm_list = [ java_field_name(f.name) for f in c.fields ] print(" public %s build() {" % (objName)) print(" return new %s" % (objName)) print(" ( %s" % ("\n , ".join(ctor_parm_list))) print(" );") print(" }") print(" }") def printPropertiesBuilder(c): print() print(" public Builder builder() {") print(" Builder builder = new Builder()") setFieldList = [ "%s(%s)" % (fn, fn) for fn in [ java_field_name(f.name) for f in c.fields ] ] print(" .%s;" % ("\n .".join(setFieldList))) print(" return builder;") print(" }") def printPropertiesClass(c): def printGetter(fieldType, fieldName): capFieldName = fieldName[0].upper() + fieldName[1:] print(" public %s get%s() { return this.%s; }" % (java_boxed_type(fieldType), capFieldName, fieldName)) jClassName = java_class_name(c.name) print() print(" public static class %sProperties extends com.rabbitmq.client.impl.AMQ%sProperties {" % (jClassName, jClassName)) #property fields for f in c.fields: (fType, fName) = (java_boxed_type(java_field_type(spec, f.domain)), java_field_name(f.name)) print(" private %s %s;" % (fType, fName)) #explicit constructor if c.fields: print() consParmList = [ "%s %s" % (java_boxed_type(java_field_type(spec,f.domain)), java_field_name(f.name)) for f in c.fields ] print(" public %sProperties(" % (jClassName)) print(" %s)" % (",\n ".join(consParmList))) print(" {") for f in c.fields: (fType, fName) = (java_field_type(spec, f.domain), java_field_name(f.name)) if fType == "Map": print(" this.%s = %s==null ? null : Collections.unmodifiableMap(new HashMap(%s));" % (fName, fName, fName)) else: print(" this.%s = %s;" % (fName, fName)) print(" }") #datainputstream constructor print() print(" public %sProperties(DataInputStream in) throws IOException {" % (jClassName)) print(" super(in);") print(" ContentHeaderPropertyReader reader = new ContentHeaderPropertyReader(in);") printReadProperties(c) print(" }") # default constructor print(" public %sProperties() {}" % (jClassName)) #class properties print(" public int getClassId() { return %i; }" % (c.index)) print(" public String getClassName() { return \"%s\"; }" % (c.name)) printPropertiesBuilder(c) #accessor methods print() for f in c.fields: (jType, jName) = (java_field_type(spec, f.domain), java_field_name(f.name)) printGetter(jType, jName) printWritePropertiesTo(c) printAppendPropertyDebugStringTo(c) printPropertiesBuilderClass(c) print(" }") def printPropertiesClasses(): for c in spec.classes: if c.hasContentProperties: printPropertiesClass(c) printHeader() print() print("public interface AMQP {") printProtocolClass() printConstants() printClassInterfaces() printPropertiesClasses() print("}") #-------------------------------------------------------------------------------- def genJavaImpl(spec): def printHeader(): printFileHeader() print("package com.rabbitmq.client.impl;") print() print("import java.io.IOException;") print("import java.io.DataInputStream;") print("import java.util.Collections;") print("import java.util.HashMap;") print("import java.util.Map;") print() print("import com.rabbitmq.client.AMQP;") print("import com.rabbitmq.client.LongString;") print("import com.rabbitmq.client.UnknownClassOrMethodId;") print("import com.rabbitmq.client.UnexpectedMethodError;") def printClassMethods(spec, c): print() print(" public static class %s {" % (java_class_name(c.name))) print(" public static final int INDEX = %s;" % (c.index)) for m in c.allMethods(): def getters(): if m.arguments: print() for a in m.arguments: print(" public %s %s() { return %s; }" % (java_field_type(spec,a.domain), java_getter_name(a.name), java_field_name(a.name))) def constructors(): print() argList = [ "%s %s" % (java_field_type(spec,a.domain),java_field_name(a.name)) for a in m.arguments ] print(" public %s(%s) {" % (java_class_name(m.name), ", ".join(argList))) fieldsToNullCheckInCons = [f for f in nullCheckedFields(spec, m)] fieldsToNullCheckInCons.sort() for f in fieldsToNullCheckInCons: print(" if (%s == null)" % (f)) print(" throw new IllegalStateException(\"Invalid configuration: '%s' must be non-null.\");" % (f)) for a in m.arguments: (jfType, jfName) = (java_field_type(spec, a.domain), java_field_name(a.name)) if jfType == "Map": print(" this.%s = %s==null ? null : Collections.unmodifiableMap(new HashMap(%s));" % (jfName, jfName, jfName)) else: print(" this.%s = %s;" % (jfName, jfName)) print(" }") consArgs = [ "rdr.read%s()" % (java_class_name(spec.resolveDomain(a.domain))) for a in m.arguments ] print(" public %s(MethodArgumentReader rdr) throws IOException {" % (java_class_name(m.name))) print(" this(%s);" % (", ".join(consArgs))) print(" }") def others(): print() print(" public int protocolClassId() { return %s; }" % (c.index)) print(" public int protocolMethodId() { return %s; }" % (m.index)) print(" public String protocolMethodName() { return \"%s.%s\";}" % (c.name, m.name)) print() print(" public boolean hasContent() { return %s; }" % (trueOrFalse(m.hasContent))) print() print(" public Object visit(MethodVisitor visitor) throws IOException") print(" { return visitor.visit(this); }") def trueOrFalse(truthVal): if truthVal: return "true" else: return "false" def argument_debug_string(): appendList = [ "%s=\")\n .append(this.%s)\n .append(\"" % (a.name, java_field_name(a.name)) for a in m.arguments ] print() print(" public void appendArgumentDebugStringTo(StringBuilder acc) {") print(" acc.append(\"(%s)\");" % ", ".join(appendList)) print(" }") def write_arguments(): print() print(" public void writeArgumentsTo(MethodArgumentWriter writer)") print(" throws IOException") print(" {") for a in m.arguments: print(" writer.write%s(this.%s);" % (java_class_name(spec.resolveDomain(a.domain)), java_field_name(a.name))) print(" }") #start print() print(" public static class %s" % (java_class_name(m.name),)) print(" extends Method") print(" implements com.rabbitmq.client.AMQP.%s.%s" % (java_class_name(c.name), java_class_name(m.name))) print(" {") print(" public static final int INDEX = %s;" % (m.index)) print() for a in m.arguments: print(" private final %s %s;" % (java_field_type(spec, a.domain), java_field_name(a.name))) getters() constructors() others() argument_debug_string() write_arguments() print(" }") print(" }") def printMethodVisitor(): print() print(" public interface MethodVisitor {") for c in spec.allClasses(): for m in c.allMethods(): print(" Object visit(%s.%s x) throws IOException;" % (java_class_name(c.name), java_class_name(m.name))) print(" }") #default method visitor print() print(" public static class DefaultMethodVisitor implements MethodVisitor {") for c in spec.allClasses(): for m in c.allMethods(): print(" public Object visit(%s.%s x) throws IOException { throw new UnexpectedMethodError(x); }" % (java_class_name(c.name), java_class_name(m.name))) print(" }") def printMethodArgumentReader(): print() print(" public static Method readMethodFrom(DataInputStream in) throws IOException {") print(" int classId = in.readShort();") print(" int methodId = in.readShort();") print(" switch (classId) {") for c in spec.allClasses(): print(" case %s:" % (c.index)) print(" switch (methodId) {") for m in c.allMethods(): fq_name = java_class_name(c.name) + '.' + java_class_name(m.name) print(" case %s: {" % (m.index)) print(" return new %s(new MethodArgumentReader(new ValueReader(in)));" % (fq_name)) print(" }") print(" default: break;") print(" } break;") print(" }") print() print(" throw new UnknownClassOrMethodId(classId, methodId);") print(" }") def printContentHeaderReader(): print() print(" public static AMQContentHeader readContentHeaderFrom(DataInputStream in) throws IOException {") print(" int classId = in.readShort();") print(" switch (classId) {") for c in spec.allClasses(): if c.fields: print(" case %s: return new %sProperties(in);" %(c.index, (java_class_name(c.name)))) print(" default: break;") print(" }") print() print(" throw new UnknownClassOrMethodId(classId);") print(" }") printHeader() print() print("public class AMQImpl implements AMQP {") for c in spec.allClasses(): printClassMethods(spec,c) printMethodVisitor() printMethodArgumentReader() printContentHeaderReader() print("}") #-------------------------------------------------------------------------------- def generateJavaApi(specPath): genJavaApi(AmqpSpec(specPath)) def generateJavaImpl(specPath): genJavaImpl(AmqpSpec(specPath)) if __name__ == "__main__": do_main(generateJavaApi, generateJavaImpl) rabbitmq-java-client-5.0.0/deploy-javadoc.sh000077500000000000000000000014501316117667700207670ustar00rootroot00000000000000#!/usr/bin/env bash DEPLOY_PATH=/home/rabbitmq/extras/releases/rabbitmq-java-client/current-javadoc # RSync user/host to deploy to. Mandatory. DEPLOY_USERHOST= # Imitate make-style variable settings as arguments while [[ $# -gt 0 ]] ; do declare "$1" shift done mandatory_vars="DEPLOY_USERHOST" optional_vars="DEPLOY_PATH" function die () { echo "$@" 2>&1 exit 1 } # Check mandatory settings for v in $mandatory_vars ; do [[ -n "${!v}" ]] || die "$v not set" done echo "Settings:" for v in $mandatory_vars $optional_vars ; do echo "${v}=${!v}" done set -e -x mvn -q clean javadoc:javadoc -Dmaven.javadoc.failOnError=false ssh $DEPLOY_USERHOST \ "rm -rf $DEPLOY_PATH; \ mkdir -p $DEPLOY_PATH" rsync -rpl --exclude '*.sh' target/site/apidocs/ $DEPLOY_USERHOST:$DEPLOY_PATH rabbitmq-java-client-5.0.0/doc/000077500000000000000000000000001316117667700162745ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/doc/channels/000077500000000000000000000000001316117667700200675ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/doc/channels/channels.tex000066400000000000000000000231731316117667700224120ustar00rootroot00000000000000\documentclass[a4paper,twoside,12pt]{article} \usepackage{zed-cm} \usepackage{graphicx} \markboth{Draft}{Version 0.1} \pagestyle{myheadings} \begin{document} \parskip 2 pt \parindent 10 pt \title{Channeling Work} \author{Steve Powell \and Rob Harrop} \maketitle % The following three commands ensure the title page is stamped as % confidential without a page number. Page numbering is started at the % table of contents. \thispagestyle{myheadings} \pagenumbering{roman} \setcounter{page}{1} %============================================================================= \abstract{A short specification arising from Rob's investigation into serving messages on a collection of channels with a limited number of threads, preserving ordering constraints.} % Cntrl-Cmd-M -- \emph{} % Cntrl-Cmd-Z -- \zed{} % Cntrl-Cmd-X -- \axdef{} % Cntrl-Cmd-S -- \schema{} % Cntrl-Cmd-C -- \texttt{} % Type checking hacks \newcommand{\true}{true} \newcommand{\false}{false} \renewcommand{\emptyset}{\varnothing} %===================================================================== \clearpage \tableofcontents \clearpage \pagenumbering{arabic} %===================================================================== \section{Introduction} The primitives in this description are $Channel$s and items of $Work$. It is assumed that work is a message transfer or acknowledgement of some kind. It is not important. What is important is that a series of items of $Work$ needs to be done for a $Channel$ and we cannot allow two items of work to be processed for the same $Channel$ at the same time. So we introduce the primitive sets: \begin{zed} [ Channel, Work ] \end{zed} and with these we can describe the general state. %===================================================================== \section{The general state of things} The basic state of the system is a collection of $Channel$s with a sequence of items of work associated with each: \begin{schema}{Pool} pool : Channel \pfun \seq Work \end{schema} The $pool$ of known channels ($\dom pool$) is partitioned into those which are $dormant$, those $ready$ for work to be done, and those which are currently being processed ($inprogress$). We define a convenience schema for each partition. This is to name them for use in explicitly stating preservation later. The $dormant$ ones have no work (but we cannot impose this constraint without the $pool$ -- we do it later): \begin{schema}{Dormant} dormant : \power Channel \end{schema} the $ready$ ones are ordered: \begin{schema}{Ready} ready : \iseq Channel \end{schema} and the rest are `in progress': \begin{schema}{InProgress} inprogress : \power Channel \end{schema} \subsection{The state of the union} We can now assemble the entire system state as follows: \begin{schema}{State} Pool \\ Dormant \\ Ready \\ InProgress \where \langle dormant, \ran ready, inprogress \rangle \partition \dom pool \also \forall c : dormant @ pool ~ c = \langle \rangle \end{schema} where we make explicit that these channel collections partition those known (in $\dom pool$), and can also impose the constraint that the $dormant$ channels have no work. %ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ \section{Work delivery} In general, as it comes in, work is added to the sequence of items associated with a channel in the $pool$. However, the precise change of state depends upon which partition the channel is in at the time. We therefore define three `deliver work' state transitions; one for each partition. In each case different partitions change as a result. They share the same signature, and underlying pool change, however: \begin{schema}{DeliverWorkCommon} \Delta State \\ w? : Work \\ c? : Channel \where c? \in \dom pool \\ pool ' = pool \oplus \{ c? \mapsto pool ~ c? \cat \langle w? \rangle \} \end{schema} each of them changes the $State$, and takes an item of work and a channel as input. In every case, the work is added to the $pool$. When the channel is dormant it moves into the ready queue (and the `in progress' partition remains unchanged): \begin{schema}{DeliverDormant} DeliverWorkCommon \\ \Xi InProgress \where c? \in dormant \\ dormant ' = dormant \setminus \{c?\} \\ ready' = ready \cat \langle c? \rangle \end{schema} (Note that in this case the resulting sequence of work is simply $\langle w? \rangle$.) When the channel is already `in progress' the partitions stay unchanged: \begin{schema}{DeliverInProgress} DeliverWorkCommon \\ \Xi InProgress \\ \Xi Dormant \\ \Xi Ready \where c? \in inprogress \end{schema} (and we need say nothing more). When the channel is ready (in the $ready$ queue) the partitions stay unchanged as well: \begin{schema}{DeliverReady} DeliverWorkCommon \\ \Xi InProgress \\ \Xi Dormant \\ \Xi Ready \where c? \in \ran ready \end{schema} (and we need say nothing more). Since the preconditions of the $Deliver$ schemas are disjoint, we may combine them without introducing any further non-determinism: \begin{zed} DeliverWork\defs DeliverDormant \lor DeliverInProgress \lor DeliverReady \end{zed} \section{Start work} When there is time (and available computing resources) we can start some work. We consider only doing one piece of work at a time, though it is easy to consider `batching' work items together. The operation that starts it picks a piece of work to do, and gives the work and channel as outputs. The dormant channels are unaffected, and the channel moves from ready to `in progress': \begin{schema}{StartWork} \Delta State \\ \Xi Dormant \\ c! : Channel \\ w! : Work \where ready \neq \langle \rangle \\ \langle c! \rangle \cat ready' = ready \\ inprogress' = inprogress \cup \{ c! \} \\ \langle w! \rangle \cat pool' ~ c! = pool ~ c! \\ \{ c! \} \ndres pool' = \{ c! \} \ndres pool \end{schema} where the channel simply gets `taken' from the front of the ready queue; the work gets `taken' from the front of the work queue for the channel; the channel gets put in the `in progress' partition and no other channels are affected. Notice that here, although apparently there might be no work left, the channel is not put into the $dormant$ partition until the current work is completed. It is quite in order for non-$dormant$ channels to have no work \emph{pro tem}, though we expect such a channel to be placed in $dormant$ eventually. \section{Our work is done} After the work is completed the channel can be taken out of `in progress'. Of course, there might already be more work to do (or not) and these cases are distinguished. We define a `partial operation' to identify the essence of work completion: \begin{schema}{EndWorkCommon} \Delta State \\ \Xi Pool \\ c? : Channel \where c? \in inprogress \\ inprogress' = inprogress \setminus \{c?\} \\ pool' = pool \end{schema} This only happens for channels in $inprogress$ and this channel is always removed from there. None of the work queues change as a result of this transition. If there is no more work to do, the channel becomes dormant (and the ready queue remains unchanged): \begin{schema}{EndWorkNoMoreToDo} EndWorkCommon \\ \Xi Ready \where pool ~ c? = \langle \rangle \\ dormant' = dormant \cup \{ c? \} \end{schema} (We could have deduced the dormant relation -- and, as it happens, the pool constraint -- from the core work and the fact that the ready queue does not change.) If there \emph{is} more work to do, the channel becomes $ready$ (though not so ready as some \emph{al}ready): \begin{schema}{EndWorkMoreToDo} EndWorkCommon \\ \Xi Dormant \where pool ~ c? \neq \langle \rangle \\ ready ' = ready \cat \langle c? \rangle \end{schema} The channel is placed on the `end' of the ready queue. Should we be so inclined, since the preconditions of the two $EndWork$ schemas are disjoint, we can unambiguously combine them: \begin{zed} EndWork \defs EndWorkMoreToDo \lor EndWorkNoMoreToDo \end{zed} \section{To begin with...} After constructing this description, we note that there is no channel creation nor deletion described, and that the initial state is not given. This is an ideal opportunity to record our intentions in these areas. We can even document the rules for pieces of work left over when a channel `crashes', in some way, or if the item of work `fails'. We limit this brief note to talk about the initial state. In the absence of channel creation or deletion, we will provide the set of channels initially: \begin{schema}{InitialState} State' \\ cs? : \power Channel \where dormant' = cs? \\ pool' = \{ c : cs? @ c \mapsto \langle \rangle \} \end{schema} The set of channels is precisely the dormant set initially, and the pool records no work at all. The $\partition$ constraint on $State$ ensures that the rest of the initial state is determined: \begin{zed} InitialState \vdash ready' = \langle \rangle \land inprogress' = \emptyset \end{zed} \section{Summary} Essentially, this simple arrangement makes sure that pieces of work for the same channel never overtake each other, even if there are free servers ready to do more work at all times. \begin{figure}[h] \centering \includegraphics*[scale=0.7]{worktransition.pdf} \caption{Channel state movements} \label{fig:statediag} \end{figure} The operations defined here can be diagrammed (see figure \ref{fig:statediag}) as transitions between three `states' of a channel, corresponding to the partitions of the $\dom pool$ collection. This picture was constructed \emph{after} the specification was written, and seems bleedin' obvious. 'Twas ever thus. This document fully type-checks (with Fuzz). \subsection{...footnote} \begin{figure}[h] \centering \includegraphics*[width=1.5\linewidth,angle=90]{whiteboard.JPG} \caption{board marks} \label{fig:whiteboard} \end{figure} Figure \ref{fig:whiteboard} is a picture of the ``whiteboard'' resulting from the original discussion and from which this document was created. \end{document} rabbitmq-java-client-5.0.0/doc/channels/worktransition.graffle000066400000000000000000002534571316117667700245340ustar00rootroot00000000000000 ActiveLayerIndex 0 ApplicationVersion com.omnigroup.OmniGraffle 138.17.0.133677 AutoAdjust BackgroundGraphic Bounds {{0, 0}, {396.85, 226.772}} Class SolidGraphic ID 2 Style shadow Draws NO stroke Draws NO CanvasOrigin {0, 0} CanvasSize {396.85, 226.772} ColumnAlign 1 ColumnSpacing 36 CreationDate 2010-11-16 18:26:14 +0000 Creator Steve Powell DisplayScale 1.000 cm = 1.000 cm GraphDocumentVersion 6 GraphicsList Class LineGraphic ControlPoints {17.0079, 7.62939e-06} {-5.66928, -11.3386} {5.66928, 11.3386} {0.0747833, -11.6339} {-0.0747833, 11.6339} {-0.0918732, -15.0182} Head ID 11 Info 2 ID 32 Points {113.386, 39.685} {155.905, 51.0236} {161.5, 82.5} {161.776, 127.559} Style stroke Bezier HeadArrow StickArrow LineType 1 TailArrow 0 Tail ID 8 Info 7 Bounds {{127.732, 27.0158}, {59, 14}} Class ShapedGraphic FitText YES Flow Resize ID 31 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Align 0 Text {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf350 {\fonttbl\f0\fswiss\fcharset0 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural \f0\fs24 \cf0 end work} VerticalPad 0 Wrap NO Class LineGraphic Head ID 10 ID 30 Points {113.386, 39.685} {226.771, 39.685} Style stroke HeadArrow StickArrow LineType 1 TailArrow 0 Tail ID 8 Info 7 Bounds {{77.9095, 87.4909}, {34, 14}} Class ShapedGraphic FitText YES Flow Resize ID 29 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Align 0 Text {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf350 {\fonttbl\f0\fswiss\fcharset0 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural \f0\fs24 \cf0 start} VerticalPad 0 Wrap NO Class LineGraphic Head ID 8 Info 10 ID 28 Points {145.335, 127.559} {80.5039, 56.6929} Style stroke HeadArrow StickArrow LineType 1 TailArrow 0 Tail ID 11 Info 1 Bounds {{102.047, 192.756}, {46, 14}} Class ShapedGraphic FitText YES Flow Resize ID 27 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Align 0 Text {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf350 {\fonttbl\f0\fswiss\fcharset0 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural \f0\fs24 \cf0 deliver} VerticalPad 0 Wrap NO Class LineGraphic ControlPoints {-1.66403, 7.39571} {8.50393, -2.83464} {-8.50393, 2.83464} {5.66929, 2.83465} {-5.66929, -2.83465} {-5.66929, 8.50394} {5.66929, -8.50394} {-4.72393, 1.88958} Head ID 11 ID 26 Points {145.335, 170.079} {135.295, 189.921} {118.287, 189.921} {112.618, 167.244} {128.894, 161.575} Style stroke Bezier HeadArrow StickArrow LineType 1 TailArrow 0 Tail ID 11 Bounds {{5.66936, 79.3701}, {46, 14}} Class ShapedGraphic FitText YES Flow Resize ID 25 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Align 0 Text {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf350 {\fonttbl\f0\fswiss\fcharset0 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural \f0\fs24 \cf0 deliver} VerticalPad 0 Wrap NO Class LineGraphic ControlPoints {-1.66403, 7.39571} {8.50393, -2.83464} {-8.50393, 2.83464} {5.66929, 2.83465} {-5.66929, -2.83465} {-5.66929, 8.50394} {5.66929, -8.50394} {-4.72393, 1.88958} Head ID 8 Info 13 ID 24 Points {47.3835, 57.1323} {36.8504, 76.5354} {19.8425, 76.5354} {14.1732, 53.8583} {30.7067, 48.3471} Style stroke Bezier HeadArrow StickArrow LineType 1 TailArrow 0 Tail ID 8 Info 12 Bounds {{215.433, 87.874}, {46, 14}} Class ShapedGraphic FitText YES Flow Resize ID 23 Shape Rectangle Style fill Draws NO shadow Draws NO stroke Draws NO Text Align 0 Text {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf350 {\fonttbl\f0\fswiss\fcharset0 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural \f0\fs24 \cf0 deliver} VerticalPad 0 Wrap NO Class LineGraphic Head ID 11 ID 12 Points {243.212, 56.6929} {194.658, 127.559} Style stroke HeadArrow StickArrow LineType 1 TailArrow 0 Tail ID 10 Bounds {{128.894, 127.559}, {82.2047, 42.5197}} Class ShapedGraphic ID 11 Magnets {-0.685994, -1.14332} {-0.261488, -1.30744} {0.261489, -1.30744} {0.685995, -1.14332} {1.14332, -0.685994} {1.30744, -0.261488} {1.30744, 0.261488} {1.14332, 0.685994} {0.685995, 1.14332} {0.261488, 1.30744} {-0.261489, 1.30744} {-0.685994, 1.14332} {-1.14332, 0.685994} {-1.30744, 0.261489} {-1.30744, -0.261489} {-1.14332, -0.685994} Shape Rectangle Style stroke CornerRadius 5 Text Text {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf350 {\fonttbl\f0\fswiss\fcharset0 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\b\fs24 \cf0 ready} VerticalPad 0 Bounds {{226.771, 14.1732}, {82.2047, 42.5197}} Class ShapedGraphic ID 10 Magnets {-0.685994, -1.14332} {-0.261488, -1.30744} {0.261488, -1.30744} {0.685994, -1.14332} {1.14332, -0.685994} {1.30744, -0.261488} {1.30744, 0.261488} {1.14332, 0.685994} {0.685994, 1.14332} {0.261488, 1.30744} {-0.261488, 1.30744} {-0.685994, 1.14332} {-1.14332, 0.685994} {-1.30744, 0.261488} {-1.30744, -0.261489} {-1.14332, -0.685994} Shape Rectangle Style stroke CornerRadius 5 Text Text {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf350 {\fonttbl\f0\fswiss\fcharset0 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\b\fs24 \cf0 dormant} VerticalPad 0 Bounds {{31.1811, 14.1732}, {82.2047, 42.5197}} Class ShapedGraphic ID 8 Magnets {-0.685994, -1.14332} {-0.261488, -1.30744} {0.261488, -1.30744} {0.685994, -1.14332} {1.14332, -0.685994} {1.30744, -0.261488} {1.30744, 0.261488} {1.14332, 0.685995} {0.685994, 1.14332} {0.261488, 1.30744} {-0.261489, 1.30744} {-0.685994, 1.14332} {-1.14332, 0.685994} {-1.30744, 0.261488} {-1.30744, -0.261489} {-1.14332, -0.685994} Shape Rectangle Style stroke CornerRadius 5 Text Text {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf350 {\fonttbl\f0\fswiss\fcharset0 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\b\fs24 \cf0 inprogress} VerticalPad 0 GridInfo GridSpacing 2.8346452713012695 MajorGridSpacing 10 ShowsGrid YES SnapsToGrid YES GuidesLocked NO GuidesVisible YES HPages 1 ImageCounter 1 KeepToScale Layers Lock NO Name Layer 1 Print YES View YES LayoutInfo Animate NO circoMinDist 18 circoSeparation 0.0 layoutEngine dot neatoSeparation 0.0 twopiSeparation 0.0 LinksVisible NO MagnetsVisible NO MasterSheets ModificationDate 2010-11-16 19:04:24 +0000 Modifier Steve Powell NotesVisible NO Orientation 2 OriginVisible NO PageBreaks YES PrintInfo NSBottomMargin float 41 NSLeftMargin float 18 NSPaperName string A4 NSPaperSize size {595.28, 841.89} NSRightMargin float 18 NSTopMargin float 18 PrintOnePage QuickLookPreview JVBERi0xLjMKJcTl8uXrp/Og0MTGCjUgMCBvYmoKPDwgL0xlbmd0aCA2IDAgUiAvRmls dGVyIC9GbGF0ZURlY29kZSA+PgpzdHJlYW0KeAG9WE1zXTUM3d9f4WWzqGP521sCzNAV pZlhwbDIvLxCSl7SvoQy/HuOfC3byU1KuoDJMKQnsp4s6RzJ75N6qz4pgx9XorI2quNe /axu1OnZHandnaL6c7dTr40OymibKAZr2VznYDyf0SlRWnDwvTr9cX/c7T/e/3lxrY5X cE0Gp/ATg7JGUyZTFAWvQ8le7Q7q9IcDqW9vaxizLQX2GrrtstraJ2yJks7FZeVJW7JB /LrV9vSn/fXF/dXn/dnt9e3x6rC/P17tFgTnYosHh9Z4Dgg3a5dDVh27VkSkySc7MCIn VkY7XGUZiEntbjjXrCgFbVLOin11zGpHyQ3vlEy1WnoMgqjdiLVj18o57anEqDrmEOia 4bR6XyakxQBfw6phL0CW6ZyVOyIG8WVpzcSIqmdwk2f4+n3cqNsd0D+k3uC/D2v7nb2r rWPUuzPupPqP1/w/6Tk00NK9k9fIp3VqqmLHpip2bNQiIpE0FZFKc7UbBQukY7FlriHa 2AfvphqGWI1GCRswV1CgqYAC9Wx2z4Is8vFTGQQSG/UsMB2Sqy1T7Wi9/yhdT9E2uQ9K J3bLQb0Dg6EZljXDKOjFVDA0o83Og8yFtHM5MvG/OWdJMcZYdY4021Zdq17jPgZ0IeWX cwjE9/gnin/+Xr26uvl4vP3tuL+7O1HnH9R35+uHPhQqi/NVOqbGcsbpkqJdOobrGwiX S1A9ob8D+dkKiDRzR6TlkcqGLY3WCS0hGKjYaN29N3Im2KwxCF0TmkJiha9KfvZlbdGG DIRXsNbuyJ94n5BK4eprFeIw4tpabRHE0M5Bn5t0cQxV1APy1TLRo+rZkthH/rg3tijT emqGwV6W9G4urQT2jkQJo6didbuR8sbeAQz2dqxRw821aiSL+MDWCY2HbukhCDLVSnVs qlXHJHNKvC8DWRXEsS/JeY/rBQhks1sJjWu/rLVSQuNeqp6rTZarAm9Q5P5LNLYRczZh zj6k8fIMja1XXj0i8OXt8XBxc/8MexfIBmGq1WFeSh3mAUFZ1MeUHFTDPN8aLMyhlIFZ jOnVKoLFriQ0ryBeFgM0a8NirQa0CL4EC+C/I++G97WuOS49BkFQxR5rxzBmWI15CnWM LCLl9US8Lx3pMbAANquOvQBBGbtVkTsiBvGFHa1mYkTVM9hjF6S2xGOUs/8Me1nDuzlZ SEcoNBULt2zYVKyO9ZQT1C6VlEYRkL3VF9q9FWbBzikblGBod7Sjx/jordD3oF6sjoxi idTWbUyK1e166rr3CekblGAjLkEQVbPaIlOx+h1HsZCvloneQj1b2zyz1G7Rwd/liTFM sehSIqmUdAkWM6NO4aeHMMQEQyiBw4+H8HF/cfn3YPCT0s6urXfMOj/08gAW4QURnMVa VbQreEdcV8kxWPsM1r5nnVHBe8Dxe8AGXALPDZaFrTNrrE4WuwNZ8DynjI7cnMWHUklY EvAE4cdDLDFgH2LtmwKwLuu63KFJMtaClq55UyG8OVaJs7Kj/KJeXZ6wJFr1an/CKw5+ uZZfruSXz/1vxxP1qzp/sy4zsv5OYTyclz7h4eF8USFVmbG4n0dqqPioIp5VNhvHiMNi alVyOmGXKrxt47XmikpRB/zN8jDBU8dHrGUJtWAzhdwGLMLoEEFQpuxtgKd2jmVPxnLz npes2bdDBNh+IqraTQLUPGQ8K3EsclB4WgW8JHOERFLW0QS8DD20vgR+gBqdKZeweKhh 7Y/dy/qDFc8UvC1x0HsK/ApozvJwxkqkY+RRghThYsWz3eZstSsxo9YY0NmFQGujLlNh cAyucGnyRntDX9MgtS+W/6JBiGvvfJLtsRIATIwJ9SUw3ydexIEk0AglSKAJvyFd4Bqg dBkqAd7W2YLNohAKVcAq6DtYhR02sHlHUESLraCf40pjoY7ghjjHcwiDyGcOAL3qmZ5i AhG3KFg95fE3MBJtbAJHgo7JBSOe0FbJRiYrr8YuQnfxpCDIwQvbg7BvFZ4yVMdrYlWo vrwTX7xUoPd1toQPCrx9wB52j4+yGf5q8IUAi701CLWKx9wcLFPGIy0YgoYCGLiK7UvU 4/9oDpnNB4UGILCxqIjS8rawXgZy/AVJ5tU945mV47rXmOJrsp5ylj2WEJutihgp1jpO 6uYs5Bd95xBAVigRDmAL20gydhxwHOTm+Qmly09l1crImjX5DjtnleILUeAjkK8Q3v5l gSs6spSycHCD8pdUDeMW4iHyr6mz1j86+LSz8QH4XqF+2wa7x2eRum7nQbxqt0kdelBb 3ks7c7cNCc8QxnXez8nrs+pGkncpv6iW1r8EuJVfjn+cLC/ML1fxqfySw+OzoGEkvwth dlhMmI6AqdgHIBcs1AZ/qkqCDgqQmTGOBMCLGmIHErIOhCVj06yTiXhokMLXE6yTkDf+ cy6wM+AxV3sVDoyoujBETJoH0jNzf0zsejG4ShHOWRJigE9cFljEKrY6C5hCEBXIHmP4 KhEbiYParXYPz8IOzwjYQcrYLmO/Wmv99h+4HWTeCmVuZHN0cmVhbQplbmRvYmoKNiAw IG9iagoxODkwCmVuZG9iagozIDAgb2JqCjw8IC9UeXBlIC9QYWdlIC9QYXJlbnQgNCAw IFIgL1Jlc291cmNlcyA3IDAgUiAvQ29udGVudHMgNSAwIFIgL01lZGlhQm94IFswIDAg Mzk2Ljg1MDQgMjI2Ljc3MTddCj4+CmVuZG9iago3IDAgb2JqCjw8IC9Qcm9jU2V0IFsg L1BERiAvVGV4dCAvSW1hZ2VCIC9JbWFnZUMgL0ltYWdlSSBdIC9Db2xvclNwYWNlIDw8 IC9DczIgMTUgMCBSCi9DczEgOCAwIFIgPj4gL0ZvbnQgPDwgL0YxLjAgMTYgMCBSIC9G Mi4wIDE3IDAgUiA+PiAvWE9iamVjdCA8PCAvSW0xIDkgMCBSCi9JbTIgMTEgMCBSIC9J bTMgMTMgMCBSID4+ID4+CmVuZG9iago5IDAgb2JqCjw8IC9MZW5ndGggMTAgMCBSIC9U eXBlIC9YT2JqZWN0IC9TdWJ0eXBlIC9JbWFnZSAvV2lkdGggMjEwIC9IZWlnaHQgMTMw IC9JbnRlcnBvbGF0ZQp0cnVlIC9Db2xvclNwYWNlIDE4IDAgUiAvSW50ZW50IC9QZXJj ZXB0dWFsIC9TTWFzayAxOSAwIFIgL0JpdHNQZXJDb21wb25lbnQKOCAvRmlsdGVyIC9G bGF0ZURlY29kZSA+PgpzdHJlYW0KeAHt0DEBAAAAwqD1T20LL4hAYcCAAQMGDBgwYMCA AQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgw YMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMG DBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCA AQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgw YMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMG DBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCA AQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQMGDBgwYMCAAQPvgQE/+wABCmVuZHN0 cmVhbQplbmRvYmoKMTAgMCBvYmoKMzgxCmVuZG9iagoxMSAwIG9iago8PCAvTGVuZ3Ro IDEyIDAgUiAvVHlwZSAvWE9iamVjdCAvU3VidHlwZSAvSW1hZ2UgL1dpZHRoIDIxMCAv SGVpZ2h0IDEzMCAvSW50ZXJwb2xhdGUKdHJ1ZSAvQ29sb3JTcGFjZSAxOCAwIFIgL0lu dGVudCAvUGVyY2VwdHVhbCAvU01hc2sgMjEgMCBSIC9CaXRzUGVyQ29tcG9uZW50Cjgg L0ZpbHRlciAvRmxhdGVEZWNvZGUgPj4Kc3RyZWFtCngB7dAxAQAAAMKg9U9tCy+IQGHA gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED74EB P/sAAQplbmRzdHJlYW0KZW5kb2JqCjEyIDAgb2JqCjM4MQplbmRvYmoKMTMgMCBvYmoK PDwgL0xlbmd0aCAxNCAwIFIgL1R5cGUgL1hPYmplY3QgL1N1YnR5cGUgL0ltYWdlIC9X aWR0aCAyMTAgL0hlaWdodCAxMzAgL0ludGVycG9sYXRlCnRydWUgL0NvbG9yU3BhY2Ug MTggMCBSIC9JbnRlbnQgL1BlcmNlcHR1YWwgL1NNYXNrIDIzIDAgUiAvQml0c1BlckNv bXBvbmVudAo4IC9GaWx0ZXIgL0ZsYXRlRGVjb2RlID4+CnN0cmVhbQp4Ae3QMQEAAADC oPVPbQsviEBhwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYM GDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIAB AwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBg wIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYM GDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIAB AwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBg wIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYM GDBgwIABA++BAT/7AAEKZW5kc3RyZWFtCmVuZG9iagoxNCAwIG9iagozODEKZW5kb2Jq CjE5IDAgb2JqCjw8IC9MZW5ndGggMjAgMCBSIC9UeXBlIC9YT2JqZWN0IC9TdWJ0eXBl IC9JbWFnZSAvV2lkdGggMjEwIC9IZWlnaHQgMTMwIC9Db2xvclNwYWNlCi9EZXZpY2VH cmF5IC9JbnRlcnBvbGF0ZSB0cnVlIC9CaXRzUGVyQ29tcG9uZW50IDggL0ZpbHRlciAv RmxhdGVEZWNvZGUgPj4Kc3RyZWFtCngB7Vz7P9P7H0+R3M3GGJvLMGPMbG4rTMtEEw2F hTk0lyZyO8QR5XJyiVxKRG5R7kWkOo/zr31fr8/HHI4N5/Tl49t3zx+k9vB5v5+f1/P9 +mx5PZ/nzplgugOmO2C6A//vd8CMwPkzAnI3Zv+yKPDTJI8LCPMzAGIj5J5gc/+QFskG iVggLiIsqQVugdiMhbn5BeT1D1gRdIANUrG8BLCysrLehc0pY3dha9gG7sYSmZlfQFbH qxTJB+ggGytr2L+tnZ39mYCdna2tjY018LIkSB2PExLC8lgiG1ug4uBIo9GcnOgkGBRg Z2knJ9iIo4O9vZ0tsgJShPqOOlB/8UE6jjQnOsPZxYXJZLq6urpRCFjeFXbh4sygO9Ec 7e1tbXY5HU6JJHTxkpWNrb0Djc5wYbqyWO4ebDabw/GkFBwOh832cGexXJkuDDqQIjgR ZTqMEhJCwVnbQHkYzkw3dzbHy8uHy/X19fPzpxR+fr6+XK6PlxeH7c4CUk7AyfqSpYUF dAjjlHYIWdnYOdAYLq4stqcX19efx+cHBgkEgmBKARsQBPH5PH8/rrcnm+XqwqA52IH0 Lh5KyQwrBIqzc3RyZrLYXlw/Hj8oWBgqChNLAOEUAtcXh4lChcECPs+P6wWcnKFMQAmr ZKxIUCJzC0srUBzdxQ34+PMFISKxJDJKKr18JQYRSxGIxWOuSKVRkeFikVDA9wdObi50 pGRpYW5Md7uEaAwokLcfXyAUR0RdjomLl8sTFApFIqWADSRck8fLYi5HRYhDBXw/bzaL iZTgLJkbKRJq7uIlkBydyfLk8oKE4khpTLxckZSsTElNTbt165aKMsDiaampN5U3khTX 4mOlkWJhEI/LQUp2NsRRMqg71Nwla1uSUECwKEIaJ1ckp6SpMu9kZeeo1XdJ5J4ydpZV q9XZWXcyVWkpyQp5nDRCFBzA9WS50B2g4xkpEpYID5GTC4vD5YeIo2Lkicq0jCx1rqag sEir1RYXF5dQBFgaNlBUWKDJU2dlpCkT5TFR4pAAqJIzDXR30eL8eQNvxc2wRDb2NIYb mxsQIpHKEm6kZmbnaoqKS3XlFRWVD6soxcOHlRXlutLiIk1udmZqckJctDg4wIftyqDZ QZEMtrvz56FEtg50poc3L1gslSmUqqzcAm1ZeWV17a/1DY8aqcaj+l9rqyvLy7QFuVkq pUIWHSbw93Jn0h2gSAZ7A4gOS+TM8vILEkXJFCkZOZp7ZRVVdQ1NzS2tT9sox9PW1uam hrqqB6VF+dnpSkVspCjQl8PCIllaGOh2IDpodA4MVzaXL4yISVBmqDVaXVVdY/OTts5n Xd09Pb3Uoqe761lnW2tzY12VTqvJUSmvXZGE8Lw9mE5wkkB2Bw6SGYjO2g5L5C8QS+XJ qhxN8YOahuYnnV29ff0DA4NDQ0PDlAEWHxwc6O/r6ep40lxfXa7VZN1KkkVjkdwYjrYo u4OMCNE5MT18+MLIuMTULCBU29jS3tX7YvDlyOvRMcox+npkeLC/91nb40fVOm3e7ZsJ MZIQOEkuKDsDB4k4Rg4MN46fIEwqV2bm3tPVNLZ2dPcPjYy+mZicnEJMUwRi8am3E29G Xw32dbU/bqi6X6hWJcmiQvlcNsrO0EGCY2RFiI4XEh6jSMsuKKtqaOnseTE8OjE5Pftu bp56vJudnhx/Pdzf3d5cX1GSfztFflks8APZQbcz0BrOm1ta29NQdKFRsuSMXG1FXXN7 94uXY29n3s0vLCwuLS1TiqWlxYWF+XfTE6PDfV1Pm2p0hTlpiphwkB0LD5LFhQPvg7Ax 2NNd2b5BILqUO5qyqsYnXf3DY5Oz8wvLK2uIjxQC119dWVqYn5l4PfS8s6W+UpuXniSL FPK98SBZXTzACFod9m43T3+BBESnLiqva+7sHRp9O/t+cWXt0/r6xsZnSrGxsbH+aW0Z KY0MdLc1VpdpbivlUlEgHiRgdKDZEYwcGSwvnjAi7roqt7iyAUo0Mj4zv7j6aX1zc2vr C8XY2tr8vL62sjA3NTb8vLO5TleYdfMaHCRfbA3WhhnZ0pzdvQOEUfHJmfml1U1tvYOj k+8WVj5tbH7Z3v5KOba3v2yury1/mJ0YedHVWl9xTw0HSQKtwZVuj+37bw8kM3gc2dJc oDGIouXKOwW62ubOvuHx6fnltY3N7a/fvp8BfENKq4tzk6OD3U8bHxbfVSXGhgf7e7ox oH0bYgTNm8nmBoqgMWQVlv/a+qx/ZGIWSrT55SvQ+YNyfP/+bXtrY215HmTX29ZUVQqt IS5CiM3OAR9IB2oEjyMnYBQUdjkhNbuoor61a2AERLe6vrn9bS+fP08Zf93J79+/fvn8 cfn9zJvh5x3NNaX5GdjseAQjeCAdZGRtD4x8BeIritScexWPnnYPvJ6aW1w7W4w2P628 nxl/2dfZXHtfk5lMMnJ2xEesIUZ0ZEQ0b21lY1vP4OjU3NLaxtZfNTrl8uwuR9YJawSM oDW82mUUFRrgzTqEkSu8qyMZPQRGQ2NT83sY7V6fkm+A1D5Gj2t1mswb8cdjlHjrbnFV Y1vvfkaU8Niz6M/H6M+frkZ/QpH2nKMfV92e+lP17X+RET5fqaKxZ90/4BG72+t+rEb4 gN1zZaq+JRitry7AG7v+3x/X6QpuK69Gi/g+7s40+ID09/8NIj7w0V2JDxN7ex28rYM3 QWeQUcseRi5GGNnY48ej4PBY+DBRUtXU3js8Bm9UP35GRlSVZd+6+2pkYmSq0T51nNRf TKqzNHWGkxKX0euaVGdSnVFxnNgLJtWZVHdi4jJ6YZPqTKozKo4Te8GkOpPqTkxcRi9s Up1JdUbFcWIvmFRnUt2JicvohU2qM6nOqDhO7AWT6kyqOzFxGb2wSXU/neouXMQRSGJC Y+/v+HBCA3/HZ1QKp/jCP1Od2SGMcIrmFDdudKl9jI78Pez/DCP9XNCP/a78zNToJ5vQ +PlmTn5kLihNrYVptJ9odgvGvZERTgyemfk6nBn8F/N1xFQnTAymqrWVj54SM5CLZ3sG 8vCJQWLy1jdoZ0614QnMqU6egTlVmELbgb5Gx51TtdiZjg67fO2mfpb4LTlLTAwG6a9r 9AF4Ui/oFyZUR8wSjxOzxGVHzRJbWNmCtYXL1897t+yb9969LIXf6Oe9p2Heu/3oeW9w gsBMvjvO5F9V3t6ZyX8z/R6Gt7a2cYSdenyDB+z62uLc1OhgTxvM5OfiTH6I0Zl89LY4 OrPANxEp2+ObmFtY/fR5E20T3yjG169gMtj4qPdNNFRoj/BNEIzA2+IfQnhbtJUNraS3 ZWkNrCDgbNmmGF++bAGh1QU0GfR1Pq4rL8zWe1vACWLY24L+I3LgOzWnEPxHHaT/aGn1 4zqYjzYpxufPG+sfV5bmYQJyoKetqWav/8jegP/oHDEESRonwJh4R1NKeMRejk2BpWp5 Ffxhn6jGx7VVMFTNTkKJfm+tryzOQ9tEKN/bw7BHDBihMxHtOqGRsqR00sfXM/AKbW8f FggT3wqFQA/h0sKHuZm3Yy9fdLX9VqsrVN/CxoBGECM+vgsXL9lCa/CCuU5415BVUIpe y96Bl2MTU7PgtHz/gWK8fz//bnZqAgj1dDyuryzV3ElBi5hxryVaqtCEzSGsicoM0g+L 9tGRsYnJqemZmZlZCgHLT09NToyNDL/o6WwFi2+hGoyJUaJD/LDowoZwBrCPBggjYvWe 5daOrr6B4Vevx8bejI+PT1AGWPzNmzEwLQ/0dXW0NtY+0ObfSUXzKA+tloTp7YB7FJ3y hMXXE03LV8FXXlDyoPbR47bO7uf9A2Apfwl4RRVg7eHhoYH+592dYMKufVCiyVYlxUeL gkhfuaFWdw5aA8oOLEhgLCe9/wXF5VX1TS1g/e/u6X3eRzGe9/Z2g/m/pQmM8iUF6gxl ApQowMeDSTfi/T+HoSDgWnZmeerzGSDO4H5FTX1jc+uTtvaOTorR0d72FLIM6msr72s1 6owUBZyiQF9PyAUxks9wbiegATM0/IkMjZT0rLzCYl1FVW19Q2PTb80U47emxkf1tdUV upLCvOz0lESZVCzwh3gG4xkamNxyCRIadnNOFMpbmeq8Qm2p7kFlVVV1TS2lqKmurqqs 0JVqC/PVtzEURCqB6Ba22yE5JztxQfosGkl0rDwpRZWZfTf/lyJtcUlpaVnZfcpQVlZW WlqsLfpFk5tzW3Uz6VqcVCLkY7wOJmgYyaJB2WFeEDQHCEDiB4dFXpZdu65MVWVmZavv 5uXl52soRH5+Xl6uOicrMz1NmZQguxIpDuHDIYIIJON5QcBoX6aTIFQSdQUykK7fUKam qVTpGRmZFCIjI12lSktNgVAnuSwmWiISQACSOxM0d0imE0HJEvNooEocH39+sEgCOVUQ u5WgSLyelJSUTCVg/euKBPlVWYw0UiIKCfQnCe1EiR14vJLm2N0oMchGw6w3yEYThmE0 2pWY2DiZHvGnDf3CcbGQjhYdGR4WGhzI84W8N6gQEfcGcZBGGGGR4Chh3JuTs6s7BzkR 8XViSXhEpB5Rpw39whHhEkmYCAPs/H29PT12wt6M54hhmfZnDEJkopcPRgwGQr5giJBy hARjymCAvy/Xi+MBBSID+Q7PGNRTgo4HZcLcRA82xkD6QgYkj8cLoBI8HsRQQhKkNwRB styYEG5JZFseQYiskjmk2EFyIpltCVGdkNTJ8fRCeFMGYnlPTw6mdWJYpxOGQB4dbKkX HlDCuE7MHyXiVCFM1Y11BuDmBpGqzgyg42iPfOAIYUassa5AtjuiStgfgJOVDRQKKoWB t2TSrTNlINenQzospt5i6C3ywQTIIwkBJegPOzm+RCwxJvlClq+DgyOlgA3gPoDMvmBi s6MqRFRqlxMZHY3B0aecF21sOWtMWdaHRx8vZ3lHewSn82QgNoZ7Q7I35lBTC4wXJyO+ dwO+9UflWH/qI9j1+etkWDilXzEGHrYDtYHTczy5HaAKP4en6kwB93Ssw3OAjaF/IK5G xRdDmzH9m+kOmO6A6Q78X9+B/wCFUvSRCmVuZHN0cmVhbQplbmRvYmoKMjAgMCBvYmoK Mzc3NgplbmRvYmoKMjEgMCBvYmoKPDwgL0xlbmd0aCAyMiAwIFIgL1R5cGUgL1hPYmpl Y3QgL1N1YnR5cGUgL0ltYWdlIC9XaWR0aCAyMTAgL0hlaWdodCAxMzAgL0NvbG9yU3Bh Y2UKL0RldmljZUdyYXkgL0ludGVycG9sYXRlIHRydWUgL0JpdHNQZXJDb21wb25lbnQg OCAvRmlsdGVyIC9GbGF0ZURlY29kZSA+PgpzdHJlYW0KeAHtnPlbUlsXxysrU0FEUAYF URRFRSXneUYpFUUxDUWvGo4353I2c8oBLdSyHMohNYfSnBue/rV37QOWKVB2rx6e+/L9 IU0ez96fs9ZegKz1vXTJJNMdMN0B0x34f78DlzFdMRJpdnP5D4MCv63lMEO6ir+wfWj2 BJs7I5aGBnFcQ7qOZI6v0BawzVy7etUMcZ2FCuMxQzCAcQNkYWH5Q1YXqx8LW1hYoM2Y I7KrZojqNyOFkg3hXAcYC0vYPoFItDYKEYkEgpWVJXCZY1C/x4Tig/EADsBYW5NsyGSy rS1FIyoO0i5tawsbsSFZWxMJiAqgsOz71YHCgCA+KDpEaxKZTKFS7expNBqdTmfgKFie Druwt6NSbREWQB0xGU49TYAg3yytAMeWakejM5gOjiwWi812wlVsNpvFcnRgMuk0eyqF bGNNtII4XbsGx8lQlLRAkG9EEpliR2MwHVlOHGcXLtfVzY2Hq9zc3Fy5XBdnDpvlwKTb U21tIE4WNyD1DCJdRkcIAkSwtgEepiOb48Ll8Tz4nl7eIAGeQhvw8uR78Ny4zhyWA4NG JZNQmAwjQYgQENQDMhV4nJxdeXwvbx9fodA/ABSIo9D6/jeFfr4Cb08PHpfDdqDbU8jW cJquG0g8lHNQEyDjbO3oDmwXNw8vgd/NgKDg0LDwiEikKJyELR4ZER4WEhzoL/T15gMT iwlhsiZokPQcJcg5ALIkABDDkcN19/IVBgSHRUbFxMUnJIpESbhKJBIlJsTHxkSGhwYF +AmAyckBIVlZmOs/SijntEAsZze+jzAwNDImXpQsTklNk6SnZ2RkSPESrJ0ukaSl3BaL EuKiwoMD/Lw9uBwNElQ8M931DoXI3MLKmmzHYDnzvPwCQiNjE8UpEmlWdk7uXbk8T6v8 i5V2VblcfjfnjiwzI+12UkJMRLC/D98VIdkQrW5c11PvLqMQWRHJVDoAeQuDwmNEtyTS 7Nw8RWFxyT2lshRUho/Q0krlveKiQoU8R5aRKk6IDgvw9XQDJAqJYKkvSFiICCQKzYHD 8xIGR8Ynp0nvyAuKleWVVfera2rrcFVtbU31/aqKsnt/Ke7KMlJEMeGBvnxXJ6Y9HCUU JB21ASXdDZRzTCdXTz8AupUukxeWlFVV1zU+aGpuacVbLU1NDxpq71eWFitys9KS48ID fDy4LDrkHRak0++XIOmu3yCQqDSWi4dPYET8rYw7+cVlVbWNTa0dj7oed/fgre7HXZ3t LQ/rqyuVhXKZJDk2zN+bB3lnC0HSWRsuX7lmbkmEEHF43jfDYsXpdxQlFdWNze1dPX1P BoeGh1X4anhocKC/t7uztan+fllRnixNFB3s58llM6g2BAudaadJOgqEiO8bFCVKy1aU VNY+bOvqeTI0MvpMPTYOmsBLsPbYmPrZqGqwv6ezpbG6vEielZIQESCAIMFJgrTTcZCw pLOhMp3cIETxtzPlxRW1Te3d/cOj6okXk69eTeGtVy8nn4+rRwb7uloB6a/cDHFMiJCP ThIJS7uTBwkdIwsi2d7B2d0nKFIkySksr3nY0TOgUk+8nJp9/WYO0zw+0iz+ZnZmanLi mar/cWvjfaUiOxWCBCeJaYfSzuzKaSI4Rta2NBaXLwyNvZWVf+/vxrbugdGxyanXc4tv l5bx19Liwtzs1Au1qr+rtb6qWC5Njg729XB2oJGJlnCQdBDdsCJRGGw3b//whDQIUV1L 15OR8cmZucXld6tr6+sbuGp9fW1tdWVp4c30pFrV19lUU6qQpcSFCT25LBoFDpIOIvRs BMeIw/MJjEzKkJf8/aCjd1gNQG/frW182ARt4Si0/ub7jdWVxbnpF88Ge9oaqopyJImQ dm5Q7VD9PlUaLgMRgWzn4OzhGxwjzlKU1jZ3DTx9Pj23tLqxubW9vbOzs4unYP3t7a0P 6yuLb6YmRvsfNVUr5dKkqCAfOEhYaThFdMXsugWBbO/oAscoLiW7sKKhrUc19vL14ruN ze3dvf39/QN8tb+/t7fzcROQZifVQ92tdWWKLHEMdpCgNOiIESIikqEweELtTs0prnrQ 2T/6fHp+eX1ze2//8PDwE96CPezvfvywujw3NaHq62isLMxOiQsV8l0c7clEXURXr2Ol ztXLPyJRcvdedVPX4LPJ2cXV9x93Dw4/fTECff50uLeztfFuYfbF6JNHD/8uzkmN15QG MtHimtnJ16rwdGRpTaFBqQuIFKXLlTUt3UPqV2+W1iBEh5+/fPmKu+Cefj7Y236/+vb1 pHqwq6m6JFeSGO7vBcWObA1PSKeJ4OmIQnfiAVGSNK+0trVHNT41B0m3sw8R+sHz7YL1 Y+WvX74c7m1vri3NvYKD1FKjlEtEUOxc2XRbPURW1lSGE08QGJUszS+ra+tVTQDRxtbu gRER7e9srsNBGhvuaa1VytNFkah8A5GlzhghIng6CgIiRTlGND2/cozogoNzbDltnCBG QLQBROOqnta60ryMJETkxICnWINE0eJMRXl9e9/IxE9Ex1bA4VsEdUQ0D8WuFxHBE1Kg gPenRDhQHF/yFFFbXVm+NPkfEB2/Oj7fn4iRiejEOfqKT1h+WvXfjZFxEH398gmrdVhl +HXWXTO3IsGbCXf00htqXQOqdTMLKxvwIujzF2Mg+vYNiA52tzaWdRGdfoN0Bd4e/UTU 0TfyfGbh3cZH9CLIqIhW5qeherfVlaNah95OoDdIvyDKKqho6ICX3kZKtDA9MdLXXl+u kIqjj94gmYiMK+tMMUJ/ZjCdo5+eCs/tP9rqvWLKOlPWnVuSnbqwKeuOvQoy1bpT+XE+ PzBlnSnrziezDF3VlHWmrDOUH+fzmCnrTFl3Ppll6KqmrDNlnaH8OJ/HTFlnyrrzySxD VzVlnSnrDOXH+TxmyjpT1p1PZhm66n83644+41NAp+p/4jO+P/kc1ij/AonaaM72Wbmx V4Yz9zMc/6z8dIyM4GPLf5MI9dcZqkEX89iZia6ezLqjfgZtx+DFbFvvKn/au4Ua2IOM sb8OAenor/sn3WjYJfXewXN+AFv8B9HZeyD1dHVqrnvOmz99eS0OfNH0QJ6xT/VH5y30 EqPOW+glxrfz9ttPRCd7iaFP1WAv8VF3dAbWHT08BkRr0B2NWp2MQNDvDd3RH072e7uy YJRPf7/39w726ubHg+qXr9+uftjeO/gELexGoM8wZgA9+YuzL55+78m/icZ19Pfkw0AV TBmEJ0pyS+4/fDTw9AVqsNvc2YMxg0+fcRaMbRwe7G5/WENzEyP9vzE38X0SRIgmQYqq Gjv60EFaWn2/BaMgBwcwiIGrDg7293a3N1GIXqqHoN27/DdmWzTTOn4hsbdlBeV1rd2D 6snZ+eW195vb27u7ezhrd3dn++PmxupbCNHoExibUOZpGwaZVBsDE1VYW2e0WJqvrG56 1D8y/mp2YXkVRsS2tj7irS0YElt/93ZuBsaPetobq4phEETTkq97ogrNiGFtnTwBDLdI cosqGyBIoxOAtLSyig3xvcdRaIZwfW11eRGAxlQwIlZbViBL0Q7rUHQ1dV6CkWWYKqfQ 2a5eMFKVIlOUVj/s6B16CkhzC2+Xl1fe4ayVleWlxfnXU5NjIwOPWxvQrCU2IubiqH/W EpsehbE31E0svVtcUdfc2Ts0Oj45Nftmbn5hYWERR8Hy83NvZqdfPlePDHS3P6guLbiT BoOJMLTMtCPrmYfFJnzRWLkgICIhVaa4V1Xf0tk7OAIjyy+npqZnZmZmcRMsPj099Wry +djocP/j9oc15UV3IUQhaHhU38zyJWyunAR2E1xPYUiMOD2nUPl3fXNHd/+g6ql6bGLi OegFXoK1JybGx56NDg/0drU+qKkozpOlQl3wcUcDvvrmyjF7BlvkNwFBir8tzS1UVtU9 bO3shtH/YdXIKM4aUamGYE6+q6MZpsqL87MlSShErgZm/5GbgQXBhspgc/l+wVGJKZm5 hfcqquuRPcPjnt6+fpzV19vT3dXZ1txYVwVmBtkScVwYnCJnR0P+DMjmBCbLIUjeN0Oj RSnSHEVRaSVYaDQ1t7a1d+Cs9rbWlqYH9TVV5SXIcEIcHwG2IFwWgwpT5cjo5ORY+SUo 32BFY0m0gZPk4i7wD41OvJ0uu6soUpZX3QeTk/qGRlzVUF9fV1NdVVFaXJiXI01NjosI 8vNEPifIQkOn4cSlS2AXBIZOyOiEzfXw8Q+Jik9OyZDl5hUUlShLy8rLKyoqcVNFRUV5 eRm40YAZzZ1MyS0wbgny80KeIBQb/V40Gr8gcHSyR0gCYXB4TEIy2AXJcnLleQpFQUEh jiooUCjywTEoOzM9VSyKiwwFcx0ex5GOXJ0M+AWhIEHeUWiA5O7tGxAcHg2WTrdTJOlS aWZWlgxHZWVlSqUZ4OokFsXHRIYFCgV8Ny0Q2FTp8XTSnCTIOwzJhccXYLZb0bHxiaKk ZLFYfAtPwfrJIrCoAuOtkEChr5c7VwMEVmL6fbc0Zm/gU2VDsWeyOFwe39v3ZkBwSFhE ZFR0zJFiL1pHC0dHgTtaKDJH8/HycHNm/4Y3GgoS+NeBwaANZveGmLwEvn7gXhcYFHyk kIvW0cJBgQEBN4W+Pt58d1cXJ0fkyXdk9nbKm+GolGMGdhgSiUy1ZziwOC6uPHe+J9gL +vjiLh+BwNsLMxnksB2ZNDvwTcQM+fTYiGmgtEiYbaIt1Z4ONpAcME50BQ9Id3d3Dzzl 7g42lG5csEwEI0gGzQ4MBn9tmghUCOkq8h4F61EbMrLqZAIVi+3EQXLGTdjyTk5s5NbJ ALNOWzIJBQi8OlGETvoYHOUc9lWLhOxHCch/lIK5qdIZTCMQgwGWqvaYoSrEB0xiNR6x hoGwKGFhMkeWt+DeC463YHircbq1w02a9SkUsL0Fe1hkensDeDDTW4MB0kQJwoSYwLQT syUmYKbEJBLJBlfBBpA3MsBYgefod2PiXwVIk4DHraO1xtEXaxetdzVL5LIMNGfwWdae KYzpCth7I0NtjbU38qHGV8heXGPx/d3gW7vd3/tyZMF+ZL+O2HAWcoGH7cChQPXt1+dH Fyj8HjpVRiW0pz+j0UeIXfGi/9G1GdPPTHfAdAdMd+D/+g78D2KJ7/8KZW5kc3RyZWFt CmVuZG9iagoyMiAwIG9iagozODMzCmVuZG9iagoyMyAwIG9iago8PCAvTGVuZ3RoIDI0 IDAgUiAvVHlwZSAvWE9iamVjdCAvU3VidHlwZSAvSW1hZ2UgL1dpZHRoIDIxMCAvSGVp Z2h0IDEzMCAvQ29sb3JTcGFjZQovRGV2aWNlR3JheSAvSW50ZXJwb2xhdGUgdHJ1ZSAv Qml0c1BlckNvbXBvbmVudCA4IC9GaWx0ZXIgL0ZsYXRlRGVjb2RlID4+CnN0cmVhbQp4 Ae2c+TdbWxTHtdQYIWQgghBTCKFCCGqsMWpqzEMMTRtiLlVaQ2kNrblKS6miyqupiuqw 3r/29rlJKEmJvC43Xet+fzC06+ac7937nHuvu/fHyIgQcQaIM0CcAeIMGBldMST9n4Ag H1ePZYy3jqdyFWZ2UWcqM2DCxOSaQcnExMTYGJm7kCssNmAGrJiampmZq2SBo9RzMDMz NYVpga0LmFL6ATum4MXCwtIKRCKRrHEWTIEEM7G0tDA3N8NcKU2dm37Ij7ExZgeZIVmT yTa2thSDkK2tDZlMtgZj4ApMoUCdu6IwQyYoPJZWJDIZrNjZU6k0Gp3OwFl0Op1GpVLt 7Sjgy9oKQmWm8nRmlFCAVH6swY49lcZgODCZTCcWi+WMr1gsJycm09GBQadS7Sg2ZBIE ylQZpjMsqQyZW1hZkyl2VDrDkclydmGz3dzdOfjL3Y3NdnVxdmI6MGj24MnKEoUJZd5v LUHKQYQg4UhkWzsqw9HJ2ZXtzvH08vbhcrm+SH64CBvaF+bg7eXlwXFju7CYyBPkHgrT WZZUhmABUah0RycXNsfTm+vH8+fzA4NA1/EUmkAgP4DH4/p4ebi7OjMZVDtb8jmWIOdQ hKysbShUBtPZjePF5QUEXheECIVh4SK1Ii5Z6nFFovAwYaggOIjv7+vj6e7KcqTbY5bQ WvpN3kGIrpmaW1rb2NEcWGyOl69/YHBomCjyRnRMbDxSAn5Cw8fFxkRHRYQLBUF8no+n GwoTBaJkds3kN0sJCxGsITDk6Mz25PoHCYQRN2LibyalpKaJxenpt3BUenq6WJyWkpyY EBcdGR56ne/nxXEBSxAlbClpDRIKkZmFFZkChty8fPkCYWRMfGKqOCMr57YkNy8fb+Xl Sm5nZ95KS74ZGyUKCeL5cFyZDHtba0tzFCRt292Vqyam5mCI6gCGeEGhopiElPSs23mF xaXS8opKUBVuQqNXlEvLSoryJdkZaYlxUWHBAVywRLezIUHeaV1JyhCRbO0ZLDYYEkbF JYuzcwtLpZWye9UKRW1dXT2OqqurrVXUyO/eqSgrys/JSE2IFgkCfDgujjRYSihIWtIO QnQNhYjOdPXwBUPxKRmSwtJKWXVtQ9P9ltYHbXjrQWtLc2O94l6VtDgvW5wYIwr293Zz hqWEgqTdEawiki3kHIfLD4mKT83MK66Q1dQ3tz7seNzZ3YO7urs6H7W3tTTWyqvKCnLS E2PCgvw82Uw6FiRjLQsJ9gUsRE6Qc8GiuJTMvNJKeX1zW0dXT9+z/oHBIbw1OND/tLf7 8cOWRoVMWpgjvhkVyudynB2oNiRzU21phzmywUIUKIxOysgtrapuaO3o6u0fejEyOjY+ PoGvxsdHR4efDzztedzWXHtXWpidGi8K5nmxmTSKtaW2tEM7nYU1hcaEEAki4sW3iyur Gx88ftI/NDI+OfVqZmbmNa6CCUy/ejkx+mKgr6v9fq2sLD8j6YYQBYlhh/YGzYV05eo1 M0uyHYPl7sMXRidnFZTLGx509g4Mj0/NvJl7O7+wsPAOTy0szM+/nX39amJ06Gl3e7Oi qkQijhdd9/N0caTagCPNhQSOzK1s7B2cPfyui+LEklJZXcuj3sGRyenZ+Xfvl5dXVlY+ 4CgYfnl5aXFhbmZq7PmzrrZGeXl+RmJUSIA3SjtYSFocoY3BlgpJ5y+ISswoKK9uau8Z GJmcmXu39GF1bR30D55CE/i4urw4/wYs9XW21slKclJiwgK57iwGhWwBW8Ppu4Yr4IhE oTm5oaRLyS6W1T/ofDY8MfN2ceXj+sbG1tbWNr7a2trc+Gf9w9LCm6nRwSftTXJpHpZ2 Hs4Me7KlmTZHaGOgs9y5QeGxaZIyeVP7k6Gx6bnFlfVPW9ufdw1BO9sb66tL868nh591 tigqCyHtBDxPV2whaW7fsNWhjcGZA8soPj2/QtECIXr55t3K2sb25y97+6ADHIXG39/b 3dlcX30/Nz022POwQVacnXwjNAD2b2xr0NjsrprAVmfv4OLBE0TezCiqqmvrHhibfrv0 8dP27t7B10ND0Nf9Lzsb6ysLbyZf9HU0yUthIQn5Pm5Mmq227RscWZGpjq5oY0jKKpY1 QNJNvF5YWd/8vHdw+O379x846/v379++7u9uf1pdnJsagbSrkUrS4sKCuO5OdNjsrhmf vleFy5GVDdWR7RUQGp2cXXqvqaNv+OXs4uqn7S/7h0o7P/EUdj4Pv+593lhbnp8eG+hq VVSgrSGIy2H9zhFcjtDmzRfGpOSUyZsfPx2Zmnv/cWNn7+Dbjx/HZv69ZB2P/PPH98P9 3a315YWZ8cGetrrK/HS4xvrCXQOFZKEtRsrLkTdydFtafb+zf/QVLKONz/tfjxxdspmj 4VSuVI5W3r2eGOppq6/Kv5UQEeyHHFn/zhGNiS5HMakSaU0L5mh5bfPY0dEAl/7Dr462 //mAHD15WH+nIOMmOIILkt2ZjgLD4HIkVbR09Y9Oz//q6NJ9nBgQmcJiBI4W30w+722v vwMXpEgBTzdH5ZqOTnw+Dr9oOGqQ/T9HOHg4NeTpGP39jv49lXX/z9HPU+cLl1//nCO4 wBqGo58/Dg92j3aGc2KEPfDZwsMEF9vrjnaG9c1ddMtgEI4g7b4dfEG3Qdhe96sjeEA6 fReEHKHHI/QwESfOLVe0dg2Mzcwvr28ZoqPZyRe97Q2yIuXjhIuDHdlS4yFW6YiudlSh aIVbb8N19BJuvhtlRZnYA5KLAzzyaTzEEo5w2uxU62iWiJE4l1hHl5OER7s3kXVwPSKy jsg6/c4AsY7gvo64C9IvefQ+isg6Iuv0Th69DySyjsg6vZNH7wOJrCOyTu/k0ftAIuuI rNM7efQ+kMg6Iuv0Th69DySyjsg6vZNH7wOJrCOyTu/k0fvA46yDcjT0jk/9Ruzvf8en +3tYg/57HSo6ucC7ciP0ZhnelaveLB//Jd9w3pXrV3OC3v6jwtvjd+UqRwbw+l8/R1CN drKeAVWjHaL6Or2X8x878A86UlYM/rGZ6flBf7x26yfeUdJ0dIH6OnUN5MmKQRwtgRsk dcXghWog2ahOFRxVK6s6l9b+7jpVVEusrLxFtcTPtNcSK08XLl81a4kTzqwlRvXeUB0N 9d4p2aXypkca9d44l7D/AENf93Z0r/c+qskPgZr8Ellje+/zEzX5UBOPnyUYHHR4sZp8 Vd+EJw+1HxXdqW/rGTzqm9g3jL6Jg/0v0N2yrHPfxFFvS0TCrfxKLb0tWH8Jnl++7EIj CLRNoN6WNh16W1D/EXTrKEsGpfKmjt6hcdR/tPZpc3vHENqPPu9sYf1HM7r1H10xNrVA L8uxovyUnBLoEetS9Yitrn/a2IQmMZy1CT1iax+WoO3tRI8YNBn8rkcM3Xyr+/gyCypq mjrUfXwrqx9RGx3eWvv4QdnHN6RzHx9s39BShZrElL2Wj9W9lotLy1i3JXQ84iWYwPL7 xflZ1Gv5VKPXEgpvNTsTVf2wqKscWhN/7Yedfj37dn4edcTiKJjA2znwMzGi7oe9fW4/ 7FHPsr8gIkEsKa6sUfUsj01MvZqGnmGcNf1qahLrWe582KxLz7IR4k2QUNpxuIHCmKSM vNKqGmVf+eDz4dHRMegsx1Vjo6Mjw0P9fT2P2ppqZdKCc/vKjZS9/3YMde9/Vr6q97+z p+9pPzT/g/Bq/0djDwz0P+t70vWoraVBx95/qI/G+AyOaCWFAp8hS8lnaGptAz5DV3c3 voiGbsAzPO54+OB+g+JeZWlBjjgx+jw+gwpzYkdnsj39fmFoyBX1Tc0tANEA4YXRQGO3 trTcb2qoq7lbJS1SMTR43m6sMxkagKKxhEsSg4XALRjnJEtSWAKck7tyAJ0oanEVTKBG fk9WVV5alJeTkZIQHY44J85ncU6MgOikZNEguA6waCKARSPOzMktKCopkwKNBsPRICgM HqqoQCia0uJCYNHcSk2MjRIiFo3LmSwaIzUvCAGQ3L38VLygFPGtzOwciSQ3Nw9f5UoA F5SVkZ6alBAbFa4jLwgFScV0clMynURRwHRKTMagTmKlgK50qVINC9/SUlKSbsbH3ogE P3xfHZhOWJAg7xB3y1HN3QoRiiKjbsTExMbFIfQVjorDsFuRorBQQVCAn4+HDtwtcKRm owG8jgmsN4yNFhQsCEVwtGM62jGt7DJ/CkdotBDBdcCI+XrryEZDQcJwb7/w67y4vjz/ ABXADjHk8FNgIJ/vz/MDLB/HTUd+HeB6TzIGmRhj0MNLCRkExh++8vHx9vLkIDtOujIG Ud4hsOUpDqQrgCCBBIkrChKGV2EgWYgDSdWRAwlQZQ1WJ53h4IhgnYjWiaucnJSoTgYN 7OjM6sQsYWHCeKrWZBslTxUDqgLQFFfRVDhVii0Z0KO68lQR+hrCdJJ5i6C3hkC9BeQt MG8R8haRfHVl3gJ0B3lCccK4xOYWlmowMQID4yoESAYzKi6xGrZ8GhOk9XelJ2TqJDxa DXDG77uZmh2NEbEvDsRG+Qc8bWTMUIThvYEJC3TOcxnLmtGCY9ChhieY2GnwjObsz/wX 9AmGoTOnSfwncQaIM0CcAeIM/M1n4D89gm8aCmVuZHN0cmVhbQplbmRvYmoKMjQgMCBv YmoKMzQ0NQplbmRvYmoKMjUgMCBvYmoKPDwgL0xlbmd0aCAyNiAwIFIgL04gMSAvQWx0 ZXJuYXRlIC9EZXZpY2VHcmF5IC9GaWx0ZXIgL0ZsYXRlRGVjb2RlID4+CnN0cmVhbQp4 AYVST0gUURz+zTYShIhBhXiIdwoJlSmsrKDadnVZlW1bldKiGGffuqOzM9Ob2TXFkwRd ojx1D6JjdOzQoZuXosCsS9cgqSAIPHXo+83s6iiEb3k73/v9/X7fe0RtnabvOylBVHND lSulp25OTYuDHylFHdROWKYV+OlicYyx67mSv7vX1mfS2LLex7V2+/Y9tZVlYCHqLba3 EPohkWYAH5mfKGWAs8Adlq/YPgE8WA6sGvAjogMPmrkw09GcdKWyLZFT5qIoKq9iO0mu +/m5xr6LtYmD/lyPZtaOvbPqqtFM1LT3RKG8D65EGc9fVPZsNRSnDeOcSEMaKfKu1d8r TMcRkSsQSgZSNWS5n2pOnXXgdRi7XbqT4/j2EKU+yWCoibXpspkdhX0AdirL7BDwBejx smIP54F7Yf9bUcOTwCdhP2SHedatH/YXrlPge4Q9NeDOFK7F8dqKH14tAUP3VCNojHNN xNPXOXOkiO8x1BmY90Y5pgsxd5aqEzeAO2EfWapmCrFd+67qJe57AnfT4zvRmzkLXKAc SXKxFdkU0DwJWBR9i7BJDjw+zh5V4HeomMAcuYnczSj3HtURG2ejUoFWeo1Xxk/jufHF +GVsGM+Afqx213t8/+njFXXXtj48+Y163DmuvZ0bVWFWcWUL3f/HMoSP2Sc5psHToVlY a9h25A+azEywDCjEfwU+l/qSE1Xc1e7tuEUSzFA+LGwluktUbinU6j2DSqwcK9gAdnCS xCxaHLhTa7o5eHfYInpt+U1XsuuG/vr2evva8h5tyqgpKBPNs0RmlLFbo+TdeNv9ZpER nzg6vue9ilrJ/klFED+FOVoq8hRV9FZQ1sRvZw5+G7Z+XD+l5/VB/TwJPa2f0a/ooxG+ DHRJz8JzUR+jSfCwaSHiEqCKgzPUTlRjjQPiKfHytFtkkf0PQBn9ZgplbmRzdHJlYW0K ZW5kb2JqCjI2IDAgb2JqCjcwNAplbmRvYmoKMTUgMCBvYmoKWyAvSUNDQmFzZWQgMjUg MCBSIF0KZW5kb2JqCjI3IDAgb2JqCjw8IC9MZW5ndGggMjggMCBSIC9OIDMgL0FsdGVy bmF0ZSAvRGV2aWNlUkdCIC9GaWx0ZXIgL0ZsYXRlRGVjb2RlID4+CnN0cmVhbQp4AYVU z2sTQRT+Nm6p0CIIWmsOsniQIklZq2hF1Db9EWJrDNsftkWQZDNJ1m426+4mtaWI5OLR Kt5F7aEH/4AeevBkL0qFWkUo3qsoYqEXLfHNbky2perAzn7z3jfvfW923wANctI09YAE 5A3HUqIRaWx8Qmr8iACOoglBNCVV2+xOJAZBg3P5e+fYeg+BW1bDe/t3snetmtK2mgeE /UDgR5rZKrDvF3EKWRICiDzfoSnHdAjf49jy7I85Tnl4wbUPKz3EWSJ8QDUtzn9NuFPN JdNAg0g4lPVxUj6c14uU1x0HaW5mxsgQvU+QprvM7qtioZxO9g6QvZ30fk6z3j7CIcIL Ga0/RriNnvWM1T/iYeGk5sSGPRwYNfT4YBW3Gqn4NcIUXxBNJ6JUcdkuDfGYrv1W8kqC cJA4ymRhgHNaSE/XTG74uocFfSbXE6/id1ZR4XmPE2fe1N3vRdoCrzAOHQwaDJoNSFAQ RQRhmLBQQIY8GjE0snI/I6sGG5N7MnUkart0YkSxQXs23D23UaTdPP4oInGUQ7UIkvxB /iqvyU/lefnLXLDYVveUrZuauvLgO8XlmbkaHtfTyONzTV58ldR2k1dHlqx5erya7Bo/ 7FeXMeaCNY/Ec7D78S1flcyXKYwUxeNV8+pLhHVaMTffn2x/Oz3iLs8utdZzrYmLN1ab l2f9akj77qq8k+ZV+U9e9fH8Z83EY+IpMSZ2iuchiZfFLvGS2EurC+JgbccInZWGKdJt kfok1WBgmrz1L10/W3i9Rn8M9VGUGczSVIn3f8IqZDSduQ5v+o/bx/wX5PeK558oAi9s 4MiZum1Tce8QoWWlbnOuAhe/0X3wtm5ro344/ARYPKsWrVI1nyC8ARx2h3oe6CmY05aW zTlShyyfk7rpymJSzFDbQ1JS1yXXZUsWs5lVYul22JnTHW4coTlC98SnSmWT+q/xEbD9 sFL5+axS2X5OGtaBl/pvwLz9RQplbmRzdHJlYW0KZW5kb2JqCjI4IDAgb2JqCjczNwpl bmRvYmoKOCAwIG9iagpbIC9JQ0NCYXNlZCAyNyAwIFIgXQplbmRvYmoKMjkgMCBvYmoK PDwgL0xlbmd0aCAzMCAwIFIgL04gMyAvQWx0ZXJuYXRlIC9EZXZpY2VSR0IgL0ZpbHRl ciAvRmxhdGVEZWNvZGUgPj4Kc3RyZWFtCngB1Vl5PFXd19/nzvdyTdc8z/M8D5nnWWYi rnkeLyENhlRoIGQqhYxFg5CUECqSoVAoJSGSQsr4HvU8z+/3fn7v+9/7z7vv5+7zvWut vfa+Z62z91rrAMC2SI6ICEHQARAaRomyNdbjdXZx5cW+AVSA7veHmuwdHaFrY2MB/tf2 YwRAe8xhqT1d/6vY/8yg9/GN9gYAsoHZXj7R3qEwbgAAoecdEUUBAPkTpg8cokTAGPUE xoxR8AJhPLGH/f/g5T3s9RujUb9l7G31AUCzAoCjJpOj/AEgCsJ03lhvf1gP0QAADEOY T2AYACRnGGt5B5B9AGDLh2UkQ0PD9/BjGIt6/Zse/3/DZLLXPzrJZP9/8J//Ao+EJzYI jI4IIcf//vF/2YWGxMD363djgHvqsBCrPdsww985H7KBOXzlhL87ESG/bQbLQOy+YQ52 MG0PS4Z5WVn/hbX8ooxsYQyPhWwiKHp7GL5nkF8Excb+L/rRhAB9KxhTw/Qc32jDv/Vc CSKb7dmMBqbfjoqxdYCxIIwfRcfaGcIY9ijoY0KAvdNfMqs+vgZ/0REIv0Aj0z8yCIZA iuneXIywzfmDw8331gDPhVAG5iAE+IIYEAX3YUAKWAB9YPBXLwX8ABnmxMK8aBAMPsE4 FB4RDo8JhzHvX3L6/0Ex+j3OHx733zXyAm9YNuafOf/MxgvP+bfOQOAD47/pZHiOPd7e 6qI9ApP/NeffEnv6fq9GtlZ2Xnbr7zWhhFHyKCWUHkoTpYVSA7woZhQ7kEIpolRRuiht lAbMUwNG4COs2f/vNe7pD73tF5sfHq/uGABz9/67199c4PhbOvCf3/+xAhDYv9i0+PcK AKD4xsHPAQD64RHxUYH+ARReXfjJ9ZXkNQ3zlpbklZeVk91j/79pe3vWn8Wu2P7eiyDm F/+ihaYAoJYD+9SBf9G8pwBo+gYA/tO/aELRsDsnAtC94B0TFftHH2rvggYEQAt7KBvg BgJAFL7P8kAZaAAdYAjMgDWwBy7gIOw/AbAPRoFDIBEkgTSQAc6DXFAISkAZqAI3wG3Q BFpBO+gGvWAAvALjYArMgAWwDH6ATQiCsBARIkFsEA8kBElA8pAqpAUZQhaQLeQCeUL+ UBgUAyVCKVAGlA0VQlehaugWdA9qh55Cg9Br6D00D32HNhBIBDWCEcGFEEbIIFQRughz hD3CHeGPiEQkIFIRZxH5iFLEdUQjoh3Ri3iFmEIsINaQAEmFZEbyIaWQqkh9pDXSFemH jEIeRaYj85ClyDpkC7IHOYycQi4if6EwKBKKFyUF+6kJygHljYpEHUVlogpRVahG1GPU MOo9ahm1gyaiOdESaHW0KdoZ7Y8+hE5D56Er0HfRXehX6Bn0DwwGw4wRwahgTDAumCDM YUwm5hKmHvMIM4iZxqxhsVg2rARWE2uNJWMp2DRsAfY6tg07hJ3B/sRR4Xhw8jgjnCsu DJeMy8PV4B7ihnCzuE08HV4Ir463xvvg4/Hn8OX4FvwL/Ax+k0BPECFoEuwJQYQkQj6h jtBFmCCsUFFR8VOpUe2nCqQ6TpVPdZPqCdV7ql/UDNTi1PrUbtQx1GepK6kfUb+mXiES icJEHaIrkUI8S6wmdhLfEn/SkGikaUxpfGiO0RTRNNIM0SzR4mmFaHVpD9Im0ObR3qF9 QbtIh6cTptOnI9MdpSuiu0c3SrdGT6KXo7emD6XPpK+hf0o/x4BlEGYwZPBhSGUoY+hk mCYhSQIkfZI3KYVUTuoizTBiGEUYTRmDGDMYbzD2My4zMTApMjkyxTEVMT1gmmJGMgsz mzKHMJ9jvs08wrzBwsWiy+LLcpqljmWIZZ2Vg1WH1Zc1nbWe9RXrBhsvmyFbMFsWWxPb JDuKXZx9P/sh9svsXeyLHIwcGhzeHOkctznecCI4xTltOQ9zlnH2ca5xcXMZc0VwFXB1 ci1yM3PrcAdx53A/5J7nIfFo8QTy5PC08XzmZeLV5Q3hzed9zLvMx8lnwhfDd5Wvn2+T X4TfgT+Zv55/UoAgoCrgJ5Aj0CGwLMgjaCmYKFgr+EYIL6QqFCB0UahHaF1YRNhJ+KRw k/CcCKuIqUiCSK3IhChRVFs0UrRU9KUYRkxVLFjsktiAOEJcSTxAvEj8hQRCQlkiUOKS xKAkWlJNMkyyVHJUilpKVypWqlbqvTSztIV0snST9JKMoIyrTJZMj8yOrJJsiGy57Lgc g5yZXLJci9x3eXF5b/ki+ZcKRAUjhWMKzQrfFCUUfRUvK44pkZQslU4qdShtK6soRynX Kc+rCKp4qhSrjKoyqtqoZqo+UUOr6akdU2tV+6WurE5Rv63+VUNKI1ijRmNun8g+333l +6Y1+TXJmlc1p7R4tTy1rmhNafNpk7VLtT/oCOj46FTozOqK6QbpXtdd0pPVi9K7q7eu r65/RP+RAdLA2CDdoN+QwdDBsNDwrRG/kb9RrdGysZLxYeNHJmgTc5Msk1FTLlNv02rT ZTMVsyNmj82pze3MC80/WIhbRFm0WCIszSwvWE5YCVmFWTVZA2tT6wvWkzYiNpE29/dj 9tvsL9r/yVbONtG2x45k52FXY/fDXs/+nP24g6hDjEOHI62jm2O147qTgVO205SzjPMR 514XdpdAl2ZXrKuja4Xr2gHDA7kHZtyU3NLcRtxF3OPcnx5kPxhy8IEHrQfZ444n2tPJ s8Zzi2xNLiWveZl6FXste+t7X/Re8NHxyfGZ99X0zfad9dP0y/ab89f0v+A/H6AdkBew GKgfWBj4LcgkqCRoPdg6uDJ4N8QppD4UF+oZei+MISw47HE4d3hc+GCERERaxFSkemRu 5HKUeVRFNBTtHt1MYYSDw74Y0ZgTMe9jtWKLYn8ecjx0J44+LiyuL148/nT8bIJRwrXD qMPehzsS+RKTEt8f0T1y9Sh01OtoxzGBY6nHZo4bH69KIiQFJz1Plk3OTl5NcUppSeVK PZ46fcL4RG0aTVpU2uhJjZMlp1CnAk/1n1Y4XXB6J90n/VmGbEZexlamd+azM3Jn8s/s nvU7239O+dzl85jzYedHsrSzqrLpsxOypy9YXmjM4c1Jz1nN9ch9mqeYV3KRcDHm4lS+ RX5zgWDB+YKtwoDCV0V6RfXFnMWni9cv+Vwauqxzua6EqySjZONK4JWxq8ZXG0uFS/PK MGWxZZ/KHct7rqleq65gr8io2K4Mq5yqsq16XK1SXV3DWXOuFlEbUzt/3e36wA2DG811 UnVX65nrM26CmzE3P9/yvDVy2/x2xx3VO3UNQg3Fd0l30xuhxvjG5aaApqlml+bBe2b3 Olo0Wu7el75f2crXWvSA6cG5h4SHqQ932xLa1h5FPFps92+f7vDoGO907nz5eP/j/i7z rifdRt2dPbo9bU80n7Q+VX9675nqs6Ze5d7GPqW+u8+Vnt/tV+5vfKHyonlAbaBlcN/g wyHtofZhg+Hul6Yve19ZvRoccRgZG3UbnRrzGZt7HfL625vYN5vjxyfQE+mTdJN5bznf lr4Te1c/pTz14L3B+74Pdh/Gp72nFz5Gf9yaSf1E/JQ3yzNbPSc/1zpvND/w+cDnmYWI hc3FtC/0X4qXRJcavup87Vt2Xp75FvVt93vmCttK5ariaseazdrbH6E/NtfTf7L9rPql +qtnw2ljdvPQFnYrf1tsu2XHfGdiN3R3N4IcRf4dCyDhHuHnB8D3SjiHcIFzhwEACI/+ 5BS/JeB0BYJlYIyBY3ADOAoYhrghd6gaARDOiPtIEWQhigVVjJZE92DCsDzYYVwu3pMg TYWiekv9jYZIq0B3gD6Z4RZplomT2YXlIusEuxBHBOdDbloef96H/GwCUYKtQhsiyqIR YpXibySxUlLSVjJ+snFySfInFJIVjyhRlP1V9quKq6HU3qrf08jbF6PpoKWizaGD0FnU HdXr0r9rUGlYbJRtnG6SbHrYjGIeZhFo6WvlY+1j47M/wDbMjmJ/xCHN8azTRecSl0rX +gONbq3uHQe7PXo9X5CHvUa9x30++C757QSQAiWDTIL9Qk6FXg8bCF+NZIlSjXahxMVk xhYduh73MH4oYT4RcYT7qOYxj+MpSTXJwyk7J7jT5E7qn3I6HZp+MqM8s+fM13Nc522z MrN7c2hzHfIKLk4UcBa6Fl0sHriMK9G5Ene1vnSunP+aW0VU5fGq89WlNc21Q9eX60j1 GjcDbxXdftGAu6vS6NhEaT5/r7al4/6r1pkH3x5utO22IztQnZjH+C5CN7Z7u2fxycDT ymdRvXK9s31Zz1WeT/XXvogZ0B7EDQ4NFQ37vJR++etV10j2KHlM9TX76+0378cfT1yb THvr+053inNq9f2zDyXTsR9tZqRgL/s2+2bu6Xzr54aFW4s3v9xZqvtatXzjW+f35VXV teJ17p8PNqK3tHbYdndh+6PhWHEfiATNEAEygE5BowgJRApiBo6tOuC4vw1tgZ7BnMYq Yz/hLuHdCHyERaoF2AMALZFOkF6VwZZEYcxlamGeYWVg02U/xHGDc45biMeb9yrfAP8P QXYhDeEDItGip8UKxEslyiQvS12QTpYJkbWVU5Qnyc8q3IE9wViZTvm1SqlqiJqyOlB/ qpG9z01TWPOrVov2KR13XVU9Rr2v+r2wN6QaeRnrmHCZbJmOm7WYF1jEWbpaaVsL2xBt 1va/s31m12Rf5pDlmOQU5Ux2sXM1OKDkJuTOfBB/cNtjxXOB/NFrynvSZ9x33G/CfzLg XeC7oMng8ZA3oW/CxsMn4Z16JmoheoWyFYs5xBDHEc+XIHJYOlH5iPZR02MOx72TKMlp KUWpt0/0ps2fojmtkO6ScSSz9Ez32c/n6bKUs90vpOXU547mfc0HBQyFwkWaxU6XKJfz Sh5cmS1lKjMuT4T3vyeVs9WYGuFaw+s+N1Lqyuu7b87fJt6Rb7C9G9h4pCmrufxeY0vP /bHWuQe/2giPONulOxQ6hR6TukDXYvdoT/uT2qc5zxJ7ffusnqv2i77gG+AcZBtiG2Z/ yf1KYER0VGZM6bX6G51xowmrSde3we9Spkphf9j+qDZz5FPPHOt88Of2RZEvV7/KLX/4 fme18kfrz6VNle2c3/ZHwdmCLHAFF8AExAU5QgXQR4QiIh0xj7RCtqBkUXVoJXQHxhmz is3BaeDm8NcIcVSe1BZEVRohWhY6Ij2WASIhGdFMGGZaFg5WYTYldkMOR85ArhBuLx5n XnO+ffyiArRwRNUrdEU4TERV5JfoXbEwcSHxUYljkrySj6TI0pB0uYyJzKJstpya3Hv5 DAUVhQ+K55S0lBaUL6roqXxRLVAzVFtWL9Iw1ljZV6JpoflTq1zbVntXp1E3Sk9eb0W/ wSDGUNlw3ajJON5Ew2TT9IHZUXMdC2DRYZlqZWJNtH5pU7zf31bBDmE3CPtIjKOpE5fT knOby3lXb9hLcG4T7rcOnvLw8FQlk8hfvfq8r/uc943xc/HXDOALRAfOBz0PvhWSGxof 5h6uFyERyRaFjVqL/kB5EdMSW3YoIy4y3iFB9TBbIpS4cRQ6hj/OkMSeLJAikapwQj1N 56TRKfPTNunuGVGZp86UnL1zrvv8aNZM9tcL6zlbuTt5O/mEAtlCl6LU4rpLoyXgishV y9Kosrzy5muvK3ar5Kp9ai7W9t0AdYr1gTcv3xq+g23Ydzey8VrT6D18i/r94NbCB08e rj7iaTfpiOzMf9zW9aEH/UTsqfWz+N6qvsl+9hcHB6oHN4dtX3aOeIyxvt6YEH/b9n5w hjLftHRhZfXXkz37/6kt7Z0JGGUAykoBcIJrI7aWAJRLAiAkD58fbQDYEAGwVwMItgIA dZwDkHHdP+cHDRCHM8sQcA7OGl+BDfgUMYCCoQvQHegVtI5gR2gjfGBvuokYg3M3MaQd 8giyCvkSBVDSKDdUOqoF9RnNgbZEJ6Fb0KsYWUwo5jrmC1YWG4ttwxFwLrhaPALvhr9P 4CKkwDvPAapRagfqEaIzcYLGi2aeNpJ2gy6Vnpa+iEGUoZFkSHrFGMC4xZTNLM78mMWD ZZM1n02FbYQ9loOVo4XzIBea6wa3Mw+ap4HXj4+db5A/Q8BYEC3YLXRa2FqEWWRctETM S1xQ/JNElWSQlKTUkvRtmUOy2nJ4uRH5awqHFO2UlJXZlHdUpuGo+oZ6tsYheJ/S0RLS xmt/1Xmp26LXAPvhXcMmo3vG90zumTaa3TKvsSixvGCVak2x8d5vY6tjJ28v7MDtyOrE 7Mzswu7Ke0DUTcFd+6ClxwHPIHKC1xnvAV+Sn6N/fsDrIJZgu5DM0M6wHxEikY5RJ6Jv U97Gih6KietO4DhMSRw+qnqsPIklOSuV4UTBSaFTjekGGWNnKPApNZpdk1OSd7+Apij3 stoVr9Ks8u6K3Wqt2mM32m+ibhs3nG4sab7b8rz1cxuxXaUzuKu65/szw74r/SuD+sMZ r3rHEG+kJ/a/DZlK+pD98cqn7rkvn38svl+6sez+bXWFsvruh8Z65s+XG/SbpltHtmt2 Rn7vH3RABtiBOLh20AUW4KrAPsgPyoIa4Dx/ByGEsEDEIEoQTxGrcM5uhUxE1iLHUVTw uRKOKkWNoKnQuuh4dCN6DaOMicc8wKLhPLoYu4jTxRXi1vEu+EcECUIRFS3VGWpG6stE CWIrjQ3NLG0SHQ9dO70vA5GhieTOCDFWMtkwbTHXsLiyElk72Q6zK7GvcNzhpHApca1z 3+dJ4jXho+Mb568UoAjqCzEJzQk/FMkTjRazEZeWIEp8keyXqpfOkqHIushpyQsp0Cj8 Uvys9FZ5WOWpartai/pdjZv7rmtWa1VqV+hU6Fbq1evfN3hiOGo0a/zTlGDGaS5joWtp Z+VnHWeTsf+SbZVdg32nw7DjJ6cNF3pXsQP6bu7u8Qfz4HxjiPzNm9fH0/eK31QAb6BH UHHwWCh9mEn40YhbkdPRTBTDmKTY53Hs8UEJrYl0R/yOPjzOkhSZ3JcqciIlbeqU5uma DP7M4rPs54qyeLIrcmRzH1y0yJ8sDC9GXsov8byqVsZc/qtiqup5Tdv1hrq6mzW3qxoq GjObI1psWxUeMrQtt/d33ug60xP+1KFX67nYC8aBraF3L1tGMsfs3zCMd01GvCNN3fxg Oj0xEzqLnrvwmXkhc3FtyfbrpeXx77QrKqu2a4E/otcTfib8itkI3fTcst3W3pHcZfpt f0agBtf3zoBm8BGih3SgCOgy1AN9g+s65nAdpwYxjqRB6iJjkTeQH1GcKEdUFuo5bHdT dCZ6BMOPicR0whWUaOwQTgVXhmfGZxGYCCVUclRj1KlEJeIcTQmtMx0j3RB9DoMziY/0 nbGH6SrzMRZvVjM2ZXZhDg5OEuc21yfuQZ523ga+Wv4KgXLBSqEbwk0i3aJjYgviu5KM UmLS2jIOsiFyJ+RLFO4rTinjVORVPdTOqj/UWNYU0HLSztTp0P2pL25w0DDPaMCEaGpl lm3+2lLAKty6bT+9rbtdhf2Ko4FTvvM3V5sDDe48B895oslJXks+qr4pfgMBPIGRQV0h HKExYUMR8pG5UVsU35jOQ+xx0fH9h6USzx/5eczv+Jtk+5SREwfTFk4dOz2ToZd59Sx0 zuf802zZC0W5+LyEi18L/Auni70uTZfYXnlUKlt29Rqp4mTldjWl5st1/xvT9eSb7297 3Zm5G9K43pzSQn+/7IHKw/5HgR24ztqu/d2bT6qeOfcRnne9SBrUHtp62TQSNsb/+sV4 7CTz21tTRu9Hp30+Ln1ymC2fW/jMv2CxGPglaMnnq8Eyz/KHb9e+23z/tXJpVXb18ZrD 2tgP1x+T647rfT/1fjb9EvqV9Wt7I2BjYFNps2Bze8trq32bZ/vo9uSOxk7uzvKu2W75 nv2j/RTgMwJuELUeHEy+3d1dEQYAmw3Adtbu7mbp7u52GZxswO9AHoX8eV+xJ4yBa+7F 5XuoWz/1+N7139t/ARv5hz8KZW5kc3RyZWFtCmVuZG9iagozMCAwIG9iago1OTU5CmVu ZG9iagoxOCAwIG9iagpbIC9JQ0NCYXNlZCAyOSAwIFIgXQplbmRvYmoKNCAwIG9iago8 PCAvVHlwZSAvUGFnZXMgL01lZGlhQm94IFswIDAgNjEyIDc5Ml0gL0NvdW50IDEgL0tp ZHMgWyAzIDAgUiBdID4+CmVuZG9iagozMSAwIG9iago8PCAvVHlwZSAvQ2F0YWxvZyAv T3V0bGluZXMgMiAwIFIgL1BhZ2VzIDQgMCBSIC9WZXJzaW9uIC8xLjQgPj4KZW5kb2Jq CjIgMCBvYmoKPDwgL0xhc3QgMzIgMCBSIC9GaXJzdCAzMyAwIFIgPj4KZW5kb2JqCjMz IDAgb2JqCjw8IC9QYXJlbnQgMzQgMCBSIC9Db3VudCAwIC9EZXN0IFsgMyAwIFIgL1hZ WiAwIDIyNi43NzE3IDAgXSAvVGl0bGUgKENhbnZhcyAxKQo+PgplbmRvYmoKMzQgMCBv YmoKPDwgPj4KZW5kb2JqCjMyIDAgb2JqCjw8IC9QYXJlbnQgMzQgMCBSIC9Db3VudCAw IC9EZXN0IFsgMyAwIFIgL1hZWiAwIDIyNi43NzE3IDAgXSAvVGl0bGUgKENhbnZhcyAx KQo+PgplbmRvYmoKMzUgMCBvYmoKPDwgL0xlbmd0aCAzNiAwIFIgL0xlbmd0aDEgODM1 MiAvRmlsdGVyIC9GbGF0ZURlY29kZSA+PgpzdHJlYW0KeAG9WQtUVNe5/vc5Z86ZJ8ww DPOA4cwwA8NjhqcwDqAccAZQGEVQAwQSRsSgBYPGmBiLJWqCos2jbdQYe83DvkzTO2Bq xqbJ9dq0TZO4bp43L5s0rXkaapuSpI3OzP3PGSTiyspyrZvVs9d//v3e//7+f/97n302 brixDzQwAjS0dIaGVoP08DsASEbvYGgokdarkS/q3bTRlkjLcgHo21cPXTeYSMvDAErn dQObp9vrbwZQHe7vC61KlMMF5BX9mJFIkznInf2DG7Ge+KS8jK+5A9f3Tpfr2zGdORi6 eXp8OI1p27rQYB9yfPgufOUOXX/DRikJfAZyYWhD33R9gu3p/wGCuUmwFhQwAHKgQIsB W3IfKJ3AYKlYjlTrWX7/tcnVn4JOLnX3oKtwRIz8zv7rf31++oJLtVVRj/UUUn2xANuw ebE8ADXB8jdVW2dKxFLxSYpAa0EEGpHmI81Byi8Ylwu/IndBaveUoCA8Ayr+NfNfnySF iP970jtMCgW1BhS926v53u3bG/NqFaQJvAwBngTAKXH/hPNhPkLmTzgdyOYlGDXhtWIK BIXXyUe9K/kL3oicCOn8P53f5z9H+sxZw3/qLOFfwHrPexv4U7VYPsE/mx+hkD3jjDBE SOafdt7K/9Kbxz/qreInXJg3wY/XIjvGH/beyj+0Q8p5MF9iDzgj5MAEf7/IjvGHsP+9 26WCexINtyXY0A5poOuPSmzd0Qj18DF+0JnDr8SGRFDx3c4Bvsvp45fVRkj2BB8Umx3j m12n+CZx6AleSAxUkei93ClJXJoY1u18nM9NjJAl1hb0vM3ZzFuxf/f9e3m38xq+Nj9C fvpYY26+s9G1tyJCpqQxRIaCimxdgvW6niA/gQbII52QTe492piHMpO7JvjtyA4cbcz1 ZkfoD4QU/qir0bUDqQIpG2l5hCwT3Nw+bhW3nCvjCrg8Loezc5lcOpcqT5Fr5UlytVwp l8tZOSOn5CBPjcT/JBSIVpTKakXGMuKbkeJaSozjC99AETkFiyDCwm1pm2pMNSnzdb56 /1e8eqTMHn/Bl4/py2iBiVjDe5va2sNHrB3hUjESt3ZcUv7/ifbVYeum1s1HWzefXRHo cwR6HIE+pJ7w7k39pvDISptt/OxmscAWpnN6Vvb2izzUF97s6POHzzr8tvFWqd1lxSvE 4laHfxxWBJa1j68Q+vwTrUJrwBHydxxtCTQunjXWrpmxGgNfMVZA7KxRHKtFanfZWIvF 4hZxrMXiWIvFsVqEFmmsgoLAmrY6kJ0AnewkeGT7wMrUgRUg/gbSmyKPtcXPyZ4HZTwa n6TRs5Eskd4+T1LhP4GDx2ArepsX4QhRgAMmSSm8TqwkH16DGLwJfwYL7Ib78R2AD8hn 6GU+JLlYpwK2wX/AofgQDEENhg+IDAwwFz6Mb4k/Hf8X1MEYPEU4oifW+HEoglEMB+Ag UVMr4+Nggma4Cb36NvgDvBGfiH+E/VfAu0RHipiq+B/RwGSY44NdcAQeI3biIPnk6vi7 mG9CGbvgSDwY34TtzmGtIlgMW3C0dwhPckgBOUDeoifjI/E7cG4ZWLYcejEMwq2wHw7C I1KtlUyGzID9+6EJy+6A5+AD+AQdbh6pIzdTr9Af0X9jqpgD8adQjuU4Xg8cIjSi4iTL ySoyRB4hj5LfkM8oLxWiffQrzBDzAMq2HHbCA/AE/B5egj/CWZiELyBKGJRpPllCtpAf Yrs/U2VUNzVM7aHeoM7RJfRbDMfslt0mezzOxF+Jf4EyZ0I+VOFKXwrt0IdhNayDG+E7 sINwsA/G4Tco7dvwNlESLSkiJaSBLCNXk2+RzXA3OUx+RU6TM+Q98iFKp6d4ykEVUZtw vG3ULuoRaoI6Tk3SOnojPUyfoN+iP2MMTDdzAsPbMo9sI5vBNnFLYz+IvR33xO+KH0C9 pGFwQh54YD5hEMVB2IGa3IWYHYTD8DD8AiZgIn6e+OApeAHlegfOweeosQwMdlJK5pIW shQlHCCD5DtkP0p4hBxDKR8nj8Or5FVyHkMMzJSC8lBXUyFqM4YDsJ96ScJHTdvpXNpD N9Ft8b/Tj9Dj9CdMNtPJrGe2MGPMfuaQLEM2T3aVrFM2JLtHdkz2rOx/ZedkU6yVHWUP s4+yL3Fybg63n4uRLJTFRrLhUXgSrW4vPYRpJywgO1CrK+A5tN5J+C2ch3/BCfgJsUKM FrWZE38AIvGdqM0n4Jf0t6Ea7qa+Ty2K19A/pRWkNP459lWM+roYQMjPy3XlZDsdWXYb n2nNSLeYTcY0Q6o+RadNTtKoVUqFnGNlDE0RcAcc9T22cE5PmMlxNDZ6xLQjhBmhSzJ6 wjbMqp9dJ2wT24WwaFZNAWuuvqymkKgpzNQkWls1VHvctoDDFj7ld9gipHNpO8a/63d0 2MKTUjwoxe+S4hqM2+3YwBYw9fttYdJjC4TrN/WPBXr8Hjc5LuBmoPS44TiAACqx4zAs CA2jc4UFYo1A2OLwB8JmB8axjM4OhFaFW5a2B/zpdnuHxx0mC3odK8PgqAsnF0w3F9uh E8xubcexPe41YZQfdqtXOVbtjgiwskeMhbraw3SoI0z1iGPoCsJGhz9svOVd05fJi7HA nksKw1R2fahvrD4s9OxG0MVkj5gK7cFUU5sNu6Vu62gPk9tQOFEISfbELBLbRHbPWltY 4ahz9I+t7UHMoaV9wiJYAo4ef0cYWtsnzIJZSnjcx01bq+wIynFPradW5FV209YEf397 Iv/FEyI3bX3qT8ibWmdwIeLYjoUoZtjWi4MgFijrXPHVNxfGeucifPh0EJzlGpRnQZhC U6Kzw7LshaHwSNu0GKF+/7Rwa/0TCrNF2pfqOrB+z5i2EhWI9bUO29ingJp1TH48Oyc0 ncNmaz8FsVDU/4wJhUnoYnyTuH9m45bUb3L0i+rbJKka0w5T4JIMTIv7lgcPnO6mCCha 2scJuaMjQuK3RcBvPY4bDH3tNVhcIBrcGj8Ohwm3GzPy7RhDCepxoHrRMmxjtrGFq8Zs 9bZ+NCkmW+JY0DfWUYSAtbUjLLCs3R4WOtJnon0dHZXYT6HYDzbB6mMd2MPa6R6QS1lF UaxU5G7CWeW0tC9tD4/408OCvwNBRyM+0dIePoH229GBtYpnJEWJh9eYpmUuQZmL87G8 NNELHmtGsIuOsTGxz7Z2hz18YmwsfUxcdYk0npAvzxCmMyIgVhERjpCRFmyLzGFPlyC3 O+woVoeIaRka8EUDwmP91yNcPiM3tqxAacslhL3fEMJzrwRh3xUhXDkj6SyEq1DmShHh 6n8fwvNmITz/6xGumZEbhRRQ2hoJ4dpvCOG6K0F4wRUh7J+RdBbCAZTZLyJc/+9DuGEW wo1fj/DCGblRyEUo7UIJ4aZvCOHmK0E4eEUIL56RdBbCS1DmxSLCLf8+hJfOQrj16xFu m5EbhVyG0rZJCC//hhBecSUIX3VFCLfPSDoL4Q6UuV1EuHMGYSE9DJf64ZHL3C584475 6ksgl/0eDjA3QBXzF6hBXoS8jsJvHc4KIxgfFdNIw7QVtmF5HXUEDMgNeM5K3AnhxQ6w eBYFCIFZ/BDHh8IbMsDvOMAvlsTD4reEHLdTPJ2BCltcfDTTkTnwGp6Bf0cJ1EY6gx6g TzI2Zi3zN1ml7EWsQeHXGuDZ+iT2y8F8wS5jrXhmZTgrDUoZY6VpyqJgOSsBs1xxxD5Q jR/0i6eqg9HqxdrPqoPaaDXUVEerRSopLtPZdS6kA8xDkQunZCe/mB9hWs//QhSEhqr4 W8xc5lq8CfNBJdwpLKmiyis2k12EeS2T5Pzjvfz3HUkaGX4R6i0FeK5mcgpzCvPFDCZd lZWe5q7kuXylyl2qqtQHIVhYWZ4/P8dSbQmme+TBcnNV9a+JGezQSH4BkojByalJFDF4 Ruc79e67RVAzWYNCnvLpUoy+FJ+PiFykgpJi0g3dJIkkE5ZjDalpZaUVXleFt6J8To4j i2M5O8btpXi616UaM4nRYC8kLqzpyMopn+Ot8Oqpt9K9xUKnq25pZdd99CNLsuZ1d/bl Zypjk4qG9UR/dPduis7IiD2jUdJVwa6NP/jv+5b/aIhK0RkUaq3R1bqwduDOc8pki3dB WWl2zZ1ddzU0/DamnrNobq4m316ZLXjKf3bfHzpLDES8nER91SCOfbITeIdohSWC+wM1 QamtlJYGo1PLsUqrU6ky0BY9z/K0i7HwlgqNOZPfb28MTOMiohKdOqNL8UmgTNbofDqE pKQYuiHNiOqzlycRRxaUa6EsBVFwIQwSLtQtB4qJPXZ23sGN/xU7T8irj23tm986fONN m5muq4KU/AthX6idlH9CjES4sOHRO59eMeeJPft+ibovip9mKlH3LGooCx4WFtbLR1P3 kXuVDEsUMlYrszTJ6rULbbeT25JHeSWdRhv1aXpjo7w5rdm40NKV1mXstJwmbzIfWt+3 fW7TLiL12p2y7VqGipB7hLIlSdcmXZ9EJyWls84sO2dMcaer0mgqi64wbsnK7FGPqCm1 xUnxSfdkmh1OhGJxAoroGcSiO6jznZksSsBxqqZ6MsVX1B1FNNZ3k/XdgPovJI6KNCMG zo6vslJUul0yANBpoYqQ5weTyOPclqt3vtEg6FVUNI0NVbW1ezONxKHq3HPh+dhJwr+b Sm/89tr1N55dvS400vTdw3V5penFoVWHiJoUknS8dpXWSF2sjrkGcdLgbUcxdArasUw0 VJmzuIhLYbM1zrwIqRFsGTa3KbmY4lP4bFexW28pzdiR7lFUuM0lpZeoOWH+Oh+qGq0/ eqpm0ocrYFKHiibdzovWbUjFGaXg5MrtulSOtWc5XRcnOU9cD44sqnxOSpmXemJs+7q9 vkxb5V7VvH6BGBpuif34hdg/k0iFOr1w8MCcrLyi5TtfPP/JW1d/tO9H9z343aZ11y4a ozeYC2744fnPXvpW5PBDpWmu6+oO1tc7aonrwj9Ik+jI0J53obs7IntW8j9VQlYzNJMu 6MLrlHFc+iynVBiNFmBdhEMHNGFvSVix5IACff73oKamJjgp2i5Bw5XoSOxttFKJGLya it10/knRo47gbflBphNvOE7WBsGLI+OVJ77TkLKR1kAy3tFbYDPyW5DvQj6G/F7k9yL/ GdJxpPfRyyZhfTveltDAo66c2KdJemejD+WxVyukoE9WohaNGFB8vPVSkGRsoYMgpGIs E2xYy4XcDIVQRBzYXwvevU0b5lPaqUnfVBRvCcUpVlej5oKT2kmdUdKetFDRFA20XSct T/QAuG4vidoN6LTK0GkZRS67c4+vUKukYqdTc1Zv8hhj76Q619ySb0SQDOVFbTuGg/Nt c9vaB5jOufW+Nu/a6FLq2Pzc5pVzFkZvonaF3EuWeDqiQ4xwaLlT8Ja19Hg8OP9R3IZC aKtpOMMmwSMjBpJNvKRd1a9iSYqWVThxwSQxSqOswphMWcy6JFey2WR+8qIKg9GnRE+k 802ieeIGMlnjS0wOHe1XzMVFj70aO23M33R3RUbsDNF7S9pH1zBd46eiWdS+FYXLttT2 RSdQxGXZdaJh0VAXf4M5yPShtoyonaCQa6SJXL1TvVNLGzWm5NUaWuY0pXIqZ5LKZJJT FUaLRV6hM5stEbLp6IyLkPYQXDTSBlKNhkY2wIb108tH8opOsNugfI74NhDq7O23Dw+P jg5ThbGPY+9j+JikEjOG1OhLf5g4fHh8/PDhidWxh8nyv31MOmM//pgSEMvhWBtzAG1T g1axSMgz6uXKDAvltHEWVunUq8xJco1JU6G1ZLF8Om9ymc32rP32lotebEp0Y8FJyYOJ 2xyKO+3QpQ1MWuKlFeUportyZLlyxC06YSD0xhtuva8ys6+69aZhK1HEos9tW1Hkib1H dIVzrt1OHTr5/cU3Pxn0RO6lfLH3Yudif4q9WOsMRJ+WnXugIW8hwoxraBsu4vNMF+hh 0XGgScNRKlnDRkiDYNZzGlattFHFlEDRBlzGVJLKpTanGiJk1VF7y+qLtv6yZObBbnEt o+wvi8sZNyJ0u7j9isaQEJb6o0qfnq/5eZU99g7R1pW0jDBdhMRO09RQzfbo50zdk4O5 C0SZKNT9m3h/GIICcMNWYYlCy+aYNbSCsatUTcqFqga739aY9yott2bZ1EomrYBJs7jd KRzjzlW53ckGpc2aFsziDB4umG0pVIM1mOyBYIHZUzj6pWFM4UYh4T6FJqzz4WFi2kii p7SnpIV6Tfc1pJtIW4a0jWbnuPDIgMuSMdoxKu2q4rYiXhyyDltOOSG9iszyO5f15ubG 4sebmydffY4QfewvrLloffeS/Pz4keXL/n4hFv8UL1O7mm2+0tJis3leYcA/su/1h572 2iorXSVpxrm5S1u3PHjq9Z/SuBAIGOIfUTfL+nGdLjqmdSfzarfuV2Q9MKRLSOOgiyWs CVWTzE4xChd8D/VkipCko/YeUT0vV5+JVk9Vi/r5a1A66E3W4H5SUqwvF896ZQaHLnFe MnAszk1n2E8s4+NZV2msSaPPLCqmB58lxbHnn42eWGAn5BUZFyxZTR1C/RhiDUwL+g49 pMLrwpBLuUK5WnmP8rDyJSUrUxKWzeB0Gg9n08zjSjRNXDcnepWbuM0ajTG5QjOq2Kna r4qo2NRUtVxD2dRqV4pKpWQ5ipfLXSkKhRjVKA1qlULOcgrgKbee1yancmk40SSNSh0h 6qNYoEQuqPXfk5v7DGk/S8x40+Kp4BnTBZ/PJ5JZskwTGmbwTPQMOuHqajw7oqbJaGGB bFjb1HrzLb8tGy00FUzHcbf2FYkb7Ho8PvAkrcI7n7iIPR3vyCncS3NcZNyZ32wxFzCx ITLvr++QotjYwNYncgoLybYXKEqZohtQMxsunKad55+PPXMPodlU0Z6lJy7+JfiqJwkz /fgnoRF/0jXjLrIUWqEN/1KsgKvE/8z4ENyPiBRjxe+LxYHG9oaGgsa+gU19G9f0hjx1 1w+sEmtdfASMNCOJrQeQvo20B+kg0s+Rfo30HNJppI+RLmBjdXz6wTTMxAl+u8xO40Cz yqU5XVL/usvK11yWlv71X1J/3WXl11+Wlv7FX1J/w2XlN1yWlv7lX1J/s1j+f8YOvZQK ZW5kc3RyZWFtCmVuZG9iagozNiAwIG9iago1MzIxCmVuZG9iagozNyAwIG9iago8PCAv VHlwZSAvRm9udERlc2NyaXB0b3IgL0FzY2VudCA3NzAgL0NhcEhlaWdodCA3MjAgL0Rl c2NlbnQgLTIzMCAvRmxhZ3MgMzIKL0ZvbnRCQm94IFstMTAxOCAtNDgxIDE0MzYgMTE1 OV0gL0ZvbnROYW1lIC9ORUhYR0crSGVsdmV0aWNhLUJvbGQgL0l0YWxpY0FuZ2xlCjAg L1N0ZW1WIDAgL01heFdpZHRoIDE1MDAgL1hIZWlnaHQgNjQ0IC9Gb250RmlsZTIgMzUg MCBSID4+CmVuZG9iagozOCAwIG9iagpbIDU1NiAwIDAgNjExIDU1NiAwIDYxMSAwIDI3 OCAwIDAgMCA4ODkgNjExIDYxMSA2MTEgMCAzODkgNTU2IDMzMyAwIDAgMCAwCjU1NiBd CmVuZG9iagoxNiAwIG9iago8PCAvVHlwZSAvRm9udCAvU3VidHlwZSAvVHJ1ZVR5cGUg L0Jhc2VGb250IC9ORUhYR0crSGVsdmV0aWNhLUJvbGQgL0ZvbnREZXNjcmlwdG9yCjM3 IDAgUiAvV2lkdGhzIDM4IDAgUiAvRmlyc3RDaGFyIDk3IC9MYXN0Q2hhciAxMjEgL0Vu Y29kaW5nIC9NYWNSb21hbkVuY29kaW5nCj4+CmVuZG9iagozOSAwIG9iago8PCAvTGVu Z3RoIDQwIDAgUiAvTGVuZ3RoMSA4ODE2IC9GaWx0ZXIgL0ZsYXRlRGVjb2RlID4+CnN0 cmVhbQp4AcVae1hU17Vfe5/nPBhmBoZ5MMPMOMwM74coMjLKiAzgA4KSKBhJAEXBaH0h CWn1kkRrxMTEGB+J/dqYpD5rHZHqoDXXpBi1j8SkrUls2iatSXPzlWtvr2nTCDN3nTNA lK/N5x/5euew9l5rP9f+7bXXPnsf2tesa4E46AIGahY0rVoC8s8ZACB5i1Y0rYrJ+r9g fHFRR7sjJnNpAMzyJauWrojJ4rMAStvS5Z3D9RPeBYhjW1uaFsfyYRDjwlZMiMlkAsap rSvaH4rJ+l6M/ctXLhrOTwij7FjR9NBw//C+JH+jaUVLrLzTinHqqpVr22OyQ8oPrFrT Mlye1KF+bwLB1HhYCQp4AASgoMWnAUD4RGkDFnOlfPwtzlLtuD/e/xnoRFm+v+opOX7d +eMrn7cMelXbxX9ggmKkvBTz6ZF0ADXB/AHV9tEcuR4G8WGozQzDDKQSpIlImZnTTNBF 9sPTSC8gMdBGtkIn0hak55DYUe4QSn1kaw8rBk6TTrCQmQEVa7870Ww3KVX2t8OE7/2u /T3TH88QM87eh8TcEweKaUryAvkeLAY7+T64ycNQCWnk+RPpy+2NmHUIViF1ITFySMih npTx9ldIFrhZgnU8kMKSk/Y/5WfbP8oPU9Jjf80bZjF6NQWlQLz9nO279v+0LbW/gnQk lnU4HUuctB+yLbfvSAmT53vsz9jCBOtsj0XrbFj1pH1F+i774nw5f/auMD3SY/dh/ryA yl5Y5LRPtF2z53rDIkE52zbbnpH/C3sqVsRiDmzUHdDZrbYd9smYlWILeicjnSGHyV7I IHt73DPtp5HF4Z6YkV60K0y+eaIyLd8dJg8HCivTdqVXet3ps+3u9HKvF/l5F4WNwr3C NGG8kCmkCR7BKSQLiaJe1IoaUS0qRVEUwuQHPSV2/gw5AiUIy5ETIi9yYfJDTGTPkKNy 4tFTIitSEcTEcPQDNF4CiWFypFcrccic5GWOD5OjJ2JJRwN2VuJYOUNLJR4DDIESkcJM CJEnwzxsSuooMZXop+p85WX/KmiUc0bCzH/9MxFbaNes2rrQYVt9aLzERG31I8VNI8y/ jNvXYVZLaWbmrLmdJzpWLVsSbHEFG13BFqTG0NaOVlOoq9nhOL5slZThCDGexuZFrVLc 1BJa5WopCy1zlTmOd8j1xmQvkbI7XGXHYUnw7rrjSwItZT0dgY6gq6ms/kRz6ZqG2/ra MtrXmtJ/0lep1Ngaqa9mud6Yvhqk7Gaprwaprwapr+ZAs9yXNPhgW23p2na0TkewbZYj lFYbmjFnQV3I0VRfFib7MbFsHXDnQMudhTSuCyxsLtgBou8hXZXiyD3Rj7kLoI2siP4P U4yT2icRjZT44Rw8CXvhGPBwEPk0uA/2wCWyDNf2QuiFKyQFctD3shCG2fBzEo2+BUvg ZSzfDq/BTjgOaqyzAgyYu424ow+jHEC+GTZGX4RUKIJvw1nwYavbYCB6KHoCc+fCPXAY jmD9nxEXPc4mRH8YvQYizME2N2LOW9HZ0WOghywohRpM3QivEDdzNdoKJihG7b4D34N9 8Cr8mTxKeqOt0Y7o5eiHaKomsEItPutJL/mQOcZ+O/qd6KfRCCKRBhnYayPsgJew/WP4 nEPXGiQPkHayg+ykAfoo7WU3ccbIEOKQDhX4VKJXfhwR6IN++Cv8g1ynJkbLtDPnoxOj /wsqmIWjlEbSAh34bMZnG47pDOFJHplOash68izZSX5JM+g9tI4+SB+iHzPVzEKmk/kl u5bt4Z7g9vCqyGfRM9EL0V+DEWxwL6yBDTi61+Ay3IAvCINtWYmbFJNSch8+XWQv7SP7 SB+tIefIZXqY/J78kVwnNylH1dRAM2k73UGP0NfoG0wbs5N5jvk98xk7laPcPu4j3i38 JtIc2RJ5I1oc/TD6ObpYEZw4M6VQDfdDE452FUyA/8BRHMXnGM5aP5yHS/LzR2KFAfgc UQCiJxYynlThU03uIktIG/kuOY3PK7Iuf6M4EVRBddRIrbSWNtMVtIv+mnYxyUwGM5NZ wBzD5yJzhbnJ3GQ5NoE1sBXsDHiCXcE+j89+9iDbw77J+bipXDU3j+vitnBPMIu4t7gr /AZ+G9/DX+f/gm5xtrBSeAJn5xLa7Ktoy1/+WJKK2o+Hb8AiUkaaYRfOxj7SBN1oXYvJ 44jXKkiLNjAbmAqah9bwCnwTrfV5WA9bmIWwL/oucxjeQUtZjk12wQG2FGzcbpydRyEP rWj4CaRnpKd5Pe5U1zinA12+NdliNhmTDIkJep02Tq1SKkSB51iGEsgKusobHSFPY4j1 uCorsyXZ1YQJTbckNOJSdoTKby8Tckj1mjDrtpIBLLlkTMlArGRgtCTROvzgz85yBF2O 0C/KXI4wWTCnDvkny1z1jtCAzFfJ/NMyH4e804kVHEFTa5kjRBodwVB5R2t3sLEsO4v0 BRAOZXaW5DgCoJIaDsH0pvXoYGG6VCIYsrjKgiGzC3nMY9zBpsWhmjl1wbJkp7Me0zBp bh32kZ3VFkI9Yat6sWvx1nAAmhslrmlhXYhpqg/RRqktXWbI6CoLGR/+yPSlOMIFn7gl M0Td5U0t3eWhQONWBFcSGyWp6QmUZtU6sFm6qb4uRDYNKyHpuAw1ldSN7QnuxmWOkMJV 6mrtXtaI4MLcuh5LwCI73xDU1PWYA2ZZyM7qM20oduLo+7KnZU+T4mKnaUMs/tNjsfS3 z0mxaUP/BxjPmjsKAJEQcM1APUOORXInLlS2SApaiqB7URHihL96gsNsQ32mhyjaDOMO ce4ZTaGu2hE1WstiyjUuK+tRmC3yJlRaj+Ubu7WTcaawvNbl6P4Md+tG18Cfb09pGk7h 3drPQMqUJnrUVkKkaYTvkDZLN4661eRqlea3Q55TlF2m4C0JKEvQSDqHEnEDr6lzhhz1 mIBvk1mzwqCoqTtOyLb6MIluCkOZrQ/fUZn778PsLMnU2sqwfxSyszAhw4lcTpajHHsu l2zF0e3onrG421HuaEVjYt1yjBkt3fW5iGBtHeIEd2OPgfrkUbalvn4ytpMrtYNVsHh3 PbawbLgFjOWk3CEslJeFmynjqambUxfqKksOBcrqcRbQfM/V1IXOoeXW12Op/FFNUeP1 baZhncejzvkZmF8QawXfXbqwifrubqnN2jqXM3Suuzu5W1pvMTlMYGxCYDghDFIRCfIw 6arBuhi5nMnyHDhdTlSrXsJ0Apr0iEXhO/tXI1w4qjfWnITaFsoIF31NCPvuBOHJd4Rw 8aimtyHsR52LJYSn/PsQnnobwiVfjXBgVG9UchpqG5ARLv2aEJ5+JwiX3RHCwVFNb0O4 HHUOSghX/PsQrrwN4RlfjfDMUb1RyVmo7UwZ4dlfE8JVd4Jw9R0hfNeoprchXIM63yUh POffh/Dc2xCu/WqE7x7VG5W8B7W9W0Z43teE8Pw7QbjujhCuH9X0NoQXoM71EsL3jiIc SA7BrX64a4zbha/dMS+8BXJ8U+L0UEp9AOxamItUhFRJLsBGPGB3YbwF5Y1IxfQw8iCX NWKswjOaHquP3Puo8TRyGmUH1EnH8P/nH5X7Z/AsGPtxGPF4awV4klDISUo8F6mRiwON LE/AE0WELKMT8BzwNr3B1DAXWQ373/hu/yv+UTwolCJCl/HMymArJbH7KDEXXxqQRC1e sF1GkmTkmffDwCIB8sL7iIrU77zM09gKh3FefoHOqfMilbLbwoN/4M5+MT3MVt3Euw1s fW70ffmUEY/nRz/8NlCUkUeUWlWy2uotqNS2KZZpBZ+oVyuY5PFCqsKmVduKM2lOevGp Ylo8PsOt1wqcaPWOM1rDpDvgMtrsgteWo6K2iSq/4PdbE4X0jIOplqnJ6daZ8d4i85Sp Pya78XDVR3YB3mFU36gauDFQrf1b1bWhfr0vF0pKBqRnQO/T6Y2+Bp3elzOQM0Aw1hl9 +XnTOwNphZMM44CY3aQw3gmmlGQnJDkSncQ5DiZRJ1hsRicxODHAO7tMovVLdwSPPPII NJCG1KSC8ZMKpxANiSe8wBtI4aTCiRM8rnECL7imkoLxeEzRJWIh7EJDXOO8Hq8UeSZO KJyUQDRrqu+v3+VsHb+iOb+W9E41qB97+Mlip/Ig9/eXznasM7rVKbqMLE9DRpJi0hvf 2nn29O7uNxdkzdi/3WDlNXHW3KVkuZhlyl5YOzuj9vW9lZV7hnZbxzHMJjVf6gpULvvR 4ztfTiDX8EYJiqJXmQHuNbQYGzwYGD9JU6GZrznAHkrm3GIijbdpQbTZhAQltRlVXE5C jjZdp7fYVV6LOcW+2bmmdBhYhNVfNXTtGiCi+Kfz6WIIWkxWhRIIMak8oLBiAGbqAWWy 6CGI2DBaegkGGRzeAMYko65A55oooQETJ+gL/vbMvvX79j/8+CHSXZs35eiLJT9YeSLy xfXfkfs/eefSz35y+ad00oSUWdT2xdSdi+pI9hefkvloa5XRq6wFT7RWvP1wE3Wgc7f4 nOWAneE0NJ5LNGj08YbEgDqQKKZbyCzVSeYCeZ25kPyu+J7iiv1d1yfGT1yqC7oLerpQ 5Jyp8c8n2VJ9vCAkOW1WQWlLUrmF3dYD1lPWd6ysOynebeXMSrWg03jjbV7O4k3NEbxm s8f7K+f+hhhAQ9ckwxv41ZBP70Nz82GU2xCzQOT8Q37tAKbKRlcOLpZj8LqAcCxv9+i0 em2CNlHL8mr3uORUD3ohm4ek2BRGwQMqg8ZD4jQuixOTOAxEk9IDcVoMJJOM2aRslxmZ GY+Q1Q2wuqEBkhDjJIMzBa1wUuGkAg1Bm+QRbZ0WCojHi0bKC4T2Xikq1GsHr3NP737y 7rzE48Jd+XM7p829GPmUmP5A7Kq0mUe/dZAjLrbigXvmLJ/54kvnGworirfn1Fi1xIV3 JpSURjzryh890U2kS3e0tY3oUouH/UxhwCp8xKI75Rmlwmi0YPl0gQGzqDjsbI5Zlb+q f8jfXx1sKfsYkfKXVA3k5yWgaegKDK6Np/DHZty8wp39ObZNoAsdzOfYtgoOBBbXUzJZ JGaKAzPy87mlXCf/kLCZ62MuMVcZJcfxeHmrYOhG+ix9mTLUp1coWA4vCvgVekHAPLwy 4HiFyFGWUaJvZHilwCt5S5yCKtNBZVbH9Tib+0hSzKug3fv95mrtxyYo8ftRT8mbEKTN VTmZ4nrtq+zmHFNmA7dee04r+kV/fh6RpmENDoUUKBAqQefqOkre+DiyhBz/ONKz+yh3 dvAIuRBZOdRMrd2Rb8jj24KDnCJjlx4w4FiVHIKGmAFjZrlbIBvyjwAWA2tLb6/khEfw ZwZwTZjBAvcF8k/xF3jK8om8N7GDbxe4RDVNNGltnAC8SaW0CBYLqNMVFivJMaWbwZyM bpc/8eXkDJt0zJP6cdXrfDhstGHJ/SUUGEacnEs3QTIptDENMehcZOOR2Ydbr9VknbLl bQikzyzKTu4lB9jcPffN/d78F4fm0Jea/Yvjkkonrm4behOVxbVcHH2PdbLVuKeZUPen AwV7xF3a55K+zx4U92sPJYXFi+I77Eea/0pUTxZ5m0lQ2/Qqs2A2G6g33pKs8BrMluQw UZxwrhlejfIugH5/eA+Ql10WGFmPKkGBK0dHPUQwIsfFIadMVHuAaDEQk3gPYTQYyGtL CjLR2afqJ8oj5A3oz/W4iijuDxNxLQn0g015s09/f9eul/ACdzDy999GBon+T3w7id+/ 675nB3uOXGOuRv4cuREZivyQZA7iZhHg0JZxrukzbAXo4K6Ax8t44iYxFSyrEbVUo9Ap 1F5RmiKdUrQkEMkfg1mfECZBnJoNsrORHDGaI66ZqpL+oX7J20ibmjQxw9OSZDTkoHvl cTq2HDG8/ABnsmmTtY8/08vm9hXupcwrDD22ZmiPtGZLo+8wJ9lZePucS3ICTxUp9nC7 9M8l7jHsyeDTUt3eQme5syK1wjsvdb53SepST6e6M65T0+FqT213t3v2pxzMSmDQTXHZ bE4CWAzJRqvJkJ2YkxavahM97kI3dY+LU7KZCabXrbYEgbXlPJ+pyhUUGi0VINeZa7Gb kkxe49Q0j+BNs+Rr7F7tVPDmmPPye0Z968CNIZ/kXYd8WuSk4fpyMURzlBystMNLK3K1 PMuzSTb1GNwWj1Njd4ICP+sQJgvfEbgM5Gx6TEtONDmJI36cE5zjNHGiV+kkHrdCSbJZ J37LwyBFZ3UScxIGsovV+tG/yoFsFSNGIa0B9LLyxub15EpuFbd2adsXXDEXa0g0JtmJ 5IkT0fl6vOS66C47uHjPFO/ap7ZMa/9N318fmE4Pc56pzy1pC6ZVP/haadt7v7t+QSCn SM2CvPnz7w2m4q40LmPGI3t+vG1B65TxFdWB8gxzgi03K/jsU5ffe4H+A23JGL1OFdwC XDlzfxSXozynIWFSEnCzST4jw2uUOgu6EbzhTgeDxhDP2BnKDCaZzZZB59L1wztXg69f 3qBifiUXPTE6vAHt0DXZwaAv1uFARt9jPBNx7y44ePLIEY8hPy4l0T7du2HB9u3cgsiv dwwFixJUhG5TiI8sped3yH5NhQv8UzYX0P8HckrJeUJhKbTSVmYpv5l9nDsAB6mIXwFo kJ3JfZvdwl1gL3LijLS1aYIoL+mlks3jZ6dwdFUvbpgONkweO8UwK/SUUPwW91gghUev js6T41mGEI4yPAPo6pWiNPBj9DSRdqWNJ8gx3myuvmGqGvrggyGzPFbJn5cY/Xp59eh9 ArpzbfW1KiEWZc6a0xlw03Q9w7CQrud53K9vaxw3j2O4mkfb9fmGfL4xLXOCNhP/cEvA rblhdYKCFOCG8D5JIZnnI8vPRdaxuYN7mNabbyFCRDqTcPuQUxNHYEMFe1iBUJJyYYZq M9MtblL+lPYzrwuXxNeVl1SqJcIysUXZpuoQOsUOZadqk9CtUkplaQXzIDzEMfPTktLw DYwtJsXsU+QpllewhFFR3PjUHPCiUsUISg1iJHD8XpFh+5VU0a8CsldtjpMwxw1PAkse VCwcHZpRRg3fqCWE1BxiI+DXHL1areI2azPxD6erV4F388ow2RpI0BNCBZ7lpIK8oBAV SpzZrQGNnmUZlRqHLVcl0m66Wbu+38RJ2ynuq+dlZvN6bf9oirS1rl69GnfXZFqQLGGp QjjfeeOtn779m97IpTNXf3km8jOEtJeZPdjHVNx8i5ky+BMEFP2c/Iu24Hekf/aLx0QG yuTvUbPxS81d+D1M+uo0D+ZDPSzAXGl2YmdDHv93AGYGZ9XVT8usbFne0dLetqhJLjHS chkyNUiNSKuQupCeRnoBKYR0Duky0gdIf5GaRtIiOaLDP0yAUZ6AY4ws9XZr/uIxsjzG W+q3jcl/YIwsfYO5tT3pjeRWeeUYec0Yee0YWf5fjFv67xiT/6Ak/x8hitYYCmVuZHN0 cmVhbQplbmRvYmoKNDAgMCBvYmoKNTU0OAplbmRvYmoKNDEgMCBvYmoKPDwgL1R5cGUg L0ZvbnREZXNjcmlwdG9yIC9Bc2NlbnQgNzcwIC9DYXBIZWlnaHQgNzE3IC9EZXNjZW50 IC0yMzAgL0ZsYWdzIDMyCi9Gb250QkJveCBbLTk1MSAtNDgxIDE0NDUgMTEyMl0gL0Zv bnROYW1lIC9KRUtYWUErSGVsdmV0aWNhIC9JdGFsaWNBbmdsZSAwCi9TdGVtViAwIC9N YXhXaWR0aCAxNTAwIC9YSGVpZ2h0IDYzNyAvRm9udEZpbGUyIDM5IDAgUiA+PgplbmRv YmoKNDIgMCBvYmoKWyAyNzggMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAw IDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMAowIDAgMCAwIDAgMCAwIDAg MCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCA1NTYgMCAw IDU1NiA1NTYKMCAwIDAgMjIyIDAgNTAwIDIyMiAwIDU1NiA1NTYgMCAwIDMzMyA1MDAg Mjc4IDAgNTAwIDcyMiBdCmVuZG9iagoxNyAwIG9iago8PCAvVHlwZSAvRm9udCAvU3Vi dHlwZSAvVHJ1ZVR5cGUgL0Jhc2VGb250IC9KRUtYWUErSGVsdmV0aWNhIC9Gb250RGVz Y3JpcHRvcgo0MSAwIFIgL1dpZHRocyA0MiAwIFIgL0ZpcnN0Q2hhciAzMiAvTGFzdENo YXIgMTE5IC9FbmNvZGluZyAvTWFjUm9tYW5FbmNvZGluZwo+PgplbmRvYmoKNDMgMCBv YmoKKE1hYyBPUyBYIDEwLjYuNSBRdWFydHogUERGQ29udGV4dCkKZW5kb2JqCjQ0IDAg b2JqCihEOjIwMTAxMTE2MTkwNDU4WjAwJzAwJykKZW5kb2JqCjEgMCBvYmoKPDwgL1By b2R1Y2VyIDQzIDAgUiAvQ3JlYXRpb25EYXRlIDQ0IDAgUiAvTW9kRGF0ZSA0NCAwIFIg Pj4KZW5kb2JqCnhyZWYKMCA0NQowMDAwMDAwMDAwIDY1NTM1IGYgCjAwMDAwMzY1MDIg MDAwMDAgbiAKMDAwMDAyMzkyMCAwMDAwMCBuIAowMDAwMDAyMDA2IDAwMDAwIG4gCjAw MDAwMjM3NTcgMDAwMDAgbiAKMDAwMDAwMDAyMiAwMDAwMCBuIAowMDAwMDAxOTg2IDAw MDAwIG4gCjAwMDAwMDIxMjAgMDAwMDAgbiAKMDAwMDAxNzYwMSAwMDAwMCBuIAowMDAw MDAyMzE4IDAwMDAwIG4gCjAwMDAwMDI5MTkgMDAwMDAgbiAKMDAwMDAwMjkzOSAwMDAw MCBuIAowMDAwMDAzNTQxIDAwMDAwIG4gCjAwMDAwMDM1NjEgMDAwMDAgbiAKMDAwMDAw NDE2MyAwMDAwMCBuIAowMDAwMDE2NzA0IDAwMDAwIG4gCjAwMDAwMjk5NDUgMDAwMDAg biAKMDAwMDAzNjIzMyAwMDAwMCBuIAowMDAwMDIzNzIwIDAwMDAwIG4gCjAwMDAwMDQx ODMgMDAwMDAgbiAKMDAwMDAwODE1MSAwMDAwMCBuIAowMDAwMDA4MTcyIDAwMDAwIG4g CjAwMDAwMTIxOTcgMDAwMDAgbiAKMDAwMDAxMjIxOCAwMDAwMCBuIAowMDAwMDE1ODU1 IDAwMDAwIG4gCjAwMDAwMTU4NzYgMDAwMDAgbiAKMDAwMDAxNjY4NCAwMDAwMCBuIAow MDAwMDE2NzQxIDAwMDAwIG4gCjAwMDAwMTc1ODEgMDAwMDAgbiAKMDAwMDAxNzYzNyAw MDAwMCBuIAowMDAwMDIzNjk5IDAwMDAwIG4gCjAwMDAwMjM4NDAgMDAwMDAgbiAKMDAw MDAyNDA4OCAwMDAwMCBuIAowMDAwMDIzOTY4IDAwMDAwIG4gCjAwMDAwMjQwNjYgMDAw MDAgbiAKMDAwMDAyNDE4NiAwMDAwMCBuIAowMDAwMDI5NTk3IDAwMDAwIG4gCjAwMDAw Mjk2MTggMDAwMDAgbiAKMDAwMDAyOTg0OSAwMDAwMCBuIAowMDAwMDMwMTI1IDAwMDAw IG4gCjAwMDAwMzU3NjMgMDAwMDAgbiAKMDAwMDAzNTc4NCAwMDAwMCBuIAowMDAwMDM2 MDA5IDAwMDAwIG4gCjAwMDAwMzY0MDggMDAwMDAgbiAKMDAwMDAzNjQ2MCAwMDAwMCBu IAp0cmFpbGVyCjw8IC9TaXplIDQ1IC9Sb290IDMxIDAgUiAvSW5mbyAxIDAgUiAvSUQg WyA8Yzc5YThlMDM5MDk1ZjA2MTk1NWVkZGZiM2YxMTc0MjE+CjxjNzlhOGUwMzkwOTVm MDYxOTU1ZWRkZmIzZjExNzQyMT4gXSA+PgpzdGFydHhyZWYKMzY1NzcKJSVFT0YKMSAw IG9iago8PC9BdXRob3IgKFN0ZXZlIFBvd2VsbCkvQ3JlYXRpb25EYXRlIChEOjIwMTAx MTE2MTgyNjAwWikvQ3JlYXRvciAoT21uaUdyYWZmbGUgNS4yLjMpL01vZERhdGUgKEQ6 MjAxMDExMTYxOTA0MDBaKS9Qcm9kdWNlciA0MyAwIFIgL1RpdGxlICh3b3JrdHJhbnNp dGlvbi5ncmFmZmxlKT4+CmVuZG9iagp4cmVmCjEgMQowMDAwMDM3NjM1IDAwMDAwIG4g CnRyYWlsZXIKPDwvSUQgWzxjNzlhOGUwMzkwOTVmMDYxOTU1ZWRkZmIzZjExNzQyMT4g PGM3OWE4ZTAzOTA5NWYwNjE5NTVlZGRmYjNmMTE3NDIxPl0gL0luZm8gMSAwIFIgL1By ZXYgMzY1NzcgL1Jvb3QgMzEgMCBSIC9TaXplIDQ1Pj4Kc3RhcnR4cmVmCjM3ODE0CiUl RU9GCg== QuickLookThumbnail TU0AKgAAEKiAP+BP8AQWDQeEQmFQuGQ2HQ+IRGJROKRWLReMRmNRuOR2PRmBwSPyOSSW TSeUSmVSuWSqQyZ/TEATF/ACBzaBS2WAGeACeAEAAKhUGhzqjUeMP2lTiCTeb0iTz+fT 2hAKiVaFy+NTQAM+vABmWEABayAB+WeoUYB2sAOW3AAr3EABW6VOgWm8SulP0ANe/ABh YEABfCTOZXmVvrFABtY0AGHIAAP5O7UyRRl75kAKTOY/IgTQYi0uzSABXacAF3VAAE63 Ra+Ozd8bMAKPbAAwbkAAbebCjvXgabUFbiAAD8fLReuO/mABV88AGjpb7RI/rZ4wgAHd ur9TvRG9gB4eMAKjzAA1+nv3hI+0AF/4AAH/PkxazvwAOf9cJXAA3v+9a0kJAYADLAwA ApBIALWAcAwchJ9wi/L9lVCoADpDEHqOQ8OOwua6q0isIn2AByRMABXxSAA5RYhJ8HeA EYAiAAIgRDSOj/HMCwOwgLgAAsgIYfh5xge4ExmAp7yK1kaAaAgAGwXBYAAewbioAAXA S/ACRssy0IK/B3HcgoLAlJ53nYc4AHuBgMgBM0ngQBEnqgxR9RLE8KlUAA8T6jLaH5OQ ATpG6FkFQ4ADFRQAAxRr6xFCRx0lFEVDnSyEHeZxTAAWh3hGuZ3nSsYbBiAB6mgZMYgY FgABqCBwAAZZ9U+CJvGLUwWiXLB9maABjHIBYAB3VwAGiaMSBECJ1SgfQSgAF4DG3WJ6 hAAAfg8dYAF2aCCiSKAexpQiFD7cgADNc9GUdIACxcbAAEkRZZTID4AAYeJ4O0EV6A0B k7nMdBzAADglDQAAPG/eRWF0aKCg6FIABIBIDKCB6CgQAeAmwAQWgAeRaF6AAiD8PwAB lGa0zsAFJHGAE9AAPOYIk/BsGHKZVluegACoLIMAAZJpxmKgiAUABiGcfAAAyA01HCfQ GN2fV2BmH03GOXhuAAFQiBe/JhVufYTa4cRMleAAcEWOwABRcSIkDt1E0WDO5UeimU5X SmywwOlMGGRQAEUZ0bBOEIHWKY56oKBQOgAIIAF+ABvnudgAAaGQYLaA1SgOVZgLNBQQ BRpAIA0A4AG2BYjJ8T481iAATSwBxmAAW4DC8ABCBrhg0E2BIAFKWZDAAFunoZcg+x2M t0563mJoQfBugAUBNF43YQBIAGiAsAAhhzwprGUZa+nGcu1CuN+zH4Yd3ld6AAHznohB NnJsZzdOJgUD/LnqZ5lVMEIQwABIBaycpA+YDMqUmy4PUCyIjvF8AAM4ix0AACWCZpAz ReuTB+FVGw3R5okHsBl1IARUpTAOBwe77gLOvBSCRiYlAiBbAADMWQumDD/QaPIWrDAQ g5cWDMMCVwNEWbcIFuAYmktzRC3Uxbd0Ut5QyQceg2IHi7HEsEFoLGKjWGSwwVYgBaKt DuGZ7YElRADBwDoAAzhJiUAAPMGoXAAAlG0Jt24nXJh4E+HEAAIgTAuY6LgSwABeD6kA D0Aw0pCDmWqFAHidxXi0ZyFoOwYGIJdIW8Z5Dyjdm9SE0gfiXFBpCAAbQACcm2ENPwPR pC9U5oBGhLFPA5EfpBGbLcAECw9ESRgLgTMdhpAHBoAAI4EhqAAFSNGIYZgrAiLMBtZw 4hfPhAWv0AA+gIIzAWPpGAwxkqwBaECNQEAGMVf29ABwDGcgHCAE5tUmCJRFiPElN0Sy Jt2UnE9C8USJj8YCM4a67AZAtAqRQcw04HjMHXQUIwQmOTwJaEiiQAAaUVXqAxp6DCmP ugPRp5kp1BHbcKBOkj2AFNEUKRllKYkxjhpcl4/AfKZUpJZPJRUSG5T1KeRWfDLJ9N6p oSuTSBnkqNeXJ4hTKTZtIHtU0AA6qoAAHNVM1hrgZVXcoA0BtQSHjdq8ABEdG59S6q4S mmzcYlU7IgLKthCDSOTpZPtvdZST1DQPUaTrzSPImloZwUgAAyWBQQgquhC4DD5gQyyB UDLCklrPTitJOSFDpsor4YwxqN2HAAMizjAgOAcAAHW0VjSSyaXPGSvC6yTjotYACW6v QhWxqq720k14mqTFTbmXNjLakesfPRug67hAAF7cWCgS1dVTYCBC5kpTaG2FGAAOF06L vEt6RUat2TnHQqIWMstqiVXZGqYYmoLbzW9ZTcoAAob2AADbe9N4EgJXXItV56F0FzLo LI9qJYv7/AABTgGThBzw2UVEYEYQABg4LWeC9rhXCblcKrYUqR4RxYXAAEnDTwrz3yvn RolVTR7AAF9iUAASsUHdrofep9UbL2YF1jEAAMMaEIJvWErhx3S00KkQfC44nGBBcbVc GQAKSATbpWxeQTsmEMK4PPKFiTGGOvUPTK1Gxt5ZjmCVZxKhs5fjflED2Y0P0Fx6Q6jR 82KgdzYxAEj16c3VMqTqzgyLPWgs/aCumT8ot3G5n+Wapjg4iAAODQwAAR6JlquymmE6 RAAzY4vN71wN6VzlEsXmmWQhECIRCzWUB5gAHbqM8R5LNHhzqAAHWqyV6ExefI+gItZZ GpKQ/CdJ2iXMAhfG+dGGn3gKQY0bVzmkAu2Nb3T+Ua4njXwZmFNr87mDMLXTCZrXe661 5Vmrdqoli028AAJm4SIY3QlWGsOLLWQTG/utswOAcFGGnvEAFwlso9AACvfBDCpYTo1a q1RoEn5nKPqMdoAN4jTAAEDhVvdyIk3OWganEQADx4oq0GoNcKE9KlwDRdeVBmhIPf2/ +AWH14IvWorpX9cAABPy0tJXMEWDAoAAFnNSKcCOoynGMNtwhMvoQ2uOr9Oadx1z8hHO Cs1q3oACWK3Oh5zItukAArOqHROnxwxFYcFjBYNmQE3X+jT6Cj2Po2BCl3FZBzVVgGu2 dlI1PYgwyu5AAGt3UuBctrEMvTVQZ3fVrA/B/rTJB66lgAGB4drIKgVddA9b0Wvj7jq6 7csVY1YEJUVmH5MjfcCE8HchuzD1IEbHAcQPL020kfaT2zTT0nhvEAz9hgOsvjxa+R6N 0ssLsgi+74/KnzRFYlj4HUu4WgyESBMB7aAAQDyajPGSN+U4EkZgdAqjMBoCatj5HxYg BgEWnj4lZKcBlEENbMaKMQYgAAc/r8FUH2ntra4sF3/OilFi6UF9+bEgcU4Hi+HMTuHW GoHCLaHgVEAsBgCO4SA2aIAGAC4KGuHUHkmuHSn+GyyABYCMdSHkHYyQDQCoY4ro6W7k f6B7BKO0O4Q0FtBUxOxStq9y46wca4/yJGJCHwG4geFoGsTGHSHGHiS8RIA2BkB25o12 ewA4Z6F8EEE+hmDEmcFuF8cmBiB4gA5aWcA8ustILcfIWMYY4UCApMpQO+/euQ8krKP0 TU3iV6B2B+CSAAAWAOQalKZyHoPwUGAQaelfBm3GrUH4lMUEudDs/IIc8KTlEEKgaQGm GGfCAKBGvmFyE42GCSCiiGHoAUmcAUoO8MF2GeZCD8DmQWHG+gyyWk8A8C6KN8FvFSwy w2pos0FuFcFALaGmXcBcDSDqR+G2yAAcAIloHIAOoKAIAK8WB0BCxGHWHohS0MRIA4Ag cQHoAucuBaAtEMsK85D0lKawFMEyP6H0BbCGAYHLAkAYH6WkkUBWLGHiRIA+AqZyBOC0 iEIMGxHkLaLfFK96NFBUFtBYCUqC1SHQGi2GBGBU12HCHM+gGMGzB8AwA0XoBCA2WCHq HiZyHEHiZ6BYHiFyaK5Y5YAWRsB2DOksBI98tJGtGum6FYFiAAHSAuBuMGHYVgHeH6cQ acZ7GYZ6BEAMcmHwBU3eA8/I6azC1CB3KGxUKRHzH2Rux+dMy0BaAgRIFcGITGB4CcBQ AAGkGCG85YBcTcUGd6AeAkXYGsHKyQBwAKkUFsGwYmBSA+12BMB2yKgI5/JLGuLTBGo2 BvLwLSFxL2gComPW2cuIuMB9MHBOcLLoJXLnMOKOJuGLMbDcAWWCBjMkKNL2FxL6CQQC GHM09Qdc7BMUJbMTM+KQPC5i3s8U8WJVMrMuOovsylC9NFMW5RNgNgZS8Oc60SU/NwJO FzN4mICPASMQysZzNsyCcbMgWDNnNBNlOSN9MBOI7U0gzaI+52ABAydSMQv8ceBBO2AA BDO9OZNislPAQc1AMAME8xM4I3OpOsLSy+Gy3muGB5PlPGKhNDPoNeOYRhMaVu1WjU9C InFHKWWk0qA2wbBkJLMBPdHofICHQa9FPvPCMvQgRuqgWWGXQuABMGB820Igz+axBev2 AAtiCEJPQU7qGsAAPCCpRXQnPrOXRaLyKcJyK4r4AA4imPHs7yIWZSFFR67+8Cy4y6JL NUwM4S4XO2Wqwm6RRgI/PtSYJSxZHkXdBezUvI1KXw4pB8zG8aIePCxAJSbu/utmQWLY 4IAAClTQ1gYqwnSe7fRfTaJQPCriPaEiT4T9SW9+6kGTT2AACnT849TxTgIbSdUEI6s0 6WGPUSAACrUZPGvw57TVKLULD3PFUmJKJu0IbvC47uCvPGE3U+3A3FTE6xUsIfUJVKIo JvOEAAG9VaShHmLjU7PAExVpKQzi2BVQIZVPVyIjVUyvQ8ABQUCxWGI0lWHeTGH2AKYm H2HsRsLKxahSAkAsRmH4He4QE0EWW4CqD8CyLmTWLMAQq3GoIqEvXLVsbmo/V5V1TfXU IsJu9NAlNa2EABWGCwIyHozsCeB0FSAACsDAcQE4FmhSDiECCgAAE6B+SuB6FRFiHcHS laGqxGBCA4RIHuAOYqCWDkDO0RJGIqEtY/KQ7YiHXTXaITV3ZLXWIJXgABXkMdXrXuzs EEE6YmCiAqjCEoGWRsCcB2dKFQFGgeByDMC6RKGKGc1EHaXoDoCuXcDOGZaGF8DsyKI/ Y+kGxRH5ZE49ZQxtXZa1V6JzZXZa2HZeJMNmPwlQIoG6FkEyAAHCBoDHREA1Y6IvapZC 7bZJa6bpbw+Ba+9PbDXpWJPBbpasABaxbva7ZPbxUyUnOOxaWXXnbHOZcExTcKqRbxcR XarCvEQmTVNarebUBRKrchOTXKEvXOTdcNa1cvVKrDR6FE0Q0VTM2wxZQUDddrPGEzdx NWzjdRZRdVTg5gMFS2j61mJu9bLtQufCveDbDBMUpdAGEregABdqDdM5VxcPa5XariK9 E5QagAIXMAvUxKgfc0IOxYxZSy/a0aKHELUjKHCGvMY42xS/ctexXU3W+hfQxocuIWrD fQ6lC0RiOas1TNPzdeU+po445WrxQIzLTHUDXVd9TbecAArjMkVK6SIIZS9a9a0IxZQC 45SQqC444419Q46LVJb0INgjSerjU2yEcaImPCxYPCIO5i3xHOyOsK34LYo1TZhSIVhX UE7Q8S8WziI2/M/mF3TPTTh8q5gfh/UHfrZRRrSlR+47hiKWFbi0hm9jN1ihOTiDUtfu AAFPjLUXUbawwnVWvUvVgY2MkBi/PHjDTa/AaRDuRs1GVEuyawMyZyJvcY3szzeZjjQh jnPuZyoQFYRQG1KqC+BsRIHaAnQKVsVgBeBaTcAeBKcW+E1CHiHCawASBY4wH4GyW4Ac Bo3fbjkJNnkNPAHUGRkUGyA0cuHeFy64GQHQcQAwAeWCAeAocWBuBOYmFyF6YYBIBg12 GKGgXwAuA4VYBkA7QLBLKrlXjBilUsHoawrY/SHoAwY4A6HdPeHqA6cuAsH+RIAwBFQK HEGEkUBOCZKqGGFQc6AiB5RIBGAc12A1GnmrOSICAAAPAQAAAwAAAAEAZQAAAQEAAwAA AAEAQAAAAQIAAwAAAAQAABFiAQMAAwAAAAEABQAAAQYAAwAAAAEAAgAAAREABAAAAAEA AAAIARIAAwAAAAEAAQAAARUAAwAAAAEABAAAARYAAwAAAAEAQAAAARcABAAAAAEAABCf ARwAAwAAAAEAAQAAAT0AAwAAAAEAAgAAAVIAAwAAAAEAAQAAAVMAAwAAAAQAABFqh3MA BwAAGewAABFyAAAAAAAIAAgACAAIAAEAAQABAAEAABnsYXBwbAIQAABtbnRyUkdCIFhZ WiAH2gALABAAEAAQAAxhY3NwQVBQTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9tYA AQAAAADTLWFwcGwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAABFkZXNjAAABUAAAAGJkc2NtAAABtAAAAkJjcHJ0AAAD+AAAANB3dHB0AAAE yAAAABRyWFlaAAAE3AAAABRnWFlaAAAE8AAAABRiWFlaAAAFBAAAABRyVFJDAAAFGAAA CAxhYXJnAAANJAAAACB2Y2d0AAANRAAABhJuZGluAAATWAAABj5jaGFkAAAZmAAAACxt bW9kAAAZxAAAAChiVFJDAAAFGAAACAxnVFJDAAAFGAAACAxhYWJnAAANJAAAACBhYWdn AAANJAAAACBkZXNjAAAAAAAAAAhEaXNwbGF5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAbWx1YwAAAAAAAAASAAAADG5sTkwAAAAWAAAA6GRhREsAAAAcAAAA/nBsUEwA AAASAAABGmVuVVMAAAASAAABLG5iTk8AAAASAAABPmZyRlIAAAAWAAABUHB0QlIAAAAY AAABZnB0UFQAAAAWAAABfnpoQ04AAAAMAAABlGVzRVMAAAASAAABoGphSlAAAAAOAAAB snJ1UlUAAAAkAAABwHN2U0UAAAAQAAAB5HpoVFcAAAAOAAAB9GRlREUAAAAQAAACAmZp RkkAAAAQAAACEml0SVQAAAAUAAACImtvS1IAAAAMAAACNgBLAGwAZQB1AHIAZQBuAC0A TABDAEQATABDAEQALQBmAGEAcgB2AGUAcwBrAOYAcgBtAEsAbwBsAG8AcgAgAEwAQwBE AEMAbwBsAG8AcgAgAEwAQwBEAEYAYQByAGcAZQAtAEwAQwBEAEwAQwBEACAAYwBvAHUA bABlAHUAcgBMAEMARAAgAEMAbwBsAG8AcgBpAGQAbwBMAEMARAAgAGEAIABDAG8AcgBl AHNfaYJyACAATABDAEQATABDAEQAIABjAG8AbABvAHIwqzDpMPwAIABMAEMARAQmBDIE NQRCBD0EPgQ5ACAEFgQaAC0ENAQ4BEEEPwQ7BDUEOQBGAOQAcgBnAC0ATABDAERfaYJy bbJmdphveTpWaABGAGEAcgBiAC0ATABDAEQAVgDkAHIAaQAtAEwAQwBEAEwAQwBEACAA YwBvAGwAbwByAGnO7LfsACAATABDAEQAAHRleHQAAAAAQ29weXJpZ2h0IEFwcGxlLCBJ bmMuLCAyMDEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABYWVogAAAAAAAA81IAAQAAAAEWz1hZ WiAAAAAAAABtgwAAOZQAAAJbWFlaIAAAAAAAAGPgAAC38QAACeZYWVogAAAAAAAAJXMA AA58AADG62N1cnYAAAAAAAAEAAAAAAUACgAPABQAGQAeACMAKAAtADIANgA7AEAARQBK AE8AVABZAF4AYwBoAG0AcgB3AHwAgQCGAIsAkACVAJoAnwCjAKgArQCyALcAvADBAMYA ywDQANUA2wDgAOUA6wDwAPYA+wEBAQcBDQETARkBHwElASsBMgE4AT4BRQFMAVIBWQFg AWcBbgF1AXwBgwGLAZIBmgGhAakBsQG5AcEByQHRAdkB4QHpAfIB+gIDAgwCFAIdAiYC LwI4AkECSwJUAl0CZwJxAnoChAKOApgCogKsArYCwQLLAtUC4ALrAvUDAAMLAxYDIQMt AzgDQwNPA1oDZgNyA34DigOWA6IDrgO6A8cD0wPgA+wD+QQGBBMEIAQtBDsESARVBGME cQR+BIwEmgSoBLYExATTBOEE8AT+BQ0FHAUrBToFSQVYBWcFdwWGBZYFpgW1BcUF1QXl BfYGBgYWBicGNwZIBlkGagZ7BowGnQavBsAG0QbjBvUHBwcZBysHPQdPB2EHdAeGB5kH rAe/B9IH5Qf4CAsIHwgyCEYIWghuCIIIlgiqCL4I0gjnCPsJEAklCToJTwlkCXkJjwmk CboJzwnlCfsKEQonCj0KVApqCoEKmAquCsUK3ArzCwsLIgs5C1ELaQuAC5gLsAvIC+EL +QwSDCoMQwxcDHUMjgynDMAM2QzzDQ0NJg1ADVoNdA2ODakNww3eDfgOEw4uDkkOZA5/ DpsOtg7SDu4PCQ8lD0EPXg96D5YPsw/PD+wQCRAmEEMQYRB+EJsQuRDXEPURExExEU8R bRGMEaoRyRHoEgcSJhJFEmQShBKjEsMS4xMDEyMTQxNjE4MTpBPFE+UUBhQnFEkUahSL FK0UzhTwFRIVNBVWFXgVmxW9FeAWAxYmFkkWbBaPFrIW1hb6Fx0XQRdlF4kXrhfSF/cY GxhAGGUYihivGNUY+hkgGUUZaxmRGbcZ3RoEGioaURp3Gp4axRrsGxQbOxtjG4obshva HAIcKhxSHHscoxzMHPUdHh1HHXAdmR3DHeweFh5AHmoelB6+HukfEx8+H2kflB+/H+og FSBBIGwgmCDEIPAhHCFIIXUhoSHOIfsiJyJVIoIiryLdIwojOCNmI5QjwiPwJB8kTSR8 JKsk2iUJJTglaCWXJccl9yYnJlcmhya3JugnGCdJJ3onqyfcKA0oPyhxKKIo1CkGKTgp aymdKdAqAio1KmgqmyrPKwIrNitpK50r0SwFLDksbiyiLNctDC1BLXYtqy3hLhYuTC6C Lrcu7i8kL1ovkS/HL/4wNTBsMKQw2zESMUoxgjG6MfIyKjJjMpsy1DMNM0YzfzO4M/E0 KzRlNJ402DUTNU01hzXCNf02NzZyNq426TckN2A3nDfXOBQ4UDiMOMg5BTlCOX85vDn5 OjY6dDqyOu87LTtrO6o76DwnPGU8pDzjPSI9YT2hPeA+ID5gPqA+4D8hP2E/oj/iQCNA ZECmQOdBKUFqQaxB7kIwQnJCtUL3QzpDfUPARANER0SKRM5FEkVVRZpF3kYiRmdGq0bw RzVHe0fASAVIS0iRSNdJHUljSalJ8Eo3Sn1KxEsMS1NLmkviTCpMcky6TQJNSk2TTdxO JU5uTrdPAE9JT5NP3VAnUHFQu1EGUVBRm1HmUjFSfFLHUxNTX1OqU/ZUQlSPVNtVKFV1 VcJWD1ZcVqlW91dEV5JX4FgvWH1Yy1kaWWlZuFoHWlZaplr1W0VblVvlXDVchlzWXSdd eF3JXhpebF69Xw9fYV+zYAVgV2CqYPxhT2GiYfViSWKcYvBjQ2OXY+tkQGSUZOllPWWS ZedmPWaSZuhnPWeTZ+loP2iWaOxpQ2maafFqSGqfavdrT2una/9sV2yvbQhtYG25bhJu a27Ebx5veG/RcCtwhnDgcTpxlXHwcktypnMBc11zuHQUdHB0zHUodYV14XY+dpt2+HdW d7N4EXhueMx5KnmJeed6RnqlewR7Y3vCfCF8gXzhfUF9oX4BfmJ+wn8jf4R/5YBHgKiB CoFrgc2CMIKSgvSDV4O6hB2EgITjhUeFq4YOhnKG14c7h5+IBIhpiM6JM4mZif6KZIrK izCLlov8jGOMyo0xjZiN/45mjs6PNo+ekAaQbpDWkT+RqJIRknqS45NNk7aUIJSKlPSV X5XJljSWn5cKl3WX4JhMmLiZJJmQmfyaaJrVm0Kbr5wcnImc951kndKeQJ6unx2fi5/6 oGmg2KFHobaiJqKWowajdqPmpFakx6U4pammGqaLpv2nbqfgqFKoxKk3qamqHKqPqwKr davprFys0K1ErbiuLa6hrxavi7AAsHWw6rFgsdayS7LCszizrrQltJy1E7WKtgG2ebbw t2i34LhZuNG5SrnCuju6tbsuu6e8IbybvRW9j74KvoS+/796v/XAcMDswWfB48JfwtvD WMPUxFHEzsVLxcjGRsbDx0HHv8g9yLzJOsm5yjjKt8s2y7bMNcy1zTXNtc42zrbPN8+4 0DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp22vvbgNwF3Ird EN2W3hzeot8p36/gNuC94UThzOJT4tvjY+Pr5HPk/OWE5g3mlucf56noMui86Ubp0Opb 6uXrcOv77IbtEe2c7ijutO9A78zwWPDl8XLx//KM8xnzp/Q09ML1UPXe9m32+/eK+Bn4 qPk4+cf6V/rn+3f8B/yY/Sn9uv5L/tz/bf//cGFyYQAAAAAAAwAAAAJmZgAA8qcAAA1Z AAAT0AAACsB2Y2d0AAAAAAAAAAAAAwEAAAIAAAAGABwARACBANMBHgFdAakCAAJYArsD JwOaBBcEnAUsBccGbgcfB9MIlQlgCi4LBAveDPEODQ8zEFsRghKxE+cVHBZZF5cY3Bol G3Acvh4PH2cgviIZI3IkvCX6JzYocCmnKtosBy0tLk4vZjB4MYEyhTOCNH01dDZnN1E4 KjkEOd46uTuWPHU9VT43PxtAAkDsQddCxUO1RKdFnEaSR4pIgkl7SnRLbkxpTWVOZE9k UGRRaFJuU3RUfVWGVo5Xl1ifWadar1u2XLxdwl7GX8tgz2HTYtdj22TiZe5m/mgTaSxq SGtmbIhtrG7Qb/RxF3I4c1l0eHWMdpt3rHi+edJ66XwCfR5+PX9fgIOBqoLTg/6FHoYx h0OIV4ltioeLpIzHje+PHZBSkYySy5QPlVWWmZfcmRyaWpuXnNCeCJ9AoHihr6LopCKl XKZyp4CokKmiqrir0qzwrhOvO7BpsZuyz7QItTe2Vrd0uJC5q7rCu9W85b3xvvq//8ED wgTDBsQJxQrGB8b9x+zI0MmnynLLMcvnzJHNN83gzqvPddA/0QjR0tKb02TULtT51cXW ktdh2DjZGtn92uHbxNyl3YbeZd9B4Bzg9OHK4p/jduRQ5S3mDebx59royem86rTrseyw 7bPuru+o8K3xw/Lw9Dj1nPce+L36c/w+/hn//wAAAAUAGQA8AHEAuAEKAUQBiAHXAisC gwLlA08DwgQ9BL8FTAXlBokHNgfmCJ0JXAohCuwL6wzxDgAPDRAkETgSUhN0FJUVuhbl GBIZQRp3G60c6B4lH2MgoSHQIvYkGiU7JlsncyiJKZkqoiujLJ4tky6CL2wwUjE0MhMy 5zOzNH01RzYQNtk3ojhsOTY6ADrJO5I8XD0mPe8+uj+IQF1BOEIUQu9Dy0SnRYRGYkdA SB1I/EnbSrpLmUx4TVpOP08mUA1Q9VHfUspTt1SjVZFWgVdyWGFZU1pEWzVcJV0WXgle /V/zYOth5GLgY91k22XbZtxn3Wjfad9q3WvbbNpt2m7bb91w4HHlcutz83T8dgZ3Engb eSF6J3sufDZ9P35Jf1WAY4F0goaDm4SyhcuG6YgOiTOKWYt9jKKNxo7qkBCRNpJdk4aU r5XXlu+YAJkSmiabPZxXnXSelp+9oOeiFaNHpHylqabIp+epBqomq0WsZK2DrqSvxrDp sg2zMrRStWm2fbeRuKS5trrHu9i86L35vwrAHMEuwjPDJcQTxQDF7MbXx8HIq8mUynzL ZcxOzTjOKM8h0BzRGdIZ0xrUHtUj1ijXL9g12TraQNtG3E7dWt5r34PgouHK4v3kOeV9 5sfoGOlr6sHsJ+2h7zHw4vKz9Kf2vPju+zf9lP//AAAABAAUADAAWgCTANwBHQFWAZkB 5AI0AooC6QNOA7oEMASuBTUFwgZYBvQHlAg7COgJpQp4C2AMTA04DiUPFxANEQcSARMD FAUVBhYPFxsYJhk1GkUbVhxpHWweYh9YIEshPCIoIw8j8CTLJaAmbic4J/kotSluKiUq 1yt/LCAswC1hLgEupC9IL+wwkjE5MeEyizM3M+I0jzU+Nes2lzdCN+04mTlFOfA6mztH O/M8nz1MPfg+pD9SP/9AtkFyQjJC80O0RHVFNkX3RrdHeUg7SPtJvUp+S0BMAEzCTYRO SE8NT9RQnFFnUjNTAlPRVKNVdVZJVx1X7li/WZBaY1s1XAhc3F2xXohfX2A4YRNh72LM Y6xkkGV1ZllnPWghaQVp6WrNa7FslW15bl1vQnArcRlyB3L1c+J0z3W6dqN3i3hxeVV6 OHsZfAF8+n4BfwmAEoEagiODK4QzhTqGQIdGiEuJUIpdi3KMiI2fjrOPxpDXkeWS75P3 lPyV/pb+mAqZMJpZm4Scrp3XnwCgJ6FNonKjlqS4pdmm/6gxqWSql6vMrQCuNK9psJ6x 07MHtDy1cbalt9e5Cbo6u2u8mr3IvvTAH8FIwnHDmMS/xeLHBcgpyU/KecuozN3OGs9e 0KnR+9NS1MPWX9gY2frcKt6/4dHldOm37pPz9PnI//8AAG5kaW4AAAAAAAAGNgAAo6IA AFckAABSTQAApCwAACUyAAANvwAAUA0AAFQ5AAIZmQABwo8AAUeuAAMBAAACAAAADgAq AEoAbACPALIA1QD6AR4BRAFrAZMBswHVAfcCGgI/AmQCigKwAtgDAAMpA1MDfQOoA9QE AAQuBFwEigS6BOoFGwVNBYEFugX0BjAGbQasBu0HMAd2B78ICghZCKsJAglcCbsKHQqD CuwLWwvXDFUM1g1YDdwOYg7pD3EP+hCEEQ8RmxIoErYTRRPVFGgU/BWSFioWxBdfF/sY mBk3GdYadhsYG7ocXh0FHa0eWB8FH7QgZiEaIdEiiyNHJAUkxiWJJk8nFifbKJ8pYiok KuYrqCxqLSwt7i6yL3cwPzEJMdYypTN3NFM1NjYZNv434zjIOa06kjt3PFw9QD4lPwk/ 70DUQbpCtEO0RLVFt0a5R7lIuUm2SrFLqkyfTZNOhE90UGNRUFJAUzJUJlUeVhhXFlgW WRpaIFsoXDNdP15NX1tgamF6Yo1j0GUTZlZnmGjZahdrU2yMbcNu9nAncVZyhXOydN52 KHd1eMZ6G3t0fNN+OH+kgReCkYQShZmHJYi2ikSL2I10jx2Q15KqlJ+Wu5kOm5WeOaBi opGkxqb/qT6rf63BsASyR7SJtp+4tbrNvOq/DcE3w2vFqcfyykXMoM7z0UPTi9XL2ALa LtxR3mzggeKS5KDmxujt6vbs4e6t8F3x9PN09N/2O/eM+NT6EftJ/H39qv7W//8AAAAQ AC8AUwB4AJ8AxQDrARMBPAFmAZEBtAHZAf4CJQJMAnUCnwLJAvQDIQNOA3wDqwPbBAsE PQRvBKIE1gULBUEFeQW2BfUGNgZ5Br0HBQdPB5wH7AhBCJoI9wlZCcAKKwqbCw8LjQwU DJ4NKw28DlAO5w+BEB8QwRFlEg0StxNdFAEUpxVQFfwWqhdaGA0Ywxl7GjUa8xuzHHQd NR33HrsfgSBIIRAh2yKnI3QkQyUVJegmvieWKHMpUCouKw0r7SzOLa8ukS90MFkxPjIl Mw4z+TTqNd420zfJOME5ujq1O7A8rD2pPqc/pkCmQadCr0O7RMhF10bnR/hJCkocSy9M QU1TTmZPeFCLUZ1SqFO0VMNV01bmV/pZEVopW0NcXV15XpZfs2DSYfFjIGRgZaBm4Ggg aV9qnGvYbRFuSG9+cLFx43MVdEV1gXbNeBp5anq8fBB9Zn6+gBeBcYLMhCeFg4bgiD2J qosijJyOGo+bkR+SppQwlb2XTJjdmm+cA52Yn2ChOaMWpPmm4KjNqr+stK6usKqyqLSm toy4cLpSvDO+Er/wwc7DrcWNx2/JVcs+zSnPFND80t/UutaM2FTaEtvF3XDfE+Cw4knj 3OVt5wXok+oW64zs9e5S753w2/IP8zf0UvVp9nP3evh6+XX6bftg/FL9P/4s/xX//wAA ABQAOQBiAI0AuADkAREBQAFwAZ4BxwHxAh0CSwJ6AqoC2wMOA0EDdgOtA+QEHARWBJEE zQULBUkFjAXWBiIGcQbDBxkHcwfSCDcIowkWCZEKFQqfCzEL2AyEDTUN6A6fD1gQFBDS EZQSWBMhE/IUxxWhFn8XYxhKGTYaJhsbHBMc/R3mHtEfwSC0IasipiOkJKclrSa3J8Yo 2CnrKv8sFC0pLj8vVTBsMYUynzO7NOA2CDcyOF85jjq+O/A9Iz5XP4xAwkH4QypEXkWW RtBIDUlOSpJL2U0jTm9Pv1ERUl1TplTzVkRXmFjxWlBbtF0fXo9gBWGBYu5kOGWDZtBo H2lxasVsG211btJwMnGVcvx0ZXXDdxp4c3nOey18kH34f2aA2oJUg9aFXobriH+J5YtC jKGOAY9kkMmSMJOblQmWepfvmWea45xineOfUqDAojCjoaUTpoen/al0qu2sZ63jr2Gw 4bJis+W1bLb3uIO6EbujvTe+zsBpwgjDq8VRxvvIqMpYzArNxc+B0T/S/NS31m7YItnP 23bdFt6x4Ebh1+Nk5O7mVeek6OvqIutM7Gntau5k70TwH/Di8aXyUPL58530MPTE9VX1 2PZa9t33VvfM+EL4t/kl+ZH5/fpo+tD7NfuZ+/38YvzB/R/9fv3d/jv+lf7w/0r/pP// AABzZjMyAAAAAAABDEIAAAXe///zJgAAB5IAAP2R///7ov///aMAAAPcAADAbG1tb2QA AAAAAAAGEAAAnKQAAAAAxkOEgAAAAAAAAAAAAAAAAAAAAAA= ReadOnly NO RowAlign 1 RowSpacing 36 SheetTitle Canvas 1 SmartAlignmentGuidesActive NO SmartDistanceGuidesActive NO UniqueID 1 UseEntirePage VPages 1 WindowInfo CurrentSheet 0 ExpandedCanvases name Canvas 1 Frame {{151, 6}, {982, 860}} ListView OutlineWidth 142 RightSidebar Sidebar SidebarWidth 116 VisibleRegion {{-17.5, -73.5}, {433, 375.5}} Zoom 2 ZoomValues Canvas 1 2 4 saveQuickLookFiles YES rabbitmq-java-client-5.0.0/doc/channels/zed-cm.sty000066400000000000000000000544441316117667700220220ustar00rootroot00000000000000% % >>> zed-cm.sty <<< % % (c) Jim Davies, February 1997 % You may copy and distribute this file freely. Any queries and % complaints can be forwarded to Jim.Davies@comlab.ox.ac.uk. However, % the author accepts no liability for the accuracy of these macros, or % their fitness for any purpose. If you make any changes to this % file, please do not distribute the results under the name `zed-cm.sty'. % >>> information <<< % This is a LaTeX2e package for typesetting Z notation using the % standard Computer Modern family. It extends the standard (Mike % Spivey) set of macros and uses the AMS symbol fonts. I'd be % happy to hear of any compatibility problems, and even happier % to hear of elegant solutions at the same time. % >>> date and version <<< \def\fileversion{1} \def\filedate{97/02/18} \def\docdate{97/02/18} \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{zed-cm}[{% \filedate\space\fileversion\space zed-cm package}] % >>> handle fuzz compatibility <<< % Some people may wish to retain the standard \[ and \] commands; the % option `nofuzz' allows them to do this. \newif\if@fuzz@ \@fuzz@true \DeclareOption{fuzz}{\@fuzz@true} \DeclareOption{nofuzz}{\@fuzz@false} \ExecuteOptions{fuzz} \ProcessOptions % >>> fonts and symbols <<< % We declare a new math version. For convenience, I have chosen the % same name as that used in oz.sty. The following code is based upon % the work of Paul King, Sebastian Rahtz, and Mike Spivey. Alan % Jeffrey's influence is everywhere. \DeclareMathVersion{zed} \SetMathAlphabet{\mathrm}{zed}{\encodingdefault}{\rmdefault}{m}{n}% \SetMathAlphabet{\mathbf}{zed}{\encodingdefault}{\rmdefault}{bx}{n}% \SetMathAlphabet{\mathsf}{zed}{\encodingdefault}{\sfdefault}{m}{n}% \SetMathAlphabet{\mathtt}{zed}{\encodingdefault}{\ttdefault}{m}{n}% \DeclareSymbolFont{italics}{\encodingdefault}{\rmdefault}{m}{it}% \DeclareSymbolFontAlphabet{\mathrm}{operators} \DeclareSymbolFontAlphabet{\mathit}{letters} \DeclareSymbolFontAlphabet{\mathcal}{symbols} \DeclareSymbolFontAlphabet{\zedit}{italics} \DeclareSymbolFont{lasy}{U}{lasy}{m}{n} \DeclareSymbolFont{AMSa}{U}{msa}{m}{n} \DeclareSymbolFont{AMSb}{U}{msb}{m}{n} \let\mho\undefined \let\Join\undefined \let\Box\undefined \let\Diamond\undefined \let\leadsto\undefined \let\sqsubset\undefined \let\sqsupset\undefined \let\lhd\undefined \let\unlhd\undefined \let\rhd\undefined \let\unrhd\undefined \DeclareMathSymbol{\mho}{\mathord}{lasy}{"30} \DeclareMathSymbol{\Join}{\mathrel}{lasy}{"31} \DeclareMathSymbol{\Box}{\mathord}{lasy}{"32} \DeclareMathSymbol{\Diamond}{\mathord}{lasy}{"33} \DeclareMathSymbol{\leadsto}{\mathrel}{lasy}{"3B} \DeclareMathSymbol{\sqsubset}{\mathrel}{lasy}{"3C} \DeclareMathSymbol{\sqsupset}{\mathrel}{lasy}{"3D} \DeclareMathSymbol{\lhd}{\mathrel}{lasy}{"01} \DeclareMathSymbol{\unlhd}{\mathrel}{lasy}{"02} \DeclareMathSymbol{\rhd}{\mathrel}{lasy}{"03} \DeclareMathSymbol{\unrhd}{\mathrel}{lasy}{"04} \DeclareSymbolFontAlphabet{\bbold}{AMSb} \mathversion{zed} \let\rightleftharpoons\undefined \let\angle\undefined \DeclareMathSymbol\boxdot{\mathbin}{AMSa}{"00} \DeclareMathSymbol\boxplus{\mathbin}{AMSa}{"01} \DeclareMathSymbol\boxtimes{\mathbin}{AMSa}{"02} \DeclareMathSymbol\square{\mathord}{AMSa}{"03} \DeclareMathSymbol\blacksquare{\mathord}{AMSa}{"04} \DeclareMathSymbol\centerdot{\mathbin}{AMSa}{"05} \DeclareMathSymbol\lozenge{\mathord}{AMSa}{"06} \DeclareMathSymbol\blacklozenge{\mathord}{AMSa}{"07} \DeclareMathSymbol\circlearrowright{\mathrel}{AMSa}{"08} \DeclareMathSymbol\circlearrowleft{\mathrel}{AMSa}{"09} \DeclareMathSymbol\rightleftharpoons{\mathrel}{AMSa}{"0A} \DeclareMathSymbol\leftrightharpoons{\mathrel}{AMSa}{"0B} \DeclareMathSymbol\boxminus{\mathbin}{AMSa}{"0C} \DeclareMathSymbol\Vdash{\mathrel}{AMSa}{"0D} \DeclareMathSymbol\Vvdash{\mathrel}{AMSa}{"0E} \DeclareMathSymbol\vDash{\mathrel}{AMSa}{"0F} \DeclareMathSymbol\twoheadrightarrow{\mathrel}{AMSa}{"10} \DeclareMathSymbol\twoheadleftarrow{\mathrel}{AMSa}{"11} \DeclareMathSymbol\leftleftarrows{\mathrel}{AMSa}{"12} \DeclareMathSymbol\rightrightarrows{\mathrel}{AMSa}{"13} \DeclareMathSymbol\upuparrows{\mathrel}{AMSa}{"14} \DeclareMathSymbol\downdownarrows{\mathrel}{AMSa}{"15} \DeclareMathSymbol\upharpoonright{\mathrel}{AMSa}{"16} \DeclareMathSymbol\downharpoonright{\mathrel}{AMSa}{"17} \DeclareMathSymbol\upharpoonleft{\mathrel}{AMSa}{"18} \DeclareMathSymbol\downharpoonleft{\mathrel}{AMSa}{"19} \DeclareMathSymbol\rightarrowtail{\mathrel}{AMSa}{"1A} \DeclareMathSymbol\leftarrowtail{\mathrel}{AMSa}{"1B} \DeclareMathSymbol\leftrightarrows{\mathrel}{AMSa}{"1C} \DeclareMathSymbol\rightleftarrows{\mathrel}{AMSa}{"1D} \DeclareMathSymbol\Lsh{\mathrel}{AMSa}{"1E} \DeclareMathSymbol\Rsh{\mathrel}{AMSa}{"1F} \DeclareMathSymbol\rightsquigarrow{\mathrel}{AMSa}{"20} \DeclareMathSymbol\leftrightsquigarrow{\mathrel}{AMSa}{"21} \DeclareMathSymbol\looparrowleft{\mathrel}{AMSa}{"22} \DeclareMathSymbol\looparrowright{\mathrel}{AMSa}{"23} \DeclareMathSymbol\circeq{\mathrel}{AMSa}{"24} \DeclareMathSymbol\succsim{\mathrel}{AMSa}{"25} \DeclareMathSymbol\gtrsim{\mathrel}{AMSa}{"26} \DeclareMathSymbol\gtrapprox{\mathrel}{AMSa}{"27} \DeclareMathSymbol\multimap{\mathrel}{AMSa}{"28} \DeclareMathSymbol\therefore{\mathrel}{AMSa}{"29} \DeclareMathSymbol\because{\mathrel}{AMSa}{"2A} \DeclareMathSymbol\doteqdot{\mathrel}{AMSa}{"2B} \DeclareMathSymbol\triangleq{\mathrel}{AMSa}{"2C} \DeclareMathSymbol\precsim{\mathrel}{AMSa}{"2D} \DeclareMathSymbol\lesssim{\mathrel}{AMSa}{"2E} \DeclareMathSymbol\lessapprox{\mathrel}{AMSa}{"2F} \DeclareMathSymbol\eqslantless{\mathrel}{AMSa}{"30} \DeclareMathSymbol\eqslantgtr{\mathrel}{AMSa}{"31} \DeclareMathSymbol\curlyeqprec{\mathrel}{AMSa}{"32} \DeclareMathSymbol\curlyeqsucc{\mathrel}{AMSa}{"33} \DeclareMathSymbol\preccurlyeq{\mathrel}{AMSa}{"34} \DeclareMathSymbol\leqq{\mathrel}{AMSa}{"35} \DeclareMathSymbol\leqslant{\mathrel}{AMSa}{"36} \DeclareMathSymbol\lessgtr{\mathrel}{AMSa}{"37} \DeclareMathSymbol\backprime{\mathord}{AMSa}{"38} \DeclareMathSymbol\risingdotseq{\mathrel}{AMSa}{"3A} \DeclareMathSymbol\fallingdotseq{\mathrel}{AMSa}{"3B} \DeclareMathSymbol\succcurlyeq{\mathrel}{AMSa}{"3C} \DeclareMathSymbol\geqq{\mathrel}{AMSa}{"3D} \DeclareMathSymbol\geqslant{\mathrel}{AMSa}{"3E} \DeclareMathSymbol\gtrless{\mathrel}{AMSa}{"3F} \DeclareMathSymbol\sqsubset{\mathrel}{AMSa}{"40} \DeclareMathSymbol\sqsupset{\mathrel}{AMSa}{"41} \DeclareMathSymbol\vartriangleright{\mathrel}{AMSa}{"42} \DeclareMathSymbol\vartriangleleft{\mathrel}{AMSa}{"43} \DeclareMathSymbol\trianglerighteq{\mathrel}{AMSa}{"44} \DeclareMathSymbol\trianglelefteq{\mathrel}{AMSa}{"45} \DeclareMathSymbol\bigstar{\mathord}{AMSa}{"46} \DeclareMathSymbol\between{\mathrel}{AMSa}{"47} \DeclareMathSymbol\blacktriangledown{\mathord}{AMSa}{"48} \DeclareMathSymbol\blacktriangleright{\mathrel}{AMSa}{"49} \DeclareMathSymbol\blacktriangleleft{\mathrel}{AMSa}{"4A} \DeclareMathSymbol\vartriangle{\mathord}{AMSa}{"4D} \DeclareMathSymbol\blacktriangle{\mathord}{AMSa}{"4E} \DeclareMathSymbol\triangledown{\mathord}{AMSa}{"4F} \DeclareMathSymbol\eqcirc{\mathrel}{AMSa}{"50} \DeclareMathSymbol\lesseqgtr{\mathrel}{AMSa}{"51} \DeclareMathSymbol\gtreqless{\mathrel}{AMSa}{"52} \DeclareMathSymbol\lesseqqgtr{\mathrel}{AMSa}{"53} \DeclareMathSymbol\gtreqqless{\mathrel}{AMSa}{"54} \DeclareMathSymbol\Rrightarrow{\mathrel}{AMSa}{"56} \DeclareMathSymbol\Lleftarrow{\mathrel}{AMSa}{"57} \DeclareMathSymbol\veebar{\mathbin}{AMSa}{"59} \DeclareMathSymbol\barwedge{\mathbin}{AMSa}{"5A} \DeclareMathSymbol\doublebarwedge{\mathbin}{AMSa}{"5B} \DeclareMathSymbol\angle{\mathord}{AMSa}{"5C} \DeclareMathSymbol\measuredangle{\mathord}{AMSa}{"5D} \DeclareMathSymbol\sphericalangle{\mathord}{AMSa}{"5E} \DeclareMathSymbol\varpropto{\mathrel}{AMSa}{"5F} \DeclareMathSymbol\smallsmile{\mathrel}{AMSa}{"60} \DeclareMathSymbol\smallfrown{\mathrel}{AMSa}{"61} \DeclareMathSymbol\Subset{\mathrel}{AMSa}{"62} \DeclareMathSymbol\Supset{\mathrel}{AMSa}{"63} \DeclareMathSymbol\Cup{\mathbin}{AMSa}{"64} \DeclareMathSymbol\Cap{\mathbin}{AMSa}{"65} \DeclareMathSymbol\curlywedge{\mathbin}{AMSa}{"66} \DeclareMathSymbol\curlyvee{\mathbin}{AMSa}{"67} \DeclareMathSymbol\leftthreetimes{\mathbin}{AMSa}{"68} \DeclareMathSymbol\rightthreetimes{\mathbin}{AMSa}{"69} \DeclareMathSymbol\subseteqq{\mathrel}{AMSa}{"6A} \DeclareMathSymbol\supseteqq{\mathrel}{AMSa}{"6B} \DeclareMathSymbol\bumpeq{\mathrel}{AMSa}{"6C} \DeclareMathSymbol\Bumpeq{\mathrel}{AMSa}{"6D} \DeclareMathSymbol\lll{\mathrel}{AMSa}{"6E} \DeclareMathSymbol\ggg{\mathrel}{AMSa}{"6F} \DeclareMathDelimiter\ulcorner{4}{AMSa}{"70}{AMSa}{"70} \DeclareMathDelimiter\urcorner{5}{AMSa}{"71}{AMSa}{"71} \DeclareMathDelimiter\llcorner{4}{AMSa}{"78}{AMSa}{"78} \DeclareMathDelimiter\lrcorner{5}{AMSa}{"79}{AMSa}{"79} \xdef\yen {\noexpand\mathhexbox\hexnumber@\symAMSa 55 } \xdef\checkmark{\noexpand\mathhexbox\hexnumber@\symAMSa 58 } \xdef\circledR {\noexpand\mathhexbox\hexnumber@\symAMSa 72 } \xdef\maltese {\noexpand\mathhexbox\hexnumber@\symAMSa 7A } \DeclareMathSymbol\circledS{\mathord}{AMSa}{"73} \DeclareMathSymbol\pitchfork{\mathrel}{AMSa}{"74} \DeclareMathSymbol\dotplus{\mathbin}{AMSa}{"75} \DeclareMathSymbol\backsim{\mathrel}{AMSa}{"76} \DeclareMathSymbol\backsimeq{\mathrel}{AMSa}{"77} \DeclareMathSymbol\complement{\mathord}{AMSa}{"7B} \DeclareMathSymbol\intercal{\mathbin}{AMSa}{"7C} \DeclareMathSymbol\circledcirc{\mathbin}{AMSa}{"7D} \DeclareMathSymbol\circledast{\mathbin}{AMSa}{"7E} \DeclareMathSymbol\circleddash{\mathbin}{AMSa}{"7F} \DeclareMathSymbol\lvertneqq{\mathrel}{AMSb}{"00} \DeclareMathSymbol\gvertneqq{\mathrel}{AMSb}{"01} \DeclareMathSymbol\nleq{\mathrel}{AMSb}{"02} \DeclareMathSymbol\ngeq{\mathrel}{AMSb}{"03} \DeclareMathSymbol\nless{\mathrel}{AMSb}{"04} \DeclareMathSymbol\ngtr{\mathrel}{AMSb}{"05} \DeclareMathSymbol\nprec{\mathrel}{AMSb}{"06} \DeclareMathSymbol\nsucc{\mathrel}{AMSb}{"07} \DeclareMathSymbol\lneqq{\mathrel}{AMSb}{"08} \DeclareMathSymbol\gneqq{\mathrel}{AMSb}{"09} \DeclareMathSymbol\nleqslant{\mathrel}{AMSb}{"0A} \DeclareMathSymbol\ngeqslant{\mathrel}{AMSb}{"0B} \DeclareMathSymbol\lneq{\mathrel}{AMSb}{"0C} \DeclareMathSymbol\gneq{\mathrel}{AMSb}{"0D} \DeclareMathSymbol\npreceq{\mathrel}{AMSb}{"0E} \DeclareMathSymbol\nsucceq{\mathrel}{AMSb}{"0F} \DeclareMathSymbol\precnsim{\mathrel}{AMSb}{"10} \DeclareMathSymbol\succnsim{\mathrel}{AMSb}{"11} \DeclareMathSymbol\lnsim{\mathrel}{AMSb}{"12} \DeclareMathSymbol\gnsim{\mathrel}{AMSb}{"13} \DeclareMathSymbol\nleqq{\mathrel}{AMSb}{"14} \DeclareMathSymbol\ngeqq{\mathrel}{AMSb}{"15} \DeclareMathSymbol\precneqq{\mathrel}{AMSb}{"16} \DeclareMathSymbol\succneqq{\mathrel}{AMSb}{"17} \DeclareMathSymbol\precnapprox{\mathrel}{AMSb}{"18} \DeclareMathSymbol\succnapprox{\mathrel}{AMSb}{"19} \DeclareMathSymbol\lnapprox{\mathrel}{AMSb}{"1A} \DeclareMathSymbol\gnapprox{\mathrel}{AMSb}{"1B} \DeclareMathSymbol\nsim{\mathrel}{AMSb}{"1C} \DeclareMathSymbol\ncong{\mathrel}{AMSb}{"1D} \DeclareMathSymbol\varsubsetneq{\mathrel}{AMSb}{"20} \DeclareMathSymbol\varsupsetneq{\mathrel}{AMSb}{"21} \DeclareMathSymbol\nsubseteqq{\mathrel}{AMSb}{"22} \DeclareMathSymbol\nsupseteqq{\mathrel}{AMSb}{"23} \DeclareMathSymbol\subsetneqq{\mathrel}{AMSb}{"24} \DeclareMathSymbol\supsetneqq{\mathrel}{AMSb}{"25} \DeclareMathSymbol\varsubsetneqq{\mathrel}{AMSb}{"26} \DeclareMathSymbol\varsupsetneqq{\mathrel}{AMSb}{"27} \DeclareMathSymbol\subsetneq{\mathrel}{AMSb}{"28} \DeclareMathSymbol\supsetneq{\mathrel}{AMSb}{"29} \DeclareMathSymbol\nsubseteq{\mathrel}{AMSb}{"2A} \DeclareMathSymbol\nsupseteq{\mathrel}{AMSb}{"2B} \DeclareMathSymbol\nparallel{\mathrel}{AMSb}{"2C} \DeclareMathSymbol\nmid{\mathrel}{AMSb}{"2D} \DeclareMathSymbol\nshortmid{\mathrel}{AMSb}{"2E} \DeclareMathSymbol\nshortparallel{\mathrel}{AMSb}{"2F} \DeclareMathSymbol\nvdash{\mathrel}{AMSb}{"30} \DeclareMathSymbol\nVdash{\mathrel}{AMSb}{"31} \DeclareMathSymbol\nvDash{\mathrel}{AMSb}{"32} \DeclareMathSymbol\nVDash{\mathrel}{AMSb}{"33} \DeclareMathSymbol\ntrianglerighteq{\mathrel}{AMSb}{"34} \DeclareMathSymbol\ntrianglelefteq{\mathrel}{AMSb}{"35} \DeclareMathSymbol\ntriangleleft{\mathrel}{AMSb}{"36} \DeclareMathSymbol\ntriangleright{\mathrel}{AMSb}{"37} \DeclareMathSymbol\nleftarrow{\mathrel}{AMSb}{"38} \DeclareMathSymbol\nrightarrow{\mathrel}{AMSb}{"39} \DeclareMathSymbol\nLeftarrow{\mathrel}{AMSb}{"3A} \DeclareMathSymbol\nRightarrow{\mathrel}{AMSb}{"3B} \DeclareMathSymbol\nLeftrightarrow{\mathrel}{AMSb}{"3C} \DeclareMathSymbol\nleftrightarrow{\mathrel}{AMSb}{"3D} \DeclareMathSymbol\divideontimes{\mathbin}{AMSb}{"3E} \DeclareMathSymbol\varnothing{\mathord}{AMSb}{"3F} \DeclareMathSymbol\mho{\mathord}{AMSb}{"66} \DeclareMathSymbol\eth{\mathord}{AMSb}{"67} \DeclareMathSymbol\eqsim{\mathrel}{AMSb}{"68} \DeclareMathSymbol\beth{\mathord}{AMSb}{"69} \DeclareMathSymbol\gimel{\mathord}{AMSb}{"6A} \DeclareMathSymbol\daleth{\mathord}{AMSb}{"6B} \DeclareMathSymbol\lessdot{\mathrel}{AMSb}{"6C} \DeclareMathSymbol\gtrdot{\mathrel}{AMSb}{"6D} \DeclareMathSymbol\ltimes{\mathbin}{AMSb}{"6E} \DeclareMathSymbol\rtimes{\mathbin}{AMSb}{"6F} \DeclareMathSymbol\shortmid{\mathrel}{AMSb}{"70} \DeclareMathSymbol\shortparallel{\mathrel}{AMSb}{"71} \DeclareMathSymbol\smallsetminus{\mathbin}{AMSb}{"72} \DeclareMathSymbol\thicksim{\mathrel}{AMSb}{"73} \DeclareMathSymbol\thickapprox{\mathrel}{AMSb}{"74} \DeclareMathSymbol\approxeq{\mathrel}{AMSb}{"75} \DeclareMathSymbol\succapprox{\mathrel}{AMSb}{"76} \DeclareMathSymbol\precapprox{\mathrel}{AMSb}{"77} \DeclareMathSymbol\curvearrowleft{\mathrel}{AMSb}{"78} \DeclareMathSymbol\curvearrowright{\mathrel}{AMSb}{"79} \DeclareMathSymbol\digamma{\mathord}{AMSb}{"7A} \DeclareMathSymbol\varkappa{\mathord}{AMSb}{"7B} \DeclareMathSymbol\hslash{\mathord}{AMSb}{"7D} \DeclareMathSymbol\hbar{\mathord}{AMSb}{"7E} \DeclareMathSymbol\backepsilon{\mathrel}{AMSb}{"7F} % A macro name has been chosen for each of the symbols in the AMS % fonts. There is no need to load any other AMS package in order to % access these symbols. % >>> fuzz <<< % This is the standard fuzz setup, apart from the oz style change to % the setmcodes macro. \def\@setmcodes#1#2#3{{\count0=#1 \count1=#3 \loop \global\mathcode\count0=\count1 \ifnum \count0<#2 \advance\count0 by1 \advance\count1 by1 \repeat}} \@setmcodes{`A}{`Z}{"7\hexnumber@\symitalics41}% \@setmcodes{`a}{`z}{"7\hexnumber@\symitalics61}% \def~{\ifmmode\,\else\penalty\@M\ \fi} \let\@mc=\mathchardef \mathcode`\;="8000 {\catcode`\;=\active \gdef;{\semicolon\;}} \@mc\semicolon="603B \def\strut@op#1{\mathop{\mathstrut{#1}}\nolimits} \def\_{\leavevmode \ifmmode\else\kern0.06em\fi \vbox{\hrule width0.5em}} \mathcode`\"="8000 \def\@kwote#1"{\hbox{\it #1}} {\catcode`\"=\active \global\let"=\@kwote} \mathchardef\spot="320F \mathcode`\@=\spot \mathcode`\|=\mid \def\bsup#1 \esup{^{#1}} \def\inrel#1{\mathrel{\underline{#1}}} \newdimen\zedindent \zedindent=\leftmargini% \newdimen\zedleftsep \zedleftsep=1em% \newdimen\zedtab \zedtab=2em% \newdimen\zedbar \zedbar=6em% \newskip\zedskip \zedskip=0.5\baselineskip plus0.333333\baselineskip% minus0.333333\baselineskip% \def\zedsize{}% \newcount\interzedlinepenalty \interzedlinepenalty=10000% \newcount\preboxpenalty \preboxpenalty=0% \newif\ifzt@p \zt@pfalse% \def\@jot{0.5\zedskip} \def\@narrow{\advance\linewidth by-\zedindent} \def\@zrulefill{\leaders\hrule height\arrayrulewidth\hfill} \def\@topline#1{\hbox to\linewidth{% \vrule height\arrayrulewidth width\arrayrulewidth \vrule height0pt depth\@jot width0pt \hbox to\zedleftsep{\@zrulefill\thinspace}% #1\thinspace\@zrulefill}} \def\@zedline{\omit \vrule height\arrayrulewidth width\linewidth \cr} \def\where{\@zskip\@jot \omit \vrule height\arrayrulewidth width\zedbar \cr \@zskip\@jot} \def\also{\crcr \noalign{\penalty\interdisplaylinepenalty \vskip\zedskip}} \def\@zskip#1{\crcr \omit \vrule height#1 width\arrayrulewidth \cr} \def\@zlign{\tabskip\z@skip\everycr{}} \let\tie=\t \def\t#1{\afterassignment\@t\count@=#1} \def\@t{\hskip\count@\zedtab} \def\@setzsize{\let\next=\@nomath\def\@nomath##1{}% \skip0=\abovedisplayskip\skip1=\belowdisplayskip \zedsize \let\@nomath=\next \abovedisplayskip=\skip0\belowdisplayskip=\skip1} \def\@zed{\ifvmode\@zleavevmode\fi $$\global\zt@ptrue \@setzsize \advance\linewidth by-\zedindent \advance\displayindent by\zedindent \def\\{\crcr}% Must have \def and not \let for nested alignments. \let\par=\relax \tabskip=0pt} \def\@znoskip{\offinterlineskip \everycr={\noalign{\ifzt@p \global\zt@pfalse \ifdim\prevdepth>-1000pt \skip0=\normalbaselineskip \advance\skip0by-\prevdepth \advance\skip0by-\ht\strutbox \ifdim\skip0<\normallineskiplimit \vskip\normallineskip \else \vskip\skip0 \fi\fi \else \penalty\interzedlinepenalty \fi}}} \def\zed{\@zed\@znoskip\halign to\linewidth\bgroup \strut$\@zlign##$\hfil \tabskip=0pt plus1fil\cr} \def\endzed{\crcr\egroup$$\global\@ignoretrue} \if@fuzz@ \def\[{\begingroup\zed} \def\]{\crcr\egroup$$\endgroup\ignorespaces} \fi \def\axdef{\def\also{\@zskip\zedskip}% \predisplaypenalty=\preboxpenalty \@zed\@znoskip \halign to\linewidth\bgroup \strut \vrule width\arrayrulewidth \hskip\zedleftsep $\@zlign##$\hfil \tabskip=0pt plus1fil\cr} \let\endaxdef=\endzed \def\schema#1{\@ifnextchar[{\@schema{#1}}{\@nschema{#1}}} \def\@schema#1[#2]{\@nschema{#1[#2]}} \def\@nschema#1{\@narrow\axdef \omit\@topline{$\strut#1$}\cr} \def\endschema{\@zskip\@jot \@zedline \endzed} \@namedef{schema*}{\@narrow\axdef \@zedline \@zskip\@jot} \expandafter\let\csname endschema*\endcsname=\endschema \def\gendef{\@ifnextchar[{\@gendef}{\@ngendef}} \def\@gendef[#1]{\@narrow\axdef \omit \setbox0=\hbox{$\strut[#1]$}% \rlap{\raise\doublerulesep\@topline{\hskip\wd0}}\@topline{\box0}\cr} \def\@ngendef{\@narrow\axdef \@zedline \omit \hbox to\linewidth{\vrule height\doublerulesep width\arrayrulewidth \@zrulefill}\cr \@zskip\@jot } \let\endgendef=\endschema \def\argue{\@zed \interzedlinepenalty=\interdisplaylinepenalty \openup\@jot \halign to\linewidth\bgroup \strut$\@zlign##$\hfil \tabskip=0pt plus1fil &\hbox to0pt{\hss[\@zlign##\unskip]}\tabskip=0pt\cr \noalign{\vskip-\@jot}} \let\endargue=\endzed \def\because#1{\noalign{\vskip-\jot}\cr} \def\syntax{\@zed\@znoskip \halign\bgroup \strut$\@zlign##$\hfil &\hfil$\@zlign{}##{}$\hfil &$\@zlign##$\hfil\cr} \let\endsyntax=\endzed \def\infrule{\@zed\@znoskip \halign\bgroup \strut\quad$\@zlign##$\quad\hfil&\quad\@zlign##\hfil\cr} \let\endinfrule=\endzed \def\derive{\crcr \noalign{\vskip\@jot} \omit\@zrulefill \@ifnextchar[{\@xderive}{\@yderive}} \def\@xderive[#1]{&$\smash{\lower 0.5ex\hbox{$[\;#1\;]$}}$\cr \noalign{\vskip\@jot}} \def\@yderive{\cr \noalign{\vskip\@jot}} \def\@zleavevmode{\if@inlabel \indent \else\if@noskipsec \indent \else\if@nobreak \global\@nobreakfalse \everypar={}\abovedisplayskip=0pt\fi {\parskip=0pt\noindent}\fi\fi} % From now on, we must depart from the text of fuzz, as we do not have % the ox symbol font at our disposal. We must choose symbols from % the AMS fonts to compensate for our loss. \let\xlambda=\lambda \let\xmu=\mu \let\xforall=\forall \let\xexists=\exists \def \bind {\mathrel{\leadsto}} \def \bindsto {\mathrel{\leadsto}} \def \lblot {{\langle}\mkern -3.5mu{|}} \def \rblot {{|}\mkern -3.5mu{\rangle}} \let\lbind=\lblot \let\rbind=\rblot \def \defs {\mathrel{\widehat=}} \def \power {\strut@op{\bbold P}} \let \cross \times \def \lambda {\strut@op{\xlambda}} \def \mu {\strut@op{\xmu}} \def \ldbrack{{[}\mkern-2mu{[}} \def \rdbrack{{]}\mkern-2mu{]}} \let \lbag \ldbrack \let \rbag \rdbrack \def \lnot {\neg\;} \def \land {\mathrel{\wedge}} \def \lor {\mathrel{\vee}} \let \implies \Rightarrow \let \iff \Leftrightarrow \def \forall {\strut@op{\xforall}} \def \exists {\strut@op{\xexists}} \def \hide {\mathrel{\backslash}} \DeclareMathSymbol{\project}{\mathrel}{AMSa}{"16} \def \pre {{\mathrm{pre}}\;} \def \semi {\mathrel{\comp}} \def \ldata {\langle\!\langle} \def \rdata {\rangle\!\rangle} \let \shows \vdash \def \pipe {\mathord>\!\!\mathord>} \def \LET {{\mathbf{let}}\;} \def \IF {{\mathbf{if}}\;} \def \IN {{\mathbf{in}}\;} \def \THEN {\mathrel{\mathbf{then}}} \def \ELSE {\mathrel{\mathbf{else}}} \let \rel \leftrightarrow \def \dom {\mathop{\mathrm{dom}}} \def \ran {\mathop{\mathrm{ran}}} \def \id {\mathop{\mathrm{id}}} \def\comp{\mathbin{\raise 0.6ex\hbox{\small\oalign{\hfil% $\scriptscriptstyle\mathrm{o}$\hfil% \cr\hfil$\scriptscriptstyle\mathrm{9}$\hfil}}}} \DeclareMathSymbol{\dres}{\mathbin}{AMSa}{"43} \DeclareMathSymbol{\rres}{\mathbin}{AMSa}{"42} \def \ndres {\mathbin{\rlap{\raise.05ex\hbox{$-$}}{\dres}}} \def \nrres {\mathbin{\rlap{\raise.05ex\hbox{$-$}}{\rres}}} \def \inv {^\sim} \def \limg {(\mskip-4.5mu|} \def \rimg {|\mskip-4.5mu)} \def\@p#1{\mathrel{\ooalign{\hfil$\mapstochar\mkern 5mu$\hfil\cr$#1$}}} \def \pfun {\@p\fun} \let \fun \rightarrow \let \inj \rightarrowtail \def \pinj {\@p\inj} \def \surj {\mathrel{\ooalign{$\fun$\hfil\cr$\mkern4mu\fun$}}} \def \bij {\mathrel{\ooalign{$\inj$\hfil\cr$\mkern5mu\fun$}}} \def \psurj {\@p\surj} \def \nat {{\bbold N}} \def \num {{\bbold Z}} \def \div {\mathbin{\mathsf{div}}} \def \mod {\mathbin{\mathsf{mod}}} \def \upto {\mathbin{\ldotp\ldotp}} \def \plus {^+} \def \star {^*} \def \finset {\strut@op{{\bbold F}}} \def\@f#1{\mathrel{\ooalign{\hfil$\mapstochar\mkern 3mu \mapstochar\mkern 5mu$\hfil\cr$#1$}}} \def \ffun {\@f\fun} \def \finj {\@f\inj} \def \seq {\mathop{\mathrm{seq}}} \def \iseq {\mathop{\mathrm{iseq}}} \def \cat {\mathbin{\raise 0.8ex\hbox{$\smallfrown$}}} \def \filter {\mathbin{\project}} \def \dcat {\mathop{\cat/}} \def \bag {\mathop{\mathrm{bag}}} \def \bcount {\mathbin{\sharp}} \def \inbag {\mathrel{\rlap{\hbox{$-$}}{\sqsubset}}} \let \subbageq \sqsubseteq \def \disjoint {{\mathsf{disjoint}}\;} \def \partition {\mathrel{\mathsf{partition}}} \def \prefix {\mathrel{\mathsf{prefix}}} \def \suffix {\mathrel{\mathsf{suffix}}} \def \inseq {\mathrel{\mathsf{in}}} \def \extract {\mathrel{\upharpoonleft}} \def \uminus@sym{\setbox0=\hbox{$\cup$}\rlap{\hbox to\wd0{\hss\raise0.3ex\hbox{$\scriptscriptstyle{-}$}\hss}}\box0} \def \uminus {\mathrel{\uminus@sym}} %% nice macro names \def \union {\cup} \def \inter {\cap} \def \Union {\bigcup} \def \Inter {\bigcap} \def \nil {\langle\rangle} \def \drop {\array[t]{@{}l@{}}} \def \enddrop {\endarray} \endinput rabbitmq-java-client-5.0.0/pom.xml000066400000000000000000000767641316117667700170700ustar00rootroot00000000000000 4.0.0 com.rabbitmq amqp-client 5.0.0 jar RabbitMQ Java Client The RabbitMQ Java client library allows Java applications to interface with RabbitMQ. http://www.rabbitmq.com ASL 2.0 http://www.apache.org/licenses/LICENSE-2.0.html repo GPL v2 http://www.gnu.org/licenses/gpl-2.0.txt repo MPL 1.1 http://www.mozilla.org/MPL/MPL-1.1.txt repo info@rabbitmq.com Team RabbitMQ Pivotal Software, Inc. https://rabbitmq.com https://github.com/rabbitmq/rabbitmq-java-client scm:git:git://github.com/rabbitmq/rabbitmq-java-client.git scm:git:git@github.com:rabbitmq/rabbitmq-java-client.git v5.0.0 Pivotal Software, Inc. http://www.rabbitmq.com UTF-8 UTF-8 1.7.25 3.2.4 1.2.3 1.1 4.12 3.0.0 2.10.0 3.0.0-M1 2.5.3 2.3 3.0.2 3.0.1 2.0 2.4.8 1.5 1.12 3.6.1 2.19.1 2.19.1 1.6 3.0.2 3.2.0 ${basedir}/src/main/scripts ${basedir}/deps ${deps.dir}/rabbitmq_codegen 0.9.1 make ${deps.dir}/rabbit ${rabbitmq.dir}/scripts/rabbitmqctl ${project.build.directory}/ca.keystore ${project.build.directory}/empty.keystore bunnies rabbit@localhost 5672 ${project.build.directory}/test-classes/${test-broker.A.nodename} hare@localhost 5673 ${project.build.directory}/test-classes/${test-broker.B.nodename} 6026DFCA in-umbrella ../../UMBRELLA.md ${basedir}/.. use-gmake FreeBSD gmake use-rabbitmqctl.bat Windows ${rabbitmq.dir}/scripts/rabbitmqctl.bat disable-java8-doclint [1.8,) -Xdoclint:none setup-test-cluster !skipTests org.codehaus.gmaven groovy-maven-plugin ${groovy.maven.plugin.version} org.codehaus.groovy groovy-all ${groovy.all.version} generate-test-resources query-test-tls-certs-dir execute ${groovy-scripts.dir}/query_test_tls_certs_dir.groovy pre-integration-test start-test-broker-A execute ${test-broker.A.nodename} ${test-broker.A.node_port} ${groovy-scripts.dir}/manage_test_broker.groovy pre-integration-test start-test-broker-B execute ${test-broker.B.nodename} ${test-broker.B.node_port} ${groovy-scripts.dir}/manage_test_broker.groovy pre-integration-test create-test-cluster execute ${test-broker.B.nodename} ${test-broker.A.nodename} ${groovy-scripts.dir}/manage_test_broker.groovy post-integration-test stop-test-broker-B execute ${test-broker.B.nodename} ${groovy-scripts.dir}/manage_test_broker.groovy post-integration-test stop-test-broker-A execute ${test-broker.A.nodename} ${groovy-scripts.dir}/manage_test_broker.groovy org.codehaus.mojo keytool-maven-plugin ${keytool.maven.plugin.version} false use-provided-test-keystores ${test-tls-certs.dir}/testca/cacert.pem org.codehaus.mojo keytool-maven-plugin ${keytool.maven.plugin.version} false integration-tests !skipTests org.apache.maven.plugins maven-failsafe-plugin ${maven.failsafe.plugin.version} ${make.bin} ${rabbitmq.dir} ${rabbitmqctl.bin} ${test-keystore.ca} ${test-keystore.empty} ${test-keystore.password} ${test-tls-certs.dir}/client/keycert.p12 changeme ${test-broker.A.nodename} ${test-broker.A.node_port} ${test-broker.A.config_file} ${test-broker.B.nodename} ${test-broker.B.node_port} ${test-broker.B.config_file} ${deps.dir} true **/ClientTests.* **/FunctionalTests.* **/SSLTests.* **/ServerTests.* **/HATests.* integration-test integration-test verify verify use-nio org.apache.maven.plugins maven-failsafe-plugin ${maven.failsafe.plugin.version} true ossrh-release org.apache.maven.plugins maven-javadoc-plugin ${maven.javadoc.plugin.version} ${javadoc.opts} true jar org.apache.maven.plugins maven-gpg-plugin ${maven.gpg.plugin.version} sign-artifacts package sign ${gpg.keyname} ossrh https://oss.sonatype.org/content/repositories/snapshots bintray-release org.apache.maven.plugins maven-javadoc-plugin ${maven.javadoc.plugin.version} ${javadoc.opts} true jar org.apache.maven.plugins maven-gpg-plugin ${maven.gpg.plugin.version} sign-artifacts package sign ${gpg.keyname} bintray-rabbitmq-maven rabbitmq-maven https://api.bintray.com/maven/rabbitmq/maven/com.rabbitmq:amqp-client/;publish=1 milestone org.apache.maven.plugins maven-javadoc-plugin ${maven.javadoc.plugin.version} ${javadoc.opts} true jar org.apache.maven.plugins maven-gpg-plugin ${maven.gpg.plugin.version} sign-artifacts package sign ${gpg.keyname} bintray-rabbitmq-maven-milestones rabbitmq-maven-milestones https://api.bintray.com/maven/rabbitmq/maven-milestones/com.rabbitmq:amqp-client/;publish=1 org.slf4j slf4j-api ${slf4j.version} io.dropwizard.metrics metrics-core ${metrics.version} true commons-cli commons-cli ${commons-cli.version} test junit junit ${junit.version} test ch.qos.logback logback-classic ${logback.version} test org.awaitility awaitility ${awaitility.version} test org.mockito mockito-core ${mockito.version} test org.hamcrest hamcrest-library 1.3 test ${basedir}/src/main/resources true ${basedir}/src/test/resources true org.apache.maven.plugins maven-resources-plugin ${maven.resources.plugin.version} org.codehaus.gmaven groovy-maven-plugin ${groovy.maven.plugin.version} org.codehaus.groovy groovy-all ${groovy.all.version} generate-sources generate-amqp-sources execute ${codegen.dir}/amqp-rabbitmq-${codegen.spec_version}.json
${project.build.directory}/generated-sources/src/main/java/com/rabbitmq/client/AMQP.java
${project.build.directory}/generated-sources/src/main/java/com/rabbitmq/client/impl/AMQImpl.java
${groovy-scripts.dir}/generate_amqp_sources.groovy
generate-test-resources remove-old-test-keystores execute ${groovy-scripts.dir}/remove_old_test_keystores.groovy
org.codehaus.mojo build-helper-maven-plugin ${build.helper.maven-plugin.version} add-generated-sources-dir generate-sources add-source ${project.build.directory}/generated-sources/src/main/java maven-compiler-plugin ${maven.compiler.plugin.version} 1.8 1.8 -Xlint:deprecation -Xlint:unchecked org.apache.maven.plugins maven-surefire-plugin ${maven.surefire.plugin.version} true org.codehaus.mojo keytool-maven-plugin ${keytool.maven.plugin.version} true generate-test-ca-keystore generate-test-resources importCertificate ${test-tls-certs.dir}/testca/cacert.pem ${test-keystore.ca} ${test-keystore.password} true server1 generate-test-empty-keystore generate-test-resources importCertificate deleteAlias ${test-tls-certs.dir}/testca/cacert.pem ${test-keystore.empty} ${test-keystore.password} true server1 org.apache.maven.plugins maven-jar-plugin ${maven.jar.plugin.version} ${project.build.outputDirectory}/META-INF/MANIFEST.MF org.apache.felix maven-bundle-plugin ${maven.bundle.plugin.version} bundle-manifest process-classes manifest com.rabbitmq* com.rabbitmq.client AMQP 0.9.1 AMQP Working Group (www.amqp.org) ${project.name} ${project.version} ${project.organization.name} ${project.url} org.codehaus.mojo versions-maven-plugin ${versions.maven.plugin.version} org.apache.maven.plugins maven-release-plugin ${maven.release.plugin.version} v@{project.version} org.apache.maven.plugins maven-source-plugin ${maven.source.plugin.version} jar org.apache.maven.plugins maven-javadoc-plugin ${maven.javadoc.plugin.version} ${javadoc.opts} true
rabbitmq-java-client-5.0.0/rabbitmq-components.mk000066400000000000000000000374341316117667700220570ustar00rootroot00000000000000ifeq ($(.DEFAULT_GOAL),) # Define default goal to `all` because this file defines some targets # before the inclusion of erlang.mk leading to the wrong target becoming # the default. .DEFAULT_GOAL = all endif # PROJECT_VERSION defaults to: # 1. the version exported by rabbitmq-server-release; # 2. the version stored in `git-revisions.txt`, if it exists; # 3. a version based on git-describe(1), if it is a Git clone; # 4. 0.0.0 PROJECT_VERSION := $(RABBITMQ_VERSION) ifeq ($(PROJECT_VERSION),) PROJECT_VERSION := $(shell \ if test -f git-revisions.txt; then \ head -n1 git-revisions.txt | \ awk '{print $$$(words $(PROJECT_DESCRIPTION) version);}'; \ else \ (git describe --dirty --abbrev=7 --tags --always --first-parent \ 2>/dev/null || echo rabbitmq_v0_0_0) | \ sed -e 's/^rabbitmq_v//' -e 's/^v//' -e 's/_/./g' -e 's/-/+/' \ -e 's/-/./g'; \ fi) endif # -------------------------------------------------------------------- # RabbitMQ components. # -------------------------------------------------------------------- # For RabbitMQ repositories, we want to checkout branches which match # the parent project. For instance, if the parent project is on a # release tag, dependencies must be on the same release tag. If the # parent project is on a topic branch, dependencies must be on the same # topic branch or fallback to `stable` or `master` whichever was the # base of the topic branch. dep_amqp_client = git_rmq rabbitmq-erlang-client $(current_rmq_ref) $(base_rmq_ref) master dep_rabbit = git_rmq rabbitmq-server $(current_rmq_ref) $(base_rmq_ref) master dep_rabbit_common = git_rmq rabbitmq-common $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_amqp1_0 = git_rmq rabbitmq-amqp1.0 $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_auth_backend_amqp = git_rmq rabbitmq-auth-backend-amqp $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_auth_backend_cache = git_rmq rabbitmq-auth-backend-cache $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_auth_backend_http = git_rmq rabbitmq-auth-backend-http $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_auth_backend_ldap = git_rmq rabbitmq-auth-backend-ldap $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_auth_mechanism_ssl = git_rmq rabbitmq-auth-mechanism-ssl $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_boot_steps_visualiser = git_rmq rabbitmq-boot-steps-visualiser $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_clusterer = git_rmq rabbitmq-clusterer $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_cli = git_rmq rabbitmq-cli $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_codegen = git_rmq rabbitmq-codegen $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_consistent_hash_exchange = git_rmq rabbitmq-consistent-hash-exchange $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_ct_client_helpers = git_rmq rabbitmq-ct-client-helpers $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_ct_helpers = git_rmq rabbitmq-ct-helpers $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_delayed_message_exchange = git_rmq rabbitmq-delayed-message-exchange $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_dotnet_client = git_rmq rabbitmq-dotnet-client $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_event_exchange = git_rmq rabbitmq-event-exchange $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_federation = git_rmq rabbitmq-federation $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_federation_management = git_rmq rabbitmq-federation-management $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_java_client = git_rmq rabbitmq-java-client $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_jms_client = git_rmq rabbitmq-jms-client $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_jms_cts = git_rmq rabbitmq-jms-cts $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_jms_topic_exchange = git_rmq rabbitmq-jms-topic-exchange $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_lvc = git_rmq rabbitmq-lvc-plugin $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_management = git_rmq rabbitmq-management $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_management_agent = git_rmq rabbitmq-management-agent $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_management_exchange = git_rmq rabbitmq-management-exchange $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_management_themes = git_rmq rabbitmq-management-themes $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_management_visualiser = git_rmq rabbitmq-management-visualiser $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_message_timestamp = git_rmq rabbitmq-message-timestamp $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_metronome = git_rmq rabbitmq-metronome $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_mqtt = git_rmq rabbitmq-mqtt $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_objc_client = git_rmq rabbitmq-objc-client $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_peer_discovery_aws = git_rmq rabbitmq-peer-discovery-aws $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_peer_discovery_common = git_rmq rabbitmq-peer-discovery-common $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_peer_discovery_consul = git_rmq rabbitmq-peer-discovery-consul $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_recent_history_exchange = git_rmq rabbitmq-recent-history-exchange $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_routing_node_stamp = git_rmq rabbitmq-routing-node-stamp $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_rtopic_exchange = git_rmq rabbitmq-rtopic-exchange $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_server_release = git_rmq rabbitmq-server-release $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_sharding = git_rmq rabbitmq-sharding $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_shovel = git_rmq rabbitmq-shovel $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_shovel_management = git_rmq rabbitmq-shovel-management $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_stomp = git_rmq rabbitmq-stomp $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_toke = git_rmq rabbitmq-toke $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_top = git_rmq rabbitmq-top $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_tracing = git_rmq rabbitmq-tracing $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_trust_store = git_rmq rabbitmq-trust-store $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_test = git_rmq rabbitmq-test $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_web_dispatch = git_rmq rabbitmq-web-dispatch $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_web_stomp = git_rmq rabbitmq-web-stomp $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_web_stomp_examples = git_rmq rabbitmq-web-stomp-examples $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_web_mqtt = git_rmq rabbitmq-web-mqtt $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_web_mqtt_examples = git_rmq rabbitmq-web-mqtt-examples $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_website = git_rmq rabbitmq-website $(current_rmq_ref) $(base_rmq_ref) live master dep_toke = git_rmq toke $(current_rmq_ref) $(base_rmq_ref) master dep_rabbitmq_public_umbrella = git_rmq rabbitmq-public-umbrella $(current_rmq_ref) $(base_rmq_ref) master # Third-party dependencies version pinning. # # We do that in this file, which is copied in all projects, to ensure # all projects use the same versions. It avoids conflicts and makes it # possible to work with rabbitmq-public-umbrella. dep_cowboy_commit = 1.1.0 dep_mochiweb = git git://github.com/basho/mochiweb.git v2.9.0p2 dep_ranch_commit = 1.3.2 dep_sockjs = git https://github.com/rabbitmq/sockjs-erlang.git 405990ea62353d98d36dbf5e1e64942d9b0a1daf dep_webmachine_commit = 1.10.8p2 dep_ranch_proxy_protocol = git git://github.com/heroku/ranch_proxy_protocol.git 1.4.2 RABBITMQ_COMPONENTS = amqp_client \ rabbit \ rabbit_common \ rabbitmq_amqp1_0 \ rabbitmq_auth_backend_amqp \ rabbitmq_auth_backend_cache \ rabbitmq_auth_backend_http \ rabbitmq_auth_backend_ldap \ rabbitmq_auth_mechanism_ssl \ rabbitmq_boot_steps_visualiser \ rabbitmq_clusterer \ rabbitmq_cli \ rabbitmq_codegen \ rabbitmq_consistent_hash_exchange \ rabbitmq_ct_client_helpers \ rabbitmq_ct_helpers \ rabbitmq_delayed_message_exchange \ rabbitmq_dotnet_client \ rabbitmq_event_exchange \ rabbitmq_federation \ rabbitmq_federation_management \ rabbitmq_java_client \ rabbitmq_jms_client \ rabbitmq_jms_cts \ rabbitmq_jms_topic_exchange \ rabbitmq_lvc \ rabbitmq_management \ rabbitmq_management_agent \ rabbitmq_management_exchange \ rabbitmq_management_themes \ rabbitmq_management_visualiser \ rabbitmq_message_timestamp \ rabbitmq_metronome \ rabbitmq_mqtt \ rabbitmq_objc_client \ rabbitmq_peer_discovery_aws \ rabbitmq_peer_discovery_common \ rabbitmq_peer_discovery_consul \ rabbitmq_recent_history_exchange \ rabbitmq_routing_node_stamp \ rabbitmq_rtopic_exchange \ rabbitmq_server_release \ rabbitmq_sharding \ rabbitmq_shovel \ rabbitmq_shovel_management \ rabbitmq_stomp \ rabbitmq_toke \ rabbitmq_top \ rabbitmq_tracing \ rabbitmq_trust_store \ rabbitmq_web_dispatch \ rabbitmq_web_mqtt \ rabbitmq_web_mqtt_examples \ rabbitmq_web_stomp \ rabbitmq_web_stomp_examples \ rabbitmq_website # Several components have a custom erlang.mk/build.config, mainly # to disable eunit. Therefore, we can't use the top-level project's # erlang.mk copy. NO_AUTOPATCH += $(RABBITMQ_COMPONENTS) ifeq ($(origin current_rmq_ref),undefined) ifneq ($(wildcard .git),) current_rmq_ref := $(shell (\ ref=$$(git branch --list | awk '/^\* \(.*detached / {ref=$$0; sub(/.*detached [^ ]+ /, "", ref); sub(/\)$$/, "", ref); print ref; exit;} /^\* / {ref=$$0; sub(/^\* /, "", ref); print ref; exit}');\ if test "$$(git rev-parse --short HEAD)" != "$$ref"; then echo "$$ref"; fi)) else current_rmq_ref := master endif endif export current_rmq_ref ifeq ($(origin base_rmq_ref),undefined) ifneq ($(wildcard .git),) base_rmq_ref := $(shell \ (git rev-parse --verify -q stable >/dev/null && \ git merge-base --is-ancestor $$(git merge-base master HEAD) stable && \ echo stable) || \ echo master) else base_rmq_ref := master endif endif export base_rmq_ref # Repository URL selection. # # First, we infer other components' location from the current project # repository URL, if it's a Git repository: # - We take the "origin" remote URL as the base # - The current project name and repository name is replaced by the # target's properties: # eg. rabbitmq-common is replaced by rabbitmq-codegen # eg. rabbit_common is replaced by rabbitmq_codegen # # If cloning from this computed location fails, we fallback to RabbitMQ # upstream which is GitHub. # Maccro to transform eg. "rabbit_common" to "rabbitmq-common". rmq_cmp_repo_name = $(word 2,$(dep_$(1))) # Upstream URL for the current project. RABBITMQ_COMPONENT_REPO_NAME := $(call rmq_cmp_repo_name,$(PROJECT)) RABBITMQ_UPSTREAM_FETCH_URL ?= https://github.com/rabbitmq/$(RABBITMQ_COMPONENT_REPO_NAME).git RABBITMQ_UPSTREAM_PUSH_URL ?= git@github.com:rabbitmq/$(RABBITMQ_COMPONENT_REPO_NAME).git # Current URL for the current project. If this is not a Git clone, # default to the upstream Git repository. ifneq ($(wildcard .git),) git_origin_fetch_url := $(shell git config remote.origin.url) git_origin_push_url := $(shell git config remote.origin.pushurl || git config remote.origin.url) RABBITMQ_CURRENT_FETCH_URL ?= $(git_origin_fetch_url) RABBITMQ_CURRENT_PUSH_URL ?= $(git_origin_push_url) else RABBITMQ_CURRENT_FETCH_URL ?= $(RABBITMQ_UPSTREAM_FETCH_URL) RABBITMQ_CURRENT_PUSH_URL ?= $(RABBITMQ_UPSTREAM_PUSH_URL) endif # Macro to replace the following pattern: # 1. /foo.git -> /bar.git # 2. /foo -> /bar # 3. /foo/ -> /bar/ subst_repo_name = $(patsubst %/$(1)/%,%/$(2)/%,$(patsubst %/$(1),%/$(2),$(patsubst %/$(1).git,%/$(2).git,$(3)))) # Macro to replace both the project's name (eg. "rabbit_common") and # repository name (eg. "rabbitmq-common") by the target's equivalent. # # This macro is kept on one line because we don't want whitespaces in # the returned value, as it's used in $(dep_fetch_git_rmq) in a shell # single-quoted string. dep_rmq_repo = $(if $(dep_$(2)),$(call subst_repo_name,$(PROJECT),$(2),$(call subst_repo_name,$(RABBITMQ_COMPONENT_REPO_NAME),$(call rmq_cmp_repo_name,$(2)),$(1))),$(pkg_$(1)_repo)) dep_rmq_commits = $(if $(dep_$(1)), \ $(wordlist 3,$(words $(dep_$(1))),$(dep_$(1))), \ $(pkg_$(1)_commit)) define dep_fetch_git_rmq fetch_url1='$(call dep_rmq_repo,$(RABBITMQ_CURRENT_FETCH_URL),$(1))'; \ fetch_url2='$(call dep_rmq_repo,$(RABBITMQ_UPSTREAM_FETCH_URL),$(1))'; \ if test "$$$$fetch_url1" != '$(RABBITMQ_CURRENT_FETCH_URL)' && \ git clone -q -n -- "$$$$fetch_url1" $(DEPS_DIR)/$(call dep_name,$(1)); then \ fetch_url="$$$$fetch_url1"; \ push_url='$(call dep_rmq_repo,$(RABBITMQ_CURRENT_PUSH_URL),$(1))'; \ elif git clone -q -n -- "$$$$fetch_url2" $(DEPS_DIR)/$(call dep_name,$(1)); then \ fetch_url="$$$$fetch_url2"; \ push_url='$(call dep_rmq_repo,$(RABBITMQ_UPSTREAM_PUSH_URL),$(1))'; \ fi; \ cd $(DEPS_DIR)/$(call dep_name,$(1)) && ( \ $(foreach ref,$(call dep_rmq_commits,$(1)), \ git checkout -q $(ref) >/dev/null 2>&1 || \ ) \ (echo "error: no valid pathspec among: $(call dep_rmq_commits,$(1))" \ 1>&2 && false) ) && \ (test "$$$$fetch_url" = "$$$$push_url" || \ git remote set-url --push origin "$$$$push_url") endef # -------------------------------------------------------------------- # Component distribution. # -------------------------------------------------------------------- list-dist-deps:: @: prepare-dist:: @: # -------------------------------------------------------------------- # rabbitmq-components.mk checks. # -------------------------------------------------------------------- # If this project is under the Umbrella project, we override $(DEPS_DIR) # to point to the Umbrella's one. We also disable `make distclean` so # $(DEPS_DIR) is not accidentally removed. ifneq ($(wildcard ../../UMBRELLA.md),) UNDER_UMBRELLA = 1 else ifneq ($(wildcard UMBRELLA.md),) UNDER_UMBRELLA = 1 endif ifeq ($(UNDER_UMBRELLA),1) ifneq ($(PROJECT),rabbitmq_public_umbrella) DEPS_DIR ?= $(abspath ..) endif ifneq ($(filter distclean distclean-deps,$(MAKECMDGOALS)),) SKIP_DEPS = 1 endif endif UPSTREAM_RMQ_COMPONENTS_MK = $(DEPS_DIR)/rabbit_common/mk/rabbitmq-components.mk check-rabbitmq-components.mk: $(verbose) cmp -s rabbitmq-components.mk \ $(UPSTREAM_RMQ_COMPONENTS_MK) || \ (echo "error: rabbitmq-components.mk must be updated!" 1>&2; \ false) ifeq ($(PROJECT),rabbit_common) rabbitmq-components-mk: @: else rabbitmq-components-mk: $(gen_verbose) cp -a $(UPSTREAM_RMQ_COMPONENTS_MK) . ifeq ($(DO_COMMIT),yes) $(verbose) git diff --quiet rabbitmq-components.mk \ || git commit -m 'Update rabbitmq-components.mk' rabbitmq-components.mk endif endif rabbitmq-java-client-5.0.0/release-versions.txt000066400000000000000000000000751316117667700215600ustar00rootroot00000000000000RELEASE_VERSION="5.0.0" DEVELOPMENT_VERSION="5.0.1-SNAPSHOT" rabbitmq-java-client-5.0.0/src/000077500000000000000000000000001316117667700163165ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/main/000077500000000000000000000000001316117667700172425ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/main/java/000077500000000000000000000000001316117667700201635ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/main/java/com/000077500000000000000000000000001316117667700207415ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/000077500000000000000000000000001316117667700225425ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/000077500000000000000000000000001316117667700240205ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/Address.java000066400000000000000000000063631316117667700262600ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; /** * A representation of network addresses, i.e. host/port pairs, * with some utility functions for parsing address strings. */ public class Address { /** host name **/ private final String _host; /** port number **/ private final int _port; /** * Construct an address from a host name and port number. * @param host the host name * @param port the port number */ public Address(String host, int port) { _host = host; _port = port; } /** * Construct an address from a host. * @param host the host name */ public Address(String host) { _host = host; _port = ConnectionFactory.USE_DEFAULT_PORT; } /** * Get the host name * @return the host name */ public String getHost() { return _host; } /** * Get the port number * @return the port number */ public int getPort() { return _port; } /** * Factory method: takes a formatted addressString string as construction parameter * @param addressString an addressString of the form "host[:port]". * @return an {@link Address} from the given data */ public static Address parseAddress(String addressString) { int idx = addressString.indexOf(':'); return (idx == -1) ? new Address(addressString) : new Address(addressString.substring(0, idx), Integer.parseInt(addressString.substring(idx+1))); } /** * Array-based factory method: takes an array of formatted address strings as construction parameter * @param addresses array of strings of form "host[:port],..." * @return a list of {@link Address} values */ public static Address[] parseAddresses(String addresses) { String[] addrs = addresses.split(" *, *"); Address[] res = new Address[addrs.length]; for (int i = 0; i < addrs.length; i++) { res[i] = Address.parseAddress(addrs[i]); } return res; } @Override public int hashCode() { return 31 * _host.hashCode() + _port; } @Override public boolean equals(Object obj) { if(this == obj) return true; if (obj == null || getClass() != obj.getClass()) return false; final Address addr = (Address)obj; return _host.equals(addr._host) && _port == addr._port; } @Override public String toString() { return _port == -1 ? _host : _host + ":" + _port; } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/AddressResolver.java000066400000000000000000000022011316117667700277650ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; import java.io.IOException; import java.util.List; /** * Strategy interface to get the potential servers to connect to. */ public interface AddressResolver { /** * Get the potential {@link Address}es to connect to. * @return candidate {@link Address}es * @throws IOException if it encounters a problem */ List
getAddresses() throws IOException; } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/AlreadyClosedException.java000066400000000000000000000033071316117667700312600ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; /** * Thrown when application tries to perform an action on connection/channel * which was already closed */ public class AlreadyClosedException extends ShutdownSignalException { /** Default for suppressing warnings without version check. */ private static final long serialVersionUID = 1L; public AlreadyClosedException(ShutdownSignalException sse) { this(sse, null); } public AlreadyClosedException(ShutdownSignalException sse, Throwable cause) { super(sse.isHardError(), sse.isInitiatedByApplication(), sse.getReason(), sse.getReference(), composeMessagePrefix(sse), ((cause == null) ? sse.getCause() : cause)); } private static String composeMessagePrefix(ShutdownSignalException sse) { String connectionOrChannel = sse.isHardError() ? "connection " : "channel "; return connectionOrChannel + "is already closed due to "; } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/AuthenticationFailureException.java000066400000000000000000000020071316117667700330300ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; /** * Thrown when the broker refuses access due to an authentication failure. */ public class AuthenticationFailureException extends PossibleAuthenticationFailureException { public AuthenticationFailureException(String reason) { super(reason); } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/BasicProperties.java000066400000000000000000000063631316117667700277710ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; import java.util.Date; import java.util.Map; public interface BasicProperties { /** * Retrieve the value in the contentType field. * @return contentType field, or null if the field has not been set. */ public abstract String getContentType(); /** * Retrieve the value in the contentEncoding field. * @return contentEncoding field, or null if the field has not been set. */ public abstract String getContentEncoding(); /** * Retrieve the table in the headers field as a map of fields names and * values. * @return headers table, or null if the headers field has not been set. */ public abstract Map getHeaders(); /** * Retrieve the value in the deliveryMode field. * @return deliveryMode field, or null if the field has not been set. */ public abstract Integer getDeliveryMode(); /** * Retrieve the value in the priority field. * @return priority field, or null if the field has not been set. */ public abstract Integer getPriority(); /** * Retrieve the value in the correlationId field. * @return correlationId field, or null if the field has not been set. */ public abstract String getCorrelationId(); /** * Retrieve the value in the replyTo field. * @return replyTo field, or null if the field has not been set. */ public abstract String getReplyTo(); /** * Retrieve the value in the expiration field. * @return expiration field, or null if the field has not been set. */ public abstract String getExpiration(); /** * Retrieve the value in the messageId field. * @return messageId field, or null if the field has not been set. */ public abstract String getMessageId(); /** * Retrieve the value in the timestamp field. * @return timestamp field, or null if the field has not been set. */ public abstract Date getTimestamp(); /** * Retrieve the value in the type field. * @return type field, or null if the field has not been set. */ public abstract String getType(); /** * Retrieve the value in the userId field. * @return userId field, or null if the field has not been set. */ public abstract String getUserId(); /** * Retrieve the value in the appId field. * @return appId field, or null if the field has not been set. */ public abstract String getAppId(); } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/BlockedCallback.java000066400000000000000000000021221316117667700276400ustar00rootroot00000000000000// Copyright (c) 2017 Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; import java.io.IOException; /** * Implement this interface in order to be notified of connection block events. * Prefer it over {@link BlockedListener} for a lambda-oriented syntax. * @see BlockedListener * @see UnblockedCallback */ @FunctionalInterface public interface BlockedCallback { void handle(String reason) throws IOException; } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/BlockedListener.java000066400000000000000000000021561316117667700277400ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; import java.io.IOException; /** * Implement this interface in order to be notified of connection block and * unblock events. * For a lambda-oriented syntax, use {@link BlockedCallback} and * {@link UnblockedCallback}. */ public interface BlockedListener { void handleBlocked(String reason) throws IOException; void handleUnblocked() throws IOException; } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/BuiltinExchangeType.java000066400000000000000000000005361316117667700306020ustar00rootroot00000000000000package com.rabbitmq.client; /** * Enum for built-in exchange types. */ public enum BuiltinExchangeType { DIRECT("direct"), FANOUT("fanout"), TOPIC("topic"), HEADERS("headers"); private final String type; BuiltinExchangeType(String type) { this.type = type; } public String getType() { return type; } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/CancelCallback.java000066400000000000000000000037221316117667700274710ustar00rootroot00000000000000// Copyright (c) 2017 Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; import java.io.IOException; import java.util.Map; /** * Callback interface to be notified of the cancellation of a consumer. * Prefer it over {@link Consumer} for a lambda-oriented syntax, * if you don't need to implement all the application callbacks. * @see DeliverCallback * @see ConsumerShutdownSignalCallback * @see Channel#basicConsume(String, boolean, String, boolean, boolean, Map, DeliverCallback, CancelCallback) * @see Channel#basicConsume(String, boolean, String, boolean, boolean, Map, DeliverCallback, ConsumerShutdownSignalCallback) * @see Channel#basicConsume(String, boolean, String, boolean, boolean, Map, DeliverCallback, CancelCallback, ConsumerShutdownSignalCallback) * @since 5.0 */ @FunctionalInterface public interface CancelCallback { /** * Called when the consumer is cancelled for reasons other than by a call to * {@link Channel#basicCancel}. For example, the queue has been deleted. * See {@link Consumer#handleCancelOk} for notification of consumer * cancellation due to {@link Channel#basicCancel}. * @param consumerTag the consumer tag associated with the consumer * @throws IOException */ void handle(String consumerTag) throws IOException; } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/Channel.java000066400000000000000000002062701316117667700262420ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; import java.io.IOException; import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeoutException; import com.rabbitmq.client.AMQP.BasicProperties; import com.rabbitmq.client.AMQP.Exchange; import com.rabbitmq.client.AMQP.Queue; import com.rabbitmq.client.AMQP.Tx; import com.rabbitmq.client.AMQP.Basic; import com.rabbitmq.client.AMQP.Confirm; /** * Interface to a channel. All non-deprecated methods of * this interface are part of the public API. * *

Tutorials

* RabbitMQ tutorials demonstrate how * key methods of this interface are used. * *

User Guide

* See Java Client User Guide. * *

Concurrency Considerations

*

* {@link Channel} instances must not be shared between * threads. Applications * should prefer using a {@link Channel} per thread * instead of sharing the same {@link Channel} across * multiple threads. While some operations on channels are safe to invoke * concurrently, some are not and will result in incorrect frame interleaving * on the wire. Sharing channels between threads will also interfere with * Publisher Confirms. * * As such, applications need to use a {@link Channel} per thread. *

* * @see RabbitMQ tutorials * @see RabbitMQ Java Client User Guide */ public interface Channel extends ShutdownNotifier, AutoCloseable { /** * Retrieve this channel's channel number. * @return the channel number */ int getChannelNumber(); /** * Retrieve the connection which carries this channel. * @return the underlying {@link Connection} */ Connection getConnection(); /** * Close this channel with the {@link com.rabbitmq.client.AMQP#REPLY_SUCCESS} close code * and message 'OK'. * * @throws java.io.IOException if an error is encountered */ @Override void close() throws IOException, TimeoutException; /** * Close this channel. * * @param closeCode the close code (See under "Reply Codes" in the AMQP specification) * @param closeMessage a message indicating the reason for closing the connection * @throws java.io.IOException if an error is encountered */ void close(int closeCode, String closeMessage) throws IOException, TimeoutException; /** * Abort this channel with the {@link com.rabbitmq.client.AMQP#REPLY_SUCCESS} close code * and message 'OK'. * * Forces the channel to close and waits for the close operation to complete. * Any encountered exceptions in the close operation are silently discarded. */ void abort() throws IOException; /** * Abort this channel. * * Forces the channel to close and waits for the close operation to complete. * Any encountered exceptions in the close operation are silently discarded. */ void abort(int closeCode, String closeMessage) throws IOException; /** * Add a {@link ReturnListener}. * @param listener the listener to add */ void addReturnListener(ReturnListener listener); /** * Add a lambda-based {@link ReturnListener}. * @see ReturnListener * @see ReturnCallback * @see Return * @param returnCallback the callback when the message is returned * @return the listener that wraps the callback */ ReturnListener addReturnListener(ReturnCallback returnCallback); /** * Remove a {@link ReturnListener}. * @param listener the listener to remove * @return true if the listener was found and removed, * false otherwise */ boolean removeReturnListener(ReturnListener listener); /** * Remove all {@link ReturnListener}s. */ void clearReturnListeners(); /** * Add a {@link ConfirmListener}. * @param listener the listener to add */ void addConfirmListener(ConfirmListener listener); /** * Add a lambda-based {@link ConfirmListener}. * @see ConfirmListener * @see ConfirmCallback * @param ackCallback callback on ack * @param nackCallback call on nack (negative ack) * @return the listener that wraps the callbacks */ ConfirmListener addConfirmListener(ConfirmCallback ackCallback, ConfirmCallback nackCallback); /** * Remove a {@link ConfirmListener}. * @param listener the listener to remove * @return true if the listener was found and removed, * false otherwise */ boolean removeConfirmListener(ConfirmListener listener); /** * Remove all {@link ConfirmListener}s. */ void clearConfirmListeners(); /** * Get the current default consumer. @see setDefaultConsumer for rationale. * @return an interface to the current default consumer. */ Consumer getDefaultConsumer(); /** * Set the current default consumer. * * Under certain circumstances it is possible for a channel to receive a * message delivery which does not match any consumer which is currently * set up via basicConsume(). This will occur after the following sequence * of events: * * ctag = basicConsume(queue, consumer); // i.e. with explicit acks * // some deliveries take place but are not acked * basicCancel(ctag); * basicRecover(false); * * Since requeue is specified to be false in the basicRecover, the spec * states that the message must be redelivered to "the original recipient" * - i.e. the same channel / consumer-tag. But the consumer is no longer * active. * * In these circumstances, you can register a default consumer to handle * such deliveries. If no default consumer is registered an * IllegalStateException will be thrown when such a delivery arrives. * * Most people will not need to use this. * * @param consumer the consumer to use, or null indicating "don't use one". */ void setDefaultConsumer(Consumer consumer); /** * Request specific "quality of service" settings. * * These settings impose limits on the amount of data the server * will deliver to consumers before requiring acknowledgements. * Thus they provide a means of consumer-initiated flow control. * @see com.rabbitmq.client.AMQP.Basic.Qos * @param prefetchSize maximum amount of content (measured in * octets) that the server will deliver, 0 if unlimited * @param prefetchCount maximum number of messages that the server * will deliver, 0 if unlimited * @param global true if the settings should be applied to the * entire channel rather than each consumer * @throws java.io.IOException if an error is encountered */ void basicQos(int prefetchSize, int prefetchCount, boolean global) throws IOException; /** * Request a specific prefetchCount "quality of service" settings * for this channel. * * @see #basicQos(int, int, boolean) * @param prefetchCount maximum number of messages that the server * will deliver, 0 if unlimited * @param global true if the settings should be applied to the * entire channel rather than each consumer * @throws java.io.IOException if an error is encountered */ void basicQos(int prefetchCount, boolean global) throws IOException; /** * Request a specific prefetchCount "quality of service" settings * for this channel. * * @see #basicQos(int, int, boolean) * @param prefetchCount maximum number of messages that the server * will deliver, 0 if unlimited * @throws java.io.IOException if an error is encountered */ void basicQos(int prefetchCount) throws IOException; /** * Publish a message. * * Publishing to a non-existent exchange will result in a channel-level * protocol exception, which closes the channel. * * Invocations of Channel#basicPublish will eventually block if a * resource-driven alarm is in effect. * * @see com.rabbitmq.client.AMQP.Basic.Publish * @see Resource-driven alarms * @param exchange the exchange to publish the message to * @param routingKey the routing key * @param props other properties for the message - routing headers etc * @param body the message body * @throws java.io.IOException if an error is encountered */ void basicPublish(String exchange, String routingKey, BasicProperties props, byte[] body) throws IOException; /** * Publish a message. * * Invocations of Channel#basicPublish will eventually block if a * resource-driven alarm is in effect. * * @see com.rabbitmq.client.AMQP.Basic.Publish * @see Resource-driven alarms * @param exchange the exchange to publish the message to * @param routingKey the routing key * @param mandatory true if the 'mandatory' flag is to be set * @param props other properties for the message - routing headers etc * @param body the message body * @throws java.io.IOException if an error is encountered */ void basicPublish(String exchange, String routingKey, boolean mandatory, BasicProperties props, byte[] body) throws IOException; /** * Publish a message. * * Publishing to a non-existent exchange will result in a channel-level * protocol exception, which closes the channel. * * Invocations of Channel#basicPublish will eventually block if a * resource-driven alarm is in effect. * * @see com.rabbitmq.client.AMQP.Basic.Publish * @see Resource-driven alarms * @param exchange the exchange to publish the message to * @param routingKey the routing key * @param mandatory true if the 'mandatory' flag is to be set * @param immediate true if the 'immediate' flag is to be * set. Note that the RabbitMQ server does not support this flag. * @param props other properties for the message - routing headers etc * @param body the message body * @throws java.io.IOException if an error is encountered */ void basicPublish(String exchange, String routingKey, boolean mandatory, boolean immediate, BasicProperties props, byte[] body) throws IOException; /** * Actively declare a non-autodelete, non-durable exchange with no extra arguments * @see com.rabbitmq.client.AMQP.Exchange.Declare * @see com.rabbitmq.client.AMQP.Exchange.DeclareOk * @param exchange the name of the exchange * @param type the exchange type * @return a declaration-confirm method to indicate the exchange was successfully declared * @throws java.io.IOException if an error is encountered */ Exchange.DeclareOk exchangeDeclare(String exchange, String type) throws IOException; /** * Actively declare a non-autodelete, non-durable exchange with no extra arguments * @see com.rabbitmq.client.AMQP.Exchange.Declare * @see com.rabbitmq.client.AMQP.Exchange.DeclareOk * @param exchange the name of the exchange * @param type the exchange type * @return a declaration-confirm method to indicate the exchange was successfully declared * @throws java.io.IOException if an error is encountered */ Exchange.DeclareOk exchangeDeclare(String exchange, BuiltinExchangeType type) throws IOException; /** * Actively declare a non-autodelete exchange with no extra arguments * @see com.rabbitmq.client.AMQP.Exchange.Declare * @see com.rabbitmq.client.AMQP.Exchange.DeclareOk * @param exchange the name of the exchange * @param type the exchange type * @param durable true if we are declaring a durable exchange (the exchange will survive a server restart) * @throws java.io.IOException if an error is encountered * @return a declaration-confirm method to indicate the exchange was successfully declared */ Exchange.DeclareOk exchangeDeclare(String exchange, String type, boolean durable) throws IOException; /** * Actively declare a non-autodelete exchange with no extra arguments * @see com.rabbitmq.client.AMQP.Exchange.Declare * @see com.rabbitmq.client.AMQP.Exchange.DeclareOk * @param exchange the name of the exchange * @param type the exchange type * @param durable true if we are declaring a durable exchange (the exchange will survive a server restart) * @throws java.io.IOException if an error is encountered * @return a declaration-confirm method to indicate the exchange was successfully declared */ Exchange.DeclareOk exchangeDeclare(String exchange, BuiltinExchangeType type, boolean durable) throws IOException; /** * Declare an exchange. * @see com.rabbitmq.client.AMQP.Exchange.Declare * @see com.rabbitmq.client.AMQP.Exchange.DeclareOk * @param exchange the name of the exchange * @param type the exchange type * @param durable true if we are declaring a durable exchange (the exchange will survive a server restart) * @param autoDelete true if the server should delete the exchange when it is no longer in use * @param arguments other properties (construction arguments) for the exchange * @return a declaration-confirm method to indicate the exchange was successfully declared * @throws java.io.IOException if an error is encountered */ Exchange.DeclareOk exchangeDeclare(String exchange, String type, boolean durable, boolean autoDelete, Map arguments) throws IOException; /** * Declare an exchange. * @see com.rabbitmq.client.AMQP.Exchange.Declare * @see com.rabbitmq.client.AMQP.Exchange.DeclareOk * @param exchange the name of the exchange * @param type the exchange type * @param durable true if we are declaring a durable exchange (the exchange will survive a server restart) * @param autoDelete true if the server should delete the exchange when it is no longer in use * @param arguments other properties (construction arguments) for the exchange * @return a declaration-confirm method to indicate the exchange was successfully declared * @throws java.io.IOException if an error is encountered */ Exchange.DeclareOk exchangeDeclare(String exchange, BuiltinExchangeType type, boolean durable, boolean autoDelete, Map arguments) throws IOException; /** * Declare an exchange, via an interface that allows the complete set of * arguments. * @see com.rabbitmq.client.AMQP.Exchange.Declare * @see com.rabbitmq.client.AMQP.Exchange.DeclareOk * @param exchange the name of the exchange * @param type the exchange type * @param durable true if we are declaring a durable exchange (the exchange will survive a server restart) * @param autoDelete true if the server should delete the exchange when it is no longer in use * @param internal true if the exchange is internal, i.e. can't be directly * published to by a client. * @param arguments other properties (construction arguments) for the exchange * @return a declaration-confirm method to indicate the exchange was successfully declared * @throws java.io.IOException if an error is encountered */ Exchange.DeclareOk exchangeDeclare(String exchange, String type, boolean durable, boolean autoDelete, boolean internal, Map arguments) throws IOException; /** * Declare an exchange, via an interface that allows the complete set of * arguments. * @see com.rabbitmq.client.AMQP.Exchange.Declare * @see com.rabbitmq.client.AMQP.Exchange.DeclareOk * @param exchange the name of the exchange * @param type the exchange type * @param durable true if we are declaring a durable exchange (the exchange will survive a server restart) * @param autoDelete true if the server should delete the exchange when it is no longer in use * @param internal true if the exchange is internal, i.e. can't be directly * published to by a client. * @param arguments other properties (construction arguments) for the exchange * @return a declaration-confirm method to indicate the exchange was successfully declared * @throws java.io.IOException if an error is encountered */ Exchange.DeclareOk exchangeDeclare(String exchange, BuiltinExchangeType type, boolean durable, boolean autoDelete, boolean internal, Map arguments) throws IOException; /** * Like {@link Channel#exchangeDeclare(String, String, boolean, boolean, java.util.Map)} but * sets nowait parameter to true and returns nothing (as there will be no response from * the server). * * @param exchange the name of the exchange * @param type the exchange type * @param durable true if we are declaring a durable exchange (the exchange will survive a server restart) * @param autoDelete true if the server should delete the exchange when it is no longer in use * @param internal true if the exchange is internal, i.e. can't be directly * published to by a client. * @param arguments other properties (construction arguments) for the exchange * @throws java.io.IOException if an error is encountered */ void exchangeDeclareNoWait(String exchange, String type, boolean durable, boolean autoDelete, boolean internal, Map arguments) throws IOException; /** * Like {@link Channel#exchangeDeclare(String, String, boolean, boolean, java.util.Map)} but * sets nowait parameter to true and returns nothing (as there will be no response from * the server). * * @param exchange the name of the exchange * @param type the exchange type * @param durable true if we are declaring a durable exchange (the exchange will survive a server restart) * @param autoDelete true if the server should delete the exchange when it is no longer in use * @param internal true if the exchange is internal, i.e. can't be directly * published to by a client. * @param arguments other properties (construction arguments) for the exchange * @throws java.io.IOException if an error is encountered */ void exchangeDeclareNoWait(String exchange, BuiltinExchangeType type, boolean durable, boolean autoDelete, boolean internal, Map arguments) throws IOException; /** * Declare an exchange passively; that is, check if the named exchange exists. * @param name check the existence of an exchange named this * @throws IOException the server will raise a 404 channel exception if the named exchange does not exist. */ Exchange.DeclareOk exchangeDeclarePassive(String name) throws IOException; /** * Delete an exchange * @see com.rabbitmq.client.AMQP.Exchange.Delete * @see com.rabbitmq.client.AMQP.Exchange.DeleteOk * @param exchange the name of the exchange * @param ifUnused true to indicate that the exchange is only to be deleted if it is unused * @return a deletion-confirm method to indicate the exchange was successfully deleted * @throws java.io.IOException if an error is encountered */ Exchange.DeleteOk exchangeDelete(String exchange, boolean ifUnused) throws IOException; /** * Like {@link Channel#exchangeDelete(String, boolean)} but sets nowait parameter to true * and returns void (as there will be no response from the server). * @see com.rabbitmq.client.AMQP.Exchange.Delete * @see com.rabbitmq.client.AMQP.Exchange.DeleteOk * @param exchange the name of the exchange * @param ifUnused true to indicate that the exchange is only to be deleted if it is unused * @throws java.io.IOException if an error is encountered */ void exchangeDeleteNoWait(String exchange, boolean ifUnused) throws IOException; /** * Delete an exchange, without regard for whether it is in use or not * @see com.rabbitmq.client.AMQP.Exchange.Delete * @see com.rabbitmq.client.AMQP.Exchange.DeleteOk * @param exchange the name of the exchange * @return a deletion-confirm method to indicate the exchange was successfully deleted * @throws java.io.IOException if an error is encountered */ Exchange.DeleteOk exchangeDelete(String exchange) throws IOException; /** * Bind an exchange to an exchange, with no extra arguments. * @see com.rabbitmq.client.AMQP.Exchange.Bind * @see com.rabbitmq.client.AMQP.Exchange.BindOk * @param destination the name of the exchange to which messages flow across the binding * @param source the name of the exchange from which messages flow across the binding * @param routingKey the routing key to use for the binding * @return a binding-confirm method if the binding was successfully created * @throws java.io.IOException if an error is encountered */ Exchange.BindOk exchangeBind(String destination, String source, String routingKey) throws IOException; /** * Bind an exchange to an exchange. * @see com.rabbitmq.client.AMQP.Exchange.Bind * @see com.rabbitmq.client.AMQP.Exchange.BindOk * @param destination the name of the exchange to which messages flow across the binding * @param source the name of the exchange from which messages flow across the binding * @param routingKey the routing key to use for the binding * @param arguments other properties (binding parameters) * @return a binding-confirm method if the binding was successfully created * @throws java.io.IOException if an error is encountered */ Exchange.BindOk exchangeBind(String destination, String source, String routingKey, Map arguments) throws IOException; /** * Like {@link Channel#exchangeBind(String, String, String, java.util.Map)} but sets nowait parameter * to true and returns void (as there will be no response from the server). * @param destination the name of the exchange to which messages flow across the binding * @param source the name of the exchange from which messages flow across the binding * @param routingKey the routing key to use for the binding * @param arguments other properties (binding parameters) * @throws java.io.IOException if an error is encountered */ void exchangeBindNoWait(String destination, String source, String routingKey, Map arguments) throws IOException; /** * Unbind an exchange from an exchange, with no extra arguments. * @see com.rabbitmq.client.AMQP.Exchange.Bind * @see com.rabbitmq.client.AMQP.Exchange.BindOk * @param destination the name of the exchange to which messages flow across the binding * @param source the name of the exchange from which messages flow across the binding * @param routingKey the routing key to use for the binding * @return a binding-confirm method if the binding was successfully created * @throws java.io.IOException if an error is encountered */ Exchange.UnbindOk exchangeUnbind(String destination, String source, String routingKey) throws IOException; /** * Unbind an exchange from an exchange. * @see com.rabbitmq.client.AMQP.Exchange.Bind * @see com.rabbitmq.client.AMQP.Exchange.BindOk * @param destination the name of the exchange to which messages flow across the binding * @param source the name of the exchange from which messages flow across the binding * @param routingKey the routing key to use for the binding * @param arguments other properties (binding parameters) * @return a binding-confirm method if the binding was successfully created * @throws java.io.IOException if an error is encountered */ Exchange.UnbindOk exchangeUnbind(String destination, String source, String routingKey, Map arguments) throws IOException; /** * Same as {@link Channel#exchangeUnbind(String, String, String, java.util.Map)} but sets no-wait parameter to true * and returns nothing (as there will be no response from the server). * @param destination the name of the exchange to which messages flow across the binding * @param source the name of the exchange from which messages flow across the binding * @param routingKey the routing key to use for the binding * @param arguments other properties (binding parameters) * @throws java.io.IOException if an error is encountered */ void exchangeUnbindNoWait(String destination, String source, String routingKey, Map arguments) throws IOException; /** * Actively declare a server-named exclusive, autodelete, non-durable queue. * The name of the new queue is held in the "queue" field of the {@link com.rabbitmq.client.AMQP.Queue.DeclareOk} result. * @see com.rabbitmq.client.AMQP.Queue.Declare * @see com.rabbitmq.client.AMQP.Queue.DeclareOk * @return a declaration-confirm method to indicate the queue was successfully declared * @throws java.io.IOException if an error is encountered */ Queue.DeclareOk queueDeclare() throws IOException; /** * Declare a queue * @see com.rabbitmq.client.AMQP.Queue.Declare * @see com.rabbitmq.client.AMQP.Queue.DeclareOk * @param queue the name of the queue * @param durable true if we are declaring a durable queue (the queue will survive a server restart) * @param exclusive true if we are declaring an exclusive queue (restricted to this connection) * @param autoDelete true if we are declaring an autodelete queue (server will delete it when no longer in use) * @param arguments other properties (construction arguments) for the queue * @return a declaration-confirm method to indicate the queue was successfully declared * @throws java.io.IOException if an error is encountered */ Queue.DeclareOk queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete, Map arguments) throws IOException; /** * Like {@link Channel#queueDeclare(String, boolean, boolean, boolean, java.util.Map)} but sets nowait * flag to true and returns no result (as there will be no response from the server). * @param queue the name of the queue * @param durable true if we are declaring a durable queue (the queue will survive a server restart) * @param exclusive true if we are declaring an exclusive queue (restricted to this connection) * @param autoDelete true if we are declaring an autodelete queue (server will delete it when no longer in use) * @param arguments other properties (construction arguments) for the queue * @throws java.io.IOException if an error is encountered */ void queueDeclareNoWait(String queue, boolean durable, boolean exclusive, boolean autoDelete, Map arguments) throws IOException; /** * Declare a queue passively; i.e., check if it exists. In AMQP * 0-9-1, all arguments aside from nowait are ignored; and sending * nowait makes this method a no-op, so we default it to false. * @see com.rabbitmq.client.AMQP.Queue.Declare * @see com.rabbitmq.client.AMQP.Queue.DeclareOk * @param queue the name of the queue * @return a declaration-confirm method to indicate the queue exists * @throws java.io.IOException if an error is encountered, * including if the queue does not exist and if the queue is * exclusively owned by another connection. */ Queue.DeclareOk queueDeclarePassive(String queue) throws IOException; /** * Delete a queue, without regard for whether it is in use or has messages on it * @see com.rabbitmq.client.AMQP.Queue.Delete * @see com.rabbitmq.client.AMQP.Queue.DeleteOk * @param queue the name of the queue * @return a deletion-confirm method to indicate the queue was successfully deleted * @throws java.io.IOException if an error is encountered */ Queue.DeleteOk queueDelete(String queue) throws IOException; /** * Delete a queue * @see com.rabbitmq.client.AMQP.Queue.Delete * @see com.rabbitmq.client.AMQP.Queue.DeleteOk * @param queue the name of the queue * @param ifUnused true if the queue should be deleted only if not in use * @param ifEmpty true if the queue should be deleted only if empty * @return a deletion-confirm method to indicate the queue was successfully deleted * @throws java.io.IOException if an error is encountered */ Queue.DeleteOk queueDelete(String queue, boolean ifUnused, boolean ifEmpty) throws IOException; /** * Like {@link Channel#queueDelete(String, boolean, boolean)} but sets nowait parameter * to true and returns nothing (as there will be no response from the server). * @see com.rabbitmq.client.AMQP.Queue.Delete * @see com.rabbitmq.client.AMQP.Queue.DeleteOk * @param queue the name of the queue * @param ifUnused true if the queue should be deleted only if not in use * @param ifEmpty true if the queue should be deleted only if empty * @throws java.io.IOException if an error is encountered */ void queueDeleteNoWait(String queue, boolean ifUnused, boolean ifEmpty) throws IOException; /** * Bind a queue to an exchange, with no extra arguments. * @see com.rabbitmq.client.AMQP.Queue.Bind * @see com.rabbitmq.client.AMQP.Queue.BindOk * @param queue the name of the queue * @param exchange the name of the exchange * @param routingKey the routing key to use for the binding * @return a binding-confirm method if the binding was successfully created * @throws java.io.IOException if an error is encountered */ Queue.BindOk queueBind(String queue, String exchange, String routingKey) throws IOException; /** * Bind a queue to an exchange. * @see com.rabbitmq.client.AMQP.Queue.Bind * @see com.rabbitmq.client.AMQP.Queue.BindOk * @param queue the name of the queue * @param exchange the name of the exchange * @param routingKey the routing key to use for the binding * @param arguments other properties (binding parameters) * @return a binding-confirm method if the binding was successfully created * @throws java.io.IOException if an error is encountered */ Queue.BindOk queueBind(String queue, String exchange, String routingKey, Map arguments) throws IOException; /** * Same as {@link Channel#queueBind(String, String, String, java.util.Map)} but sets nowait * parameter to true and returns void (as there will be no response * from the server). * @param queue the name of the queue * @param exchange the name of the exchange * @param routingKey the routing key to use for the binding * @param arguments other properties (binding parameters) * @throws java.io.IOException if an error is encountered */ void queueBindNoWait(String queue, String exchange, String routingKey, Map arguments) throws IOException; /** * Unbinds a queue from an exchange, with no extra arguments. * @see com.rabbitmq.client.AMQP.Queue.Unbind * @see com.rabbitmq.client.AMQP.Queue.UnbindOk * @param queue the name of the queue * @param exchange the name of the exchange * @param routingKey the routing key to use for the binding * @return an unbinding-confirm method if the binding was successfully deleted * @throws java.io.IOException if an error is encountered */ Queue.UnbindOk queueUnbind(String queue, String exchange, String routingKey) throws IOException; /** * Unbind a queue from an exchange. * @see com.rabbitmq.client.AMQP.Queue.Unbind * @see com.rabbitmq.client.AMQP.Queue.UnbindOk * @param queue the name of the queue * @param exchange the name of the exchange * @param routingKey the routing key to use for the binding * @param arguments other properties (binding parameters) * @return an unbinding-confirm method if the binding was successfully deleted * @throws java.io.IOException if an error is encountered */ Queue.UnbindOk queueUnbind(String queue, String exchange, String routingKey, Map arguments) throws IOException; /** * Purges the contents of the given queue. * @see com.rabbitmq.client.AMQP.Queue.Purge * @see com.rabbitmq.client.AMQP.Queue.PurgeOk * @param queue the name of the queue * @return a purge-confirm method if the purge was executed successfully * @throws java.io.IOException if an error is encountered */ Queue.PurgeOk queuePurge(String queue) throws IOException; /** * Retrieve a message from a queue using {@link com.rabbitmq.client.AMQP.Basic.Get} * @see com.rabbitmq.client.AMQP.Basic.Get * @see com.rabbitmq.client.AMQP.Basic.GetOk * @see com.rabbitmq.client.AMQP.Basic.GetEmpty * @param queue the name of the queue * @param autoAck true if the server should consider messages * acknowledged once delivered; false if the server should expect * explicit acknowledgements * @return a {@link GetResponse} containing the retrieved message data * @throws java.io.IOException if an error is encountered */ GetResponse basicGet(String queue, boolean autoAck) throws IOException; /** * Acknowledge one or several received * messages. Supply the deliveryTag from the {@link com.rabbitmq.client.AMQP.Basic.GetOk} * or {@link com.rabbitmq.client.AMQP.Basic.Deliver} method * containing the received message being acknowledged. * @see com.rabbitmq.client.AMQP.Basic.Ack * @param deliveryTag the tag from the received {@link com.rabbitmq.client.AMQP.Basic.GetOk} or {@link com.rabbitmq.client.AMQP.Basic.Deliver} * @param multiple true to acknowledge all messages up to and * including the supplied delivery tag; false to acknowledge just * the supplied delivery tag. * @throws java.io.IOException if an error is encountered */ void basicAck(long deliveryTag, boolean multiple) throws IOException; /** * Reject one or several received messages. * * Supply the deliveryTag from the {@link com.rabbitmq.client.AMQP.Basic.GetOk} * or {@link com.rabbitmq.client.AMQP.Basic.GetOk} method containing the message to be rejected. * @see com.rabbitmq.client.AMQP.Basic.Nack * @param deliveryTag the tag from the received {@link com.rabbitmq.client.AMQP.Basic.GetOk} or {@link com.rabbitmq.client.AMQP.Basic.Deliver} * @param multiple true to reject all messages up to and including * the supplied delivery tag; false to reject just the supplied * delivery tag. * @param requeue true if the rejected message(s) should be requeued rather * than discarded/dead-lettered * @throws java.io.IOException if an error is encountered */ void basicNack(long deliveryTag, boolean multiple, boolean requeue) throws IOException; /** * Reject a message. Supply the deliveryTag from the {@link com.rabbitmq.client.AMQP.Basic.GetOk} * or {@link com.rabbitmq.client.AMQP.Basic.Deliver} method * containing the received message being rejected. * @see com.rabbitmq.client.AMQP.Basic.Reject * @param deliveryTag the tag from the received {@link com.rabbitmq.client.AMQP.Basic.GetOk} or {@link com.rabbitmq.client.AMQP.Basic.Deliver} * @param requeue true if the rejected message should be requeued rather than discarded/dead-lettered * @throws java.io.IOException if an error is encountered */ void basicReject(long deliveryTag, boolean requeue) throws IOException; /** * Start a non-nolocal, non-exclusive consumer, with * explicit acknowledgement and a server-generated consumerTag. * @param queue the name of the queue * @param callback an interface to the consumer object * @return the consumerTag generated by the server * @throws java.io.IOException if an error is encountered * @see com.rabbitmq.client.AMQP.Basic.Consume * @see com.rabbitmq.client.AMQP.Basic.ConsumeOk * @see #basicAck * @see #basicConsume(String, boolean, String, boolean, boolean, Map, Consumer) */ String basicConsume(String queue, Consumer callback) throws IOException; /** * Start a non-nolocal, non-exclusive consumer, with * explicit acknowledgement and a server-generated consumerTag. * Provide access only to basic.deliver and * basic.cancel AMQP methods (which is sufficient * for most cases). See methods with a {@link Consumer} argument * to have access to all the application callbacks. * @param queue the name of the queue * @param deliverCallback callback when a message is delivered * @param cancelCallback callback when the consumer is cancelled * @return the consumerTag generated by the server * @throws IOException if an error is encountered * @see com.rabbitmq.client.AMQP.Basic.Consume * @see com.rabbitmq.client.AMQP.Basic.ConsumeOk * @see #basicAck * @see #basicConsume(String, boolean, String, boolean, boolean, Map, Consumer) * @since 5.0 */ String basicConsume(String queue, DeliverCallback deliverCallback, CancelCallback cancelCallback) throws IOException; /** * Start a non-nolocal, non-exclusive consumer, with * explicit acknowledgement and a server-generated consumerTag. * Provide access only to basic.deliver and * shutdown signal callbacks (which is sufficient * for most cases). See methods with a {@link Consumer} argument * to have access to all the application callbacks. * @param queue the name of the queue * @param deliverCallback callback when a message is delivered * @param shutdownSignalCallback callback when the channel/connection is shut down * @return the consumerTag generated by the server * @throws IOException if an error is encountered * @see com.rabbitmq.client.AMQP.Basic.Consume * @see com.rabbitmq.client.AMQP.Basic.ConsumeOk * @see #basicAck * @see #basicConsume(String, boolean, String, boolean, boolean, Map, Consumer) * @since 5.0 */ String basicConsume(String queue, DeliverCallback deliverCallback, ConsumerShutdownSignalCallback shutdownSignalCallback) throws IOException; /** * Start a non-nolocal, non-exclusive consumer, with * explicit acknowledgement and a server-generated consumerTag. * Provide access to basic.deliver, basic.cancel * and shutdown signal callbacks (which is sufficient * for most cases). See methods with a {@link Consumer} argument * to have access to all the application callbacks. * @param queue the name of the queue * @param deliverCallback callback when a message is delivered * @param cancelCallback callback when the consumer is cancelled * @param shutdownSignalCallback callback when the channel/connection is shut down * @return the consumerTag generated by the server * @throws IOException if an error is encountered * @see com.rabbitmq.client.AMQP.Basic.Consume * @see com.rabbitmq.client.AMQP.Basic.ConsumeOk * @see #basicAck * @see #basicConsume(String, boolean, String, boolean, boolean, Map, Consumer) * @since 5.0 */ String basicConsume(String queue, DeliverCallback deliverCallback, CancelCallback cancelCallback, ConsumerShutdownSignalCallback shutdownSignalCallback) throws IOException; /** * Start a non-nolocal, non-exclusive consumer, with * a server-generated consumerTag. * @param queue the name of the queue * @param autoAck true if the server should consider messages * acknowledged once delivered; false if the server should expect * explicit acknowledgements * @param callback an interface to the consumer object * @return the consumerTag generated by the server * @throws java.io.IOException if an error is encountered * @see com.rabbitmq.client.AMQP.Basic.Consume * @see com.rabbitmq.client.AMQP.Basic.ConsumeOk * @see #basicConsume(String, boolean, String, boolean, boolean, Map, Consumer) */ String basicConsume(String queue, boolean autoAck, Consumer callback) throws IOException; /** * Start a non-nolocal, non-exclusive consumer, with * a server-generated consumerTag. * Provide access only to basic.deliver and * basic.cancel AMQP methods (which is sufficient * for most cases). See methods with a {@link Consumer} argument * to have access to all the application callbacks. * @param queue the name of the queue * @param autoAck true if the server should consider messages * acknowledged once delivered; false if the server should expect * explicit acknowledgements * @param deliverCallback callback when a message is delivered * @param cancelCallback callback when the consumer is cancelled * @return the consumerTag generated by the server * @throws IOException if an error is encountered * @see com.rabbitmq.client.AMQP.Basic.Consume * @see com.rabbitmq.client.AMQP.Basic.ConsumeOk * @see #basicAck * @see #basicConsume(String, boolean, String, boolean, boolean, Map, Consumer) * @since 5.0 */ String basicConsume(String queue, boolean autoAck, DeliverCallback deliverCallback, CancelCallback cancelCallback) throws IOException; /** * Start a non-nolocal, non-exclusive consumer, with * a server-generated consumerTag. * Provide access only to basic.deliver and * shutdown signal callbacks (which is sufficient * for most cases). See methods with a {@link Consumer} argument * to have access to all the application callbacks. * @param queue the name of the queue * @param autoAck true if the server should consider messages * acknowledged once delivered; false if the server should expect * explicit acknowledgements * @param deliverCallback callback when a message is delivered * @param shutdownSignalCallback callback when the channel/connection is shut down * @return the consumerTag generated by the server * @throws IOException if an error is encountered * @see com.rabbitmq.client.AMQP.Basic.Consume * @see com.rabbitmq.client.AMQP.Basic.ConsumeOk * @see #basicAck * @see #basicConsume(String, boolean, String, boolean, boolean, Map, Consumer) * @since 5.0 */ String basicConsume(String queue, boolean autoAck, DeliverCallback deliverCallback, ConsumerShutdownSignalCallback shutdownSignalCallback) throws IOException; /** * Start a non-nolocal, non-exclusive consumer, with * a server-generated consumerTag. * Provide access to basic.deliver, basic.cancel * and shutdown signal callbacks (which is sufficient * for most cases). See methods with a {@link Consumer} argument * to have access to all the application callbacks. * @param queue the name of the queue * @param autoAck true if the server should consider messages * acknowledged once delivered; false if the server should expect * explicit acknowledgements * @param deliverCallback callback when a message is delivered * @param cancelCallback callback when the consumer is cancelled * @param shutdownSignalCallback callback when the channel/connection is shut down * @return the consumerTag generated by the server * @throws IOException if an error is encountered * @see com.rabbitmq.client.AMQP.Basic.Consume * @see com.rabbitmq.client.AMQP.Basic.ConsumeOk * @see #basicAck * @see #basicConsume(String, boolean, String, boolean, boolean, Map, Consumer) * @since 5.0 */ String basicConsume(String queue, boolean autoAck, DeliverCallback deliverCallback, CancelCallback cancelCallback, ConsumerShutdownSignalCallback shutdownSignalCallback) throws IOException; /** * Start a non-nolocal, non-exclusive consumer, with * a server-generated consumerTag and specified arguments. * @param queue the name of the queue * @param autoAck true if the server should consider messages * acknowledged once delivered; false if the server should expect * explicit acknowledgements * @param arguments a set of arguments for the consume * @param callback an interface to the consumer object * @return the consumerTag generated by the server * @throws java.io.IOException if an error is encountered * @see com.rabbitmq.client.AMQP.Basic.Consume * @see com.rabbitmq.client.AMQP.Basic.ConsumeOk * @see #basicConsume(String, boolean, String, boolean, boolean, Map, Consumer) */ String basicConsume(String queue, boolean autoAck, Map arguments, Consumer callback) throws IOException; /** * Start a non-nolocal, non-exclusive consumer, with * a server-generated consumerTag and specified arguments. * Provide access only to basic.deliver and * basic.cancel AMQP methods (which is sufficient * for most cases). See methods with a {@link Consumer} argument * to have access to all the application callbacks. * @param queue the name of the queue * @param autoAck true if the server should consider messages * acknowledged once delivered; false if the server should expect * explicit acknowledgements * @param arguments a set of arguments for the consume * @param deliverCallback callback when a message is delivered * @param cancelCallback callback when the consumer is cancelled * @return the consumerTag generated by the server * @throws IOException if an error is encountered * @see com.rabbitmq.client.AMQP.Basic.Consume * @see com.rabbitmq.client.AMQP.Basic.ConsumeOk * @see #basicAck * @see #basicConsume(String, boolean, String, boolean, boolean, Map, Consumer) * @since 5.0 */ String basicConsume(String queue, boolean autoAck, Map arguments, DeliverCallback deliverCallback, CancelCallback cancelCallback) throws IOException; /** * Start a non-nolocal, non-exclusive consumer, with * a server-generated consumerTag and specified arguments. * Provide access only to basic.deliver and * shutdown signal callbacks (which is sufficient * for most cases). See methods with a {@link Consumer} argument * to have access to all the application callbacks. * @param queue the name of the queue * @param autoAck true if the server should consider messages * acknowledged once delivered; false if the server should expect * explicit acknowledgements * @param arguments a set of arguments for the consume * @param deliverCallback callback when a message is delivered * @param shutdownSignalCallback callback when the channel/connection is shut down * @return the consumerTag generated by the server * @throws IOException if an error is encountered * @see com.rabbitmq.client.AMQP.Basic.Consume * @see com.rabbitmq.client.AMQP.Basic.ConsumeOk * @see #basicAck * @see #basicConsume(String, boolean, String, boolean, boolean, Map, Consumer) * @since 5.0 */ String basicConsume(String queue, boolean autoAck, Map arguments, DeliverCallback deliverCallback, ConsumerShutdownSignalCallback shutdownSignalCallback) throws IOException; /** * Start a non-nolocal, non-exclusive consumer, with * a server-generated consumerTag and specified arguments. * Provide access to basic.deliver, basic.cancel * and shutdown signal callbacks (which is sufficient * for most cases). See methods with a {@link Consumer} argument * to have access to all the application callbacks. * @param queue the name of the queue * @param autoAck true if the server should consider messages * acknowledged once delivered; false if the server should expect * explicit acknowledgements * @param arguments a set of arguments for the consume * @param deliverCallback callback when a message is delivered * @param cancelCallback callback when the consumer is cancelled * @param shutdownSignalCallback callback when the channel/connection is shut down * @return the consumerTag generated by the server * @throws IOException if an error is encountered * @see com.rabbitmq.client.AMQP.Basic.Consume * @see com.rabbitmq.client.AMQP.Basic.ConsumeOk * @see #basicAck * @see #basicConsume(String, boolean, String, boolean, boolean, Map, Consumer) * @since 5.0 */ String basicConsume(String queue, boolean autoAck, Map arguments, DeliverCallback deliverCallback, CancelCallback cancelCallback, ConsumerShutdownSignalCallback shutdownSignalCallback) throws IOException; /** * Start a non-nolocal, non-exclusive consumer. * @param queue the name of the queue * @param autoAck true if the server should consider messages * acknowledged once delivered; false if the server should expect * explicit acknowledgements * @param consumerTag a client-generated consumer tag to establish context * @param callback an interface to the consumer object * @return the consumerTag associated with the new consumer * @throws java.io.IOException if an error is encountered * @see com.rabbitmq.client.AMQP.Basic.Consume * @see com.rabbitmq.client.AMQP.Basic.ConsumeOk * @see #basicConsume(String, boolean, String, boolean, boolean, Map, Consumer) */ String basicConsume(String queue, boolean autoAck, String consumerTag, Consumer callback) throws IOException; /** * Start a non-nolocal, non-exclusive consumer. * Provide access only to basic.deliver and * basic.cancel AMQP methods (which is sufficient * for most cases). See methods with a {@link Consumer} argument * to have access to all the application callbacks. * @param queue the name of the queue * @param autoAck true if the server should consider messages * acknowledged once delivered; false if the server should expect * explicit acknowledgements * @param consumerTag a client-generated consumer tag to establish context * @param deliverCallback callback when a message is delivered * @param cancelCallback callback when the consumer is cancelled * @return the consumerTag associated with the new consumer * @throws java.io.IOException if an error is encountered * @see com.rabbitmq.client.AMQP.Basic.Consume * @see com.rabbitmq.client.AMQP.Basic.ConsumeOk * @see #basicConsume(String, boolean, String, boolean, boolean, Map, Consumer) * @since 5.0 */ String basicConsume(String queue, boolean autoAck, String consumerTag, DeliverCallback deliverCallback, CancelCallback cancelCallback) throws IOException; /** * Start a non-nolocal, non-exclusive consumer. * Provide access only to basic.deliver and * shutdown signal callbacks (which is sufficient * for most cases). See methods with a {@link Consumer} argument * to have access to all the application callbacks. * @param queue the name of the queue * @param autoAck true if the server should consider messages * acknowledged once delivered; false if the server should expect * explicit acknowledgements * @param consumerTag a client-generated consumer tag to establish context * @param deliverCallback callback when a message is delivered * @param shutdownSignalCallback callback when the channel/connection is shut down * @return the consumerTag associated with the new consumer * @throws java.io.IOException if an error is encountered * @see com.rabbitmq.client.AMQP.Basic.Consume * @see com.rabbitmq.client.AMQP.Basic.ConsumeOk * @see #basicConsume(String, boolean, String, boolean, boolean, Map, Consumer) * @since 5.0 */ String basicConsume(String queue, boolean autoAck, String consumerTag, DeliverCallback deliverCallback, ConsumerShutdownSignalCallback shutdownSignalCallback) throws IOException; /** * Start a non-nolocal, non-exclusive consumer. * Provide access to basic.deliver, basic.cancel * and shutdown signal callbacks (which is sufficient * for most cases). See methods with a {@link Consumer} argument * to have access to all the application callbacks. * @param queue the name of the queue * @param autoAck true if the server should consider messages * acknowledged once delivered; false if the server should expect * explicit acknowledgements * @param consumerTag a client-generated consumer tag to establish context * @param deliverCallback callback when a message is delivered * @param cancelCallback callback when the consumer is cancelled * @param shutdownSignalCallback callback when the channel/connection is shut down * @return the consumerTag associated with the new consumer * @throws java.io.IOException if an error is encountered * @see com.rabbitmq.client.AMQP.Basic.Consume * @see com.rabbitmq.client.AMQP.Basic.ConsumeOk * @see #basicConsume(String, boolean, String, boolean, boolean, Map, Consumer) * @since 5.0 */ String basicConsume(String queue, boolean autoAck, String consumerTag, DeliverCallback deliverCallback, CancelCallback cancelCallback, ConsumerShutdownSignalCallback shutdownSignalCallback) throws IOException; /** * Start a consumer. Calls the consumer's {@link Consumer#handleConsumeOk} * method. * @param queue the name of the queue * @param autoAck true if the server should consider messages * acknowledged once delivered; false if the server should expect * explicit acknowledgements * @param consumerTag a client-generated consumer tag to establish context * @param noLocal True if the server should not deliver to this consumer * messages published on this channel's connection. Note that the RabbitMQ server does not support this flag. * @param exclusive true if this is an exclusive consumer * @param callback an interface to the consumer object * @param arguments a set of arguments for the consume * @return the consumerTag associated with the new consumer * @throws java.io.IOException if an error is encountered * @see com.rabbitmq.client.AMQP.Basic.Consume * @see com.rabbitmq.client.AMQP.Basic.ConsumeOk */ String basicConsume(String queue, boolean autoAck, String consumerTag, boolean noLocal, boolean exclusive, Map arguments, Consumer callback) throws IOException; /** * Start a consumer. Calls the consumer's {@link Consumer#handleConsumeOk} * method. * Provide access only to basic.deliver and * basic.cancel AMQP methods (which is sufficient * for most cases). See methods with a {@link Consumer} argument * to have access to all the application callbacks. * @param queue the name of the queue * @param autoAck true if the server should consider messages * acknowledged once delivered; false if the server should expect * explicit acknowledgements * @param consumerTag a client-generated consumer tag to establish context * @param noLocal True if the server should not deliver to this consumer * messages published on this channel's connection. Note that the RabbitMQ server does not support this flag. * @param exclusive true if this is an exclusive consumer * @param arguments a set of arguments for the consume * @param deliverCallback callback when a message is delivered * @param cancelCallback callback when the consumer is cancelled * @return the consumerTag associated with the new consumer * @throws java.io.IOException if an error is encountered * @see com.rabbitmq.client.AMQP.Basic.Consume * @see com.rabbitmq.client.AMQP.Basic.ConsumeOk * @since 5.0 */ String basicConsume(String queue, boolean autoAck, String consumerTag, boolean noLocal, boolean exclusive, Map arguments, DeliverCallback deliverCallback, CancelCallback cancelCallback) throws IOException; /** * Start a consumer. Calls the consumer's {@link Consumer#handleConsumeOk} * method. * Provide access only to basic.deliver and * shutdown signal callbacks (which is sufficient * for most cases). See methods with a {@link Consumer} argument * to have access to all the application callbacks. * @param queue the name of the queue * @param autoAck true if the server should consider messages * acknowledged once delivered; false if the server should expect * explicit acknowledgements * @param consumerTag a client-generated consumer tag to establish context * @param noLocal True if the server should not deliver to this consumer * messages published on this channel's connection. Note that the RabbitMQ server does not support this flag. * @param exclusive true if this is an exclusive consumer * @param arguments a set of arguments for the consume * @param deliverCallback callback when a message is delivered * @param shutdownSignalCallback callback when the channel/connection is shut down * @return the consumerTag associated with the new consumer * @throws java.io.IOException if an error is encountered * @see com.rabbitmq.client.AMQP.Basic.Consume * @see com.rabbitmq.client.AMQP.Basic.ConsumeOk * @since 5.0 */ String basicConsume(String queue, boolean autoAck, String consumerTag, boolean noLocal, boolean exclusive, Map arguments, DeliverCallback deliverCallback, ConsumerShutdownSignalCallback shutdownSignalCallback) throws IOException; /** * Start a consumer. Calls the consumer's {@link Consumer#handleConsumeOk} * method. * Provide access to basic.deliver, basic.cancel * and shutdown signal callbacks (which is sufficient * for most cases). See methods with a {@link Consumer} argument * to have access to all the application callbacks. * @param queue the name of the queue * @param autoAck true if the server should consider messages * acknowledged once delivered; false if the server should expect * explicit acknowledgements * @param consumerTag a client-generated consumer tag to establish context * @param noLocal True if the server should not deliver to this consumer * messages published on this channel's connection. Note that the RabbitMQ server does not support this flag. * @param exclusive true if this is an exclusive consumer * @param arguments a set of arguments for the consume * @param deliverCallback callback when a message is delivered * @param cancelCallback callback when the consumer is cancelled * @param shutdownSignalCallback callback when the channel/connection is shut down * @return the consumerTag associated with the new consumer * @throws java.io.IOException if an error is encountered * @see com.rabbitmq.client.AMQP.Basic.Consume * @see com.rabbitmq.client.AMQP.Basic.ConsumeOk * @since 5.0 */ String basicConsume(String queue, boolean autoAck, String consumerTag, boolean noLocal, boolean exclusive, Map arguments, DeliverCallback deliverCallback, CancelCallback cancelCallback, ConsumerShutdownSignalCallback shutdownSignalCallback) throws IOException; /** * Cancel a consumer. Calls the consumer's {@link Consumer#handleCancelOk} * method. * @param consumerTag a client- or server-generated consumer tag to establish context * @throws IOException if an error is encountered, or if the consumerTag is unknown * @see com.rabbitmq.client.AMQP.Basic.Cancel * @see com.rabbitmq.client.AMQP.Basic.CancelOk */ void basicCancel(String consumerTag) throws IOException; /** *

* Ask the broker to resend unacknowledged messages. In 0-8 * basic.recover is asynchronous; in 0-9-1 it is synchronous, and * the new, deprecated method basic.recover_async is asynchronous. *

* Equivalent to calling basicRecover(true), messages * will be requeued and possibly delivered to a different consumer. * @see #basicRecover(boolean) */ Basic.RecoverOk basicRecover() throws IOException; /** * Ask the broker to resend unacknowledged messages. In 0-8 * basic.recover is asynchronous; in 0-9-1 it is synchronous, and * the new, deprecated method basic.recover_async is asynchronous. * @param requeue If true, messages will be requeued and possibly * delivered to a different consumer. If false, messages will be * redelivered to the same consumer. */ Basic.RecoverOk basicRecover(boolean requeue) throws IOException; /** * Enables TX mode on this channel. * @see com.rabbitmq.client.AMQP.Tx.Select * @see com.rabbitmq.client.AMQP.Tx.SelectOk * @return a transaction-selection method to indicate the transaction was successfully initiated * @throws java.io.IOException if an error is encountered */ Tx.SelectOk txSelect() throws IOException; /** * Commits a TX transaction on this channel. * @see com.rabbitmq.client.AMQP.Tx.Commit * @see com.rabbitmq.client.AMQP.Tx.CommitOk * @return a transaction-commit method to indicate the transaction was successfully committed * @throws java.io.IOException if an error is encountered */ Tx.CommitOk txCommit() throws IOException; /** * Rolls back a TX transaction on this channel. * @see com.rabbitmq.client.AMQP.Tx.Rollback * @see com.rabbitmq.client.AMQP.Tx.RollbackOk * @return a transaction-rollback method to indicate the transaction was successfully rolled back * @throws java.io.IOException if an error is encountered */ Tx.RollbackOk txRollback() throws IOException; /** * Enables publisher acknowledgements on this channel. * @see com.rabbitmq.client.AMQP.Confirm.Select * @throws java.io.IOException if an error is encountered */ Confirm.SelectOk confirmSelect() throws IOException; /** * When in confirm mode, returns the sequence number of the next * message to be published. * @return the sequence number of the next message to be published */ long getNextPublishSeqNo(); /** * Wait until all messages published since the last call have been * either ack'd or nack'd by the broker. Note, when called on a * non-Confirm channel, waitForConfirms throws an IllegalStateException. * @return whether all the messages were ack'd (and none were nack'd) * @throws java.lang.IllegalStateException */ boolean waitForConfirms() throws InterruptedException; /** * Wait until all messages published since the last call have been * either ack'd or nack'd by the broker; or until timeout elapses. * If the timeout expires a TimeoutException is thrown. When * called on a non-Confirm channel, waitForConfirms throws an * IllegalStateException. * @return whether all the messages were ack'd (and none were nack'd) * @throws java.lang.IllegalStateException */ boolean waitForConfirms(long timeout) throws InterruptedException, TimeoutException; /** Wait until all messages published since the last call have * been either ack'd or nack'd by the broker. If any of the * messages were nack'd, waitForConfirmsOrDie will throw an * IOException. When called on a non-Confirm channel, it will * throw an IllegalStateException. * @throws java.lang.IllegalStateException */ void waitForConfirmsOrDie() throws IOException, InterruptedException; /** Wait until all messages published since the last call have * been either ack'd or nack'd by the broker; or until timeout elapses. * If the timeout expires a TimeoutException is thrown. If any of the * messages were nack'd, waitForConfirmsOrDie will throw an * IOException. When called on a non-Confirm channel, it will * throw an IllegalStateException. * @throws java.lang.IllegalStateException */ void waitForConfirmsOrDie(long timeout) throws IOException, InterruptedException, TimeoutException; /** * Asynchronously send a method over this channel. * @param method method to transmit over this channel. * @throws IOException Problem transmitting method. */ void asyncRpc(Method method) throws IOException; /** * Synchronously send a method over this channel. * @param method method to transmit over this channel. * @return command response to method. Caller should cast as appropriate. * @throws IOException Problem transmitting method. */ Command rpc(Method method) throws IOException; /** * Returns the number of messages in a queue ready to be delivered * to consumers. This method assumes the queue exists. If it doesn't, * an exception will be closed with an exception. * @param queue the name of the queue * @return the number of messages in ready state * @throws IOException Problem transmitting method. */ long messageCount(String queue) throws IOException; /** * Returns the number of consumers on a queue. * This method assumes the queue exists. If it doesn't, * an exception will be closed with an exception. * @param queue the name of the queue * @return the number of consumers * @throws IOException Problem transmitting method. */ long consumerCount(String queue) throws IOException; /** * Asynchronously send a method over this channel. * @param method method to transmit over this channel. * @return a completable future that completes when the result is received * @throws IOException Problem transmitting method. */ CompletableFuture asyncCompletableRpc(Method method) throws IOException; } ChannelContinuationTimeoutException.java000066400000000000000000000030221316117667700337720ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/clientpackage com.rabbitmq.client; import java.io.IOException; import java.util.concurrent.TimeoutException; /** * Exception thrown when a channel times out on a continuation during a RPC call. * @since 4.1.0 */ public class ChannelContinuationTimeoutException extends IOException { /** * The channel that performed the call. * Typed as Object as the underlying * object that performs the call might * not be an implementation of {@link Channel}. */ private final Object channel; /** * The number of the channel that performed the call. */ private final int channelNumber; /** * The request method that timed out. */ private final Method method; public ChannelContinuationTimeoutException(TimeoutException cause, Object channel, int channelNumber, Method method) { super( "Continuation call for method " + method + " on channel " + channel + " (#" + channelNumber + ") timed out", cause ); this.channel = channel; this.channelNumber = channelNumber; this.method = method; } /** * * @return request method that timed out */ public Method getMethod() { return method; } /** * channel that performed the call * @return */ public Object getChannel() { return channel; } /** * * @return number of the channel that performed the call */ public int getChannelNumber() { return channelNumber; } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/Command.java000066400000000000000000000032201316117667700262360ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; /** * Interface to a container for an AMQP method-and-arguments, with optional content header and body. */ public interface Command { /** * Retrieves the {@link Method} held within this Command. Downcast to * concrete (implementation-specific!) subclasses as necessary. * * @return the command's method. */ Method getMethod(); /** * Retrieves the ContentHeader subclass instance held as part of this Command, if any. * * Downcast to one of the inner classes of AMQP, * for instance {@link AMQP.BasicProperties}, as appropriate. * * @return the Command's {@link ContentHeader}, or null if none */ ContentHeader getContentHeader(); /** * Retrieves the body byte array that travelled as part of this * Command, if any. * * @return the Command's content body, or null if none */ byte[] getContentBody(); } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/ConfirmCallback.java000066400000000000000000000024501316117667700276760ustar00rootroot00000000000000// Copyright (c) 2017 Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; import java.io.IOException; /** * Implement this interface in order to be notified of Confirm events. * Acks represent messages handled successfully; Nacks represent * messages lost by the broker. Note, the lost messages could still * have been delivered to consumers, but the broker cannot guarantee * this. * Prefer this interface over {@link ConfirmListener} for * a lambda-oriented syntax. * @see ConfirmListener */ @FunctionalInterface public interface ConfirmCallback { void handle(long deliveryTag, boolean multiple) throws IOException; } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/ConfirmListener.java000066400000000000000000000025101316117667700277640ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; import java.io.IOException; /** * Implement this interface in order to be notified of Confirm events. * Acks represent messages handled successfully; Nacks represent * messages lost by the broker. Note, the lost messages could still * have been delivered to consumers, but the broker cannot guarantee * this. * For a lambda-oriented syntax, use {@link ConfirmCallback}. */ public interface ConfirmListener { void handleAck(long deliveryTag, boolean multiple) throws IOException; void handleNack(long deliveryTag, boolean multiple) throws IOException; } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/Connection.java000066400000000000000000000247421316117667700267730ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; import java.io.Closeable; import java.io.IOException; import java.net.InetAddress; import java.util.Map; import java.util.concurrent.ExecutorService; /** * Public API: Interface to an AMQ connection. See the see the spec for details. *

* To connect to a broker, fill in a {@link ConnectionFactory} and use a {@link ConnectionFactory} as follows: * *

 * ConnectionFactory factory = new ConnectionFactory();
 * factory.setHost(hostName);
 * factory.setPort(portNumber);
 * factory.setVirtualHost(virtualHost);
 * factory.setUsername(username);
 * factory.setPassword(password);
 * Connection conn = factory.newConnection();
 *
 * // Then open a channel:
 *
 * Channel channel = conn.createChannel();
 * 
* Or, more compactly: * *
 * ConnectionFactory factory = new ConnectionFactory();
 * factory.setUri("amqp://username:password@hostName:portNumber/virtualHost");
 * Connection conn = factory.newConnection();
 * Channel channel = conn.createChannel()
 * 
* * Current implementations are thread-safe for code at the client API level, * and in fact thread-safe internally except for code within RPC calls. */ public interface Connection extends ShutdownNotifier, Closeable { // rename to AMQPConnection later, this is a temporary name /** * Retrieve the host. * @return the hostname of the peer we're connected to. */ InetAddress getAddress(); /** * Retrieve the port number. * @return the port number of the peer we're connected to. */ int getPort(); /** * Get the negotiated maximum channel number. Usable channel * numbers range from 1 to this number, inclusive. * * @return the maximum channel number permitted for this connection. */ int getChannelMax(); /** * Get the negotiated maximum frame size. * * @return the maximum frame size, in octets; zero if unlimited */ int getFrameMax(); /** * Get the negotiated heartbeat interval. * * @return the heartbeat interval, in seconds; zero if none */ int getHeartbeat(); /** * Get a copy of the map of client properties sent to the server * * @return a copy of the map of client properties */ Map getClientProperties(); /** * Returns client-provided connection name, if any. Note that the value * returned does not uniquely identify a connection and cannot be used * as a connection identifier in HTTP API requests. * * * * @return client-provided connection name, if any * @see ConnectionFactory#newConnection(Address[], String) * @see ConnectionFactory#newConnection(ExecutorService, Address[], String) */ String getClientProvidedName(); /** * Retrieve the server properties. * @return a map of the server properties. This typically includes the product name and version of the server. */ Map getServerProperties(); /** * Create a new channel, using an internally allocated channel number. * If automatic connection recovery * is enabled, the channel returned by this method will be {@link Recoverable}. * * @return a new channel descriptor, or null if none is available * @throws IOException if an I/O problem is encountered */ Channel createChannel() throws IOException; /** * Create a new channel, using the specified channel number if possible. * @param channelNumber the channel number to allocate * @return a new channel descriptor, or null if this channel number is already in use * @throws IOException if an I/O problem is encountered */ Channel createChannel(int channelNumber) throws IOException; /** * Close this connection and all its channels * with the {@link com.rabbitmq.client.AMQP#REPLY_SUCCESS} close code * and message 'OK'. * * Waits for all the close operations to complete. * * @throws IOException if an I/O problem is encountered */ @Override void close() throws IOException; /** * Close this connection and all its channels. * * Waits for all the close operations to complete. * * @param closeCode the close code (See under "Reply Codes" in the AMQP specification) * @param closeMessage a message indicating the reason for closing the connection * @throws IOException if an I/O problem is encountered */ void close(int closeCode, String closeMessage) throws IOException; /** * Close this connection and all its channels * with the {@link com.rabbitmq.client.AMQP#REPLY_SUCCESS} close code * and message 'OK'. * * This method behaves in a similar way as {@link #close()}, with the only difference * that it waits with a provided timeout for all the close operations to * complete. When timeout is reached the socket is forced to close. * * @param timeout timeout (in milliseconds) for completing all the close-related * operations, use -1 for infinity * @throws IOException if an I/O problem is encountered */ void close(int timeout) throws IOException; /** * Close this connection and all its channels. * * Waits with the given timeout for all the close operations to complete. * When timeout is reached the socket is forced to close. * * @param closeCode the close code (See under "Reply Codes" in the AMQP specification) * @param closeMessage a message indicating the reason for closing the connection * @param timeout timeout (in milliseconds) for completing all the close-related * operations, use -1 for infinity * @throws IOException if an I/O problem is encountered */ void close(int closeCode, String closeMessage, int timeout) throws IOException; /** * Abort this connection and all its channels * with the {@link com.rabbitmq.client.AMQP#REPLY_SUCCESS} close code * and message 'OK'. * * Forces the connection to close. * Any encountered exceptions in the close operations are silently discarded. */ void abort(); /** * Abort this connection and all its channels. * * Forces the connection to close and waits for all the close operations to complete. * Any encountered exceptions in the close operations are silently discarded. * * @param closeCode the close code (See under "Reply Codes" in the AMQP specification) * @param closeMessage a message indicating the reason for closing the connection */ void abort(int closeCode, String closeMessage); /** * Abort this connection and all its channels * with the {@link com.rabbitmq.client.AMQP#REPLY_SUCCESS} close code * and message 'OK'. * * This method behaves in a similar way as {@link #abort()}, with the only difference * that it waits with a provided timeout for all the close operations to * complete. When timeout is reached the socket is forced to close. * * @param timeout timeout (in milliseconds) for completing all the close-related * operations, use -1 for infinity */ void abort(int timeout); /** * Abort this connection and all its channels. * * Forces the connection to close and waits with the given timeout * for all the close operations to complete. When timeout is reached * the socket is forced to close. * Any encountered exceptions in the close operations are silently discarded. * * @param closeCode the close code (See under "Reply Codes" in the AMQP specification) * @param closeMessage a message indicating the reason for closing the connection * @param timeout timeout (in milliseconds) for completing all the close-related * operations, use -1 for infinity */ void abort(int closeCode, String closeMessage, int timeout); /** * Add a {@link BlockedListener}. * @param listener the listener to add */ void addBlockedListener(BlockedListener listener); /** * Add a lambda-based {@link BlockedListener}. * @see BlockedListener * @see BlockedCallback * @see UnblockedCallback * @param blockedCallback the callback when the connection is blocked * @param unblockedCallback the callback when the connection is unblocked * @return the listener that wraps the callback */ BlockedListener addBlockedListener(BlockedCallback blockedCallback, UnblockedCallback unblockedCallback); /** * Remove a {@link BlockedListener}. * @param listener the listener to remove * @return true if the listener was found and removed, * false otherwise */ boolean removeBlockedListener(BlockedListener listener); /** * Remove all {@link BlockedListener}s. */ void clearBlockedListeners(); /** * Get the exception handler. * * @see com.rabbitmq.client.ExceptionHandler */ ExceptionHandler getExceptionHandler(); /** * Returns a unique ID for this connection. * * This ID must be unique, otherwise some services * like the metrics collector won't work properly. * This ID doesn't have to be provided by the client, * services that require it will be assigned automatically * if not set. * * @return unique ID for this connection. */ String getId(); /** * Sets a unique ID for this connection. * * This ID must be unique, otherwise some services * like the metrics collector won't work properly. * This ID doesn't have to be provided by the client, * services that require it will be assigned automatically * if not set. */ void setId(String id); } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/ConnectionFactory.java000066400000000000000000001413621316117667700303210ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; import com.rabbitmq.client.impl.*; import com.rabbitmq.client.impl.nio.NioParams; import com.rabbitmq.client.impl.nio.SocketChannelFrameHandlerFactory; import com.rabbitmq.client.impl.recovery.AutorecoveringConnection; import javax.net.SocketFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.net.URLDecoder; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.util.*; import java.util.concurrent.*; import static java.util.concurrent.TimeUnit.*; /** * Convenience factory class to facilitate opening a {@link Connection} to a RabbitMQ node. * * Most connection and socket settings are configured using this factory. * Some settings that apply to connections can also be configured here * and will apply to all connections produced by this factory. */ public class ConnectionFactory implements Cloneable { /** Default user name */ public static final String DEFAULT_USER = "guest"; /** Default password */ public static final String DEFAULT_PASS = "guest"; /** Default virtual host */ public static final String DEFAULT_VHOST = "/"; /** Default maximum channel number; * zero for unlimited */ public static final int DEFAULT_CHANNEL_MAX = 0; /** Default maximum frame size; * zero means no limit */ public static final int DEFAULT_FRAME_MAX = 0; /** Default heart-beat interval; * 60 seconds */ public static final int DEFAULT_HEARTBEAT = 60; /** The default host */ public static final String DEFAULT_HOST = "localhost"; /** 'Use the default port' port */ public static final int USE_DEFAULT_PORT = -1; /** The default non-ssl port */ public static final int DEFAULT_AMQP_PORT = AMQP.PROTOCOL.PORT; /** The default ssl port */ public static final int DEFAULT_AMQP_OVER_SSL_PORT = 5671; /** The default TCP connection timeout: 60 seconds */ public static final int DEFAULT_CONNECTION_TIMEOUT = 60000; /** * The default AMQP 0-9-1 connection handshake timeout. See DEFAULT_CONNECTION_TIMEOUT * for TCP (socket) connection timeout. */ public static final int DEFAULT_HANDSHAKE_TIMEOUT = 10000; /** The default shutdown timeout; * zero means wait indefinitely */ public static final int DEFAULT_SHUTDOWN_TIMEOUT = 10000; /** The default continuation timeout for RPC calls in channels: 10 minutes */ public static final int DEFAULT_CHANNEL_RPC_TIMEOUT = (int) MINUTES.toMillis(10); private static final String PREFERRED_TLS_PROTOCOL = "TLSv1.2"; private static final String FALLBACK_TLS_PROTOCOL = "TLSv1"; private String username = DEFAULT_USER; private String password = DEFAULT_PASS; private String virtualHost = DEFAULT_VHOST; private String host = DEFAULT_HOST; private int port = USE_DEFAULT_PORT; private int requestedChannelMax = DEFAULT_CHANNEL_MAX; private int requestedFrameMax = DEFAULT_FRAME_MAX; private int requestedHeartbeat = DEFAULT_HEARTBEAT; private int connectionTimeout = DEFAULT_CONNECTION_TIMEOUT; private int handshakeTimeout = DEFAULT_HANDSHAKE_TIMEOUT; private int shutdownTimeout = DEFAULT_SHUTDOWN_TIMEOUT; private Map _clientProperties = AMQConnection.defaultClientProperties(); private SocketFactory socketFactory = null; private SaslConfig saslConfig = DefaultSaslConfig.PLAIN; private ExecutorService sharedExecutor; private ThreadFactory threadFactory = Executors.defaultThreadFactory(); // minimises the number of threads rapid closure of many // connections uses, see rabbitmq/rabbitmq-java-client#86 private ExecutorService shutdownExecutor; private ScheduledExecutorService heartbeatExecutor; private SocketConfigurator socketConf = new DefaultSocketConfigurator(); private ExceptionHandler exceptionHandler = new DefaultExceptionHandler(); private boolean automaticRecovery = true; private boolean topologyRecovery = true; // long is used to make sure the users can use both ints // and longs safely. It is unlikely that anybody'd need // to use recovery intervals > Integer.MAX_VALUE in practice. private long networkRecoveryInterval = 5000; private MetricsCollector metricsCollector; private boolean nio = false; private FrameHandlerFactory frameHandlerFactory; private NioParams nioParams = new NioParams(); private SslContextFactory sslContextFactory; /** * Continuation timeout on RPC calls. * @since 4.1.0 */ private int channelRpcTimeout = DEFAULT_CHANNEL_RPC_TIMEOUT; /** * Whether or not channels check the reply type of an RPC call. * Default is false. * @since 4.2.0 */ private boolean channelShouldCheckRpcResponseType = false; /** @return the default host to use for connections */ public String getHost() { return host; } /** @param host the default host to use for connections */ public void setHost(String host) { this.host = host; } public static int portOrDefault(int port, boolean ssl) { if (port != USE_DEFAULT_PORT) return port; else if (ssl) return DEFAULT_AMQP_OVER_SSL_PORT; else return DEFAULT_AMQP_PORT; } /** @return the default port to use for connections */ public int getPort() { return portOrDefault(port, isSSL()); } /** * Set the target port. * @param port the default port to use for connections */ public void setPort(int port) { this.port = port; } /** * Retrieve the user name. * @return the AMQP user name to use when connecting to the broker */ public String getUsername() { return this.username; } /** * Set the user name. * @param username the AMQP user name to use when connecting to the broker */ public void setUsername(String username) { this.username = username; } /** * Retrieve the password. * @return the password to use when connecting to the broker */ public String getPassword() { return this.password; } /** * Set the password. * @param password the password to use when connecting to the broker */ public void setPassword(String password) { this.password = password; } /** * Retrieve the virtual host. * @return the virtual host to use when connecting to the broker */ public String getVirtualHost() { return this.virtualHost; } /** * Set the virtual host. * @param virtualHost the virtual host to use when connecting to the broker */ public void setVirtualHost(String virtualHost) { this.virtualHost = virtualHost; } /** * Convenience method for setting the fields in an AMQP URI: host, * port, username, password and virtual host. If any part of the * URI is ommited, the ConnectionFactory's corresponding variable * is left unchanged. * @param uri is the AMQP URI containing the data */ public void setUri(URI uri) throws URISyntaxException, NoSuchAlgorithmException, KeyManagementException { if ("amqp".equals(uri.getScheme().toLowerCase())) { // nothing special to do } else if ("amqps".equals(uri.getScheme().toLowerCase())) { setPort(DEFAULT_AMQP_OVER_SSL_PORT); // SSL context factory not set yet, we use the default one if (this.sslContextFactory == null) { useSslProtocol(); } } else { throw new IllegalArgumentException("Wrong scheme in AMQP URI: " + uri.getScheme()); } String host = uri.getHost(); if (host != null) { setHost(host); } int port = uri.getPort(); if (port != -1) { setPort(port); } String userInfo = uri.getRawUserInfo(); if (userInfo != null) { String userPass[] = userInfo.split(":"); if (userPass.length > 2) { throw new IllegalArgumentException("Bad user info in AMQP " + "URI: " + userInfo); } setUsername(uriDecode(userPass[0])); if (userPass.length == 2) { setPassword(uriDecode(userPass[1])); } } String path = uri.getRawPath(); if (path != null && path.length() > 0) { if (path.indexOf('/', 1) != -1) { throw new IllegalArgumentException("Multiple segments in " + "path of AMQP URI: " + path); } setVirtualHost(uriDecode(uri.getPath().substring(1))); } } /** * Convenience method for setting the fields in an AMQP URI: host, * port, username, password and virtual host. If any part of the * URI is ommited, the ConnectionFactory's corresponding variable * is left unchanged. Note that not all valid AMQP URIs are * accepted; in particular, the hostname must be given if the * port, username or password are given, and escapes in the * hostname are not permitted. * @param uriString is the AMQP URI containing the data */ public void setUri(String uriString) throws URISyntaxException, NoSuchAlgorithmException, KeyManagementException { setUri(new URI(uriString)); } private String uriDecode(String s) { try { // URLDecode decodes '+' to a space, as for // form encoding. So protect plus signs. return URLDecoder.decode(s.replace("+", "%2B"), "US-ASCII"); } catch (IOException e) { throw new RuntimeException(e); } } /** * Retrieve the requested maximum channel number * @return the initially requested maximum channel number; zero for unlimited */ public int getRequestedChannelMax() { return this.requestedChannelMax; } /** * Set the requested maximum channel number * @param requestedChannelMax initially requested maximum channel number; zero for unlimited */ public void setRequestedChannelMax(int requestedChannelMax) { this.requestedChannelMax = requestedChannelMax; } /** * Retrieve the requested maximum frame size * @return the initially requested maximum frame size, in octets; zero for unlimited */ public int getRequestedFrameMax() { return this.requestedFrameMax; } /** * Set the requested maximum frame size * @param requestedFrameMax initially requested maximum frame size, in octets; zero for unlimited */ public void setRequestedFrameMax(int requestedFrameMax) { this.requestedFrameMax = requestedFrameMax; } /** * Retrieve the requested heartbeat interval. * @return the initially requested heartbeat interval, in seconds; zero for none */ public int getRequestedHeartbeat() { return this.requestedHeartbeat; } /** * Set the TCP connection timeout. * @param timeout connection TCP establishment timeout in milliseconds; zero for infinite */ public void setConnectionTimeout(int timeout) { if(timeout < 0) { throw new IllegalArgumentException("TCP connection timeout cannot be negative"); } this.connectionTimeout = timeout; } /** * Retrieve the TCP connection timeout. * @return the TCP connection timeout, in milliseconds; zero for infinite */ public int getConnectionTimeout() { return this.connectionTimeout; } /** * Retrieve the AMQP 0-9-1 protocol handshake timeout. * @return the AMQP0-9-1 protocol handshake timeout, in milliseconds */ public int getHandshakeTimeout() { return handshakeTimeout; } /** * Set the AMQP0-9-1 protocol handshake timeout. * @param timeout the AMQP0-9-1 protocol handshake timeout, in milliseconds */ public void setHandshakeTimeout(int timeout) { if(timeout < 0) { throw new IllegalArgumentException("handshake timeout cannot be negative"); } this.handshakeTimeout = timeout; } /** * Set the shutdown timeout. This is the amount of time that Consumer implementations have to * continue working through deliveries (and other Consumer callbacks) after the connection * has closed but before the ConsumerWorkService is torn down. If consumers exceed this timeout * then any remaining queued deliveries (and other Consumer callbacks, including * the Consumer's handleShutdownSignal() invocation) will be lost. * @param shutdownTimeout shutdown timeout in milliseconds; zero for infinite; default 10000 */ public void setShutdownTimeout(int shutdownTimeout) { this.shutdownTimeout = shutdownTimeout; } /** * Retrieve the shutdown timeout. * @return the shutdown timeout, in milliseconds; zero for infinite */ public int getShutdownTimeout() { return shutdownTimeout; } /** * Set the requested heartbeat timeout. Heartbeat frames will be sent at about 1/2 the timeout interval. * If server heartbeat timeout is configured to a non-zero value, this method can only be used * to lower the value; otherwise any value provided by the client will be used. * @param requestedHeartbeat the initially requested heartbeat timeout, in seconds; zero for none * @see RabbitMQ Heartbeats Guide */ public void setRequestedHeartbeat(int requestedHeartbeat) { this.requestedHeartbeat = requestedHeartbeat; } /** * Retrieve the currently-configured table of client properties * that will be sent to the server during connection * startup. Clients may add, delete, and alter keys in this * table. Such changes will take effect when the next new * connection is started using this factory. * @return the map of client properties * @see #setClientProperties */ public Map getClientProperties() { return _clientProperties; } /** * Replace the table of client properties that will be sent to the * server during subsequent connection startups. * @param clientProperties the map of extra client properties * @see #getClientProperties */ public void setClientProperties(Map clientProperties) { _clientProperties = clientProperties; } /** * Gets the sasl config to use when authenticating * @return the sasl config * @see com.rabbitmq.client.SaslConfig */ public SaslConfig getSaslConfig() { return saslConfig; } /** * Sets the sasl config to use when authenticating * @param saslConfig * @see com.rabbitmq.client.SaslConfig */ public void setSaslConfig(SaslConfig saslConfig) { this.saslConfig = saslConfig; } /** * Retrieve the socket factory used to make connections with. */ public SocketFactory getSocketFactory() { return this.socketFactory; } /** * Set the socket factory used to create sockets for new connections. Can be * used to customize TLS-related settings by passing in a * javax.net.ssl.SSLSocketFactory instance. * Note this applies only to blocking IO, not to * NIO, as the NIO API doesn't use the SocketFactory API. * @see #useSslProtocol */ public void setSocketFactory(SocketFactory factory) { this.socketFactory = factory; } /** * Get the socket configurator. * * @see #setSocketConfigurator(SocketConfigurator) */ @SuppressWarnings("unused") public SocketConfigurator getSocketConfigurator() { return socketConf; } /** * Set the socket configurator. This gets a chance to "configure" a socket * before it has been opened. The default socket configurator disables * Nagle's algorithm. * * @param socketConfigurator the configurator to use */ public void setSocketConfigurator(SocketConfigurator socketConfigurator) { this.socketConf = socketConfigurator; } /** * Set the executor to use for consumer operation dispatch * by default for newly created connections. * All connections that use this executor share it. * * It's developer's responsibility to shut down the executor * when it is no longer needed. * * @param executor executor service to be used for * consumer operation */ public void setSharedExecutor(ExecutorService executor) { this.sharedExecutor = executor; } /** * Set the executor to use for connection shutdown. * All connections that use this executor share it. * * It's developer's responsibility to shut down the executor * when it is no longer needed. * * @param executor executor service to be used for * connection shutdown */ public void setShutdownExecutor(ExecutorService executor) { this.shutdownExecutor = executor; } /** * Set the executor to use to send heartbeat frames. * All connections that use this executor share it. * * It's developer's responsibility to shut down the executor * when it is no longer needed. * * @param executor executor service to be used to send heartbeat */ public void setHeartbeatExecutor(ScheduledExecutorService executor) { this.heartbeatExecutor = executor; } /** * Retrieve the thread factory used to instantiate new threads. * @see ThreadFactory */ public ThreadFactory getThreadFactory() { return threadFactory; } /** * Set the thread factory used to instantiate new threads. * @see ThreadFactory */ public void setThreadFactory(ThreadFactory threadFactory) { this.threadFactory = threadFactory; } /** * Get the exception handler. * * @see com.rabbitmq.client.ExceptionHandler */ public ExceptionHandler getExceptionHandler() { return exceptionHandler; } /** * Set the exception handler to use for newly created connections. * @see com.rabbitmq.client.ExceptionHandler */ public void setExceptionHandler(ExceptionHandler exceptionHandler) { if (exceptionHandler == null) { throw new IllegalArgumentException("exception handler cannot be null!"); } this.exceptionHandler = exceptionHandler; } public boolean isSSL(){ return getSocketFactory() instanceof SSLSocketFactory || sslContextFactory != null; } /** * Convenience method for setting up a SSL socket factory/engine, using * the DEFAULT_SSL_PROTOCOL and a trusting TrustManager. * Note the trust manager will trust every server certificate presented * to it, this is convenient for local development but * not recommended to use in production as it provides no protection * against man-in-the-middle attacks. */ public void useSslProtocol() throws NoSuchAlgorithmException, KeyManagementException { useSslProtocol(computeDefaultTlsProcotol(SSLContext.getDefault().getSupportedSSLParameters().getProtocols())); } /** * Convenience method for setting up a SSL socket factory/engine, using * the supplied protocol and a very trusting TrustManager. * Note the trust manager will trust every server certificate presented * to it, this is convenient for local development but * not recommended to use in production as it provides no protection * against man-in-the-middle attacks. * The produced {@link SSLContext} instance will be shared by all * the connections created by this connection factory. Use * {@link #setSslContextFactory(SslContextFactory)} for more flexibility. * @see #setSslContextFactory(SslContextFactory) */ public void useSslProtocol(String protocol) throws NoSuchAlgorithmException, KeyManagementException { useSslProtocol(protocol, new TrustEverythingTrustManager()); } /** * Convenience method for setting up an SSL socket factory/engine. * Pass in the SSL protocol to use, e.g. "TLSv1" or "TLSv1.2". * The produced {@link SSLContext} instance will be shared with all * the connections created by this connection factory. Use * {@link #setSslContextFactory(SslContextFactory)} for more flexibility. * @param protocol SSL protocol to use. * @see #setSslContextFactory(SslContextFactory) */ public void useSslProtocol(String protocol, TrustManager trustManager) throws NoSuchAlgorithmException, KeyManagementException { SSLContext c = SSLContext.getInstance(protocol); c.init(null, new TrustManager[] { trustManager }, null); useSslProtocol(c); } /** * Convenience method for setting up an SSL socket socketFactory/engine. * Pass in an initialized SSLContext. * The {@link SSLContext} instance will be shared with all * the connections created by this connection factory. Use * {@link #setSslContextFactory(SslContextFactory)} for more flexibility. * @param context An initialized SSLContext * @see #setSslContextFactory(SslContextFactory) */ public void useSslProtocol(SSLContext context) { this.sslContextFactory = name -> context; setSocketFactory(context.getSocketFactory()); } public static String computeDefaultTlsProcotol(String[] supportedProtocols) { if(supportedProtocols != null) { for (String supportedProtocol : supportedProtocols) { if(PREFERRED_TLS_PROTOCOL.equalsIgnoreCase(supportedProtocol)) { return supportedProtocol; } } } return FALLBACK_TLS_PROTOCOL; } /** * Returns true if automatic connection recovery * is enabled, false otherwise * @return true if automatic connection recovery is enabled, false otherwise * @see Automatic Recovery */ public boolean isAutomaticRecoveryEnabled() { return automaticRecovery; } /** * Enables or disables automatic connection recovery. * @param automaticRecovery if true, enables connection recovery * @see Automatic Recovery */ public void setAutomaticRecoveryEnabled(boolean automaticRecovery) { this.automaticRecovery = automaticRecovery; } /** * Returns true if topology recovery is enabled, false otherwise * @return true if topology recovery is enabled, false otherwise * @see Automatic Recovery */ @SuppressWarnings("unused") public boolean isTopologyRecoveryEnabled() { return topologyRecovery; } /** * Enables or disables topology recovery * @param topologyRecovery if true, enables topology recovery * @see Automatic Recovery */ public void setTopologyRecoveryEnabled(boolean topologyRecovery) { this.topologyRecovery = topologyRecovery; } public void setMetricsCollector(MetricsCollector metricsCollector) { this.metricsCollector = metricsCollector; } public MetricsCollector getMetricsCollector() { return metricsCollector; } protected synchronized FrameHandlerFactory createFrameHandlerFactory() throws IOException { if(nio) { if(this.frameHandlerFactory == null) { if(this.nioParams.getNioExecutor() == null && this.nioParams.getThreadFactory() == null) { this.nioParams.setThreadFactory(getThreadFactory()); } this.frameHandlerFactory = new SocketChannelFrameHandlerFactory(connectionTimeout, nioParams, isSSL(), sslContextFactory); } return this.frameHandlerFactory; } else { return new SocketFrameHandlerFactory(connectionTimeout, socketFactory, socketConf, isSSL(), this.shutdownExecutor, sslContextFactory); } } /** * Create a new broker connection, picking the first available address from * the list. * * If automatic connection recovery * is enabled, the connection returned by this method will be {@link Recoverable}. Future * reconnection attempts will pick a random accessible address from the provided list. * * @param addrs an array of known broker addresses (hostname/port pairs) to try in order * @return an interface to the connection * @throws IOException if it encounters a problem */ public Connection newConnection(Address[] addrs) throws IOException, TimeoutException { return newConnection(this.sharedExecutor, Arrays.asList(addrs), null); } /** * Create a new broker connection, picking the first available address from * the list provided by the {@link AddressResolver}. * * If automatic connection recovery * is enabled, the connection returned by this method will be {@link Recoverable}. Future * reconnection attempts will pick a random accessible address provided by the {@link AddressResolver}. * * @param addressResolver discovery service to list potential addresses (hostname/port pairs) to connect to * @return an interface to the connection * @throws IOException if it encounters a problem * @see Automatic Recovery */ public Connection newConnection(AddressResolver addressResolver) throws IOException, TimeoutException { return newConnection(this.sharedExecutor, addressResolver, null); } /** * Create a new broker connection with a client-provided name, picking the first available address from * the list. * * If automatic connection recovery * is enabled, the connection returned by this method will be {@link Recoverable}. Future * reconnection attempts will pick a random accessible address from the provided list. * * @param addrs an array of known broker addresses (hostname/port pairs) to try in order * @param clientProvidedName application-specific connection name, will be displayed * in the management UI if RabbitMQ server supports it. * This value doesn't have to be unique and cannot be used * as a connection identifier e.g. in HTTP API requests. * This value is supposed to be human-readable. * @return an interface to the connection * @throws IOException if it encounters a problem */ public Connection newConnection(Address[] addrs, String clientProvidedName) throws IOException, TimeoutException { return newConnection(this.sharedExecutor, Arrays.asList(addrs), clientProvidedName); } /** * Create a new broker connection, picking the first available address from * the list. * * If automatic connection recovery * is enabled, the connection returned by this method will be {@link Recoverable}. Future * reconnection attempts will pick a random accessible address from the provided list. * * @param addrs a List of known broker addresses (hostname/port pairs) to try in order * @return an interface to the connection * @throws IOException if it encounters a problem */ public Connection newConnection(List
addrs) throws IOException, TimeoutException { return newConnection(this.sharedExecutor, addrs, null); } /** * Create a new broker connection with a client-provided name, picking the first available address from * the list. * * If automatic connection recovery * is enabled, the connection returned by this method will be {@link Recoverable}. Future * reconnection attempts will pick a random accessible address from the provided list. * * @param addrs a List of known broker addresses (hostname/port pairs) to try in order * @param clientProvidedName application-specific connection name, will be displayed * in the management UI if RabbitMQ server supports it. * This value doesn't have to be unique and cannot be used * as a connection identifier e.g. in HTTP API requests. * This value is supposed to be human-readable. * @return an interface to the connection * @throws IOException if it encounters a problem */ public Connection newConnection(List
addrs, String clientProvidedName) throws IOException, TimeoutException { return newConnection(this.sharedExecutor, addrs, clientProvidedName); } /** * Create a new broker connection, picking the first available address from * the list. * * If automatic connection recovery * is enabled, the connection returned by this method will be {@link Recoverable}. Future * reconnection attempts will pick a random accessible address from the provided list. * * @param executor thread execution service for consumers on the connection * @param addrs an array of known broker addresses (hostname/port pairs) to try in order * @return an interface to the connection * @throws java.io.IOException if it encounters a problem * @see Automatic Recovery */ public Connection newConnection(ExecutorService executor, Address[] addrs) throws IOException, TimeoutException { return newConnection(executor, Arrays.asList(addrs), null); } /** * Create a new broker connection with a client-provided name, picking the first available address from * the list. * * If automatic connection recovery * is enabled, the connection returned by this method will be {@link Recoverable}. Future * reconnection attempts will pick a random accessible address from the provided list. * * @param executor thread execution service for consumers on the connection * @param addrs an array of known broker addresses (hostname/port pairs) to try in order * @param clientProvidedName application-specific connection name, will be displayed * in the management UI if RabbitMQ server supports it. * This value doesn't have to be unique and cannot be used * as a connection identifier e.g. in HTTP API requests. * This value is supposed to be human-readable. * @return an interface to the connection * @throws java.io.IOException if it encounters a problem * @see Automatic Recovery */ public Connection newConnection(ExecutorService executor, Address[] addrs, String clientProvidedName) throws IOException, TimeoutException { return newConnection(executor, Arrays.asList(addrs), clientProvidedName); } /** * Create a new broker connection, picking the first available address from * the list. * * If automatic connection recovery * is enabled, the connection returned by this method will be {@link Recoverable}. Future * reconnection attempts will pick a random accessible address from the provided list. * * @param executor thread execution service for consumers on the connection * @param addrs a List of known broker addrs (hostname/port pairs) to try in order * @return an interface to the connection * @throws java.io.IOException if it encounters a problem * @see Automatic Recovery */ public Connection newConnection(ExecutorService executor, List
addrs) throws IOException, TimeoutException { return newConnection(executor, addrs, null); } /** * Create a new broker connection, picking the first available address from * the list provided by the {@link AddressResolver}. * * If automatic connection recovery * is enabled, the connection returned by this method will be {@link Recoverable}. Future * reconnection attempts will pick a random accessible address provided by the {@link AddressResolver}. * * @param executor thread execution service for consumers on the connection * @param addressResolver discovery service to list potential addresses (hostname/port pairs) to connect to * @return an interface to the connection * @throws java.io.IOException if it encounters a problem * @see Automatic Recovery */ public Connection newConnection(ExecutorService executor, AddressResolver addressResolver) throws IOException, TimeoutException { return newConnection(executor, addressResolver, null); } /** * Create a new broker connection with a client-provided name, picking the first available address from * the list. * * If automatic connection recovery * is enabled, the connection returned by this method will be {@link Recoverable}. Future * reconnection attempts will pick a random accessible address from the provided list. * * @param executor thread execution service for consumers on the connection * @param addrs a List of known broker addrs (hostname/port pairs) to try in order * @param clientProvidedName application-specific connection name, will be displayed * in the management UI if RabbitMQ server supports it. * This value doesn't have to be unique and cannot be used * as a connection identifier e.g. in HTTP API requests. * This value is supposed to be human-readable. * @return an interface to the connection * @throws java.io.IOException if it encounters a problem * @see Automatic Recovery */ public Connection newConnection(ExecutorService executor, List
addrs, String clientProvidedName) throws IOException, TimeoutException { return newConnection(executor, createAddressResolver(addrs), clientProvidedName); } /** * Create a new broker connection with a client-provided name, picking the first available address from * the list provided by the {@link AddressResolver}. * * If automatic connection recovery * is enabled, the connection returned by this method will be {@link Recoverable}. Future * reconnection attempts will pick a random accessible address provided by the {@link AddressResolver}. * * @param executor thread execution service for consumers on the connection * @param addressResolver discovery service to list potential addresses (hostname/port pairs) to connect to * @param clientProvidedName application-specific connection name, will be displayed * in the management UI if RabbitMQ server supports it. * This value doesn't have to be unique and cannot be used * as a connection identifier e.g. in HTTP API requests. * This value is supposed to be human-readable. * @return an interface to the connection * @throws java.io.IOException if it encounters a problem * @see Automatic Recovery */ public Connection newConnection(ExecutorService executor, AddressResolver addressResolver, String clientProvidedName) throws IOException, TimeoutException { if(this.metricsCollector == null) { this.metricsCollector = new NoOpMetricsCollector(); } // make sure we respect the provided thread factory FrameHandlerFactory fhFactory = createFrameHandlerFactory(); ConnectionParams params = params(executor); // set client-provided via a client property if (clientProvidedName != null) { Map properties = new HashMap(params.getClientProperties()); properties.put("connection_name", clientProvidedName); params.setClientProperties(properties); } if (isAutomaticRecoveryEnabled()) { // see com.rabbitmq.client.impl.recovery.RecoveryAwareAMQConnectionFactory#newConnection AutorecoveringConnection conn = new AutorecoveringConnection(params, fhFactory, addressResolver, metricsCollector); conn.init(); return conn; } else { List
addrs = addressResolver.getAddresses(); Exception lastException = null; for (Address addr : addrs) { try { FrameHandler handler = fhFactory.create(addr, clientProvidedName); AMQConnection conn = createConnection(params, handler, metricsCollector); conn.start(); this.metricsCollector.newConnection(conn); return conn; } catch (IOException e) { lastException = e; } catch (TimeoutException te) { lastException = te; } } if (lastException != null) { if (lastException instanceof IOException) { throw (IOException) lastException; } else if (lastException instanceof TimeoutException) { throw (TimeoutException) lastException; } } throw new IOException("failed to connect"); } } public ConnectionParams params(ExecutorService consumerWorkServiceExecutor) { ConnectionParams result = new ConnectionParams(); result.setUsername(username); result.setPassword(password); result.setConsumerWorkServiceExecutor(consumerWorkServiceExecutor); result.setVirtualHost(virtualHost); result.setClientProperties(getClientProperties()); result.setRequestedFrameMax(requestedFrameMax); result.setRequestedChannelMax(requestedChannelMax); result.setShutdownTimeout(shutdownTimeout); result.setSaslConfig(saslConfig); result.setNetworkRecoveryInterval(networkRecoveryInterval); result.setTopologyRecovery(topologyRecovery); result.setExceptionHandler(exceptionHandler); result.setThreadFactory(threadFactory); result.setHandshakeTimeout(handshakeTimeout); result.setRequestedHeartbeat(requestedHeartbeat); result.setShutdownExecutor(shutdownExecutor); result.setHeartbeatExecutor(heartbeatExecutor); result.setChannelRpcTimeout(channelRpcTimeout); result.setChannelShouldCheckRpcResponseType(channelShouldCheckRpcResponseType); return result; } protected AMQConnection createConnection(ConnectionParams params, FrameHandler frameHandler, MetricsCollector metricsCollector) { return new AMQConnection(params, frameHandler, metricsCollector); } /** * Create a new broker connection. * * If automatic connection recovery * is enabled, the connection returned by this method will be {@link Recoverable}. Reconnection * attempts will always use the address configured on {@link ConnectionFactory}. * * @return an interface to the connection * @throws IOException if it encounters a problem */ public Connection newConnection() throws IOException, TimeoutException { return newConnection(this.sharedExecutor, Collections.singletonList(new Address(getHost(), getPort()))); } /** * Create a new broker connection. * * If automatic connection recovery * is enabled, the connection returned by this method will be {@link Recoverable}. Reconnection * attempts will always use the address configured on {@link ConnectionFactory}. * * @param connectionName client-provided connection name (an arbitrary string). Will * be displayed in management UI if the server supports it. * @return an interface to the connection * @throws IOException if it encounters a problem */ public Connection newConnection(String connectionName) throws IOException, TimeoutException { return newConnection(this.sharedExecutor, Collections.singletonList(new Address(getHost(), getPort())), connectionName); } /** * Create a new broker connection. * * If automatic connection recovery * is enabled, the connection returned by this method will be {@link Recoverable}. Reconnection * attempts will always use the address configured on {@link ConnectionFactory}. * * @param executor thread execution service for consumers on the connection * @return an interface to the connection * @throws IOException if it encounters a problem */ public Connection newConnection(ExecutorService executor) throws IOException, TimeoutException { return newConnection(executor, Collections.singletonList(new Address(getHost(), getPort()))); } /** * Create a new broker connection. * * If automatic connection recovery * is enabled, the connection returned by this method will be {@link Recoverable}. Reconnection * attempts will always use the address configured on {@link ConnectionFactory}. * * @param executor thread execution service for consumers on the connection * @param connectionName client-provided connection name (an arbitrary string). Will * be displayed in management UI if the server supports it. * @return an interface to the connection * @throws IOException if it encounters a problem */ public Connection newConnection(ExecutorService executor, String connectionName) throws IOException, TimeoutException { return newConnection(executor, Collections.singletonList(new Address(getHost(), getPort())), connectionName); } protected AddressResolver createAddressResolver(List
addresses) { if(addresses.size() == 1) { return new DnsRecordIpAddressResolver(addresses.get(0), isSSL()); } else { return new ListAddressResolver(addresses); } } @Override public ConnectionFactory clone(){ try { return (ConnectionFactory)super.clone(); } catch (CloneNotSupportedException e) { throw new RuntimeException(e); } } /** * Returns automatic connection recovery interval in milliseconds. * @return how long will automatic recovery wait before attempting to reconnect, in ms; default is 5000 */ public long getNetworkRecoveryInterval() { return networkRecoveryInterval; } /** * Sets connection recovery interval. Default is 5000. * @param networkRecoveryInterval how long will automatic recovery wait before attempting to reconnect, in ms */ public void setNetworkRecoveryInterval(int networkRecoveryInterval) { this.networkRecoveryInterval = networkRecoveryInterval; } /** * Sets connection recovery interval. Default is 5000. * @param networkRecoveryInterval how long will automatic recovery wait before attempting to reconnect, in ms */ public void setNetworkRecoveryInterval(long networkRecoveryInterval) { this.networkRecoveryInterval = networkRecoveryInterval; } /** * Sets the parameters when using NIO. * * * @param nioParams * @see NioParams */ public void setNioParams(NioParams nioParams) { this.nioParams = nioParams; } /** * Use non-blocking IO (NIO) for communication with the server. * With NIO, several connections created from the same {@link ConnectionFactory} * can use the same IO thread. * * A client process using a lot of not-so-active connections can benefit * from NIO, as it would use fewer threads than with the traditional, blocking IO mode. * * Use {@link NioParams} to tune NIO and a {@link SocketChannelConfigurator} to * configure the underlying {@link java.nio.channels.SocketChannel}s for connections. * * @see NioParams * @see SocketChannelConfigurator * @see java.nio.channels.SocketChannel * @see java.nio.channels.Selector */ public void useNio() { this.nio = true; } /** * Use blocking IO for communication with the server. * With blocking IO, each connection creates its own thread * to read data from the server. */ public void useBlockingIo() { this.nio = false; } /** * Set the continuation timeout for RPC calls in channels. * Default is 10 minutes. 0 means no timeout. * @param channelRpcTimeout */ public void setChannelRpcTimeout(int channelRpcTimeout) { if(channelRpcTimeout < 0) { throw new IllegalArgumentException("Timeout cannot be less than 0"); } this.channelRpcTimeout = channelRpcTimeout; } /** * Get the timeout for RPC calls in channels. * @return */ public int getChannelRpcTimeout() { return channelRpcTimeout; } /** * The factory to create SSL contexts. * This provides more flexibility to create {@link SSLContext}s * for different connections than sharing the {@link SSLContext} * with all the connections produced by the connection factory * (which is the case with the {@link #useSslProtocol()} methods). * This way, different connections with a different certificate * for each of them is a possible scenario. * @param sslContextFactory * @see #useSslProtocol(SSLContext) * @since 5.0.0 */ public void setSslContextFactory(SslContextFactory sslContextFactory) { this.sslContextFactory = sslContextFactory; } /** * When set to true, channels will check the response type (e.g. queue.declare * expects a queue.declare-ok response) of RPC calls * and ignore those that do not match. * Default is false. * @param channelShouldCheckRpcResponseType */ public void setChannelShouldCheckRpcResponseType(boolean channelShouldCheckRpcResponseType) { this.channelShouldCheckRpcResponseType = channelShouldCheckRpcResponseType; } public boolean isChannelShouldCheckRpcResponseType() { return channelShouldCheckRpcResponseType; } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/Consumer.java000066400000000000000000000102351316117667700264570ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; import java.io.IOException; /** *

Interface for application callback objects to receive notifications and messages from * a queue by subscription. * Most implementations will subclass {@link DefaultConsumer}. *

*

* The methods of this interface are invoked in a dispatch * thread which is separate from the {@link Connection}'s thread. This * allows {@link Consumer}s to call {@link Channel} or {@link * Connection} methods without causing a deadlock. *

* The {@link Consumer}s on a particular {@link Channel} are invoked serially on one or more * dispatch threads. {@link Consumer}s should avoid executing long-running code * because this will delay dispatch of messages to other {@link Consumer}s on the same * {@link Channel}. * * For a lambda-oriented syntax, use {@link DeliverCallback}, * {@link CancelCallback}, and {@link ConsumerShutdownSignalCallback}. * * @see Channel#basicConsume(String, boolean, String, boolean, boolean, java.util.Map, Consumer) * @see Channel#basicCancel */ public interface Consumer { /** * Called when the consumer is registered by a call to any of the * {@link Channel#basicConsume} methods. * @param consumerTag the consumer tag associated with the consumer */ void handleConsumeOk(String consumerTag); /** * Called when the consumer is cancelled by a call to {@link Channel#basicCancel}. * @param consumerTag the consumer tag associated with the consumer */ void handleCancelOk(String consumerTag); /** * Called when the consumer is cancelled for reasons other than by a call to * {@link Channel#basicCancel}. For example, the queue has been deleted. * See {@link #handleCancelOk} for notification of consumer * cancellation due to {@link Channel#basicCancel}. * @param consumerTag the consumer tag associated with the consumer * @throws IOException */ void handleCancel(String consumerTag) throws IOException; /** * Called when either the channel or the underlying connection has been shut down. * @param consumerTag the consumer tag associated with the consumer * @param sig a {@link ShutdownSignalException} indicating the reason for the shut down */ void handleShutdownSignal(String consumerTag, ShutdownSignalException sig); /** * Called when a basic.recover-ok is received * in reply to a basic.recover. All messages * received before this is invoked that haven't been ack'ed will be * re-delivered. All messages received afterwards won't be. * @param consumerTag the consumer tag associated with the consumer */ void handleRecoverOk(String consumerTag); /** * Called when a basic.deliver is received for this consumer. * @param consumerTag the consumer tag associated with the consumer * @param envelope packaging data for the message * @param properties content header data for the message * @param body the message body (opaque, client-specific byte array) * @throws IOException if the consumer encounters an I/O error while processing the message * @see Envelope */ void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException; } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/ConsumerCancelledException.java000066400000000000000000000025251316117667700321340ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; import com.rabbitmq.utility.SensibleClone; public class ConsumerCancelledException extends RuntimeException implements SensibleClone { /** Default for non-checking. */ private static final long serialVersionUID = 1L; @Override public ConsumerCancelledException sensibleClone() { try { return (ConsumerCancelledException) super.clone(); } catch (CloneNotSupportedException e) { // You've got to be kidding me throw new RuntimeException(e); } } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/ConsumerShutdownSignalCallback.java000066400000000000000000000035631316117667700327740ustar00rootroot00000000000000// Copyright (c) 2017 Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; import java.util.Map; /** * Callback interface to be notified when either the consumer channel * or the underlying connection has been shut down. * Prefer it over {@link Consumer} for a lambda-oriented syntax, * if you don't need to implement all the application callbacks. * @see CancelCallback * @see DeliverCallback * @see Channel#basicConsume(String, boolean, String, boolean, boolean, Map, DeliverCallback, CancelCallback) * @see Channel#basicConsume(String, boolean, String, boolean, boolean, Map, DeliverCallback, ConsumerShutdownSignalCallback) * @see Channel#basicConsume(String, boolean, String, boolean, boolean, Map, DeliverCallback, CancelCallback, ConsumerShutdownSignalCallback) * @since 5.0 */ @FunctionalInterface public interface ConsumerShutdownSignalCallback { /** * Called when either the channel or the underlying connection has been shut down. * @param consumerTag the consumer tag associated with the consumer * @param sig a {@link ShutdownSignalException} indicating the reason for the shut down */ void handleShutdownSignal(String consumerTag, ShutdownSignalException sig); } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/ContentHeader.java000066400000000000000000000030471316117667700274120ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; /** * Public API for abstract AMQP content header objects. */ public interface ContentHeader extends Cloneable { /** * Retrieve the class ID (see the spec for a list of allowable IDs). * @return class ID of this ContentHeader. Properly an unsigned short, i.e. only the lowest 16 bits are significant */ public abstract int getClassId(); /** * Retrieve the class name, eg "basic" (see the spec for a list of these). * @return class name of this ContentHeader */ public abstract String getClassName(); /** * A debugging utility - enable properties to be appended to a string buffer for use as trace messages. * @param buffer a place to append the properties as a string */ public void appendPropertyDebugStringTo(StringBuilder buffer); } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/DefaultConsumer.java000066400000000000000000000064531316117667700277730ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; import java.io.IOException; /** * Convenience class providing a default implementation of {@link Consumer}. * We anticipate that most Consumer implementations will subclass this class. */ public class DefaultConsumer implements Consumer { /** Channel that this consumer is associated with. */ private final Channel _channel; /** Consumer tag for this consumer. */ private volatile String _consumerTag; /** * Constructs a new instance and records its association to the passed-in channel. * @param channel the channel to which this consumer is attached */ public DefaultConsumer(Channel channel) { _channel = channel; } /** * Stores the most recently passed-in consumerTag - semantically, there should be only one. * @see Consumer#handleConsumeOk */ @Override public void handleConsumeOk(String consumerTag) { this._consumerTag = consumerTag; } /** * No-op implementation of {@link Consumer#handleCancelOk}. * @param consumerTag the defined consumer tag (client- or server-generated) */ @Override public void handleCancelOk(String consumerTag) { // no work to do } /** * No-op implementation of {@link Consumer#handleCancel(String)} * @param consumerTag the defined consumer tag (client- or server-generated) */ @Override public void handleCancel(String consumerTag) throws IOException { // no work to do } /** * No-op implementation of {@link Consumer#handleShutdownSignal}. */ @Override public void handleShutdownSignal(String consumerTag, ShutdownSignalException sig) { // no work to do } /** * No-op implementation of {@link Consumer#handleRecoverOk}. */ @Override public void handleRecoverOk(String consumerTag) { // no work to do } /** * No-op implementation of {@link Consumer#handleDelivery}. */ @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { // no work to do } /** * Retrieve the channel. * @return the channel this consumer is attached to. */ public Channel getChannel() { return _channel; } /** * Retrieve the consumer tag. * @return the most recently notified consumer tag. */ public String getConsumerTag() { return _consumerTag; } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/DefaultSaslConfig.java000066400000000000000000000036751316117667700302330ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; import com.rabbitmq.client.impl.ExternalMechanism; import com.rabbitmq.client.impl.PlainMechanism; import java.util.Arrays; import java.util.HashSet; import java.util.Set; /** * Default SASL configuration. Uses one of our built-in mechanisms. */ public class DefaultSaslConfig implements SaslConfig { private final String mechanism; public static final DefaultSaslConfig PLAIN = new DefaultSaslConfig("PLAIN"); public static final DefaultSaslConfig EXTERNAL = new DefaultSaslConfig("EXTERNAL"); /** * Create a DefaultSaslConfig with an explicit mechanism to use. * * @param mechanism - a SASL mechanism to use */ private DefaultSaslConfig(String mechanism) { this.mechanism = mechanism; } @Override public SaslMechanism getSaslMechanism(String[] serverMechanisms) { Set server = new HashSet(Arrays.asList(serverMechanisms)); if (server.contains(mechanism)) { if (mechanism.equals("PLAIN")) { return new PlainMechanism(); } else if (mechanism.equals("EXTERNAL")) { return new ExternalMechanism(); } } return null; } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/DefaultSocketChannelConfigurator.java000066400000000000000000000030331316117667700332730ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; import java.io.IOException; import java.nio.channels.SocketChannel; public class DefaultSocketChannelConfigurator implements SocketChannelConfigurator { /** * Provides a hook to insert custom configuration of the {@link SocketChannel}s * used to connect to an AMQP server before they connect. * * The default behaviour of this method is to disable Nagle's * algorithm to get more consistently low latency. However it * may be overridden freely and there is no requirement to retain * this behaviour. * * @param socketChannel The socket channel that is to be used for the Connection */ @Override public void configure(SocketChannel socketChannel) throws IOException { socketChannel.socket().setTcpNoDelay(true); } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/DefaultSocketConfigurator.java000066400000000000000000000030101316117667700317750ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; import java.io.IOException; import java.net.Socket; public class DefaultSocketConfigurator implements SocketConfigurator { /** * Provides a hook to insert custom configuration of the sockets * used to connect to an AMQP server before they connect. * * The default behaviour of this method is to disable Nagle's * algorithm to get more consistently low latency. However it * may be overridden freely and there is no requirement to retain * this behaviour. * * @param socket The socket that is to be used for the Connection */ @Override public void configure(Socket socket) throws IOException { // disable Nagle's algorithm, for more consistently low latency socket.setTcpNoDelay(true); } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/DeliverCallback.java000066400000000000000000000036001316117667700276710ustar00rootroot00000000000000// Copyright (c) 2017 Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; import java.io.IOException; import java.util.Map; /** * Callback interface to be notified when a message is delivered. * Prefer it over {@link Consumer} for a lambda-oriented syntax, * if you don't need to implement all the application callbacks. * @see CancelCallback * @see ConsumerShutdownSignalCallback * @see Channel#basicConsume(String, boolean, String, boolean, boolean, Map, DeliverCallback, CancelCallback) * @see Channel#basicConsume(String, boolean, String, boolean, boolean, Map, DeliverCallback, ConsumerShutdownSignalCallback) * @see Channel#basicConsume(String, boolean, String, boolean, boolean, Map, DeliverCallback, CancelCallback, ConsumerShutdownSignalCallback) * @since 5.0 */ @FunctionalInterface public interface DeliverCallback { /** * Called when a basic.deliver is received for this consumer. * @param consumerTag the consumer tag associated with the consumer * @param message the delivered message * @throws IOException if the consumer encounters an I/O error while processing the message */ void handle(String consumerTag, Delivery message) throws IOException; } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/Delivery.java000066400000000000000000000031521316117667700264470ustar00rootroot00000000000000// Copyright (c) 2017 Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; /** * Encapsulates an arbitrary message - simple "bean" holder structure. */ public class Delivery { private final Envelope _envelope; private final AMQP.BasicProperties _properties; private final byte[] _body; public Delivery(Envelope envelope, AMQP.BasicProperties properties, byte[] body) { _envelope = envelope; _properties = properties; _body = body; } /** * Retrieve the message envelope. * @return the message envelope */ public Envelope getEnvelope() { return _envelope; } /** * Retrieve the message properties. * @return the message properties */ public AMQP.BasicProperties getProperties() { return _properties; } /** * Retrieve the message body. * @return the message body */ public byte[] getBody() { return _body; } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/DnsRecordIpAddressResolver.java000066400000000000000000000055211316117667700320720ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; import java.io.IOException; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; /** * {@link AddressResolver} that resolves DNS record IPs. * Uses {@link InetAddress} internally. * The first returned address is used when automatic recovery is NOT enabled * at the {@link ConnectionFactory} level. * When automatic recovery is enabled, a random address will be picked up * from the returned list of {@link Address}es. */ public class DnsRecordIpAddressResolver implements AddressResolver { private final Address address; private final boolean ssl; public DnsRecordIpAddressResolver(String hostname, int port, boolean ssl) { this(new Address(hostname, port), ssl); } public DnsRecordIpAddressResolver(String hostname, int port) { this(new Address(hostname, port), false); } public DnsRecordIpAddressResolver() { this("localhost"); } public DnsRecordIpAddressResolver(String hostname) { this(new Address(hostname), false); } public DnsRecordIpAddressResolver(Address address) { this(address, false); } public DnsRecordIpAddressResolver(Address address, boolean ssl) { this.address = address; this.ssl = ssl; } /** * Get the IP addresses from a DNS query * @return candidate {@link Address}es * @throws IOException if DNS resolution fails */ @Override public List
getAddresses() throws UnknownHostException { String hostName = address.getHost(); int portNumber = ConnectionFactory.portOrDefault(address.getPort(), ssl); InetAddress[] inetAddresses = resolveIpAddresses(hostName); List
addresses = new ArrayList
(); for (InetAddress inetAddress : inetAddresses) { addresses.add(new Address(inetAddress.getHostAddress(), portNumber)); } return addresses; } protected InetAddress[] resolveIpAddresses(String hostName) throws UnknownHostException { return InetAddress.getAllByName(hostName); } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/DnsSrvRecordAddressResolver.java000066400000000000000000000131541316117667700322750ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; import javax.naming.NamingEnumeration; import javax.naming.NamingException; import javax.naming.directory.Attributes; import javax.naming.directory.DirContext; import javax.naming.directory.InitialDirContext; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.Hashtable; import java.util.List; /** * {@link AddressResolver} that resolves addresses against a DNS SRV request. * SRV records contain the hostname and the port for a given service. * They also support priorities, to give precedence to a given host * over other hosts. * Note the hosts returned by the SRV query must be resolvable by * the DNS servers of the underlying platform (or the default ones * specified for this Java process). This class does not issue a * query for A records after the SRV query. * This implementation returns the highest-priority records first. * This behavior can be changed by overriding the {@code sort} method. * * This implementation uses internally the {@code com.sun.jndi.dns.DnsContextFactory} * class for the DNS query. * * The first returned address is used when automatic recovery is NOT enabled * at the {@link ConnectionFactory} level. * When automatic recovery is enabled, a random address will be picked up * from the returned list of {@link Address}es. * */ public class DnsSrvRecordAddressResolver implements AddressResolver { /** * the SRV service information. * e.g. _sip._tcp.example.com or rabbitmq.service.consul */ private final String service; /** * URLs of the DNS servers. * e.g. dns://server1.example.com/example.com * Default to {@code dns:}, that is the DNS server of the * underlying platform. */ private final String dnsUrls; public DnsSrvRecordAddressResolver(String service) { this(service, "dns:"); } public DnsSrvRecordAddressResolver(String service, String dnsUrls) { this.service = service; this.dnsUrls = dnsUrls; } @Override public List
getAddresses() throws IOException { List records = lookupSrvRecords(service, dnsUrls); records = sort(records); List
addresses = new ArrayList
(); for (SrvRecord record : records) { addresses.add(new Address(record.getHost(), record.getPort())); } return addresses; } protected List lookupSrvRecords(String service, String dnsUrls) throws IOException { Hashtable env = new Hashtable(); env.put("java.naming.factory.initial", "com.sun.jndi.dns.DnsContextFactory"); env.put("java.naming.provider.url", dnsUrls); List records = new ArrayList(); try { DirContext ctx = new InitialDirContext(env); Attributes attributes = ctx.getAttributes(service, new String[] { "SRV" }); NamingEnumeration servers = attributes.get("srv").getAll(); while (servers.hasMore()) { records.add(mapSrvRecord((String) servers.next())); } } catch(NamingException e) { throw new IOException("Error during DNS SRV query", e); } return records; } protected SrvRecord mapSrvRecord(String srvResult) { return SrvRecord.fromSrvQueryResult(srvResult); } protected List sort(List records) { Collections.sort(records); return records; } public static class SrvRecord implements Comparable { private final int priority; private final int weight; private final int port; private final String host; public SrvRecord(int priority, int weight, int port, String host) { this.priority = priority; this.weight = weight; this.port = port; int lastDotIndex = host.lastIndexOf("."); if(lastDotIndex > 0) { this.host = host.substring(0, lastDotIndex); } else { this.host = host; } } public int getPriority() { return priority; } public int getWeight() { return weight; } public int getPort() { return port; } public String getHost() { return host; } public static SrvRecord fromSrvQueryResult(String srvResult) { String[] fields = srvResult.split(" "); return new SrvRecord( Integer.parseInt(fields[0]), Integer.parseInt(fields[1]), Integer.parseInt(fields[2]), fields[3] ); } @Override public int compareTo(SrvRecord o) { return (this.priority < o.getPriority()) ? -1 : ((this.priority == o.getPriority()) ? 0 : 1); } } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/Envelope.java000066400000000000000000000056271316117667700264520ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; /** * Encapsulates a group of parameters used for AMQP's Basic methods */ public class Envelope { private final long _deliveryTag; private final boolean _redeliver; private final String _exchange; private final String _routingKey; /** * Construct an {@link Envelope} with the specified construction parameters * @param deliveryTag the delivery tag * @param redeliver true if this is a redelivery following a failed ack * @param exchange the exchange used for the current operation * @param routingKey the associated routing key */ public Envelope(long deliveryTag, boolean redeliver, String exchange, String routingKey) { this._deliveryTag = deliveryTag; this._redeliver = redeliver; this._exchange = exchange; this._routingKey = routingKey; } /** * Get the delivery tag included in this parameter envelope * @return the delivery tag */ public long getDeliveryTag() { return _deliveryTag; } /** * Get the redelivery flag included in this parameter envelope. This is a * hint as to whether this message may have been delivered before (but not * acknowledged). If the flag is not set, the message definitely has not * been delivered before. If it is set, it may have been delivered before. * * @return the redelivery flag */ public boolean isRedeliver() { return _redeliver; } /** * Get the name of the exchange included in this parameter envelope * @return the exchange */ public String getExchange() { return _exchange; } /** * Get the routing key included in this parameter envelope * @return the routing key */ public String getRoutingKey() { return _routingKey; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("Envelope(deliveryTag=").append(_deliveryTag); sb.append(", redeliver=").append(_redeliver); sb.append(", exchange=").append(_exchange); sb.append(", routingKey=").append(_routingKey); sb.append(")"); return sb.toString(); } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/ExceptionHandler.java000066400000000000000000000113551316117667700301240ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; /** * Interface to an exception-handling object. */ public interface ExceptionHandler { /** * Perform any required exception processing for the situation * when the driver thread for the connection has an exception * signalled to it that it can't otherwise deal with. * @param conn the Connection that caught the exception * @param exception the exception caught in the driver thread */ void handleUnexpectedConnectionDriverException(Connection conn, Throwable exception); /** * Perform any required exception processing for the situation * when the driver thread for the connection has called a * ReturnListener's handleReturn method, and that method has * thrown an exception. * @param channel the ChannelN that held the ReturnListener * @param exception the exception thrown by ReturnListener.handleReturn */ void handleReturnListenerException(Channel channel, Throwable exception); /** * Perform any required exception processing for the situation * when the driver thread for the connection has called a * ConfirmListener's handleAck or handleNack method, and that * method has thrown an exception. * @param channel the ChannelN that held the ConfirmListener * @param exception the exception thrown by ConfirmListener.handleAck */ void handleConfirmListenerException(Channel channel, Throwable exception); /** * Perform any required exception processing for the situation * when the driver thread for the connection has called a * BlockedListener's method, and that method has * thrown an exception. * @param connection the Connection that held the BlockedListener * @param exception the exception thrown by the BlockedListener */ void handleBlockedListenerException(Connection connection, Throwable exception); /** * Perform any required exception processing for the situation * when the driver thread for the connection has called a method * on a Consumer, and that method has thrown an exception. * @param channel the ChannelN that held the Consumer * @param exception the exception thrown by the Consumer * @param consumer the Consumer that caused the fault * @param consumerTag the Consumer's consumerTag * @param methodName the name of the method on the Consumer that threw the exception */ void handleConsumerException(Channel channel, Throwable exception, Consumer consumer, String consumerTag, String methodName); /** * Perform any required exception processing for the situation * when the driver thread for the connection has an exception * during connection recovery that it can't otherwise deal with. * @param conn the Connection that caught the exception * @param exception the exception caught in the driver thread */ void handleConnectionRecoveryException(Connection conn, Throwable exception); /** * Perform any required exception processing for the situation * when the driver thread for the connection has an exception * during channel recovery that it can't otherwise deal with. * @param ch the Channel that caught the exception * @param exception the exception caught in the driver thread */ void handleChannelRecoveryException(Channel ch, Throwable exception); /** * Perform any required exception processing for the situation * when the driver thread for the connection has an exception * during topology (exchanges, queues, bindings, consumers) recovery * that it can't otherwise deal with. * @param conn the Connection that caught the exception * @param ch the Channel that caught the exception * @param exception the exception caught in the driver thread */ void handleTopologyRecoveryException(Connection conn, Channel ch, TopologyRecoveryException exception); } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/GetResponse.java000066400000000000000000000066541316117667700271340ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; import com.rabbitmq.client.AMQP.BasicProperties; /** * Encapsulates the response from a {@link Channel#basicGet} message-retrieval method call * - essentially a static bean "holder" with message response data. */ public class GetResponse { private final Envelope envelope; private final BasicProperties props; private final byte[] body; private final int messageCount; /** * Construct a {@link GetResponse} with the specified construction parameters * @param envelope the {@link Envelope} * @param props message properties * @param body the message body * @param messageCount the server's most recent estimate of the number of messages remaining on the queue */ public GetResponse(Envelope envelope, BasicProperties props, byte[] body, int messageCount) { this.envelope = envelope; this.props = props; this.body = body; this.messageCount = messageCount; } /** * Get the {@link Envelope} included in this response * @return the envelope */ public Envelope getEnvelope() { return envelope; } /** * Get the {@link BasicProperties} included in this response * @return the properties */ public BasicProperties getProps() { return props; } /** * Get the message body included in this response * @return the message body */ public byte[] getBody() { return body; } /** * Get the server's most recent estimate of the number of messages * remaining on the queue. This number can only ever be a rough * estimate, because of concurrent activity at the server and the * delay between the server sending its estimate and the client * receiving and processing the message containing the estimate. * *

According to the AMQP specification, this figure does not * include the message being delivered. For example, this field * will be zero in the simplest case of a single reader issuing a * Basic.Get on a private queue holding a single message (the * message being delivered in this GetResponse). * * @return an estimate of the number of messages remaining to be * read from the queue */ public int getMessageCount() { return messageCount; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("GetResponse(envelope=").append(envelope); sb.append(", props=").append(props); sb.append(", messageCount=").append(messageCount); sb.append(", body=(elided, ").append(body.length).append(" bytes long)"); sb.append(")"); return sb.toString(); } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/JDKSaslConfig.java000066400000000000000000000116021316117667700272440ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; import com.rabbitmq.client.impl.LongStringHelper; import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.NameCallback; import javax.security.auth.callback.PasswordCallback; import javax.security.auth.callback.UnsupportedCallbackException; import javax.security.sasl.Sasl; import javax.security.sasl.SaslClient; import javax.security.sasl.SaslException; import java.io.IOException; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; /** * Implementation of SaslConfig that uses the JDK SASL implementation. This is * not the default since it does not work on Java 1.4, Android or IBM's JDK. * @see com.rabbitmq.client.ConnectionFactory */ public class JDKSaslConfig implements SaslConfig { private static final String[] DEFAULT_PREFERRED_MECHANISMS = new String[]{"PLAIN"}; private final ConnectionFactory factory; private final List mechanisms; private final CallbackHandler callbackHandler; /** * Create a JDKSaslConfig which only wants to use PLAIN. * * @param factory - the ConnectionFactory to use to obtain username, password and host */ public JDKSaslConfig(ConnectionFactory factory) { this(factory, DEFAULT_PREFERRED_MECHANISMS); } /** * Create a JDKSaslConfig with a list of mechanisms to use. * * @param factory - the ConnectionFactory to use to obtain username, password and host * @param mechanisms - a list of SASL mechanisms to use (in descending order of preference) */ public JDKSaslConfig(ConnectionFactory factory, String[] mechanisms) { this.factory = factory; callbackHandler = new UsernamePasswordCallbackHandler(factory); this.mechanisms = Arrays.asList(mechanisms); } @Override public SaslMechanism getSaslMechanism(String[] serverMechanisms) { Set server = new HashSet(Arrays.asList(serverMechanisms)); for (String mechanism: mechanisms) { if (server.contains(mechanism)) { try { SaslClient saslClient = Sasl.createSaslClient(new String[]{mechanism}, null, "AMQP", factory.getHost(), null, callbackHandler); if (saslClient != null) return new JDKSaslMechanism(saslClient); } catch (SaslException e) { throw new RuntimeException(e); } } } return null; } private class JDKSaslMechanism implements SaslMechanism { private final SaslClient client; public JDKSaslMechanism(SaslClient client) { this.client = client; } @Override public String getName() { return client.getMechanismName(); } @Override public LongString handleChallenge(LongString challenge, String username, String password) { try { return LongStringHelper.asLongString(client.evaluateChallenge(challenge.getBytes())); } catch (SaslException e) { throw new RuntimeException(e); } } } private class UsernamePasswordCallbackHandler implements CallbackHandler { private final ConnectionFactory factory; public UsernamePasswordCallbackHandler(ConnectionFactory factory) { this.factory = factory; } @Override public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { for (Callback callback: callbacks) { if (callback instanceof NameCallback) { NameCallback nc = (NameCallback)callback; nc.setName(factory.getUsername()); } else if (callback instanceof PasswordCallback) { PasswordCallback pc = (PasswordCallback)callback; pc.setPassword(factory.getPassword().toCharArray()); } else { throw new UnsupportedCallbackException (callback, "Unrecognized Callback"); } } } } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/ListAddressResolver.java000066400000000000000000000022251316117667700306270ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; import java.util.List; /** * Simple implementation of {@link AddressResolver} that returns a fixed list. */ public class ListAddressResolver implements AddressResolver { private final List

addresses; public ListAddressResolver(List
addresses) { this.addresses = addresses; } @Override public List
getAddresses() { return addresses; } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/LongString.java000066400000000000000000000043341316117667700267550ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; import java.io.DataInputStream; import java.io.IOException; /** * An object providing access to a LongString. * This might be implemented to read directly from connection * socket, depending on the size of the content to be read - * long strings may contain up to 4Gb of content. */ public interface LongString { public static final long MAX_LENGTH = 0xffffffffL; /** * @return the length of the string in bytes between 0 and MAX_LENGTH (inclusive) */ public long length(); /** * Get the content stream. * Repeated calls to this function return the same stream, * which may not support rewind. * @return An input stream that reads the content of the string * @throws IOException if an error is encountered */ public DataInputStream getStream() throws IOException; /** * Get the content as a byte array. This need not be a copy. Updates to the * returned array may change the value of the string. * Repeated calls to this function may return the same array. * This function will fail if this string's length is greater than {@link Integer#MAX_VALUE}, * throwing an {@link IllegalStateException}. * @return the array of bytes containing the content of the {@link LongString} */ public byte [] getBytes(); /** * Get the content as a String. Uses UTF-8 as encoding. * @return he content of the {@link LongString} as a string */ @Override public String toString(); } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/MalformedFrameException.java000066400000000000000000000022711316117667700314250ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; import java.io.IOException; /** * Encapsulates a frame format error at the wire level. */ public class MalformedFrameException extends IOException { /** Standard serialization ID. */ private static final long serialVersionUID = 1L; /** * Instantiate a MalformedFrameException. * @param reason a string describing the exception */ public MalformedFrameException(String reason) { super(reason); } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/MapRpcServer.java000066400000000000000000000070661316117667700272450ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.util.HashMap; import java.util.Map; import com.rabbitmq.client.impl.MethodArgumentReader; import com.rabbitmq.client.impl.MethodArgumentWriter; import com.rabbitmq.client.impl.ValueReader; import com.rabbitmq.client.impl.ValueWriter; /** * Subclass of RpcServer which uses AMQP wire-format encoded tables as * requests and replies. */ public class MapRpcServer extends RpcServer { public MapRpcServer(Channel channel) throws IOException { super(channel); } public MapRpcServer(Channel channel, String queueName) throws IOException { super(channel, queueName); } /** * Overridden to delegate to handleMapCall. */ @Override public byte[] handleCall(byte[] requestBody, AMQP.BasicProperties replyProperties) { try { return encode(handleMapCall(decode(requestBody), replyProperties)); } catch (IOException ioe) { return new byte[0]; } } public static Map decode(byte[] requestBody) throws IOException { MethodArgumentReader reader = new MethodArgumentReader(new ValueReader (new DataInputStream (new ByteArrayInputStream(requestBody)))); Map request = reader.readTable(); return request; } public static byte[] encode(Map reply) throws IOException { ByteArrayOutputStream buffer = new ByteArrayOutputStream(); MethodArgumentWriter writer = new MethodArgumentWriter(new ValueWriter(new DataOutputStream(buffer))); writer.writeTable(reply); writer.flush(); return buffer.toByteArray(); } /** * Delegates to {@link MapRpcServer#handleMapCall(Map)}. */ public Map handleMapCall(Map request, AMQP.BasicProperties replyProperties) { return handleMapCall(request); } /** * Default implementation override in subclasses. Returns the empty string. */ public Map handleMapCall(Map request) { return new HashMap(); } /** * Overridden to delegate to handleMapCast. */ @Override public void handleCast(byte[] requestBody) { try { handleMapCast(decode(requestBody)); } catch (IOException ioe) { // Do nothing. } } /** * Default implementation override in subclasses. Does nothing. */ public void handleMapCast(Map requestBody) { // Do nothing. } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/MessageProperties.java000066400000000000000000000066241316117667700303340ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; import com.rabbitmq.client.AMQP.BasicProperties; import com.rabbitmq.client.impl.AMQContentHeader; /** * Constant holder class with useful static instances of {@link AMQContentHeader}. * These are intended for use with {@link Channel#basicPublish} and other Channel methods. */ public class MessageProperties { /** Empty basic properties, with no fields set */ public static final BasicProperties MINIMAL_BASIC = new BasicProperties(null, null, null, null, null, null, null, null, null, null, null, null, null, null); /** Empty basic properties, with only deliveryMode set to 2 (persistent) */ public static final BasicProperties MINIMAL_PERSISTENT_BASIC = new BasicProperties(null, null, null, 2, null, null, null, null, null, null, null, null, null, null); /** Content-type "application/octet-stream", deliveryMode 1 (nonpersistent), priority zero */ public static final BasicProperties BASIC = new BasicProperties("application/octet-stream", null, null, 1, 0, null, null, null, null, null, null, null, null, null); /** Content-type "application/octet-stream", deliveryMode 2 (persistent), priority zero */ public static final BasicProperties PERSISTENT_BASIC = new BasicProperties("application/octet-stream", null, null, 2, 0, null, null, null, null, null, null, null, null, null); /** Content-type "text/plain", deliveryMode 1 (nonpersistent), priority zero */ public static final BasicProperties TEXT_PLAIN = new BasicProperties("text/plain", null, null, 1, 0, null, null, null, null, null, null, null, null, null); /** Content-type "text/plain", deliveryMode 2 (persistent), priority zero */ public static final BasicProperties PERSISTENT_TEXT_PLAIN = new BasicProperties("text/plain", null, null, 2, 0, null, null, null, null, null, null, null, null, null); } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/Method.java000066400000000000000000000025771316117667700261160ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; /** * Public interface to objects representing an AMQP 0-9-1 method * @see http://www.rabbitmq.com/specification.html. */ public interface Method { /** * Retrieve the protocol class ID * @return the AMQP protocol class ID of this Method */ int protocolClassId(); /* properly an unsigned short */ /** * Retrieve the protocol method ID * @return the AMQP protocol method ID of this Method */ int protocolMethodId(); /* properly an unsigned short */ /** * Retrieve the method name * @return the AMQP protocol method name of this Method */ String protocolMethodName(); } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/MetricsCollector.java000066400000000000000000000034401316117667700301410ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; /** * Interface to gather execution data of the client. * Note transactions are not supported: they deal with * publishing and acknowledgments and the collector contract * assumes then that published messages and acks sent * in a transaction are always counted, even if the * transaction is rolled back. * */ public interface MetricsCollector { void newConnection(Connection connection); void closeConnection(Connection connection); void newChannel(Channel channel); void closeChannel(Channel channel); void basicPublish(Channel channel); void consumedMessage(Channel channel, long deliveryTag, boolean autoAck); void consumedMessage(Channel channel, long deliveryTag, String consumerTag); void basicAck(Channel channel, long deliveryTag, boolean multiple); void basicNack(Channel channel, long deliveryTag); void basicReject(Channel channel, long deliveryTag); void basicConsume(Channel channel, String consumerTag, boolean autoAck); void basicCancel(Channel channel, String consumerTag); } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/MissedHeartbeatException.java000066400000000000000000000021661316117667700316130ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; import java.net.SocketTimeoutException; /** * Encapsulates an exception indicating that the connection has missed too many heartbeats * and is being shut down. */ public class MissedHeartbeatException extends SocketTimeoutException { private static final long serialVersionUID = 1L; public MissedHeartbeatException(String reason) { super(reason); } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/NoOpMetricsCollector.java000066400000000000000000000035471316117667700307450ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; /** * */ public class NoOpMetricsCollector implements MetricsCollector { @Override public void newConnection(Connection connection) { } @Override public void closeConnection(Connection connection) { } @Override public void newChannel(Channel channel) { } @Override public void closeChannel(Channel channel) { } @Override public void basicAck(Channel channel, long deliveryTag, boolean multiple) { } @Override public void basicNack(Channel channel, long deliveryTag) { } @Override public void basicReject(Channel channel, long deliveryTag) { } @Override public void basicConsume(Channel channel, String consumerTag, boolean autoAck) { } @Override public void basicCancel(Channel channel, String consumerTag) { } @Override public void basicPublish(Channel channel) { } @Override public void consumedMessage(Channel channel, long deliveryTag, boolean autoAck) { } @Override public void consumedMessage(Channel channel, long deliveryTag, String consumerTag) { } } PossibleAuthenticationFailureException.java000066400000000000000000000024261316117667700344570ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; import java.io.IOException; /** * Thrown when the likely cause is an authentication failure. */ public class PossibleAuthenticationFailureException extends IOException { /** Default for non-checking. */ private static final long serialVersionUID = 1L; public PossibleAuthenticationFailureException(Throwable cause) { super("Possibly caused by authentication failure"); super.initCause(cause); } public PossibleAuthenticationFailureException(String reason) { super(reason); } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/ProtocolVersionMismatchException.java000066400000000000000000000046441316117667700334070ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; import com.rabbitmq.client.impl.Version; import java.net.ProtocolException; /** * Thrown to indicate that the server does not support the wire protocol version * we requested immediately after opening the TCP socket. */ public class ProtocolVersionMismatchException extends ProtocolException { /** Default serialVersionUID for serializability without version checking. */ private static final long serialVersionUID = 1L; private final Version clientVersion; private final Version serverVersion; public ProtocolVersionMismatchException(Version clientVersion, Version serverVersion) { super("Protocol version mismatch: expected " + clientVersion + ", got " + serverVersion); this.clientVersion = clientVersion; this.serverVersion = serverVersion; } /** The client's AMQP specification version. */ public Version getClientVersion() { return clientVersion; } /** The server's AMQP specification version. */ public Version getServerVersion() { return serverVersion; } /** The client's AMQP specification major version. */ public int getClientMajor() { return clientVersion.getMajor(); } /** The client's AMQP specification minor version. */ public int getClientMinor() { return clientVersion.getMinor(); } /** The server's AMQP specification major version. */ public int getServerMajor() { return serverVersion.getMajor(); } /** The server's AMQP specification minor version. */ public int getServerMinor() { return serverVersion.getMinor(); } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/Recoverable.java000066400000000000000000000026751316117667700271260ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; /** * Provides a way to register (network, AMQP 0-9-1) connection recovery * callbacks. * * When connection recovery is enabled via {@link ConnectionFactory}, * {@link ConnectionFactory#newConnection()} and {@link Connection#createChannel()} * return {@link Recoverable} connections and channels. * * @see com.rabbitmq.client.impl.recovery.AutorecoveringConnection * @see com.rabbitmq.client.impl.recovery.AutorecoveringChannel */ public interface Recoverable { /** * Registers a connection recovery callback. * * @param listener Callback function */ void addRecoveryListener(RecoveryListener listener); void removeRecoveryListener(RecoveryListener listener); } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/RecoverableChannel.java000066400000000000000000000004211316117667700304020ustar00rootroot00000000000000package com.rabbitmq.client; import com.rabbitmq.client.Channel; import com.rabbitmq.client.Recoverable; /** * Convenient interface when working against auto-recovery channels. * * @since 4.0.0 */ public interface RecoverableChannel extends Recoverable, Channel { } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/RecoverableConnection.java000066400000000000000000000003151316117667700311330ustar00rootroot00000000000000package com.rabbitmq.client; /** * Convenient interface when working against auto-recovery connections. * * @since 4.0.0 */ public interface RecoverableConnection extends Recoverable, Connection { } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/RecoveryListener.java000066400000000000000000000026701316117667700301740ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; /** * A RecoveryListener receives notifications about completed automatic connection * recovery. * * @since 3.3.0 */ public interface RecoveryListener { /** * Invoked when automatic connection recovery has completed. * This includes topology recovery if it was enabled. * @param recoverable a {@link Recoverable} connection. */ void handleRecovery(Recoverable recoverable); /** * Invoked before automatic connection recovery starts. * This means no recovery steps were performed at this point * during recovery process. * @param recoverable a {@link Recoverable} connection. */ void handleRecoveryStarted(Recoverable recoverable); } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/Return.java000066400000000000000000000033701316117667700261450ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; /** * */ public class Return { private final int replyCode; private final String replyText; private final String exchange; private final String routingKey; private final AMQP.BasicProperties properties; private final byte[] body; public Return(int replyCode, String replyText, String exchange, String routingKey, AMQP.BasicProperties properties, byte[] body) { this.replyCode = replyCode; this.replyText = replyText; this.exchange = exchange; this.routingKey = routingKey; this.properties = properties; this.body = body; } public int getReplyCode() { return replyCode; } public String getReplyText() { return replyText; } public String getExchange() { return exchange; } public String getRoutingKey() { return routingKey; } public AMQP.BasicProperties getProperties() { return properties; } public byte[] getBody() { return body; } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/ReturnCallback.java000066400000000000000000000022261316117667700275610ustar00rootroot00000000000000// Copyright (c) 2017 Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; /** * Implement this interface in order to be notified of failed * deliveries when basicPublish is called with "mandatory" or * "immediate" flags set. * Prefer this interface over {@link ReturnListener} for * a simpler, lambda-oriented syntax. * @see Channel#basicPublish * @see ReturnListener * @see Return */ @FunctionalInterface public interface ReturnCallback { void handle(Return returnMessage); } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/ReturnListener.java000066400000000000000000000024271316117667700276550ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; import java.io.IOException; /** * Implement this interface in order to be notified of failed * deliveries when basicPublish is called with "mandatory" or * "immediate" flags set. * For a lambda-oriented syntax, use {@link ReturnCallback}. * @see Channel#basicPublish */ public interface ReturnListener { void handleReturn(int replyCode, String replyText, String exchange, String routingKey, AMQP.BasicProperties properties, byte[] body) throws IOException; } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/RpcClient.java000066400000000000000000000410311316117667700265450ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.EOFException; import java.io.IOException; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.TimeoutException; import com.rabbitmq.client.impl.MethodArgumentReader; import com.rabbitmq.client.impl.MethodArgumentWriter; import com.rabbitmq.client.impl.ValueReader; import com.rabbitmq.client.impl.ValueWriter; import com.rabbitmq.utility.BlockingCell; /** * Convenience class which manages simple RPC-style communication. * The class is agnostic about the format of RPC arguments / return values. * It simply provides a mechanism for sending a message to an exchange with a given routing key, * and waiting for a response. */ public class RpcClient { /** Channel we are communicating on */ private final Channel _channel; /** Exchange to send requests to */ private final String _exchange; /** Routing key to use for requests */ private final String _routingKey; /** Queue where the server should put the reply */ private final String _replyTo; /** timeout to use on call responses */ private final int _timeout; /** NO_TIMEOUT value must match convention on {@link BlockingCell#uninterruptibleGet(int)} */ protected final static int NO_TIMEOUT = -1; /** Map from request correlation ID to continuation BlockingCell */ private final Map> _continuationMap = new HashMap>(); /** Contains the most recently-used request correlation ID */ private int _correlationId; /** Consumer attached to our reply queue */ private DefaultConsumer _consumer; /** * Construct a new RpcClient that will communicate on the given channel, sending * requests to the given exchange with the given routing key. * * Causes the creation of a temporary private autodelete queue. The name of this queue can be specified. * @param channel the channel to use for communication * @param exchange the exchange to connect to * @param routingKey the routing key * @param replyTo the queue where the server should put the reply * @param timeout milliseconds before timing out on wait for response * @throws IOException if an error is encountered */ public RpcClient(Channel channel, String exchange, String routingKey, String replyTo, int timeout) throws IOException { _channel = channel; _exchange = exchange; _routingKey = routingKey; _replyTo = replyTo; if (timeout < NO_TIMEOUT) throw new IllegalArgumentException("Timeout arguument must be NO_TIMEOUT(-1) or non-negative."); _timeout = timeout; _correlationId = 0; _consumer = setupConsumer(); } /** * Construct a new RpcClient that will communicate on the given channel, sending * requests to the given exchange with the given routing key. * * Causes the creation of a temporary private autodelete queue. * The name of the queue can be provided (only relevant for RabbitMQ servers * that do not support Direct Reply-to. * * Waits forever for responses (that is, no timeout). * @param channel the channel to use for communication * @param exchange the exchange to connect to * @param routingKey the routing key * @param replyTo the queue where the server should put the reply * @throws IOException if an error is encountered */ public RpcClient(Channel channel, String exchange, String routingKey, String replyTo) throws IOException { this(channel, exchange, routingKey, replyTo, NO_TIMEOUT); } /** * Construct a new RpcClient that will communicate on the given channel, sending * requests to the given exchange with the given routing key. * * Direct Reply-to will be used * for response propagation. * * Waits forever for responses (that is, no timeout). * @param channel the channel to use for communication * @param exchange the exchange to connect to * @param routingKey the routing key * @throws IOException if an error is encountered */ public RpcClient(Channel channel, String exchange, String routingKey) throws IOException { this(channel, exchange, routingKey, "amq.rabbitmq.reply-to", NO_TIMEOUT); } /** *

* Construct a new RpcClient that will communicate on the given channel, sending * requests to the given exchange with the given routing key. *

* * Causes the creation of a temporary private autodelete queue. The name of this queue will be * "amq.rabbitmq.reply-to". * @param channel the channel to use for communication * @param exchange the exchange to connect to * @param routingKey the routing key * @param timeout milliseconds before timing out on wait for response * @throws IOException if an error is encountered */ public RpcClient(Channel channel, String exchange, String routingKey, int timeout) throws IOException { this(channel, exchange, routingKey, "amq.rabbitmq.reply-to", timeout); } /** * Private API - ensures the RpcClient is correctly open. * @throws IOException if an error is encountered */ public void checkConsumer() throws IOException { if (_consumer == null) { throw new EOFException("RpcClient is closed"); } } /** * Public API - cancels the consumer, thus deleting the temporary queue, and marks the RpcClient as closed. * @throws IOException if an error is encountered */ public void close() throws IOException { if (_consumer != null) { _channel.basicCancel(_consumer.getConsumerTag()); _consumer = null; } } /** * Registers a consumer on the reply queue. * @throws IOException if an error is encountered * @return the newly created and registered consumer */ protected DefaultConsumer setupConsumer() throws IOException { DefaultConsumer consumer = new DefaultConsumer(_channel) { @Override public void handleShutdownSignal(String consumerTag, ShutdownSignalException signal) { synchronized (_continuationMap) { for (Entry> entry : _continuationMap.entrySet()) { entry.getValue().set(signal); } _consumer = null; } } @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { synchronized (_continuationMap) { String replyId = properties.getCorrelationId(); BlockingCell blocker =_continuationMap.remove(replyId); if (blocker == null) { throw new IllegalStateException("No outstanding request for correlation ID " + replyId); } blocker.set(new Response(consumerTag, envelope, properties, body)); } } }; _channel.basicConsume(_replyTo, true, consumer); return consumer; } public void publish(AMQP.BasicProperties props, byte[] message) throws IOException { _channel.basicPublish(_exchange, _routingKey, props, message); } public Response doCall(AMQP.BasicProperties props, byte[] message) throws IOException, ShutdownSignalException, TimeoutException { checkConsumer(); BlockingCell k = new BlockingCell(); synchronized (_continuationMap) { _correlationId++; String replyId = "" + _correlationId; props = ((props==null) ? new AMQP.BasicProperties.Builder() : props.builder()) .correlationId(replyId).replyTo(_replyTo).build(); _continuationMap.put(replyId, k); } publish(props, message); Object reply = k.uninterruptibleGet(_timeout); if (reply instanceof ShutdownSignalException) { ShutdownSignalException sig = (ShutdownSignalException) reply; ShutdownSignalException wrapper = new ShutdownSignalException(sig.isHardError(), sig.isInitiatedByApplication(), sig.getReason(), sig.getReference()); wrapper.initCause(sig); throw wrapper; } else { return (Response) reply; } } public byte[] primitiveCall(AMQP.BasicProperties props, byte[] message) throws IOException, ShutdownSignalException, TimeoutException { return doCall(props, message).getBody(); } /** * Perform a simple byte-array-based RPC roundtrip. * @param message the byte array request message to send * @return the byte array response received * @throws ShutdownSignalException if the connection dies during our wait * @throws IOException if an error is encountered * @throws TimeoutException if a response is not received within the configured timeout */ public byte[] primitiveCall(byte[] message) throws IOException, ShutdownSignalException, TimeoutException { return primitiveCall(null, message); } /** * Perform a simple byte-array-based RPC roundtrip * * Useful if you need to get at more than just the body of the message * * @param message the byte array request message to send * @return The response object is an envelope that contains all of the data provided to the `handleDelivery` consumer * @throws ShutdownSignalException if the connection dies during our wait * @throws IOException if an error is encountered * @throws TimeoutException if a response is not received within the configured timeout */ public Response responseCall(byte[] message) throws IOException, ShutdownSignalException, TimeoutException { return doCall(null, message); } /** * Perform a simple string-based RPC roundtrip. * @param message the string request message to send * @return the string response received * @throws ShutdownSignalException if the connection dies during our wait * @throws IOException if an error is encountered * @throws TimeoutException if a timeout occurs before the response is received */ @SuppressWarnings("unused") public String stringCall(String message) throws IOException, ShutdownSignalException, TimeoutException { byte[] request; try { request = message.getBytes(StringRpcServer.STRING_ENCODING); } catch (IOException _e) { request = message.getBytes(); } byte[] reply = primitiveCall(request); try { return new String(reply, StringRpcServer.STRING_ENCODING); } catch (IOException _e) { return new String(reply); } } /** * Perform an AMQP wire-protocol-table based RPC roundtrip

* * There are some restrictions on the values appearing in the table:
* they must be of type {@link String}, {@link LongString}, {@link Integer}, {@link java.math.BigDecimal}, {@link Date}, * or (recursively) a {@link Map} of the enclosing type. * * @param message the table to send * @return the table received * @throws ShutdownSignalException if the connection dies during our wait * @throws IOException if an error is encountered * @throws TimeoutException if a timeout occurs before a response is received */ public Map mapCall(Map message) throws IOException, ShutdownSignalException, TimeoutException { ByteArrayOutputStream buffer = new ByteArrayOutputStream(); MethodArgumentWriter writer = new MethodArgumentWriter(new ValueWriter(new DataOutputStream(buffer))); writer.writeTable(message); writer.flush(); byte[] reply = primitiveCall(buffer.toByteArray()); MethodArgumentReader reader = new MethodArgumentReader(new ValueReader(new DataInputStream(new ByteArrayInputStream(reply)))); return reader.readTable(); } /** * Perform an AMQP wire-protocol-table based RPC roundtrip, first * constructing the table from an array of alternating keys (in * even-numbered elements, starting at zero) and values (in * odd-numbered elements, starting at one)
* Restrictions on value arguments apply as in {@link RpcClient#mapCall(Map)}. * * @param keyValuePairs alternating {key, value, key, value, ...} data to send * @return the table received * @throws ShutdownSignalException if the connection dies during our wait * @throws IOException if an error is encountered * @throws TimeoutException if a timeout occurs before a response is received */ public Map mapCall(Object[] keyValuePairs) throws IOException, ShutdownSignalException, TimeoutException { Map message = new HashMap(); for (int i = 0; i < keyValuePairs.length; i += 2) { message.put((String) keyValuePairs[i], keyValuePairs[i + 1]); } return mapCall(message); } /** * Retrieve the channel. * @return the channel to which this client is connected */ public Channel getChannel() { return _channel; } /** * Retrieve the exchange. * @return the exchange to which this client is connected */ public String getExchange() { return _exchange; } /** * Retrieve the routing key. * @return the routing key for messages to this client */ public String getRoutingKey() { return _routingKey; } /** * Retrieve the continuation map. * @return the map of objects to blocking cells for this client */ public Map> getContinuationMap() { return _continuationMap; } /** * Retrieve the correlation id. * @return the most recently used correlation id */ public int getCorrelationId() { return _correlationId; } /** * Retrieve the consumer. * @return an interface to the client's consumer object */ public Consumer getConsumer() { return _consumer; } /** * The response object is an envelope that contains all of the data provided to the `handleDelivery` consumer */ public static class Response { protected String consumerTag; protected Envelope envelope; protected AMQP.BasicProperties properties; protected byte[] body; public Response() { } public Response( final String consumerTag, final Envelope envelope, final AMQP.BasicProperties properties, final byte[] body) { this.consumerTag = consumerTag; this.envelope = envelope; this.properties = properties; this.body = body; } public String getConsumerTag() { return consumerTag; } public Envelope getEnvelope() { return envelope; } public AMQP.BasicProperties getProperties() { return properties; } public byte[] getBody() { return body; } } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/RpcServer.java000066400000000000000000000277461316117667700266160ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; import com.rabbitmq.utility.Utility; import java.io.IOException; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; /** * Class which manages a request queue for a simple RPC-style service. * The class is agnostic about the format of RPC arguments / return values. */ public class RpcServer { /** Channel we are communicating on */ private final Channel _channel; /** Queue to receive requests from */ private final String _queueName; /** Boolean controlling the exit from the mainloop. */ private volatile boolean _mainloopRunning = true; /** Consumer attached to our request queue */ private RpcConsumer _consumer; /** * Creates an RpcServer listening on a temporary exclusive * autodelete queue. */ public RpcServer(Channel channel) throws IOException { this(channel, null); } /** * If the passed-in queue name is null, creates a server-named * temporary exclusive autodelete queue to use; otherwise expects * the queue to have already been declared. */ public RpcServer(Channel channel, String queueName) throws IOException { _channel = channel; if (queueName == null || queueName.equals("")) { _queueName = _channel.queueDeclare().getQueue(); } else { _queueName = queueName; } _consumer = setupConsumer(); } /** * Public API - cancels the consumer, thus deleting the queue, if * it was a temporary queue, and marks the RpcServer as closed. * @throws IOException if an error is encountered */ public void close() throws IOException { if (_consumer != null) { _channel.basicCancel(_consumer.getConsumerTag()); _consumer = null; } terminateMainloop(); } /** * Registers a consumer on the reply queue. * @throws IOException if an error is encountered * @return the newly created and registered consumer */ protected RpcConsumer setupConsumer() throws IOException { RpcConsumer consumer = new DefaultRpcConsumer(_channel); _channel.basicConsume(_queueName, consumer); return consumer; } /** * Public API - main server loop. Call this to begin processing * requests. Request processing will continue until the Channel * (or its underlying Connection) is shut down, or until * terminateMainloop() is called. * * Note that if the mainloop is blocked waiting for a request, the * termination flag is not checked until a request is received, so * a good time to call terminateMainloop() is during a request * handler. * * @return the exception that signalled the Channel shutdown, or null for orderly shutdown */ public ShutdownSignalException mainloop() throws IOException { try { while (_mainloopRunning) { Delivery request; try { request = _consumer.nextDelivery(); } catch (InterruptedException ie) { continue; } processRequest(request); _channel.basicAck(request.getEnvelope().getDeliveryTag(), false); } return null; } catch (ShutdownSignalException sse) { return sse; } } /** * Call this method to terminate the mainloop. * * Note that if the mainloop is blocked waiting for a request, the * termination flag is not checked until a request is received, so * a good time to call terminateMainloop() is during a request * handler. */ public void terminateMainloop() { _mainloopRunning = false; } /** * Private API - Process a single request. Called from mainloop(). */ public void processRequest(Delivery request) throws IOException { AMQP.BasicProperties requestProperties = request.getProperties(); String correlationId = requestProperties.getCorrelationId(); String replyTo = requestProperties.getReplyTo(); if (correlationId != null && replyTo != null) { AMQP.BasicProperties.Builder replyPropertiesBuilder = new AMQP.BasicProperties.Builder().correlationId(correlationId); AMQP.BasicProperties replyProperties = preprocessReplyProperties(request, replyPropertiesBuilder); byte[] replyBody = handleCall(request, replyProperties); replyProperties = postprocessReplyProperties(request, replyProperties.builder()); _channel.basicPublish("", replyTo, replyProperties, replyBody); } else { handleCast(request); } } /** * Lowest-level response method. Calls * handleCall(AMQP.BasicProperties,byte[],AMQP.BasicProperties). */ public byte[] handleCall(Delivery request, AMQP.BasicProperties replyProperties) { return handleCall(request.getProperties(), request.getBody(), replyProperties); } /** * Mid-level response method. Calls * handleCall(byte[],AMQP.BasicProperties). */ public byte[] handleCall(AMQP.BasicProperties requestProperties, byte[] requestBody, AMQP.BasicProperties replyProperties) { return handleCall(requestBody, replyProperties); } /** * High-level response method. Returns an empty response by * default - override this (or other handleCall and handleCast * methods) in subclasses. */ public byte[] handleCall(byte[] requestBody, AMQP.BasicProperties replyProperties) { return new byte[0]; } /** * Gives a chance to set/modify reply properties before handling call. * Note the correlationId property is already set. * @param request the inbound message * @param builder the reply properties builder * @return the properties to pass in to the handling call */ protected AMQP.BasicProperties preprocessReplyProperties(Delivery request, AMQP.BasicProperties.Builder builder) { return builder.build(); } /** * Gives a chance to set/modify reply properties after the handling call * @param request the inbound message * @param builder the reply properties builder * @return the properties to pass in to the response message */ protected AMQP.BasicProperties postprocessReplyProperties(Delivery request, AMQP.BasicProperties.Builder builder) { return builder.build(); } /** * Lowest-level handler method. Calls * handleCast(AMQP.BasicProperties,byte[]). */ public void handleCast(Delivery request) { handleCast(request.getProperties(), request.getBody()); } /** * Mid-level handler method. Calls * handleCast(byte[]). */ public void handleCast(AMQP.BasicProperties requestProperties, byte[] requestBody) { handleCast(requestBody); } /** * High-level handler method. Does nothing by default - override * this (or other handleCast and handleCast methods) in * subclasses. */ public void handleCast(byte[] requestBody) { // Does nothing. } /** * Retrieve the channel. * @return the channel to which this server is connected */ public Channel getChannel() { return _channel; } /** * Retrieve the queue name. * @return the queue which this server is consuming from */ public String getQueueName() { return _queueName; } public interface RpcConsumer extends Consumer { Delivery nextDelivery() throws InterruptedException, ShutdownSignalException, ConsumerCancelledException; String getConsumerTag(); } private static class DefaultRpcConsumer extends DefaultConsumer implements RpcConsumer { // Marker object used to signal the queue is in shutdown mode. // It is only there to wake up consumers. The canonical representation // of shutting down is the presence of _shutdown. // Invariant: This is never on _queue unless _shutdown != null. private static final Delivery POISON = new Delivery(null, null, null); private final BlockingQueue _queue; // When this is non-null the queue is in shutdown mode and nextDelivery should // throw a shutdown signal exception. private volatile ShutdownSignalException _shutdown; private volatile ConsumerCancelledException _cancelled; public DefaultRpcConsumer(Channel ch) { this(ch, new LinkedBlockingQueue<>()); } public DefaultRpcConsumer(Channel ch, BlockingQueue q) { super(ch); this._queue = q; } @Override public Delivery nextDelivery() throws InterruptedException, ShutdownSignalException, ConsumerCancelledException { return handle(_queue.take()); } @Override public void handleShutdownSignal(String consumerTag, ShutdownSignalException sig) { _shutdown = sig; _queue.add(POISON); } @Override public void handleCancel(String consumerTag) throws IOException { _cancelled = new ConsumerCancelledException(); _queue.add(POISON); } @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { checkShutdown(); this._queue.add(new Delivery(envelope, properties, body)); } /** * Check if we are in shutdown mode and if so throw an exception. */ private void checkShutdown() { if (_shutdown != null) throw Utility.fixStackTrace(_shutdown); } /** * If delivery is not POISON nor null, return it. *

* If delivery, _shutdown and _cancelled are all null, return null. *

* If delivery is POISON re-insert POISON into the queue and * throw an exception if POISONed for no reason. *

* Otherwise, if we are in shutdown mode or cancelled, * throw a corresponding exception. */ private Delivery handle(Delivery delivery) { if (delivery == POISON || delivery == null && (_shutdown != null || _cancelled != null)) { if (delivery == POISON) { _queue.add(POISON); if (_shutdown == null && _cancelled == null) { throw new IllegalStateException( "POISON in queue, but null _shutdown and null _cancelled. " + "This should never happen, please report as a BUG"); } } if (null != _shutdown) throw Utility.fixStackTrace(_shutdown); if (null != _cancelled) throw Utility.fixStackTrace(_cancelled); } return delivery; } } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/SaslConfig.java000066400000000000000000000020071316117667700267120ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; /** * This interface represents a hook to allow you to control how exactly * a sasl client is selected during authentication. * @see com.rabbitmq.client.ConnectionFactory */ public interface SaslConfig { SaslMechanism getSaslMechanism(String[] mechanisms); } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/SaslMechanism.java000066400000000000000000000025061316117667700274150ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; /** * Our own view of a SASL authentication mechanism, introduced to remove a * dependency on javax.security.sasl. */ public interface SaslMechanism { /** * The name of this mechanism (e.g. PLAIN) * @return the name */ String getName(); /** * Handle one round of challenge-response * @param challenge the challenge this round, or null on first round. * @param username name of user * @param password for username * @return response */ LongString handleChallenge(LongString challenge, String username, String password); } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/ShutdownListener.java000066400000000000000000000026721316117667700302130ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; import java.util.EventListener; /** * A ShutdownListener receives information about the shutdown of connections and * channels. Note that when a connection is shut down, its associated channels are also * considered shut down and their ShutdownListeners will be notified (with the same cause). * Because of this, and the fact that channel ShutdownListeners execute in the connection's * thread, attempting to make blocking calls on a connection inside the listener will * lead to deadlock. * * @see ShutdownNotifier * @see ShutdownSignalException */ @FunctionalInterface public interface ShutdownListener extends EventListener { void shutdownCompleted(ShutdownSignalException cause); } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/ShutdownNotifier.java000066400000000000000000000042501316117667700301770ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; /** * Interface for components that are shutdown capable and * that allow listeners to be added for shutdown signals * * @see ShutdownListener * @see ShutdownSignalException */ public interface ShutdownNotifier { /** * Add shutdown listener. * If the component is already closed, handler is fired immediately * * @param listener {@link ShutdownListener} to the component */ void addShutdownListener(ShutdownListener listener); /** * Remove shutdown listener for the component. * * @param listener {@link ShutdownListener} to be removed */ void removeShutdownListener(ShutdownListener listener); /** * Get the shutdown reason object * @return ShutdownSignalException if component is closed, null otherwise */ ShutdownSignalException getCloseReason(); /** * Protected API - notify the listeners attached to the component * @see com.rabbitmq.client.ShutdownListener */ void notifyListeners(); /** * Determine whether the component is currently open. * Will return false if we are currently closing. * Checking this method should be only for information, * because of the race conditions - state can change after the call. * Instead just execute and try to catch ShutdownSignalException * and IOException * * @return true when component is open, false otherwise */ boolean isOpen(); } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/ShutdownSignalException.java000066400000000000000000000123741316117667700315220ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; import com.rabbitmq.utility.SensibleClone; /** * Encapsulates a shutdown condition for a connection to an AMQP broker. * Depending on HardError when calling * {@link com.rabbitmq.client.ShutdownSignalException#getReference()} we will * either get a reference to the Connection or Channel instance that fired * this exception. */ public class ShutdownSignalException extends RuntimeException implements SensibleClone { /** Default for non-checking. */ private static final long serialVersionUID = 1L; /** True if the connection is shut down, or false if this signal refers to a channel */ private final boolean _hardError; /** * True if this exception is caused by explicit application * action; false if it originated with the broker or as a result * of detectable non-deliberate application failure */ private final boolean _initiatedByApplication; /** Possible explanation */ private final Method _reason; /** Either Channel or Connection instance, depending on _hardError */ private final Object _ref; /** * Construct a ShutdownSignalException from the arguments. * @param hardError the relevant hard error * @param initiatedByApplication if the shutdown was client-initiated * @param reason AMQP method describing the exception reason * @param ref Reference to Connection or Channel that fired the signal */ public ShutdownSignalException(boolean hardError, boolean initiatedByApplication, Method reason, Object ref) { this(hardError, initiatedByApplication, reason, ref, "", null); } /** * Construct a ShutdownSignalException from the arguments. * @param hardError the relevant hard error * @param initiatedByApplication if the shutdown was client-initiated * @param reason AMQP method describing the exception reason * @param ref Reference to Connection or Channel that fired the signal * @param messagePrefix prefix to add to exception message */ public ShutdownSignalException(boolean hardError, boolean initiatedByApplication, Method reason, Object ref, String messagePrefix, Throwable cause) { super(composeMessage(hardError, initiatedByApplication, reason, messagePrefix, cause)); this._hardError = hardError; this._initiatedByApplication = initiatedByApplication; this._reason = reason; // Depending on hardError what we got is either Connection or Channel reference this._ref = ref; } private static String composeMessage(boolean hardError, boolean initiatedByApplication, Method reason, String messagePrefix, Throwable cause) { final String connectionOrChannel = hardError ? "connection" : "channel"; final String appInitiated = "clean " + connectionOrChannel + " shutdown"; final String nonAppInitiated = connectionOrChannel + " error"; final String explanation = initiatedByApplication ? appInitiated : nonAppInitiated; StringBuilder result = new StringBuilder(messagePrefix).append(explanation); if(reason != null) { result.append("; protocol method: ").append(reason); } if(cause != null) { result.append("; cause: ").append(cause); } return result.toString(); } /** @return true if this signals a connection error, or false if a channel error */ public boolean isHardError() { return _hardError; } /** @return true if this exception was caused by explicit application * action; false if it originated with the broker or as a result * of detectable non-deliberate application failure */ public boolean isInitiatedByApplication() { return _initiatedByApplication; } /** @return the reason, if any */ public Method getReason() { return _reason; } /** @return Reference to Connection or Channel object that fired the signal **/ public Object getReference() { return _ref; } @Override public ShutdownSignalException sensibleClone() { try { return (ShutdownSignalException)super.clone(); } catch (CloneNotSupportedException e) { // You've got to be kidding me throw new RuntimeException(e); } } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/SocketChannelConfigurator.java000066400000000000000000000021301316117667700317630ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; import java.io.IOException; import java.nio.channels.SocketChannel; public interface SocketChannelConfigurator { /** * Provides a hook to insert custom configuration of the {@link SocketChannel}s * used to connect to an AMQP server before they connect. */ void configure(SocketChannel socketChannel) throws IOException; } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/SocketConfigurator.java000066400000000000000000000020421316117667700304740ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; import java.io.IOException; import java.net.Socket; public interface SocketConfigurator { /** * Provides a hook to insert custom configuration of the sockets * used to connect to an AMQP server before they connect. */ void configure(Socket socket) throws IOException; } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/SslContextFactory.java000066400000000000000000000024271316117667700303260ustar00rootroot00000000000000// Copyright (c) 2017-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; import javax.net.ssl.SSLContext; /** * A factory to create {@link SSLContext}s. * * @see ConnectionFactory#setSslContextFactory(SslContextFactory) * @since 5.0.0 */ public interface SslContextFactory { /** * Create a {@link SSLContext} for a given name. * The name is typically the name of the connection. * @param name name of the connection the SSLContext is used for * @return the SSLContext for this name * @see ConnectionFactory#newConnection(String) */ SSLContext create(String name); } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/SslEngineConfigurator.java000066400000000000000000000021631316117667700311370ustar00rootroot00000000000000// Copyright (c) 2017-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; import javax.net.ssl.SSLEngine; import java.io.IOException; public interface SslEngineConfigurator { /** * Provides a hook to insert custom configuration of the {@link SSLEngine}s * used to connect to an AMQP server before they connect. * Note this is used only when NIO are in use. */ void configure(SSLEngine sslEngine) throws IOException; } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/StringRpcServer.java000066400000000000000000000055411316117667700277720ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; import java.io.IOException; /** * Subclass of RpcServer which accepts UTF-8 string requests. */ public class StringRpcServer extends RpcServer { public StringRpcServer(Channel channel) throws IOException { super(channel); } public StringRpcServer(Channel channel, String queueName) throws IOException { super(channel, queueName); } public static final String STRING_ENCODING = "UTF-8"; /** * Overridden to do UTF-8 processing, and delegate to * handleStringCall. If UTF-8 is not understood by this JVM, falls * back to the platform default. */ @Override @SuppressWarnings("unused") public byte[] handleCall(byte[] requestBody, AMQP.BasicProperties replyProperties) { String request; try { request = new String(requestBody, STRING_ENCODING); } catch (IOException _e) { request = new String(requestBody); } String reply = handleStringCall(request, replyProperties); try { return reply.getBytes(STRING_ENCODING); } catch (IOException _e) { return reply.getBytes(); } } /** * Delegates to handleStringCall(String). */ public String handleStringCall(String request, AMQP.BasicProperties replyProperties) { return handleStringCall(request); } /** * Default implementation - override in subclasses. Returns the empty string. */ public String handleStringCall(String request) { return ""; } /** * Overridden to do UTF-8 processing, and delegate to * handleStringCast. If requestBody cannot be interpreted as UTF-8 * tries the platform default. */ @Override public void handleCast(byte[] requestBody) { try { handleStringCast(new String(requestBody, STRING_ENCODING)); } catch (IOException _e) { handleStringCast(new String(requestBody)); } } /** * Default implementation - override in subclasses. Does nothing. */ public void handleStringCast(String requestBody) { // Do nothing. } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/TopologyRecoveryException.java000066400000000000000000000021161316117667700320750ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; /** * Indicates an exception thrown during topology recovery. * * @see com.rabbitmq.client.ConnectionFactory#setTopologyRecoveryEnabled(boolean) * @since 3.3.0 */ public class TopologyRecoveryException extends Exception { public TopologyRecoveryException(String message, Throwable cause) { super(message, cause); } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/TrustEverythingTrustManager.java000066400000000000000000000043071316117667700324120ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; import org.slf4j.LoggerFactory; import javax.net.ssl.X509TrustManager; import java.security.cert.X509Certificate; /** * Convenience class providing a default implementation of javax.net.ssl.X509TrustManager. * Trusts every single certificate presented to it. */ public class TrustEverythingTrustManager implements X509TrustManager { public TrustEverythingTrustManager() { LoggerFactory.getLogger(TrustEverythingTrustManager.class).warn( "This trust manager trusts every certificate, effectively disabling peer verification. " + "This is convenient for local development but prone to man-in-the-middle attacks. " + "Please see http://www.rabbitmq.com/ssl.html#validating-cerficates to learn more about peer certificate validation." ); } /** * Doesn't even bother looking at its arguments, simply returns, * which makes the check succeed. */ @Override public void checkClientTrusted(X509Certificate[] chain, String authType) { // Do nothing. } /** * Doesn't even bother looking at its arguments, simply returns, * which makes the check succeed. */ @Override public void checkServerTrusted(X509Certificate[] chain, String authType) { // Do nothing. } /** * Always returns an empty array of X509Certificates. */ @Override public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/UnblockedCallback.java000066400000000000000000000021071316117667700302060ustar00rootroot00000000000000// Copyright (c) 2017 Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; import java.io.IOException; /** * Implement this interface in order to be notified of connection unblock events. * Prefer it over {@link BlockedListener} for a lambda-oriented syntax. * @see BlockedListener * @see BlockedCallback */ @FunctionalInterface public interface UnblockedCallback { void handle() throws IOException; } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/UnexpectedFrameError.java000066400000000000000000000030601316117667700307530ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; import com.rabbitmq.client.impl.Frame; /** * Thrown when the command parser hits an unexpected frame type. */ public class UnexpectedFrameError extends RuntimeException { private static final long serialVersionUID = 1L; private final Frame _frame; private final int _expectedFrameType; public UnexpectedFrameError(Frame frame, int expectedFrameType) { super("Received frame: " + frame + ", expected type " + expectedFrameType); _frame = frame; _expectedFrameType = expectedFrameType; } public static long getSerialVersionUID() { return serialVersionUID; } public Frame getReceivedFrame() { return _frame; } public int getExpectedFrameType() { return _expectedFrameType; } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/UnexpectedMethodError.java000066400000000000000000000037031316117667700311450ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; /** * Indicates that a {@link Method} object was supplied that was not * expected. For instance, {@link Channel#basicGet} throws this if it * receives anything other than {@link AMQP.Basic.GetOk} or * {@link AMQP.Basic.GetEmpty}, and the * {@link com.rabbitmq.client.impl.AMQImpl.DefaultMethodVisitor DefaultMethodVisitor} * throws this as the action within each visitor case. */ public class UnexpectedMethodError extends RuntimeException { private static final long serialVersionUID = 1L; private final Method _method; /** * Construct an UnexpectedMethodError with the given method parameter * @param method the unexpected method */ public UnexpectedMethodError(Method method) { _method = method; } /** * Return a string representation of this error. * @return a string describing the error */ @Override public String toString() { return super.toString() + ": " + _method; } /** * Return the wrapped method. * @return the method whose appearance was "unexpected" and was deemed an error */ public Method getMethod() { return _method; } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/UnknownClassOrMethodId.java000066400000000000000000000030761316117667700312350ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; import java.io.IOException; /** * Thrown when the protocol handlers detect an unknown class number or * method number. */ public class UnknownClassOrMethodId extends IOException { private static final long serialVersionUID = 1L; private static final int NO_METHOD_ID = -1; public final int classId; public final int methodId; public UnknownClassOrMethodId(int classId) { this(classId, NO_METHOD_ID); } public UnknownClassOrMethodId(int classId, int methodId) { this.classId = classId; this.methodId = methodId; } @Override public String toString() { if (this.methodId == NO_METHOD_ID) { return super.toString() + "<" + classId + ">"; } else { return super.toString() + "<" + classId + "." + methodId + ">"; } } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/000077500000000000000000000000001316117667700247615ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/AMQBasicProperties.java000066400000000000000000000023421316117667700312620ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl; import java.io.DataInputStream; import java.io.IOException; import com.rabbitmq.client.BasicProperties; public abstract class AMQBasicProperties extends AMQContentHeader implements BasicProperties { protected AMQBasicProperties() { } protected AMQBasicProperties(DataInputStream in) throws IOException { super(in); } @Override public Object clone() throws CloneNotSupportedException { return super.clone(); } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/AMQChannel.java000066400000000000000000000524351316117667700275440ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl; import com.rabbitmq.client.*; import com.rabbitmq.client.AMQP.Basic; import com.rabbitmq.client.AMQP.Confirm; import com.rabbitmq.client.AMQP.Exchange; import com.rabbitmq.client.AMQP.Queue; import com.rabbitmq.client.AMQP.Tx; import com.rabbitmq.client.Method; import com.rabbitmq.utility.BlockingValueOrException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeoutException; import java.util.function.Supplier; /** * Base class modelling an AMQ channel. Subclasses implement * {@link com.rabbitmq.client.Channel#close} and * {@link #processAsync processAsync()}, and may choose to override * {@link #processShutdownSignal processShutdownSignal()} and * {@link #rpc rpc()}. * * @see ChannelN * @see Connection */ public abstract class AMQChannel extends ShutdownNotifierComponent { private static final Logger LOGGER = LoggerFactory.getLogger(AMQChannel.class); protected static final int NO_RPC_TIMEOUT = 0; /** * Protected; used instead of synchronizing on the channel itself, * so that clients can themselves use the channel to synchronize * on. */ protected final Object _channelMutex = new Object(); /** The connection this channel is associated with. */ private final AMQConnection _connection; /** This channel's channel number. */ private final int _channelNumber; /** Command being assembled */ private AMQCommand _command = new AMQCommand(); /** The current outstanding RPC request, if any. (Could become a queue in future.) */ private RpcWrapper _activeRpc = null; /** Whether transmission of content-bearing methods should be blocked */ public volatile boolean _blockContent = false; /** Timeout for RPC calls */ protected final int _rpcTimeout; private final boolean _checkRpcResponseType; /** * Construct a channel on the given connection, with the given channel number. * @param connection the underlying connection for this channel * @param channelNumber the allocated reference number for this channel */ public AMQChannel(AMQConnection connection, int channelNumber) { this._connection = connection; this._channelNumber = channelNumber; if(connection.getChannelRpcTimeout() < 0) { throw new IllegalArgumentException("Continuation timeout on RPC calls cannot be less than 0"); } this._rpcTimeout = connection.getChannelRpcTimeout(); this._checkRpcResponseType = connection.willCheckRpcResponseType(); } /** * Public API - Retrieves this channel's channel number. * @return the channel number */ public int getChannelNumber() { return _channelNumber; } /** * Private API - When the Connection receives a Frame for this * channel, it passes it to this method. * @param frame the incoming frame * @throws IOException if an error is encountered */ public void handleFrame(Frame frame) throws IOException { AMQCommand command = _command; if (command.handleFrame(frame)) { // a complete command has rolled off the assembly line _command = new AMQCommand(); // prepare for the next one handleCompleteInboundCommand(command); } } /** * Placeholder until we address bug 15786 (implementing a proper exception hierarchy). * In the meantime, this at least won't throw away any information from the wrapped exception. * @param ex the exception to wrap * @return the wrapped exception */ public static IOException wrap(ShutdownSignalException ex) { return wrap(ex, null); } public static IOException wrap(ShutdownSignalException ex, String message) { IOException ioe = new IOException(message); ioe.initCause(ex); return ioe; } /** * Placeholder until we address bug 15786 (implementing a proper exception hierarchy). */ public AMQCommand exnWrappingRpc(Method m) throws IOException { try { return privateRpc(m); } catch (AlreadyClosedException ace) { // Do not wrap it since it means that connection/channel // was closed in some action in the past throw ace; } catch (ShutdownSignalException ex) { throw wrap(ex); } } public CompletableFuture exnWrappingAsyncRpc(Method m) throws IOException { try { return privateAsyncRpc(m); } catch (AlreadyClosedException ace) { // Do not wrap it since it means that connection/channel // was closed in some action in the past throw ace; } catch (ShutdownSignalException ex) { throw wrap(ex); } } /** * Private API - handle a command which has been assembled * @throws IOException if there's any problem * * @param command the incoming command * @throws IOException */ public void handleCompleteInboundCommand(AMQCommand command) throws IOException { // First, offer the command to the asynchronous-command // handling mechanism, which gets to act as a filter on the // incoming command stream. If processAsync() returns true, // the command has been dealt with by the filter and so should // not be processed further. It will return true for // asynchronous commands (deliveries/returns/other events), // and false for commands that should be passed on to some // waiting RPC continuation. if (!processAsync(command)) { // The filter decided not to handle/consume the command, // so it must be a response to an earlier RPC. if (_checkRpcResponseType) { synchronized (_channelMutex) { // check if this reply command is intended for the current waiting request before calling nextOutstandingRpc() if (!_activeRpc.canHandleReply(command)) { // this reply command is not intended for the current waiting request // most likely a previous request timed out and this command is the reply for that. // Throw this reply command away so we don't stop the current request from waiting for its reply return; } } } final RpcWrapper nextOutstandingRpc = nextOutstandingRpc(); // the outstanding RPC can be null when calling Channel#asyncRpc if(nextOutstandingRpc != null) { nextOutstandingRpc.complete(command); markRpcFinished(); } } } public void enqueueRpc(RpcContinuation k) { doEnqueueRpc(() -> new RpcContinuationRpcWrapper(k)); } public void enqueueAsyncRpc(Method method, CompletableFuture future) { doEnqueueRpc(() -> new CompletableFutureRpcWrapper(method, future)); } private void doEnqueueRpc(Supplier rpcWrapperSupplier) { synchronized (_channelMutex) { boolean waitClearedInterruptStatus = false; while (_activeRpc != null) { try { _channelMutex.wait(); } catch (InterruptedException e) { waitClearedInterruptStatus = true; } } if (waitClearedInterruptStatus) { Thread.currentThread().interrupt(); } _activeRpc = rpcWrapperSupplier.get(); } } public boolean isOutstandingRpc() { synchronized (_channelMutex) { return (_activeRpc != null); } } public RpcWrapper nextOutstandingRpc() { synchronized (_channelMutex) { RpcWrapper result = _activeRpc; _activeRpc = null; _channelMutex.notifyAll(); return result; } } protected void markRpcFinished() { // no-op } public void ensureIsOpen() throws AlreadyClosedException { if (!isOpen()) { throw new AlreadyClosedException(getCloseReason()); } } /** * Protected API - sends a {@link Method} to the broker and waits for the * next in-bound Command from the broker: only for use from * non-connection-MainLoop threads! */ public AMQCommand rpc(Method m) throws IOException, ShutdownSignalException { return privateRpc(m); } public AMQCommand rpc(Method m, int timeout) throws IOException, ShutdownSignalException, TimeoutException { return privateRpc(m, timeout); } private AMQCommand privateRpc(Method m) throws IOException, ShutdownSignalException { SimpleBlockingRpcContinuation k = new SimpleBlockingRpcContinuation(m); rpc(m, k); // At this point, the request method has been sent, and we // should wait for the reply to arrive. // // Calling getReply() on the continuation puts us to sleep // until the connection's reader-thread throws the reply over // the fence or the RPC times out (if enabled) if(_rpcTimeout == NO_RPC_TIMEOUT) { return k.getReply(); } else { try { return k.getReply(_rpcTimeout); } catch (TimeoutException e) { throw wrapTimeoutException(m, e); } } } private void cleanRpcChannelState() { try { // clean RPC channel state nextOutstandingRpc(); markRpcFinished(); } catch (Exception ex) { LOGGER.warn("Error while cleaning timed out channel RPC: {}", ex.getMessage()); } } /** Cleans RPC channel state after a timeout and wraps the TimeoutException in a ChannelContinuationTimeoutException */ protected ChannelContinuationTimeoutException wrapTimeoutException(final Method m, final TimeoutException e) { cleanRpcChannelState(); return new ChannelContinuationTimeoutException(e, this, this._channelNumber, m); } private CompletableFuture privateAsyncRpc(Method m) throws IOException, ShutdownSignalException { CompletableFuture future = new CompletableFuture<>(); asyncRpc(m, future); return future; } private AMQCommand privateRpc(Method m, int timeout) throws IOException, ShutdownSignalException, TimeoutException { SimpleBlockingRpcContinuation k = new SimpleBlockingRpcContinuation(m); rpc(m, k); try { return k.getReply(timeout); } catch (TimeoutException e) { cleanRpcChannelState(); throw e; } } public void rpc(Method m, RpcContinuation k) throws IOException { synchronized (_channelMutex) { ensureIsOpen(); quiescingRpc(m, k); } } public void quiescingRpc(Method m, RpcContinuation k) throws IOException { synchronized (_channelMutex) { enqueueRpc(k); quiescingTransmit(m); } } public void asyncRpc(Method m, CompletableFuture future) throws IOException { synchronized (_channelMutex) { ensureIsOpen(); quiescingAsyncRpc(m, future); } } public void quiescingAsyncRpc(Method m, CompletableFuture future) throws IOException { synchronized (_channelMutex) { enqueueAsyncRpc(m, future); quiescingTransmit(m); } } /** * Protected API - called by nextCommand to check possibly handle an incoming Command before it is returned to the caller of nextCommand. If this method * returns true, the command is considered handled and is not passed back to nextCommand's caller; if it returns false, nextCommand returns the command as * usual. This is used in subclasses to implement handling of Basic.Return and Basic.Deliver messages, as well as Channel.Close and Connection.Close. * @param command the command to handle asynchronously * @return true if we handled the command; otherwise the caller should consider it "unhandled" */ public abstract boolean processAsync(Command command) throws IOException; @Override public String toString() { return "AMQChannel(" + _connection + "," + _channelNumber + ")"; } /** * Protected API - respond, in the driver thread, to a {@link ShutdownSignalException}. * @param signal the signal to handle * @param ignoreClosed the flag indicating whether to ignore the AlreadyClosedException * thrown when the channel is already closed * @param notifyRpc the flag indicating whether any remaining rpc continuation should be * notified with the given signal */ public void processShutdownSignal(ShutdownSignalException signal, boolean ignoreClosed, boolean notifyRpc) { try { synchronized (_channelMutex) { if (!setShutdownCauseIfOpen(signal)) { if (!ignoreClosed) throw new AlreadyClosedException(getCloseReason()); } _channelMutex.notifyAll(); } } finally { if (notifyRpc) notifyOutstandingRpc(signal); } } public void notifyOutstandingRpc(ShutdownSignalException signal) { RpcWrapper k = nextOutstandingRpc(); if (k != null) { k.shutdown(signal); } } public void transmit(Method m) throws IOException { synchronized (_channelMutex) { transmit(new AMQCommand(m)); } } public void transmit(AMQCommand c) throws IOException { synchronized (_channelMutex) { ensureIsOpen(); quiescingTransmit(c); } } public void quiescingTransmit(Method m) throws IOException { synchronized (_channelMutex) { quiescingTransmit(new AMQCommand(m)); } } public void quiescingTransmit(AMQCommand c) throws IOException { synchronized (_channelMutex) { if (c.getMethod().hasContent()) { while (_blockContent) { try { _channelMutex.wait(); } catch (InterruptedException ignored) {} // This is to catch a situation when the thread wakes up during // shutdown. Currently, no command that has content is allowed // to send anything in a closing state. ensureIsOpen(); } } c.transmit(this); } } public AMQConnection getConnection() { return _connection; } public interface RpcContinuation { void handleCommand(AMQCommand command); /** @return true if the reply command can be handled for this request */ boolean canHandleReply(AMQCommand command); void handleShutdownSignal(ShutdownSignalException signal); } public static abstract class BlockingRpcContinuation implements RpcContinuation { public final BlockingValueOrException _blocker = new BlockingValueOrException(); protected final Method request; public BlockingRpcContinuation() { request = null; } public BlockingRpcContinuation(final Method request) { this.request = request; } @Override public void handleCommand(AMQCommand command) { _blocker.setValue(transformReply(command)); } @Override public void handleShutdownSignal(ShutdownSignalException signal) { _blocker.setException(signal); } public T getReply() throws ShutdownSignalException { return _blocker.uninterruptibleGetValue(); } public T getReply(int timeout) throws ShutdownSignalException, TimeoutException { return _blocker.uninterruptibleGetValue(timeout); } @Override public boolean canHandleReply(AMQCommand command) { return isResponseCompatibleWithRequest(request, command.getMethod()); } public abstract T transformReply(AMQCommand command); public static boolean isResponseCompatibleWithRequest(Method request, Method response) { // make a best effort attempt to ensure the reply was intended for this rpc request // Ideally each rpc request would tag an id on it that could be returned and referenced on its reply. // But because that would be a very large undertaking to add passively this logic at least protects against ClassCastExceptions if (request != null) { if (request instanceof Basic.Qos) { return response instanceof Basic.QosOk; } else if (request instanceof Basic.Get) { return response instanceof Basic.GetOk || response instanceof Basic.GetEmpty; } else if (request instanceof Basic.Consume) { if (!(response instanceof Basic.ConsumeOk)) return false; // can also check the consumer tags match here. handle case where request consumer tag is empty and server-generated. final String consumerTag = ((Basic.Consume) request).getConsumerTag(); return consumerTag == null || consumerTag.equals("") || consumerTag.equals(((Basic.ConsumeOk) response).getConsumerTag()); } else if (request instanceof Basic.Cancel) { if (!(response instanceof Basic.CancelOk)) return false; // can also check the consumer tags match here return ((Basic.Cancel) request).getConsumerTag().equals(((Basic.CancelOk) response).getConsumerTag()); } else if (request instanceof Basic.Recover) { return response instanceof Basic.RecoverOk; } else if (request instanceof Exchange.Declare) { return response instanceof Exchange.DeclareOk; } else if (request instanceof Exchange.Delete) { return response instanceof Exchange.DeleteOk; } else if (request instanceof Exchange.Bind) { return response instanceof Exchange.BindOk; } else if (request instanceof Exchange.Unbind) { return response instanceof Exchange.UnbindOk; } else if (request instanceof Queue.Declare) { // we cannot check the queue name, as the server can strip some characters // see QueueLifecycle test and https://github.com/rabbitmq/rabbitmq-server/issues/710 return response instanceof Queue.DeclareOk; } else if (request instanceof Queue.Delete) { return response instanceof Queue.DeleteOk; } else if (request instanceof Queue.Bind) { return response instanceof Queue.BindOk; } else if (request instanceof Queue.Unbind) { return response instanceof Queue.UnbindOk; } else if (request instanceof Queue.Purge) { return response instanceof Queue.PurgeOk; } else if (request instanceof Tx.Select) { return response instanceof Tx.SelectOk; } else if (request instanceof Tx.Commit) { return response instanceof Tx.CommitOk; } else if (request instanceof Tx.Rollback) { return response instanceof Tx.RollbackOk; } else if (request instanceof Confirm.Select) { return response instanceof Confirm.SelectOk; } } // for passivity default to true return true; } } public static class SimpleBlockingRpcContinuation extends BlockingRpcContinuation { public SimpleBlockingRpcContinuation() { super(); } public SimpleBlockingRpcContinuation(final Method method) { super(method); } @Override public AMQCommand transformReply(AMQCommand command) { return command; } } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/AMQCommand.java000066400000000000000000000150401316117667700275410ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.IOException; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.Command; /** * AMQP 0-9-1-specific implementation of {@link Command} which accumulates * method, header and body from a series of frames, unless these are * supplied at construction time. *

Concurrency

* This class is thread-safe. */ public class AMQCommand implements Command { /** EMPTY_FRAME_SIZE = 8 = 1 + 2 + 4 + 1 *
  • 1 byte of frame type
  • *
  • 2 bytes of channel number
  • *
  • 4 bytes of frame payload length
  • *
  • 1 byte of payload trailer FRAME_END byte
* See {@link #checkEmptyFrameSize}, an assertion checked at * startup. */ public static final int EMPTY_FRAME_SIZE = 8; /** The assembler for this command - synchronised on - contains all the state */ private final CommandAssembler assembler; /** Construct a command ready to fill in by reading frames */ public AMQCommand() { this(null, null, null); } /** * Construct a command with just a method, and without header or body. * @param method the wrapped method */ public AMQCommand(com.rabbitmq.client.Method method) { this(method, null, null); } /** * Construct a command with a specified method, header and body. * @param method the wrapped method * @param contentHeader the wrapped content header * @param body the message body data */ public AMQCommand(com.rabbitmq.client.Method method, AMQContentHeader contentHeader, byte[] body) { this.assembler = new CommandAssembler((Method) method, contentHeader, body); } /** Public API - {@inheritDoc} */ @Override public Method getMethod() { return this.assembler.getMethod(); } /** Public API - {@inheritDoc} */ @Override public AMQContentHeader getContentHeader() { return this.assembler.getContentHeader(); } /** Public API - {@inheritDoc} */ @Override public byte[] getContentBody() { return this.assembler.getContentBody(); } public boolean handleFrame(Frame f) throws IOException { return this.assembler.handleFrame(f); } /** * Sends this command down the named channel on the channel's * connection, possibly in multiple frames. * @param channel the channel on which to transmit the command * @throws IOException if an error is encountered */ public void transmit(AMQChannel channel) throws IOException { int channelNumber = channel.getChannelNumber(); AMQConnection connection = channel.getConnection(); synchronized (assembler) { Method m = this.assembler.getMethod(); connection.writeFrame(m.toFrame(channelNumber)); if (m.hasContent()) { byte[] body = this.assembler.getContentBody(); connection.writeFrame(this.assembler.getContentHeader() .toFrame(channelNumber, body.length)); int frameMax = connection.getFrameMax(); int bodyPayloadMax = (frameMax == 0) ? body.length : frameMax - EMPTY_FRAME_SIZE; for (int offset = 0; offset < body.length; offset += bodyPayloadMax) { int remaining = body.length - offset; int fragmentLength = (remaining < bodyPayloadMax) ? remaining : bodyPayloadMax; Frame frame = Frame.fromBodyFragment(channelNumber, body, offset, fragmentLength); connection.writeFrame(frame); } } } connection.flush(); } @Override public String toString() { return toString(false); } public String toString(boolean suppressBody){ synchronized (assembler) { return new StringBuilder() .append('{') .append(this.assembler.getMethod()) .append(", ") .append(this.assembler.getContentHeader()) .append(", ") .append(contentBodyStringBuilder( this.assembler.getContentBody(), suppressBody)) .append('}').toString(); } } private static StringBuilder contentBodyStringBuilder(byte[] body, boolean suppressBody) { try { if (suppressBody) { return new StringBuilder().append(body.length).append(" bytes of payload"); } else { return new StringBuilder().append('\"').append(new String(body, "UTF-8")).append('\"'); } } catch (Exception e) { return new StringBuilder().append('|').append(body.length).append('|'); } } /** Called to check internal code assumptions. */ public static void checkPreconditions() { checkEmptyFrameSize(); } /** * Since we're using a pre-computed value for EMPTY_FRAME_SIZE we * check this is actually correct when run against the framing * code in Frame. */ private static void checkEmptyFrameSize() { Frame f = new Frame(AMQP.FRAME_BODY, 0, new byte[0]); ByteArrayOutputStream s = new ByteArrayOutputStream(); try { f.writeTo(new DataOutputStream(s)); } catch (IOException ioe) { throw new IllegalStateException("IOException while checking EMPTY_FRAME_SIZE"); } int actualLength = s.toByteArray().length; if (EMPTY_FRAME_SIZE != actualLength) { throw new IllegalStateException("Internal error: expected EMPTY_FRAME_SIZE(" + EMPTY_FRAME_SIZE + ") is not equal to computed value: " + actualLength); } } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/AMQConnection.java000066400000000000000000001156351316117667700302750ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl; import com.rabbitmq.client.*; import com.rabbitmq.client.Method; import com.rabbitmq.client.impl.AMQChannel.BlockingRpcContinuation; import com.rabbitmq.client.impl.recovery.RecoveryCanBeginListener; import com.rabbitmq.utility.BlockingCell; import com.rabbitmq.utility.Utility; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.EOFException; import java.io.IOException; import java.net.InetAddress; import java.net.SocketException; import java.net.SocketTimeoutException; import java.util.*; import java.util.concurrent.*; final class Copyright { final static String COPYRIGHT="Copyright (c) 2007-2016 Pivotal Software, Inc."; final static String LICENSE="Licensed under the MPL. See http://www.rabbitmq.com/"; } /** * Concrete class representing and managing an AMQP connection to a broker. *

* To create a broker connection, use {@link ConnectionFactory}. See {@link Connection} * for an example. */ public class AMQConnection extends ShutdownNotifierComponent implements Connection, NetworkConnection { private static final Logger LOGGER = LoggerFactory.getLogger(AMQConnection.class); // we want socket write and channel shutdown timeouts to kick in after // the heartbeat one, so we use a value of 105% of the effective heartbeat timeout public static final double CHANNEL_SHUTDOWN_TIMEOUT_MULTIPLIER = 1.05; private final ExecutorService consumerWorkServiceExecutor; private final ScheduledExecutorService heartbeatExecutor; private final ExecutorService shutdownExecutor; private Thread mainLoopThread; private ThreadFactory threadFactory = Executors.defaultThreadFactory(); private String id; private final List recoveryCanBeginListeners = Collections.synchronizedList(new ArrayList()); /** * Retrieve a copy of the default table of client properties that * will be sent to the server during connection startup. This * method is called when each new ConnectionFactory instance is * constructed. * @return a map of client properties * @see Connection#getClientProperties */ public static Map defaultClientProperties() { Map props = new HashMap(); props.put("product", LongStringHelper.asLongString("RabbitMQ")); props.put("version", LongStringHelper.asLongString(ClientVersion.VERSION)); props.put("platform", LongStringHelper.asLongString("Java")); props.put("copyright", LongStringHelper.asLongString(Copyright.COPYRIGHT)); props.put("information", LongStringHelper.asLongString(Copyright.LICENSE)); Map capabilities = new HashMap(); capabilities.put("publisher_confirms", true); capabilities.put("exchange_exchange_bindings", true); capabilities.put("basic.nack", true); capabilities.put("consumer_cancel_notify", true); capabilities.put("connection.blocked", true); capabilities.put("authentication_failure_close", true); props.put("capabilities", capabilities); return props; } private static final Version clientVersion = new Version(AMQP.PROTOCOL.MAJOR, AMQP.PROTOCOL.MINOR); /** The special channel 0 (not managed by the _channelManager) */ private final AMQChannel _channel0; protected ConsumerWorkService _workService = null; /** Frame source/sink */ private final FrameHandler _frameHandler; /** Flag controlling the main driver loop's termination */ private volatile boolean _running = false; /** Handler for (uncaught) exceptions that crop up in the {@link MainLoop}. */ private final ExceptionHandler _exceptionHandler; /** Object used for blocking main application thread when doing all the necessary * connection shutdown operations */ private final BlockingCell _appContinuation = new BlockingCell(); /** Flag indicating whether the client received Connection.Close message from the broker */ private volatile boolean _brokerInitiatedShutdown; /** Flag indicating we are still negotiating the connection in start */ private volatile boolean _inConnectionNegotiation; /** Manages heart-beat sending for this connection */ private HeartbeatSender _heartbeatSender; private final String _virtualHost; private final Map _clientProperties; private final SaslConfig saslConfig; private final int requestedHeartbeat; private final int requestedChannelMax; private final int requestedFrameMax; private final int handshakeTimeout; private final int shutdownTimeout; private final String username; private final String password; private final Collection blockedListeners = new CopyOnWriteArrayList(); protected final MetricsCollector metricsCollector; private final int channelRpcTimeout; private final boolean channelShouldCheckRpcResponseType; /* State modified after start - all volatile */ /** Maximum frame length, or zero if no limit is set */ private volatile int _frameMax = 0; /** Count of socket-timeouts that have happened without any incoming frames */ private volatile int _missedHeartbeats = 0; /** Currently-configured heart-beat interval, in seconds. 0 meaning none. */ private volatile int _heartbeat = 0; /** Object that manages a set of channels */ private volatile ChannelManager _channelManager; /** Saved server properties field from connection.start */ private volatile Map _serverProperties; /** * Protected API - respond, in the driver thread, to a ShutdownSignal. * @param channel the channel to disconnect */ public final void disconnectChannel(ChannelN channel) { ChannelManager cm = _channelManager; if (cm != null) cm.releaseChannelNumber(channel); } private void ensureIsOpen() throws AlreadyClosedException { if (!isOpen()) { throw new AlreadyClosedException(getCloseReason()); } } /** {@inheritDoc} */ @Override public InetAddress getAddress() { return _frameHandler.getAddress(); } @Override public InetAddress getLocalAddress() { return _frameHandler.getLocalAddress(); } /** {@inheritDoc} */ @Override public int getPort() { return _frameHandler.getPort(); } @Override public int getLocalPort() { return _frameHandler.getLocalPort(); } public FrameHandler getFrameHandler(){ return _frameHandler; } /** {@inheritDoc} */ @Override public Map getServerProperties() { return _serverProperties; } public AMQConnection(ConnectionParams params, FrameHandler frameHandler) { this(params, frameHandler, new NoOpMetricsCollector()); } /** Construct a new connection * @param params parameters for it */ public AMQConnection(ConnectionParams params, FrameHandler frameHandler, MetricsCollector metricsCollector) { checkPreconditions(); this.username = params.getUsername(); this.password = params.getPassword(); this._frameHandler = frameHandler; this._virtualHost = params.getVirtualHost(); this._exceptionHandler = params.getExceptionHandler(); this._clientProperties = new HashMap(params.getClientProperties()); this.requestedFrameMax = params.getRequestedFrameMax(); this.requestedChannelMax = params.getRequestedChannelMax(); this.requestedHeartbeat = params.getRequestedHeartbeat(); this.handshakeTimeout = params.getHandshakeTimeout(); this.shutdownTimeout = params.getShutdownTimeout(); this.saslConfig = params.getSaslConfig(); this.consumerWorkServiceExecutor = params.getConsumerWorkServiceExecutor(); this.heartbeatExecutor = params.getHeartbeatExecutor(); this.shutdownExecutor = params.getShutdownExecutor(); this.threadFactory = params.getThreadFactory(); if(params.getChannelRpcTimeout() < 0) { throw new IllegalArgumentException("Continuation timeout on RPC calls cannot be less than 0"); } this.channelRpcTimeout = params.getChannelRpcTimeout(); this.channelShouldCheckRpcResponseType = params.channelShouldCheckRpcResponseType(); this._channel0 = new AMQChannel(this, 0) { @Override public boolean processAsync(Command c) throws IOException { return getConnection().processControlCommand(c); } }; this._channelManager = null; this._brokerInitiatedShutdown = false; this._inConnectionNegotiation = true; // we start out waiting for the first protocol response this.metricsCollector = metricsCollector; } private void initializeConsumerWorkService() { this._workService = new ConsumerWorkService(consumerWorkServiceExecutor, threadFactory, shutdownTimeout); } private void initializeHeartbeatSender() { this._heartbeatSender = new HeartbeatSender(_frameHandler, heartbeatExecutor, threadFactory); } /** * Start up the connection, including the MainLoop thread. * Sends the protocol * version negotiation header, and runs through * Connection.Start/.StartOk, Connection.Tune/.TuneOk, and then * calls Connection.Open and waits for the OpenOk. Sets heart-beat * and frame max values after tuning has taken place. * @throws IOException if an error is encountered * either before, or during, protocol negotiation; * sub-classes {@link ProtocolVersionMismatchException} and * {@link PossibleAuthenticationFailureException} will be thrown in the * corresponding circumstances. {@link AuthenticationFailureException} * will be thrown if the broker closes the connection with ACCESS_REFUSED. * If an exception is thrown, connection resources allocated can all be * garbage collected when the connection object is no longer referenced. */ public void start() throws IOException, TimeoutException { initializeConsumerWorkService(); initializeHeartbeatSender(); this._running = true; // Make sure that the first thing we do is to send the header, // which should cause any socket errors to show up for us, rather // than risking them pop out in the MainLoop AMQChannel.SimpleBlockingRpcContinuation connStartBlocker = new AMQChannel.SimpleBlockingRpcContinuation(); // We enqueue an RPC continuation here without sending an RPC // request, since the protocol specifies that after sending // the version negotiation header, the client (connection // initiator) is to wait for a connection.start method to // arrive. _channel0.enqueueRpc(connStartBlocker); try { // The following two lines are akin to AMQChannel's // transmit() method for this pseudo-RPC. _frameHandler.setTimeout(handshakeTimeout); _frameHandler.sendHeader(); } catch (IOException ioe) { _frameHandler.close(); throw ioe; } this._frameHandler.initialize(this); AMQP.Connection.Start connStart; AMQP.Connection.Tune connTune = null; try { connStart = (AMQP.Connection.Start) connStartBlocker.getReply(handshakeTimeout/2).getMethod(); _serverProperties = Collections.unmodifiableMap(connStart.getServerProperties()); Version serverVersion = new Version(connStart.getVersionMajor(), connStart.getVersionMinor()); if (!Version.checkVersion(clientVersion, serverVersion)) { throw new ProtocolVersionMismatchException(clientVersion, serverVersion); } String[] mechanisms = connStart.getMechanisms().toString().split(" "); SaslMechanism sm = this.saslConfig.getSaslMechanism(mechanisms); if (sm == null) { throw new IOException("No compatible authentication mechanism found - " + "server offered [" + connStart.getMechanisms() + "]"); } LongString challenge = null; LongString response = sm.handleChallenge(null, this.username, this.password); do { Method method = (challenge == null) ? new AMQP.Connection.StartOk.Builder() .clientProperties(_clientProperties) .mechanism(sm.getName()) .response(response) .build() : new AMQP.Connection.SecureOk.Builder().response(response).build(); try { Method serverResponse = _channel0.rpc(method, handshakeTimeout/2).getMethod(); if (serverResponse instanceof AMQP.Connection.Tune) { connTune = (AMQP.Connection.Tune) serverResponse; } else { challenge = ((AMQP.Connection.Secure) serverResponse).getChallenge(); response = sm.handleChallenge(challenge, this.username, this.password); } } catch (ShutdownSignalException e) { Method shutdownMethod = e.getReason(); if (shutdownMethod instanceof AMQP.Connection.Close) { AMQP.Connection.Close shutdownClose = (AMQP.Connection.Close) shutdownMethod; if (shutdownClose.getReplyCode() == AMQP.ACCESS_REFUSED) { throw new AuthenticationFailureException(shutdownClose.getReplyText()); } } throw new PossibleAuthenticationFailureException(e); } } while (connTune == null); } catch (TimeoutException te) { _frameHandler.close(); throw te; } catch (ShutdownSignalException sse) { _frameHandler.close(); throw AMQChannel.wrap(sse); } catch(IOException ioe) { _frameHandler.close(); throw ioe; } try { int channelMax = negotiateChannelMax(this.requestedChannelMax, connTune.getChannelMax()); _channelManager = instantiateChannelManager(channelMax, threadFactory); int frameMax = negotiatedMaxValue(this.requestedFrameMax, connTune.getFrameMax()); this._frameMax = frameMax; int heartbeat = negotiatedMaxValue(this.requestedHeartbeat, connTune.getHeartbeat()); setHeartbeat(heartbeat); _channel0.transmit(new AMQP.Connection.TuneOk.Builder() .channelMax(channelMax) .frameMax(frameMax) .heartbeat(heartbeat) .build()); _channel0.exnWrappingRpc(new AMQP.Connection.Open.Builder() .virtualHost(_virtualHost) .build()); } catch (IOException ioe) { _heartbeatSender.shutdown(); _frameHandler.close(); throw ioe; } catch (ShutdownSignalException sse) { _heartbeatSender.shutdown(); _frameHandler.close(); throw AMQChannel.wrap(sse); } // We can now respond to errors having finished tailoring the connection this._inConnectionNegotiation = false; } protected ChannelManager instantiateChannelManager(int channelMax, ThreadFactory threadFactory) { ChannelManager result = new ChannelManager(this._workService, channelMax, threadFactory, this.metricsCollector); configureChannelManager(result); return result; } protected void configureChannelManager(ChannelManager channelManager) { channelManager.setShutdownExecutor(this.shutdownExecutor); channelManager.setChannelShutdownTimeout((int) ((requestedHeartbeat * CHANNEL_SHUTDOWN_TIMEOUT_MULTIPLIER) * 1000)); } /** * Package private API, allows for easier testing. */ public void startMainLoop() { MainLoop loop = new MainLoop(); final String name = "AMQP Connection " + getHostAddress() + ":" + getPort(); mainLoopThread = Environment.newThread(threadFactory, loop, name); mainLoopThread.start(); } /** * Private API, allows for easier simulation of bogus clients. */ protected int negotiateChannelMax(int requestedChannelMax, int serverMax) { return negotiatedMaxValue(requestedChannelMax, serverMax); } /** * Private API - check required preconditions and protocol invariants */ private static void checkPreconditions() { AMQCommand.checkPreconditions(); } /** {@inheritDoc} */ @Override public int getChannelMax() { ChannelManager cm = _channelManager; if (cm == null) return 0; return cm.getChannelMax(); } /** {@inheritDoc} */ @Override public int getFrameMax() { return _frameMax; } /** {@inheritDoc} */ @Override public int getHeartbeat() { return _heartbeat; } /** * Protected API - set the heartbeat timeout. Should only be called * during tuning. */ public void setHeartbeat(int heartbeat) { try { _heartbeatSender.setHeartbeat(heartbeat); _heartbeat = heartbeat; // Divide by four to make the maximum unwanted delay in // sending a timeout be less than a quarter of the // timeout setting. _frameHandler.setTimeout(heartbeat * 1000 / 4); } catch (SocketException se) { // should do more here? } } /** * Makes it possible to override thread factory that is used * to instantiate connection network I/O loop. Only necessary * in the environments with restricted * @param threadFactory thread factory to use */ public void setThreadFactory(ThreadFactory threadFactory) { this.threadFactory = threadFactory; } /** * @return Thread factory used by this connection. */ public ThreadFactory getThreadFactory() { return threadFactory; } @Override public Map getClientProperties() { return new HashMap(_clientProperties); } @Override public String getClientProvidedName() { return (String) _clientProperties.get("connection_name"); } /** * Protected API - retrieve the current ExceptionHandler */ @Override public ExceptionHandler getExceptionHandler() { return _exceptionHandler; } /** Public API * * @return true if this work service instance uses its own consumerWorkServiceExecutor (as opposed to a shared one) */ public boolean willShutDownConsumerExecutor() { return this._workService.usesPrivateExecutor(); } /** Public API - {@inheritDoc} */ @Override public Channel createChannel(int channelNumber) throws IOException { ensureIsOpen(); ChannelManager cm = _channelManager; if (cm == null) return null; Channel channel = cm.createChannel(this, channelNumber); metricsCollector.newChannel(channel); return channel; } /** Public API - {@inheritDoc} */ @Override public Channel createChannel() throws IOException { ensureIsOpen(); ChannelManager cm = _channelManager; if (cm == null) return null; Channel channel = cm.createChannel(this); metricsCollector.newChannel(channel); return channel; } /** * Public API - sends a frame directly to the broker. */ public void writeFrame(Frame f) throws IOException { _frameHandler.writeFrame(f); _heartbeatSender.signalActivity(); } /** * Public API - flush the output buffers */ public void flush() throws IOException { _frameHandler.flush(); } private static int negotiatedMaxValue(int clientValue, int serverValue) { return (clientValue == 0 || serverValue == 0) ? Math.max(clientValue, serverValue) : Math.min(clientValue, serverValue); } private class MainLoop implements Runnable { /** * Channel reader thread main loop. Reads a frame, and if it is * not a heartbeat frame, dispatches it to the channel it refers to. * Continues running until the "running" flag is set false by * shutdown(). */ @Override public void run() { try { while (_running) { Frame frame = _frameHandler.readFrame(); readFrame(frame); } } catch (Throwable ex) { handleFailure(ex); } finally { doFinalShutdown(); } } } /** private API */ public boolean handleReadFrame(Frame frame) { if(_running) { try { readFrame(frame); return true; } catch (Throwable ex) { try { handleFailure(ex); } finally { doFinalShutdown(); } } } return false; } public boolean isRunning() { return _running; } public boolean hasBrokerInitiatedShutdown() { return _brokerInitiatedShutdown; } private void readFrame(Frame frame) throws IOException { if (frame != null) { _missedHeartbeats = 0; if (frame.type == AMQP.FRAME_HEARTBEAT) { // Ignore it: we've already just reset the heartbeat counter. } else { if (frame.channel == 0) { // the special channel _channel0.handleFrame(frame); } else { if (isOpen()) { // If we're still _running, but not isOpen(), then we // must be quiescing, which means any inbound frames // for non-zero channels (and any inbound commands on // channel zero that aren't Connection.CloseOk) must // be discarded. ChannelManager cm = _channelManager; if (cm != null) { ChannelN channel; try { channel = cm.getChannel(frame.channel); } catch(UnknownChannelException e) { // this can happen if channel has been closed, // but there was e.g. an in-flight delivery. // just ignoring the frame to avoid closing the whole connection LOGGER.info("Received a frame on an unknown channel, ignoring it"); return; } channel.handleFrame(frame); } } } } } else { // Socket timeout waiting for a frame. // Maybe missed heartbeat. handleSocketTimeout(); } } /** private API */ public void handleHeartbeatFailure() { Exception ex = new MissedHeartbeatException("Heartbeat missing with heartbeat = " + _heartbeat + " seconds"); try { _exceptionHandler.handleUnexpectedConnectionDriverException(this, ex); shutdown(null, false, ex, true); } finally { doFinalShutdown(); } } /** private API */ public void handleIoError(Throwable ex) { try { handleFailure(ex); } finally { doFinalShutdown(); } } private void handleFailure(Throwable ex) { if(ex instanceof EOFException) { if (!_brokerInitiatedShutdown) shutdown(null, false, ex, true); } else { _exceptionHandler.handleUnexpectedConnectionDriverException(AMQConnection.this, ex); shutdown(null, false, ex, true); } } /** private API */ public void doFinalShutdown() { _frameHandler.close(); _appContinuation.set(null); notifyListeners(); // assuming that shutdown listeners do not do anything // asynchronously, e.g. start new threads, this effectively // guarantees that we only begin recovery when all shutdown // listeners have executed notifyRecoveryCanBeginListeners(); } private void notifyRecoveryCanBeginListeners() { ShutdownSignalException sse = this.getCloseReason(); for(RecoveryCanBeginListener fn : Utility.copy(this.recoveryCanBeginListeners)) { fn.recoveryCanBegin(sse); } } public void addRecoveryCanBeginListener(RecoveryCanBeginListener fn) { this.recoveryCanBeginListeners.add(fn); } public void removeRecoveryCanBeginListener(RecoveryCanBeginListener fn) { this.recoveryCanBeginListeners.remove(fn); } /** * Called when a frame-read operation times out * @throws MissedHeartbeatException if heart-beats have been missed */ private void handleSocketTimeout() throws SocketTimeoutException { if (_inConnectionNegotiation) { throw new SocketTimeoutException("Timeout during Connection negotiation"); } if (_heartbeat == 0) { // No heart-beating return; } // We check against 8 = 2 * 4 because we need to wait for at // least two complete heartbeat setting intervals before // complaining, and we've set the socket timeout to a quarter // of the heartbeat setting in setHeartbeat above. if (++_missedHeartbeats > (2 * 4)) { throw new MissedHeartbeatException("Heartbeat missing with heartbeat = " + _heartbeat + " seconds"); } } /** * Handles incoming control commands on channel zero. * @see ChannelN#processAsync */ @SuppressWarnings("unused") public boolean processControlCommand(Command c) throws IOException { // Similar trick to ChannelN.processAsync used here, except // we're interested in whole-connection quiescing. // See the detailed comments in ChannelN.processAsync. Method method = c.getMethod(); if (isOpen()) { if (method instanceof AMQP.Connection.Close) { handleConnectionClose(c); return true; } else if (method instanceof AMQP.Connection.Blocked) { AMQP.Connection.Blocked blocked = (AMQP.Connection.Blocked) method; try { for (BlockedListener l : this.blockedListeners) { l.handleBlocked(blocked.getReason()); } } catch (Throwable ex) { getExceptionHandler().handleBlockedListenerException(this, ex); } return true; } else if (method instanceof AMQP.Connection.Unblocked) { try { for (BlockedListener l : this.blockedListeners) { l.handleUnblocked(); } } catch (Throwable ex) { getExceptionHandler().handleBlockedListenerException(this, ex); } return true; } else { return false; } } else { if (method instanceof AMQP.Connection.Close) { // Already shutting down, so just send back a CloseOk. try { _channel0.quiescingTransmit(new AMQP.Connection.CloseOk.Builder().build()); } catch (IOException ignored) { } // ignore return true; } else if (method instanceof AMQP.Connection.CloseOk) { // It's our final "RPC". Time to shut down. _running = false; // If Close was sent from within the MainLoop we // will not have a continuation to return to, so // we treat this as processed in that case. return !_channel0.isOutstandingRpc(); } else { // Ignore all others. return true; } } } public void handleConnectionClose(Command closeCommand) { ShutdownSignalException sse = shutdown(closeCommand.getMethod(), false, null, _inConnectionNegotiation); try { _channel0.quiescingTransmit(new AMQP.Connection.CloseOk.Builder().build()); } catch (IOException ignored) { } // ignore _brokerInitiatedShutdown = true; SocketCloseWait scw = new SocketCloseWait(sse); // if shutdown executor is configured, use it. Otherwise // execut socket close monitor the old fashioned way. // see rabbitmq/rabbitmq-java-client#91 if(shutdownExecutor != null) { shutdownExecutor.execute(scw); } else { final String name = "RabbitMQ connection shutdown monitor " + getHostAddress() + ":" + getPort(); Thread waiter = Environment.newThread(threadFactory, scw, name); waiter.start(); } } // same as ConnectionFactory.DEFAULT_SHUTDOWN_TIMEOUT private static long SOCKET_CLOSE_TIMEOUT = 10000; private class SocketCloseWait implements Runnable { private final ShutdownSignalException cause; public SocketCloseWait(ShutdownSignalException sse) { cause = sse; } @Override public void run() { try { // TODO: use a sensible timeout here _appContinuation.get(SOCKET_CLOSE_TIMEOUT); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } catch (TimeoutException ignored) { // this releases the thread } finally { _running = false; _channel0.notifyOutstandingRpc(cause); } } } /** * Protected API - causes all attached channels to terminate (shutdown) with a ShutdownSignal * built from the argument, and stops this connection from accepting further work from the * application. {@link com.rabbitmq.client.ShutdownListener ShutdownListener}s for the * connection are notified when the main loop terminates. * @param reason description of reason for the exception * @param initiatedByApplication true if caused by a client command * @param cause trigger exception which caused shutdown * @param notifyRpc true if outstanding rpc should be informed of shutdown * @return a shutdown signal built using the given arguments */ public ShutdownSignalException shutdown(Method reason, boolean initiatedByApplication, Throwable cause, boolean notifyRpc) { ShutdownSignalException sse = startShutdown(reason, initiatedByApplication, cause, notifyRpc); finishShutdown(sse); return sse; } private ShutdownSignalException startShutdown(Method reason, boolean initiatedByApplication, Throwable cause, boolean notifyRpc) { ShutdownSignalException sse = new ShutdownSignalException(true,initiatedByApplication, reason, this); sse.initCause(cause); if (!setShutdownCauseIfOpen(sse)) { if (initiatedByApplication) throw new AlreadyClosedException(getCloseReason(), cause); } // stop any heartbeating _heartbeatSender.shutdown(); _channel0.processShutdownSignal(sse, !initiatedByApplication, notifyRpc); return sse; } private void finishShutdown(ShutdownSignalException sse) { ChannelManager cm = _channelManager; if (cm != null) cm.handleSignal(sse); } /** Public API - {@inheritDoc} */ @Override public void close() throws IOException { close(-1); } /** Public API - {@inheritDoc} */ @Override public void close(int timeout) throws IOException { close(AMQP.REPLY_SUCCESS, "OK", timeout); } /** Public API - {@inheritDoc} */ @Override public void close(int closeCode, String closeMessage) throws IOException { close(closeCode, closeMessage, -1); } /** Public API - {@inheritDoc} */ @Override public void close(int closeCode, String closeMessage, int timeout) throws IOException { close(closeCode, closeMessage, true, null, timeout, false); } /** Public API - {@inheritDoc} */ @Override public void abort() { abort(-1); } /** Public API - {@inheritDoc} */ @Override public void abort(int closeCode, String closeMessage) { abort(closeCode, closeMessage, -1); } /** Public API - {@inheritDoc} */ @Override public void abort(int timeout) { abort(AMQP.REPLY_SUCCESS, "OK", timeout); } /** Public API - {@inheritDoc} */ @Override public void abort(int closeCode, String closeMessage, int timeout) { try { close(closeCode, closeMessage, true, null, timeout, true); } catch (IOException ignored) { } // ignore } /** * Protected API - Delegates to {@link * #close(int,String,boolean,Throwable,int,boolean) the * six-argument close method}, passing -1 for the timeout, and * false for the abort flag. */ public void close(int closeCode, String closeMessage, boolean initiatedByApplication, Throwable cause) throws IOException { close(closeCode, closeMessage, initiatedByApplication, cause, -1, false); } // TODO: Make this private /** * Protected API - Close this connection with the given code, message, source * and timeout value for all the close operations to complete. * Specifies if any encountered exceptions should be ignored. */ public void close(int closeCode, String closeMessage, boolean initiatedByApplication, Throwable cause, int timeout, boolean abort) throws IOException { boolean sync = !(Thread.currentThread() == mainLoopThread); try { AMQP.Connection.Close reason = new AMQP.Connection.Close.Builder() .replyCode(closeCode) .replyText(closeMessage) .build(); final ShutdownSignalException sse = startShutdown(reason, initiatedByApplication, cause, true); if(sync){ BlockingRpcContinuation k = new BlockingRpcContinuation(){ @Override public AMQCommand transformReply(AMQCommand command) { AMQConnection.this.finishShutdown(sse); return command; }}; _channel0.quiescingRpc(reason, k); k.getReply(timeout); } else { _channel0.quiescingTransmit(reason); } } catch (TimeoutException tte) { if (!abort) { ShutdownSignalException sse = new ShutdownSignalException(true, true, null, this); sse.initCause(cause); throw sse; } } catch (ShutdownSignalException sse) { if (!abort) throw sse; } catch (IOException ioe) { if (!abort) throw ioe; } finally { if(sync) _frameHandler.close(); } } @Override public String toString() { final String virtualHost = "/".equals(_virtualHost) ? _virtualHost : "/" + _virtualHost; return "amqp://" + this.username + "@" + getHostAddress() + ":" + getPort() + virtualHost; } private String getHostAddress() { return getAddress() == null ? null : getAddress().getHostAddress(); } @Override public void addBlockedListener(BlockedListener listener) { blockedListeners.add(listener); } @Override public BlockedListener addBlockedListener(BlockedCallback blockedCallback, UnblockedCallback unblockedCallback) { BlockedListener blockedListener = new BlockedListener() { @Override public void handleBlocked(String reason) throws IOException { blockedCallback.handle(reason); } @Override public void handleUnblocked() throws IOException { unblockedCallback.handle(); } }; this.addBlockedListener(blockedListener); return blockedListener; } @Override public boolean removeBlockedListener(BlockedListener listener) { return blockedListeners.remove(listener); } @Override public void clearBlockedListeners() { blockedListeners.clear(); } /** Public API - {@inheritDoc} */ @Override public String getId() { return id; } /** Public API - {@inheritDoc} */ @Override public void setId(String id) { this.id = id; } public int getChannelRpcTimeout() { return channelRpcTimeout; } public boolean willCheckRpcResponseType() { return channelShouldCheckRpcResponseType; } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/AMQContentHeader.java000066400000000000000000000054601316117667700307130ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.ContentHeader; /** * Implementation of ContentHeader - specialized by autogenerated code in AMQP.java. */ public abstract class AMQContentHeader implements ContentHeader { /** * Private API - Called by {@link AMQChannel#handleFrame}. Parses the header frame. */ private long bodySize; protected AMQContentHeader() { this.bodySize = 0; } protected AMQContentHeader(DataInputStream in) throws IOException { in.readShort(); // weight not currently used this.bodySize = in.readLong(); } public long getBodySize() { return bodySize; } private void writeTo(DataOutputStream out, long bodySize) throws IOException { out.writeShort(0); // weight - not currently used out.writeLong(bodySize); writePropertiesTo(new ContentHeaderPropertyWriter(out)); } /** * Private API - Autogenerated writer for this header */ public abstract void writePropertiesTo(ContentHeaderPropertyWriter writer) throws IOException; /** Public API - {@inheritDoc} */ @Override public void appendPropertyDebugStringTo(StringBuilder acc) { acc.append("(?)"); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("#contentHeader<").append(getClassName()).append(">"); this.appendPropertyDebugStringTo(sb); return sb.toString(); } /** * Private API - Called by {@link AMQCommand#transmit} */ public Frame toFrame(int channelNumber, long bodySize) throws IOException { Frame frame = new Frame(AMQP.FRAME_HEADER, channelNumber); DataOutputStream bodyOut = frame.getOutputStream(); bodyOut.writeShort(getClassId()); writeTo(bodyOut, bodySize); return frame; } @Override public Object clone() throws CloneNotSupportedException { return super.clone(); } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/AbstractFrameHandlerFactory.java000066400000000000000000000010431316117667700331660ustar00rootroot00000000000000package com.rabbitmq.client.impl; import com.rabbitmq.client.SocketConfigurator; /** * */ public abstract class AbstractFrameHandlerFactory implements FrameHandlerFactory { protected final int connectionTimeout; protected final SocketConfigurator configurator; protected final boolean ssl; protected AbstractFrameHandlerFactory(int connectionTimeout, SocketConfigurator configurator, boolean ssl) { this.connectionTimeout = connectionTimeout; this.configurator = configurator; this.ssl = ssl; } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/AbstractMetricsCollector.java000066400000000000000000000326511316117667700325740ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl; import com.rabbitmq.client.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * Base class for {@link MetricsCollector}. * Implements tricky logic such as keeping track of acknowledged and * rejected messages. Sub-classes just need to implement * the logic to increment their metrics. * Note transactions are not supported (see {@link MetricsCollector}. * * @see MetricsCollector */ public abstract class AbstractMetricsCollector implements MetricsCollector { private static final Logger LOGGER = LoggerFactory.getLogger(AbstractMetricsCollector.class); private final ConcurrentMap connectionState = new ConcurrentHashMap(); private final Runnable markAcknowledgedMessageAction = new Runnable() { @Override public void run() { markAcknowledgedMessage(); } }; private final Runnable markRejectedMessageAction = new Runnable() { @Override public void run() { markRejectedMessage(); } }; @Override public void newConnection(final Connection connection) { try { if(connection.getId() == null) { connection.setId(UUID.randomUUID().toString()); } incrementConnectionCount(connection); connectionState.put(connection.getId(), new ConnectionState(connection)); connection.addShutdownListener(new ShutdownListener() { @Override public void shutdownCompleted(ShutdownSignalException cause) { closeConnection(connection); } }); } catch(Exception e) { LOGGER.info("Error while computing metrics in newConnection: " + e.getMessage()); } } @Override public void closeConnection(Connection connection) { try { ConnectionState removed = connectionState.remove(connection.getId()); if(removed != null) { decrementConnectionCount(connection); } } catch(Exception e) { LOGGER.info("Error while computing metrics in closeConnection: " + e.getMessage()); } } @Override public void newChannel(final Channel channel) { try { incrementChannelCount(channel); channel.addShutdownListener(new ShutdownListener() { @Override public void shutdownCompleted(ShutdownSignalException cause) { closeChannel(channel); } }); connectionState(channel.getConnection()).channelState.put(channel.getChannelNumber(), new ChannelState(channel)); } catch(Exception e) { LOGGER.info("Error while computing metrics in newChannel: " + e.getMessage()); } } @Override public void closeChannel(Channel channel) { try { ChannelState removed = connectionState(channel.getConnection()).channelState.remove(channel.getChannelNumber()); if(removed != null) { decrementChannelCount(channel); } } catch(Exception e) { LOGGER.info("Error while computing metrics in closeChannel: " + e.getMessage()); } } @Override public void basicPublish(Channel channel) { try { markPublishedMessage(); } catch(Exception e) { LOGGER.info("Error while computing metrics in basicPublish: " + e.getMessage()); } } @Override public void basicConsume(Channel channel, String consumerTag, boolean autoAck) { try { if(!autoAck) { ChannelState channelState = channelState(channel); channelState.lock.lock(); try { channelState(channel).consumersWithManualAck.add(consumerTag); } finally { channelState.lock.unlock(); } } } catch(Exception e) { LOGGER.info("Error while computing metrics in basicConsume: " + e.getMessage()); } } @Override public void basicCancel(Channel channel, String consumerTag) { try { ChannelState channelState = channelState(channel); channelState.lock.lock(); try { channelState(channel).consumersWithManualAck.remove(consumerTag); } finally { channelState.lock.unlock(); } } catch(Exception e) { LOGGER.info("Error while computing metrics in basicCancel: " + e.getMessage()); } } @Override public void consumedMessage(Channel channel, long deliveryTag, boolean autoAck) { try { markConsumedMessage(); if(!autoAck) { ChannelState channelState = channelState(channel); channelState.lock.lock(); try { channelState(channel).unackedMessageDeliveryTags.add(deliveryTag); } finally { channelState.lock.unlock(); } } } catch(Exception e) { LOGGER.info("Error while computing metrics in consumedMessage: " + e.getMessage()); } } @Override public void consumedMessage(Channel channel, long deliveryTag, String consumerTag) { try { markConsumedMessage(); ChannelState channelState = channelState(channel); channelState.lock.lock(); try { if(channelState.consumersWithManualAck.contains(consumerTag)) { channelState.unackedMessageDeliveryTags.add(deliveryTag); } } finally { channelState.lock.unlock(); } } catch(Exception e) { LOGGER.info("Error while computing metrics in consumedMessage: " + e.getMessage()); } } @Override public void basicAck(Channel channel, long deliveryTag, boolean multiple) { try { updateChannelStateAfterAckReject(channel, deliveryTag, multiple, markAcknowledgedMessageAction); } catch(Exception e) { LOGGER.info("Error while computing metrics in basicAck: " + e.getMessage()); } } @Override public void basicNack(Channel channel, long deliveryTag) { try { updateChannelStateAfterAckReject(channel, deliveryTag, true, markRejectedMessageAction); } catch(Exception e) { LOGGER.info("Error while computing metrics in basicNack: " + e.getMessage()); } } @Override public void basicReject(Channel channel, long deliveryTag) { try { updateChannelStateAfterAckReject(channel, deliveryTag, false, markRejectedMessageAction); } catch(Exception e) { LOGGER.info("Error while computing metrics in basicReject: " + e.getMessage()); } } private void updateChannelStateAfterAckReject(Channel channel, long deliveryTag, boolean multiple, Runnable action) { ChannelState channelState = channelState(channel); channelState.lock.lock(); try { if(multiple) { Iterator iterator = channelState.unackedMessageDeliveryTags.iterator(); while(iterator.hasNext()) { long messageDeliveryTag = iterator.next(); if(messageDeliveryTag <= deliveryTag) { iterator.remove(); action.run(); } } } else { channelState.unackedMessageDeliveryTags.remove(deliveryTag); action.run(); } } finally { channelState.lock.unlock(); } } private ConnectionState connectionState(Connection connection) { return connectionState.get(connection.getId()); } private ChannelState channelState(Channel channel) { return connectionState(channel.getConnection()).channelState.get(channel.getChannelNumber()); } /** * Clean inner state for close connections and channels. * Inner state is automatically cleaned on connection * and channel closing. * Thus, this method is provided as a safety net, to be externally * called periodically if closing of resources wouldn't work * properly for some corner cases. */ public void cleanStaleState() { try { Iterator> connectionStateIterator = connectionState.entrySet().iterator(); while(connectionStateIterator.hasNext()) { Map.Entry connectionEntry = connectionStateIterator.next(); Connection connection = connectionEntry.getValue().connection; if(connection.isOpen()) { Iterator> channelStateIterator = connectionEntry.getValue().channelState.entrySet().iterator(); while(channelStateIterator.hasNext()) { Map.Entry channelStateEntry = channelStateIterator.next(); Channel channel = channelStateEntry.getValue().channel; if(!channel.isOpen()) { channelStateIterator.remove(); decrementChannelCount(channel); LOGGER.info("Ripped off state of channel {} of connection {}. This is abnormal, please report.", channel.getChannelNumber(), connection.getId()); } } } else { connectionStateIterator.remove(); decrementConnectionCount(connection); for(int i = 0; i < connectionEntry.getValue().channelState.size(); i++) { decrementChannelCount(null); } LOGGER.info("Ripped off state of connection {}. This is abnormal, please report.", connection.getId()); } } } catch(Exception e) { LOGGER.info("Error during periodic clean of metricsCollector: "+e.getMessage()); } } private static class ConnectionState { final ConcurrentMap channelState = new ConcurrentHashMap(); final Connection connection; private ConnectionState(Connection connection) { this.connection = connection; } } private static class ChannelState { final Lock lock = new ReentrantLock(); final Set unackedMessageDeliveryTags = new HashSet(); final Set consumersWithManualAck = new HashSet(); final Channel channel; private ChannelState(Channel channel) { this.channel = channel; } } /** * Increments connection count. * The connection object is passed in as complementary information * and without any guarantee of not being null. * @param connection the connection that has been created (can be null) */ protected abstract void incrementConnectionCount(Connection connection); /** * Decrements connection count. * The connection object is passed in as complementary information * and without any guarantee of not being null. * @param connection the connection that has been closed (can be null) */ protected abstract void decrementConnectionCount(Connection connection); /** * Increments channel count. * The channel object is passed in as complementary information * and without any guarantee of not being null. * @param channel the channel that has been created (can be null) */ protected abstract void incrementChannelCount(Channel channel); /** * Decrements channel count. * The channel object is passed in as complementary information * and without any guarantee of not being null. * @param channel */ protected abstract void decrementChannelCount(Channel channel); /** * Marks the event of a published message. */ protected abstract void markPublishedMessage(); /** * Marks the event of a consumed message. */ protected abstract void markConsumedMessage(); /** * Marks the event of an acknowledged message. */ protected abstract void markAcknowledgedMessage(); /** * Marks the event of a rejected message. */ protected abstract void markRejectedMessage(); } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/CRDemoMechanism.java000066400000000000000000000037051316117667700305670ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl; import com.rabbitmq.client.LongString; import com.rabbitmq.client.SaslConfig; import com.rabbitmq.client.SaslMechanism; import java.util.Arrays; /** Provides equivalent security to PLAIN but demos use of Connection.Secure(Ok) START-OK: Username SECURE: "Please tell me your password" SECURE-OK: Password */ public class CRDemoMechanism implements SaslMechanism { private static final String NAME = "RABBIT-CR-DEMO"; private int round = 0; @Override public String getName() { return NAME; } @Override public LongString handleChallenge(LongString challenge, String username, String password) { round++; if (round == 1) { return LongStringHelper.asLongString(username); } else { return LongStringHelper.asLongString("My password is " + password); } } public static class CRDemoSaslConfig implements SaslConfig { @Override public SaslMechanism getSaslMechanism(String[] mechanisms) { if (Arrays.asList(mechanisms).contains(NAME)) { return new CRDemoMechanism(); } else { return null; } } } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/ChannelManager.java000066400000000000000000000255411316117667700304760ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl; import com.rabbitmq.client.ConnectionFactory; import com.rabbitmq.client.MetricsCollector; import com.rabbitmq.client.NoOpMetricsCollector; import com.rabbitmq.client.ShutdownSignalException; import com.rabbitmq.utility.IntAllocator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.concurrent.*; /** * Manages a set of channels, indexed by channel number (1.._channelMax). */ public class ChannelManager { private static final Logger LOGGER = LoggerFactory.getLogger(ChannelManager.class); /** Monitor for _channelMap and channelNumberAllocator */ private final Object monitor = new Object(); /** Mapping from 1.._channelMax to {@link ChannelN} instance */ private final Map _channelMap = new HashMap(); private final IntAllocator channelNumberAllocator; private final ConsumerWorkService workService; private final Set shutdownSet = new HashSet(); /** Maximum channel number available on this connection. */ private final int _channelMax; private ExecutorService shutdownExecutor; private final ThreadFactory threadFactory; private int channelShutdownTimeout = (int) ((ConnectionFactory.DEFAULT_HEARTBEAT * AMQConnection.CHANNEL_SHUTDOWN_TIMEOUT_MULTIPLIER) * 1000); protected final MetricsCollector metricsCollector; public int getChannelMax(){ return _channelMax; } public ChannelManager(ConsumerWorkService workService, int channelMax) { this(workService, channelMax, Executors.defaultThreadFactory()); } public ChannelManager(ConsumerWorkService workService, int channelMax, ThreadFactory threadFactory) { this(workService, channelMax, threadFactory, new NoOpMetricsCollector()); } public ChannelManager(ConsumerWorkService workService, int channelMax, ThreadFactory threadFactory, MetricsCollector metricsCollector) { if (channelMax == 0) { // The framing encoding only allows for unsigned 16-bit integers // for the channel number channelMax = (1 << 16) - 1; } _channelMax = channelMax; channelNumberAllocator = new IntAllocator(1, channelMax); this.workService = workService; this.threadFactory = threadFactory; this.metricsCollector = metricsCollector; } /** * Looks up a channel on this connection. * @param channelNumber the number of the required channel * @return the channel on this connection with number channelNumber * @throws UnknownChannelException if there is no channel with number channelNumber on this connection */ public ChannelN getChannel(int channelNumber) { synchronized (this.monitor) { ChannelN ch = _channelMap.get(channelNumber); if(ch == null) throw new UnknownChannelException(channelNumber); return ch; } } /** * Handle shutdown. All the managed {@link com.rabbitmq.client.Channel Channel}s are shutdown. * @param signal reason for shutdown */ public void handleSignal(final ShutdownSignalException signal) { Set channels; synchronized(this.monitor) { channels = new HashSet(_channelMap.values()); } for (final ChannelN channel : channels) { releaseChannelNumber(channel); // async shutdown if possible // see https://github.com/rabbitmq/rabbitmq-java-client/issues/194 Runnable channelShutdownRunnable = new Runnable() { @Override public void run() { channel.processShutdownSignal(signal, true, true); } }; if(this.shutdownExecutor == null) { channelShutdownRunnable.run(); } else { Future channelShutdownTask = this.shutdownExecutor.submit(channelShutdownRunnable); try { channelShutdownTask.get(channelShutdownTimeout, TimeUnit.MILLISECONDS); } catch (Exception e) { LOGGER.warn("Couldn't properly close channel {} on shutdown after waiting for {} ms", channel.getChannelNumber(), channelShutdownTimeout); channelShutdownTask.cancel(true); } } shutdownSet.add(channel.getShutdownLatch()); channel.notifyListeners(); } scheduleShutdownProcessing(); } private void scheduleShutdownProcessing() { final Set sdSet = new HashSet(shutdownSet); final ConsumerWorkService ssWorkService = workService; Runnable target = new Runnable() { @Override public void run() { for (CountDownLatch latch : sdSet) { try { int shutdownTimeout = ssWorkService.getShutdownTimeout(); if (shutdownTimeout == 0) latch.await(); else latch.await(shutdownTimeout, TimeUnit.MILLISECONDS); } catch (Throwable e) { /*ignored*/ } } ssWorkService.shutdown(); } }; if(this.shutdownExecutor != null) { shutdownExecutor.execute(target); } else { Thread shutdownThread = Environment.newThread(threadFactory, target, "ConsumerWorkService shutdown monitor", true); shutdownThread.start(); } } public ChannelN createChannel(AMQConnection connection) throws IOException { ChannelN ch; synchronized (this.monitor) { int channelNumber = channelNumberAllocator.allocate(); if (channelNumber == -1) { return null; } else { ch = addNewChannel(connection, channelNumber); } } ch.open(); // now that it's been safely added return ch; } public ChannelN createChannel(AMQConnection connection, int channelNumber) throws IOException { ChannelN ch; synchronized (this.monitor) { if (channelNumberAllocator.reserve(channelNumber)) { ch = addNewChannel(connection, channelNumber); } else { return null; } } ch.open(); // now that it's been safely added return ch; } private ChannelN addNewChannel(AMQConnection connection, int channelNumber) { if (_channelMap.containsKey(channelNumber)) { // That number's already allocated! Can't do it // This should never happen unless something has gone // badly wrong with our implementation. throw new IllegalStateException("We have attempted to " + "create a channel with a number that is already in " + "use. This should never happen. " + "Please report this as a bug."); } ChannelN ch = instantiateChannel(connection, channelNumber, this.workService); _channelMap.put(ch.getChannelNumber(), ch); return ch; } protected ChannelN instantiateChannel(AMQConnection connection, int channelNumber, ConsumerWorkService workService) { return new ChannelN(connection, channelNumber, workService, this.metricsCollector); } /** * Remove the channel from the channel map and free the number for re-use. * This method must be safe to call multiple times on the same channel. If * it is not then things go badly wrong. */ public void releaseChannelNumber(ChannelN channel) { // Warning, here be dragons. Not great big ones, but little baby ones // which will nibble on your toes and occasionally trip you up when // you least expect it. (Pixies? HP2) // Basically, there's a race that can end us up here. It almost never // happens, but it's easier to repair it when it does than prevent it // from happening in the first place. // If we end up doing a Channel.close in one thread and a Channel.open // with the same channel number in another, the two can overlap in such // a way as to cause disconnectChannel on the old channel to try to // remove the new one. Ideally we would fix this race at the source, // but it's much easier to just catch it here. synchronized (this.monitor) { int channelNumber = channel.getChannelNumber(); ChannelN existing = _channelMap.remove(channelNumber); // Nothing to do here. Move along. if (existing == null) return; // Oops, we've gone and stomped on someone else's channel. Put it // back and pretend we didn't touch it. else if (existing != channel) { _channelMap.put(channelNumber, existing); return; } channelNumberAllocator.free(channelNumber); } } public ExecutorService getShutdownExecutor() { return shutdownExecutor; } public void setShutdownExecutor(ExecutorService shutdownExecutor) { this.shutdownExecutor = shutdownExecutor; } /** * Set the shutdown timeout for channels. * This is the amount of time the manager waits for a channel to * shutdown before giving up. * Works only when the {@code shutdownExecutor} property is set. * Default to {@link com.rabbitmq.client.ConnectionFactory#DEFAULT_HEARTBEAT} + 5 % seconds * @param channelShutdownTimeout shutdown timeout in milliseconds */ public void setChannelShutdownTimeout(int channelShutdownTimeout) { this.channelShutdownTimeout = channelShutdownTimeout; } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/ChannelN.java000066400000000000000000001675201316117667700273250ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl; import java.io.IOException; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.SortedSet; import java.util.TreeSet; import java.util.concurrent.*; import com.rabbitmq.client.ConfirmCallback; import com.rabbitmq.client.*; import com.rabbitmq.client.AMQP.BasicProperties; import com.rabbitmq.client.Method; import com.rabbitmq.client.impl.AMQImpl.Basic; import com.rabbitmq.client.impl.AMQImpl.Channel; import com.rabbitmq.client.impl.AMQImpl.Confirm; import com.rabbitmq.client.impl.AMQImpl.Exchange; import com.rabbitmq.client.impl.AMQImpl.Queue; import com.rabbitmq.client.impl.AMQImpl.Tx; import com.rabbitmq.utility.Utility; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Main interface to AMQP protocol functionality. Public API - * Implementation of all AMQChannels except channel zero. *

* To open a channel, *

 * {@link Connection} conn = ...;
 * {@link ChannelN} ch1 = conn.{@link Connection#createChannel createChannel}();
 * 
*/ public class ChannelN extends AMQChannel implements com.rabbitmq.client.Channel { private static final String UNSPECIFIED_OUT_OF_BAND = ""; private static final Logger LOGGER = LoggerFactory.getLogger(ChannelN.class); /** Map from consumer tag to {@link Consumer} instance. *

* Note that, in general, this map should ONLY ever be accessed * from the connection's reader thread. We go to some pains to * ensure this is the case - see the use of * BlockingRpcContinuation to inject code into the reader thread * in basicConsume and basicCancel. */ private final Map _consumers = Collections.synchronizedMap(new HashMap()); /* All listeners collections are in CopyOnWriteArrayList objects */ /** The ReturnListener collection. */ private final Collection returnListeners = new CopyOnWriteArrayList(); /** The ConfirmListener collection. */ private final Collection confirmListeners = new CopyOnWriteArrayList(); /** Sequence number of next published message requiring confirmation.*/ private long nextPublishSeqNo = 0L; /** The current default consumer, or null if there is none. */ private volatile Consumer defaultConsumer = null; /** Dispatcher of consumer work for this channel */ private final ConsumerDispatcher dispatcher; /** Future boolean for shutting down */ private volatile CountDownLatch finishedShutdownFlag = null; /** Set of currently unconfirmed messages (i.e. messages that have * not been ack'd or nack'd by the server yet. */ private final SortedSet unconfirmedSet = Collections.synchronizedSortedSet(new TreeSet()); /** Whether any nacks have been received since the last waitForConfirms(). */ private volatile boolean onlyAcksReceived = true; private final MetricsCollector metricsCollector; /** * Construct a new channel on the given connection with the given * channel number. Usually not called directly - call * Connection.createChannel instead. * @see Connection#createChannel * @param connection The connection associated with this channel * @param channelNumber The channel number to be associated with this channel * @param workService service for managing this channel's consumer callbacks */ public ChannelN(AMQConnection connection, int channelNumber, ConsumerWorkService workService) { this(connection, channelNumber, workService, new NoOpMetricsCollector()); } /** * Construct a new channel on the given connection with the given * channel number. Usually not called directly - call * Connection.createChannel instead. * @see Connection#createChannel * @param connection The connection associated with this channel * @param channelNumber The channel number to be associated with this channel * @param workService service for managing this channel's consumer callbacks * @param metricsCollector service for managing metrics */ public ChannelN(AMQConnection connection, int channelNumber, ConsumerWorkService workService, MetricsCollector metricsCollector) { super(connection, channelNumber); this.dispatcher = new ConsumerDispatcher(connection, this, workService); this.metricsCollector = metricsCollector; } /** * Package method: open the channel. * This is only called from {@link ChannelManager}. * @throws IOException if any problem is encountered */ public void open() throws IOException { // wait for the Channel.OpenOk response, and ignore it exnWrappingRpc(new Channel.Open(UNSPECIFIED_OUT_OF_BAND)); } @Override public void addReturnListener(ReturnListener listener) { returnListeners.add(listener); } @Override public ReturnListener addReturnListener(ReturnCallback returnCallback) { ReturnListener returnListener = (replyCode, replyText, exchange, routingKey, properties, body) -> returnCallback.handle(new Return( replyCode, replyText, exchange, routingKey, properties, body )); this.addReturnListener(returnListener); return returnListener; } @Override public boolean removeReturnListener(ReturnListener listener) { return returnListeners.remove(listener); } @Override public void clearReturnListeners() { returnListeners.clear(); } @Override public void addConfirmListener(ConfirmListener listener) { confirmListeners.add(listener); } @Override public ConfirmListener addConfirmListener(ConfirmCallback ackCallback, ConfirmCallback nackCallback) { ConfirmListener confirmListener = new ConfirmListener() { @Override public void handleAck(long deliveryTag, boolean multiple) throws IOException { ackCallback.handle(deliveryTag, multiple); } @Override public void handleNack(long deliveryTag, boolean multiple) throws IOException { nackCallback.handle(deliveryTag, multiple); } }; this.addConfirmListener(confirmListener); return confirmListener; } @Override public boolean removeConfirmListener(ConfirmListener listener) { return confirmListeners.remove(listener); } @Override public void clearConfirmListeners() { confirmListeners.clear(); } /** {@inheritDoc} */ @Override public boolean waitForConfirms() throws InterruptedException { boolean confirms = false; try { confirms = waitForConfirms(0L); } catch (TimeoutException e) { } return confirms; } /** {@inheritDoc} */ @Override public boolean waitForConfirms(long timeout) throws InterruptedException, TimeoutException { if (nextPublishSeqNo == 0L) throw new IllegalStateException("Confirms not selected"); long startTime = System.currentTimeMillis(); synchronized (unconfirmedSet) { while (true) { if (getCloseReason() != null) { throw Utility.fixStackTrace(getCloseReason()); } if (unconfirmedSet.isEmpty()) { boolean aux = onlyAcksReceived; onlyAcksReceived = true; return aux; } if (timeout == 0L) { unconfirmedSet.wait(); } else { long elapsed = System.currentTimeMillis() - startTime; if (timeout > elapsed) { unconfirmedSet.wait(timeout - elapsed); } else { throw new TimeoutException(); } } } } } /** {@inheritDoc} */ @Override public void waitForConfirmsOrDie() throws IOException, InterruptedException { try { waitForConfirmsOrDie(0L); } catch (TimeoutException e) { } } /** {@inheritDoc} */ @Override public void waitForConfirmsOrDie(long timeout) throws IOException, InterruptedException, TimeoutException { try { if (!waitForConfirms(timeout)) { close(AMQP.REPLY_SUCCESS, "NACKS RECEIVED", true, null, false); throw new IOException("nacks received"); } } catch (TimeoutException e) { close(AMQP.PRECONDITION_FAILED, "TIMEOUT WAITING FOR ACK"); throw(e); } } /** Returns the current default consumer. */ @Override public Consumer getDefaultConsumer() { return defaultConsumer; } /** * Sets the current default consumer. * A null argument is interpreted to mean "do not use a default consumer". */ @Override public void setDefaultConsumer(Consumer consumer) { defaultConsumer = consumer; } /** * Sends a ShutdownSignal to all active consumers. * Idempotent. * @param signal an exception signalling channel shutdown */ private void broadcastShutdownSignal(ShutdownSignalException signal) { this.finishedShutdownFlag = this.dispatcher.handleShutdownSignal(Utility.copy(_consumers), signal); } /** * Start to shutdown -- defer rest of processing until ready */ private void startProcessShutdownSignal(ShutdownSignalException signal, boolean ignoreClosed, boolean notifyRpc) { super.processShutdownSignal(signal, ignoreClosed, notifyRpc); } /** * Finish shutdown processing -- idempotent */ private void finishProcessShutdownSignal() { this.dispatcher.quiesce(); broadcastShutdownSignal(getCloseReason()); synchronized (unconfirmedSet) { unconfirmedSet.notifyAll(); } } /** * Protected API - overridden to quiesce consumer work and broadcast the signal * to all consumers after calling the superclass's method. */ @Override public void processShutdownSignal(ShutdownSignalException signal, boolean ignoreClosed, boolean notifyRpc) { startProcessShutdownSignal(signal, ignoreClosed, notifyRpc); finishProcessShutdownSignal(); } CountDownLatch getShutdownLatch() { return this.finishedShutdownFlag; } private void releaseChannel() { getConnection().disconnectChannel(this); } /** * Protected API - Filters the inbound command stream, processing * Basic.Deliver, Basic.Return and Channel.Close specially. If * we're in quiescing mode, all inbound commands are ignored, * except for Channel.Close and Channel.CloseOk. */ @Override public boolean processAsync(Command command) throws IOException { // If we are isOpen(), then we process commands normally. // // If we are not, however, then we are in a quiescing, or // shutting-down state as the result of an application // decision to close this channel, and we are to discard all // incoming commands except for a close and close-ok. Method method = command.getMethod(); // we deal with channel.close in the same way, regardless if (method instanceof Channel.Close) { asyncShutdown(command); return true; } if (isOpen()) { // We're in normal running mode. if (method instanceof Basic.Deliver) { processDelivery(command, (Basic.Deliver) method); return true; } else if (method instanceof Basic.Return) { callReturnListeners(command, (Basic.Return) method); return true; } else if (method instanceof Channel.Flow) { Channel.Flow channelFlow = (Channel.Flow) method; synchronized (_channelMutex) { _blockContent = !channelFlow.getActive(); transmit(new Channel.FlowOk(!_blockContent)); _channelMutex.notifyAll(); } return true; } else if (method instanceof Basic.Ack) { Basic.Ack ack = (Basic.Ack) method; callConfirmListeners(command, ack); handleAckNack(ack.getDeliveryTag(), ack.getMultiple(), false); return true; } else if (method instanceof Basic.Nack) { Basic.Nack nack = (Basic.Nack) method; callConfirmListeners(command, nack); handleAckNack(nack.getDeliveryTag(), nack.getMultiple(), true); return true; } else if (method instanceof Basic.RecoverOk) { for (Map.Entry entry : Utility.copy(_consumers).entrySet()) { this.dispatcher.handleRecoverOk(entry.getValue(), entry.getKey()); } // Unlike all the other cases we still want this RecoverOk to // be handled by whichever RPC continuation invoked Recover, // so return false return false; } else if (method instanceof Basic.Cancel) { Basic.Cancel m = (Basic.Cancel)method; String consumerTag = m.getConsumerTag(); Consumer callback = _consumers.remove(consumerTag); if (callback == null) { callback = defaultConsumer; } if (callback != null) { try { this.dispatcher.handleCancel(callback, consumerTag); } catch (Throwable ex) { getConnection().getExceptionHandler().handleConsumerException(this, ex, callback, consumerTag, "handleCancel"); } } return true; } else { return false; } } else { // We're in quiescing mode == !isOpen() if (method instanceof Channel.CloseOk) { // We're quiescing, and we see a channel.close-ok: // this is our signal to leave quiescing mode and // finally shut down for good. Let it be handled as an // RPC reply one final time by returning false. return false; } else { // We're quiescing, and this inbound command should be // discarded as per spec. "Consume" it by returning // true. return true; } } } protected void processDelivery(Command command, Basic.Deliver method) { Basic.Deliver m = method; Consumer callback = _consumers.get(m.getConsumerTag()); if (callback == null) { if (defaultConsumer == null) { // No handler set. We should blow up as this message // needs acking, just dropping it is not enough. See bug // 22587 for discussion. throw new IllegalStateException("Unsolicited delivery -" + " see Channel.setDefaultConsumer to handle this" + " case."); } else { callback = defaultConsumer; } } Envelope envelope = new Envelope(m.getDeliveryTag(), m.getRedelivered(), m.getExchange(), m.getRoutingKey()); try { // call metricsCollector before the dispatching (which is async anyway) // this way, the message is inside the stats before it is handled // in case a manual ack in the callback, the stats will be able to record the ack metricsCollector.consumedMessage(this, m.getDeliveryTag(), m.getConsumerTag()); this.dispatcher.handleDelivery(callback, m.getConsumerTag(), envelope, (BasicProperties) command.getContentHeader(), command.getContentBody()); } catch (Throwable ex) { getConnection().getExceptionHandler().handleConsumerException(this, ex, callback, m.getConsumerTag(), "handleDelivery"); } } private void callReturnListeners(Command command, Basic.Return basicReturn) { try { for (ReturnListener l : this.returnListeners) { l.handleReturn(basicReturn.getReplyCode(), basicReturn.getReplyText(), basicReturn.getExchange(), basicReturn.getRoutingKey(), (BasicProperties) command.getContentHeader(), command.getContentBody()); } } catch (Throwable ex) { getConnection().getExceptionHandler().handleReturnListenerException(this, ex); } } private void callConfirmListeners(@SuppressWarnings("unused") Command command, Basic.Ack ack) { try { for (ConfirmListener l : this.confirmListeners) { l.handleAck(ack.getDeliveryTag(), ack.getMultiple()); } } catch (Throwable ex) { getConnection().getExceptionHandler().handleConfirmListenerException(this, ex); } } private void callConfirmListeners(@SuppressWarnings("unused") Command command, Basic.Nack nack) { try { for (ConfirmListener l : this.confirmListeners) { l.handleNack(nack.getDeliveryTag(), nack.getMultiple()); } } catch (Throwable ex) { getConnection().getExceptionHandler().handleConfirmListenerException(this, ex); } } private void asyncShutdown(Command command) throws IOException { ShutdownSignalException signal = new ShutdownSignalException(false, false, command.getMethod(), this); synchronized (_channelMutex) { try { processShutdownSignal(signal, true, false); quiescingTransmit(new Channel.CloseOk()); } finally { releaseChannel(); notifyOutstandingRpc(signal); } } notifyListeners(); } /** Public API - {@inheritDoc} */ @Override public void close() throws IOException, TimeoutException { close(AMQP.REPLY_SUCCESS, "OK"); } /** Public API - {@inheritDoc} */ @Override public void close(int closeCode, String closeMessage) throws IOException, TimeoutException { close(closeCode, closeMessage, true, null, false); } /** Public API - {@inheritDoc} */ @Override public void abort() throws IOException { abort(AMQP.REPLY_SUCCESS, "OK"); } /** Public API - {@inheritDoc} */ @Override public void abort(int closeCode, String closeMessage) throws IOException { try { close(closeCode, closeMessage, true, null, true); } catch (IOException _e) { /* ignored */ } catch (TimeoutException _e) { /* ignored */ } } /** * Protected API - Close channel with code and message, indicating * the source of the closure and a causing exception (null if * none). * @param closeCode the close code (See under "Reply Codes" in the AMQP specification) * @param closeMessage a message indicating the reason for closing the connection * @param initiatedByApplication true if this comes from an API call, false otherwise * @param cause exception triggering close * @param abort true if we should close and ignore errors * @throws IOException if an error is encountered */ protected void close(int closeCode, String closeMessage, boolean initiatedByApplication, Throwable cause, boolean abort) throws IOException, TimeoutException { // First, notify all our dependents that we are shutting down. // This clears isOpen(), so no further work from the // application side will be accepted, and any inbound commands // will be discarded (unless they're channel.close-oks). Channel.Close reason = new Channel.Close(closeCode, closeMessage, 0, 0); ShutdownSignalException signal = new ShutdownSignalException(false, initiatedByApplication, reason, this); if (cause != null) { signal.initCause(cause); } BlockingRpcContinuation k = new BlockingRpcContinuation(){ @Override public AMQCommand transformReply(AMQCommand command) { ChannelN.this.finishProcessShutdownSignal(); return command; }}; boolean notify = false; try { // Synchronize the block below to avoid race conditions in case // connnection wants to send Connection-CloseOK synchronized (_channelMutex) { startProcessShutdownSignal(signal, !initiatedByApplication, true); quiescingRpc(reason, k); } // Now that we're in quiescing state, channel.close was sent and // we wait for the reply. We ignore the result. // (It's NOT always close-ok.) notify = true; // do not wait indefinitely k.getReply(10000); } catch (TimeoutException ise) { if (!abort) throw ise; } catch (ShutdownSignalException sse) { if (!abort) throw sse; } catch (IOException ioe) { if (!abort) throw ioe; } finally { if (abort || notify) { // Now we know everything's been cleaned up and there should // be no more surprises arriving on the wire. Release the // channel number, and dissociate this ChannelN instance from // our connection so that any further frames inbound on this // channel can be caught as the errors they are. releaseChannel(); notifyListeners(); } } } /** Public API - {@inheritDoc} */ @Override public void basicQos(int prefetchSize, int prefetchCount, boolean global) throws IOException { exnWrappingRpc(new Basic.Qos(prefetchSize, prefetchCount, global)); } /** Public API - {@inheritDoc} */ @Override public void basicQos(int prefetchCount, boolean global) throws IOException { basicQos(0, prefetchCount, global); } /** Public API - {@inheritDoc} */ @Override public void basicQos(int prefetchCount) throws IOException { basicQos(0, prefetchCount, false); } /** Public API - {@inheritDoc} */ @Override public void basicPublish(String exchange, String routingKey, BasicProperties props, byte[] body) throws IOException { basicPublish(exchange, routingKey, false, props, body); } /** Public API - {@inheritDoc} */ @Override public void basicPublish(String exchange, String routingKey, boolean mandatory, BasicProperties props, byte[] body) throws IOException { basicPublish(exchange, routingKey, mandatory, false, props, body); } /** Public API - {@inheritDoc} */ @Override public void basicPublish(String exchange, String routingKey, boolean mandatory, boolean immediate, BasicProperties props, byte[] body) throws IOException { if (nextPublishSeqNo > 0) { unconfirmedSet.add(getNextPublishSeqNo()); nextPublishSeqNo++; } BasicProperties useProps = props; if (props == null) { useProps = MessageProperties.MINIMAL_BASIC; } transmit(new AMQCommand(new Basic.Publish.Builder() .exchange(exchange) .routingKey(routingKey) .mandatory(mandatory) .immediate(immediate) .build(), useProps, body)); metricsCollector.basicPublish(this); } /** Public API - {@inheritDoc} */ @Override public Exchange.DeclareOk exchangeDeclare(String exchange, String type, boolean durable, boolean autoDelete, Map arguments) throws IOException { return exchangeDeclare(exchange, type, durable, autoDelete, false, arguments); } /** Public API - {@inheritDoc} */ @Override public Exchange.DeclareOk exchangeDeclare(String exchange, BuiltinExchangeType type, boolean durable, boolean autoDelete, Map arguments) throws IOException { return exchangeDeclare(exchange, type.getType(), durable, autoDelete, arguments); } @Override public void exchangeDeclareNoWait(String exchange, String type, boolean durable, boolean autoDelete, boolean internal, Map arguments) throws IOException { transmit(new AMQCommand(new Exchange.Declare.Builder() .exchange(exchange) .type(type) .durable(durable) .autoDelete(autoDelete) .internal(internal) .arguments(arguments) .passive(false) .nowait(true) .build())); } @Override public void exchangeDeclareNoWait(String exchange, BuiltinExchangeType type, boolean durable, boolean autoDelete, boolean internal, Map arguments) throws IOException { exchangeDeclareNoWait(exchange, type.getType(), durable, autoDelete, internal, arguments); } /** Public API - {@inheritDoc} */ @Override public Exchange.DeclareOk exchangeDeclare(String exchange, String type, boolean durable, boolean autoDelete, boolean internal, Map arguments) throws IOException { return (Exchange.DeclareOk) exnWrappingRpc(new Exchange.Declare.Builder() .exchange(exchange) .type(type) .durable(durable) .autoDelete(autoDelete) .internal(internal) .arguments(arguments) .build()) .getMethod(); } /** Public API - {@inheritDoc} */ @Override public Exchange.DeclareOk exchangeDeclare(String exchange, BuiltinExchangeType type, boolean durable, boolean autoDelete, boolean internal, Map arguments) throws IOException { return exchangeDeclare(exchange, type.getType(), durable, autoDelete, internal, arguments); } /** Public API - {@inheritDoc} */ @Override public Exchange.DeclareOk exchangeDeclare(String exchange, String type, boolean durable) throws IOException { return exchangeDeclare(exchange, type, durable, false, null); } /** Public API - {@inheritDoc} */ @Override public Exchange.DeclareOk exchangeDeclare(String exchange, BuiltinExchangeType type, boolean durable) throws IOException { return exchangeDeclare(exchange, type.getType(), durable); } /** Public API - {@inheritDoc} */ @Override public Exchange.DeclareOk exchangeDeclare(String exchange, String type) throws IOException { return exchangeDeclare(exchange, type, false, false, null); } /** Public API - {@inheritDoc} */ @Override public Exchange.DeclareOk exchangeDeclare(String exchange, BuiltinExchangeType type) throws IOException { return exchangeDeclare(exchange, type.getType()); } /** Public API - {@inheritDoc} */ @Override public Exchange.DeclareOk exchangeDeclarePassive(String exchange) throws IOException { return (Exchange.DeclareOk) exnWrappingRpc(new Exchange.Declare.Builder() .exchange(exchange) .type("") .passive() .build()) .getMethod(); } /** Public API - {@inheritDoc} */ @Override public Exchange.DeleteOk exchangeDelete(String exchange, boolean ifUnused) throws IOException { return (Exchange.DeleteOk) exnWrappingRpc(new Exchange.Delete.Builder() .exchange(exchange) .ifUnused(ifUnused) .build()) .getMethod(); } /** Public API - {@inheritDoc} */ @Override public void exchangeDeleteNoWait(String exchange, boolean ifUnused) throws IOException { transmit(new AMQCommand(new Exchange.Delete.Builder() .exchange(exchange) .ifUnused(ifUnused) .nowait(true) .build())); } /** Public API - {@inheritDoc} */ @Override public Exchange.DeleteOk exchangeDelete(String exchange) throws IOException { return exchangeDelete(exchange, false); } /** Public API - {@inheritDoc} */ @Override public Exchange.BindOk exchangeBind(String destination, String source, String routingKey, Map arguments) throws IOException { return (Exchange.BindOk) exnWrappingRpc(new Exchange.Bind.Builder() .destination(destination) .source(source) .routingKey(routingKey) .arguments(arguments) .build()) .getMethod(); } /** Public API - {@inheritDoc} */ @Override public void exchangeBindNoWait(String destination, String source, String routingKey, Map arguments) throws IOException { transmit(new AMQCommand(new Exchange.Bind.Builder() .destination(destination) .source(source) .routingKey(routingKey) .arguments(arguments) .nowait(true) .build())); } /** Public API - {@inheritDoc} */ @Override public Exchange.BindOk exchangeBind(String destination, String source, String routingKey) throws IOException { return exchangeBind(destination, source, routingKey, null); } /** Public API - {@inheritDoc} */ @Override public Exchange.UnbindOk exchangeUnbind(String destination, String source, String routingKey, Map arguments) throws IOException { return (Exchange.UnbindOk) exnWrappingRpc(new Exchange.Unbind.Builder() .destination(destination) .source(source) .routingKey(routingKey) .arguments(arguments) .build()) .getMethod(); } /** Public API - {@inheritDoc} */ @Override public Exchange.UnbindOk exchangeUnbind(String destination, String source, String routingKey) throws IOException { return exchangeUnbind(destination, source, routingKey, null); } /** Public API - {@inheritDoc} */ @Override public void exchangeUnbindNoWait(String destination, String source, String routingKey, Map arguments) throws IOException { transmit(new AMQCommand(new Exchange.Unbind.Builder() .destination(destination) .source(source) .routingKey(routingKey) .arguments(arguments) .nowait(true) .build())); } /** Public API - {@inheritDoc} */ @Override public Queue.DeclareOk queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete, Map arguments) throws IOException { validateQueueNameLength(queue); return (Queue.DeclareOk) exnWrappingRpc(new Queue.Declare.Builder() .queue(queue) .durable(durable) .exclusive(exclusive) .autoDelete(autoDelete) .arguments(arguments) .build()) .getMethod(); } /** Public API - {@inheritDoc} */ @Override public com.rabbitmq.client.AMQP.Queue.DeclareOk queueDeclare() throws IOException { return queueDeclare("", false, true, true, null); } /** Public API - {@inheritDoc} */ @Override public void queueDeclareNoWait(String queue, boolean durable, boolean exclusive, boolean autoDelete, Map arguments) throws IOException { validateQueueNameLength(queue); transmit(new AMQCommand(new Queue.Declare.Builder() .queue(queue) .durable(durable) .exclusive(exclusive) .autoDelete(autoDelete) .arguments(arguments) .passive(false) .nowait(true) .build())); } /** Public API - {@inheritDoc} */ @Override public Queue.DeclareOk queueDeclarePassive(String queue) throws IOException { validateQueueNameLength(queue); return (Queue.DeclareOk) exnWrappingRpc(new Queue.Declare.Builder() .queue(queue) .passive() .exclusive() .autoDelete() .build()) .getMethod(); } /** Public API - {@inheritDoc} */ @Override public long messageCount(String queue) throws IOException { Queue.DeclareOk ok = queueDeclarePassive(queue); return ok.getMessageCount(); } /** Public API - {@inheritDoc} */ @Override public long consumerCount(String queue) throws IOException { Queue.DeclareOk ok = queueDeclarePassive(queue); return ok.getConsumerCount(); } /** Public API - {@inheritDoc} */ @Override public Queue.DeleteOk queueDelete(String queue, boolean ifUnused, boolean ifEmpty) throws IOException { validateQueueNameLength(queue); return (Queue.DeleteOk) exnWrappingRpc(new Queue.Delete.Builder() .queue(queue) .ifUnused(ifUnused) .ifEmpty(ifEmpty) .build()) .getMethod(); } @Override public void queueDeleteNoWait(String queue, boolean ifUnused, boolean ifEmpty) throws IOException { validateQueueNameLength(queue); transmit(new AMQCommand(new Queue.Delete.Builder() .queue(queue) .ifUnused(ifUnused) .ifEmpty(ifEmpty) .nowait(true) .build())); } /** Public API - {@inheritDoc} */ @Override public Queue.DeleteOk queueDelete(String queue) throws IOException { return queueDelete(queue, false, false); } /** Public API - {@inheritDoc} */ @Override public Queue.BindOk queueBind(String queue, String exchange, String routingKey, Map arguments) throws IOException { validateQueueNameLength(queue); return (Queue.BindOk) exnWrappingRpc(new Queue.Bind.Builder() .queue(queue) .exchange(exchange) .routingKey(routingKey) .arguments(arguments) .build()) .getMethod(); } /** Public API - {@inheritDoc} */ @Override public Queue.BindOk queueBind(String queue, String exchange, String routingKey) throws IOException { return queueBind(queue, exchange, routingKey, null); } /** Public API - {@inheritDoc} */ @Override public void queueBindNoWait(String queue, String exchange, String routingKey, Map arguments) throws IOException { validateQueueNameLength(queue); transmit(new AMQCommand(new Queue.Bind.Builder() .queue(queue) .exchange(exchange) .routingKey(routingKey) .arguments(arguments) .nowait(true) .build())); } /** Public API - {@inheritDoc} */ @Override public Queue.UnbindOk queueUnbind(String queue, String exchange, String routingKey, Map arguments) throws IOException { validateQueueNameLength(queue); return (Queue.UnbindOk) exnWrappingRpc(new Queue.Unbind.Builder() .queue(queue) .exchange(exchange) .routingKey(routingKey) .arguments(arguments) .build()) .getMethod(); } /** Public API - {@inheritDoc} */ @Override public Queue.PurgeOk queuePurge(String queue) throws IOException { validateQueueNameLength(queue); return (Queue.PurgeOk) exnWrappingRpc(new Queue.Purge.Builder() .queue(queue) .build()) .getMethod(); } /** Public API - {@inheritDoc} */ @Override public Queue.UnbindOk queueUnbind(String queue, String exchange, String routingKey) throws IOException { return queueUnbind(queue, exchange, routingKey, null); } /** Public API - {@inheritDoc} */ @Override public GetResponse basicGet(String queue, boolean autoAck) throws IOException { validateQueueNameLength(queue); AMQCommand replyCommand = exnWrappingRpc(new Basic.Get.Builder() .queue(queue) .noAck(autoAck) .build()); Method method = replyCommand.getMethod(); if (method instanceof Basic.GetOk) { Basic.GetOk getOk = (Basic.GetOk)method; Envelope envelope = new Envelope(getOk.getDeliveryTag(), getOk.getRedelivered(), getOk.getExchange(), getOk.getRoutingKey()); BasicProperties props = (BasicProperties)replyCommand.getContentHeader(); byte[] body = replyCommand.getContentBody(); int messageCount = getOk.getMessageCount(); metricsCollector.consumedMessage(this, getOk.getDeliveryTag(), autoAck); return new GetResponse(envelope, props, body, messageCount); } else if (method instanceof Basic.GetEmpty) { return null; } else { throw new UnexpectedMethodError(method); } } /** Public API - {@inheritDoc} */ @Override public void basicAck(long deliveryTag, boolean multiple) throws IOException { transmit(new Basic.Ack(deliveryTag, multiple)); metricsCollector.basicAck(this, deliveryTag, multiple); } /** Public API - {@inheritDoc} */ @Override public void basicNack(long deliveryTag, boolean multiple, boolean requeue) throws IOException { transmit(new Basic.Nack(deliveryTag, multiple, requeue)); metricsCollector.basicNack(this, deliveryTag); } /** Public API - {@inheritDoc} */ @Override public void basicReject(long deliveryTag, boolean requeue) throws IOException { transmit(new Basic.Reject(deliveryTag, requeue)); metricsCollector.basicReject(this, deliveryTag); } /** Public API - {@inheritDoc} */ @Override public String basicConsume(String queue, Consumer callback) throws IOException { return basicConsume(queue, false, callback); } /** Public API - {@inheritDoc} */ @Override public String basicConsume(String queue, DeliverCallback deliverCallback, CancelCallback cancelCallback) throws IOException { return basicConsume(queue, consumerFromDeliverCancelCallbacks(deliverCallback, cancelCallback)); } /** Public API - {@inheritDoc} */ @Override public String basicConsume(String queue, DeliverCallback deliverCallback, ConsumerShutdownSignalCallback shutdownSignalCallback) throws IOException { return basicConsume(queue, consumerFromDeliverShutdownCallbacks(deliverCallback, shutdownSignalCallback)); } /** Public API - {@inheritDoc} */ @Override public String basicConsume(String queue, DeliverCallback deliverCallback, CancelCallback cancelCallback, ConsumerShutdownSignalCallback shutdownSignalCallback) throws IOException { return basicConsume(queue, consumerFromDeliverCancelShutdownCallbacks(deliverCallback, cancelCallback, shutdownSignalCallback)); } /** Public API - {@inheritDoc} */ @Override public String basicConsume(String queue, boolean autoAck, Consumer callback) throws IOException { return basicConsume(queue, autoAck, "", callback); } /** Public API - {@inheritDoc} */ @Override public String basicConsume(String queue, boolean autoAck, DeliverCallback deliverCallback, ConsumerShutdownSignalCallback shutdownSignalCallback) throws IOException { return basicConsume(queue, autoAck, "", consumerFromDeliverShutdownCallbacks(deliverCallback, shutdownSignalCallback)); } /** Public API - {@inheritDoc} */ @Override public String basicConsume(String queue, boolean autoAck, DeliverCallback deliverCallback, CancelCallback cancelCallback) throws IOException { return basicConsume(queue, autoAck, "", consumerFromDeliverCancelCallbacks(deliverCallback, cancelCallback)); } @Override public String basicConsume(String queue, boolean autoAck, DeliverCallback deliverCallback, CancelCallback cancelCallback, ConsumerShutdownSignalCallback shutdownSignalCallback) throws IOException { return basicConsume(queue, autoAck, "", consumerFromDeliverCancelShutdownCallbacks(deliverCallback, cancelCallback, shutdownSignalCallback)); } /** Public API - {@inheritDoc} */ @Override public String basicConsume(String queue, boolean autoAck, Map arguments, Consumer callback) throws IOException { return basicConsume(queue, autoAck, "", false, false, arguments, callback); } /** Public API - {@inheritDoc} */ @Override public String basicConsume(String queue, boolean autoAck, Map arguments, DeliverCallback deliverCallback, CancelCallback cancelCallback) throws IOException { return basicConsume(queue, autoAck, "", false, false, arguments, consumerFromDeliverCancelCallbacks(deliverCallback, cancelCallback)); } /** Public API - {@inheritDoc} */ @Override public String basicConsume(String queue, boolean autoAck, Map arguments, DeliverCallback deliverCallback, ConsumerShutdownSignalCallback shutdownSignalCallback) throws IOException { return basicConsume(queue, autoAck, "", false, false, arguments, consumerFromDeliverShutdownCallbacks(deliverCallback, shutdownSignalCallback)); } /** Public API - {@inheritDoc} */ @Override public String basicConsume(String queue, boolean autoAck, Map arguments, DeliverCallback deliverCallback, CancelCallback cancelCallback, ConsumerShutdownSignalCallback shutdownSignalCallback) throws IOException { return basicConsume(queue, autoAck, "", false, false, arguments, consumerFromDeliverCancelShutdownCallbacks(deliverCallback, cancelCallback, shutdownSignalCallback)); } /** Public API - {@inheritDoc} */ @Override public String basicConsume(String queue, boolean autoAck, String consumerTag, Consumer callback) throws IOException { return basicConsume(queue, autoAck, consumerTag, false, false, null, callback); } /** Public API - {@inheritDoc} */ @Override public String basicConsume(String queue, boolean autoAck, String consumerTag, DeliverCallback deliverCallback, CancelCallback cancelCallback) throws IOException { return basicConsume(queue, autoAck, consumerTag, false, false, null, consumerFromDeliverCancelCallbacks(deliverCallback, cancelCallback)); } /** Public API - {@inheritDoc} */ @Override public String basicConsume(String queue, boolean autoAck, String consumerTag, DeliverCallback deliverCallback, ConsumerShutdownSignalCallback shutdownSignalCallback) throws IOException { return basicConsume(queue, autoAck, consumerTag, false, false, null, consumerFromDeliverShutdownCallbacks(deliverCallback, shutdownSignalCallback)); } /** Public API - {@inheritDoc} */ @Override public String basicConsume(String queue, boolean autoAck, String consumerTag, DeliverCallback deliverCallback, CancelCallback cancelCallback, ConsumerShutdownSignalCallback shutdownSignalCallback) throws IOException { return basicConsume(queue, autoAck, consumerTag , false, false, null, consumerFromDeliverCancelShutdownCallbacks(deliverCallback, cancelCallback, shutdownSignalCallback)); } /** Public API - {@inheritDoc} */ @Override public String basicConsume(String queue, boolean autoAck, String consumerTag, boolean noLocal, boolean exclusive, Map arguments, DeliverCallback deliverCallback, CancelCallback cancelCallback) throws IOException { return basicConsume(queue, autoAck, consumerTag, noLocal, exclusive, arguments, consumerFromDeliverCancelCallbacks(deliverCallback, cancelCallback)); } /** Public API - {@inheritDoc} */ @Override public String basicConsume(String queue, boolean autoAck, String consumerTag, boolean noLocal, boolean exclusive, Map arguments, DeliverCallback deliverCallback, ConsumerShutdownSignalCallback shutdownSignalCallback) throws IOException { return basicConsume(queue, autoAck, consumerTag, noLocal, exclusive, arguments, consumerFromDeliverShutdownCallbacks(deliverCallback, shutdownSignalCallback)); } @Override public String basicConsume(String queue, boolean autoAck, String consumerTag, boolean noLocal, boolean exclusive, Map arguments, DeliverCallback deliverCallback, CancelCallback cancelCallback, ConsumerShutdownSignalCallback shutdownSignalCallback) throws IOException { return basicConsume(queue, autoAck, consumerTag, noLocal, exclusive, arguments, consumerFromDeliverCancelShutdownCallbacks(deliverCallback, cancelCallback, shutdownSignalCallback)); } /** Public API - {@inheritDoc} */ @Override public String basicConsume(String queue, final boolean autoAck, String consumerTag, boolean noLocal, boolean exclusive, Map arguments, final Consumer callback) throws IOException { final Method m = new Basic.Consume.Builder() .queue(queue) .consumerTag(consumerTag) .noLocal(noLocal) .noAck(autoAck) .exclusive(exclusive) .arguments(arguments) .build(); BlockingRpcContinuation k = new BlockingRpcContinuation(m) { @Override public String transformReply(AMQCommand replyCommand) { String actualConsumerTag = ((Basic.ConsumeOk) replyCommand.getMethod()).getConsumerTag(); _consumers.put(actualConsumerTag, callback); // need to register consumer in stats before it actually starts consuming metricsCollector.basicConsume(ChannelN.this, actualConsumerTag, autoAck); dispatcher.handleConsumeOk(callback, actualConsumerTag); return actualConsumerTag; } }; rpc(m, k); try { if(_rpcTimeout == NO_RPC_TIMEOUT) { return k.getReply(); } else { try { return k.getReply(_rpcTimeout); } catch (TimeoutException e) { throw wrapTimeoutException(m, e); } } } catch(ShutdownSignalException ex) { throw wrap(ex); } } private Consumer consumerFromDeliverCancelCallbacks(final DeliverCallback deliverCallback, final CancelCallback cancelCallback) { return new Consumer() { @Override public void handleConsumeOk(String consumerTag) { } @Override public void handleCancelOk(String consumerTag) { } @Override public void handleCancel(String consumerTag) throws IOException { cancelCallback.handle(consumerTag); } @Override public void handleShutdownSignal(String consumerTag, ShutdownSignalException sig) { } @Override public void handleRecoverOk(String consumerTag) { } @Override public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties, byte[] body) throws IOException { deliverCallback.handle(consumerTag, new Delivery(envelope, properties, body)); } }; } private Consumer consumerFromDeliverShutdownCallbacks(final DeliverCallback deliverCallback, final ConsumerShutdownSignalCallback shutdownSignalCallback) { return new Consumer() { @Override public void handleConsumeOk(String consumerTag) { } @Override public void handleCancelOk(String consumerTag) { } @Override public void handleCancel(String consumerTag) throws IOException { } @Override public void handleShutdownSignal(String consumerTag, ShutdownSignalException sig) { shutdownSignalCallback.handleShutdownSignal(consumerTag, sig); } @Override public void handleRecoverOk(String consumerTag) { } @Override public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties, byte[] body) throws IOException { deliverCallback.handle(consumerTag, new Delivery(envelope, properties, body)); } }; } private Consumer consumerFromDeliverCancelShutdownCallbacks(final DeliverCallback deliverCallback, final CancelCallback cancelCallback, final ConsumerShutdownSignalCallback shutdownSignalCallback) { return new Consumer() { @Override public void handleConsumeOk(String consumerTag) { } @Override public void handleCancelOk(String consumerTag) { } @Override public void handleCancel(String consumerTag) throws IOException { cancelCallback.handle(consumerTag); } @Override public void handleShutdownSignal(String consumerTag, ShutdownSignalException sig) { shutdownSignalCallback.handleShutdownSignal(consumerTag, sig); } @Override public void handleRecoverOk(String consumerTag) { } @Override public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties, byte[] body) throws IOException { deliverCallback.handle(consumerTag, new Delivery(envelope, properties, body)); } }; } /** Public API - {@inheritDoc} */ @Override public void basicCancel(final String consumerTag) throws IOException { final Consumer originalConsumer = _consumers.get(consumerTag); if (originalConsumer == null) throw new IOException("Unknown consumerTag"); final Method m = new Basic.Cancel(consumerTag, false); BlockingRpcContinuation k = new BlockingRpcContinuation(m) { @Override public Consumer transformReply(AMQCommand replyCommand) { if (!(replyCommand.getMethod() instanceof Basic.CancelOk)) LOGGER.warn("Received reply {} was not of expected method Basic.CancelOk", replyCommand.getMethod()); _consumers.remove(consumerTag); //may already have been removed dispatcher.handleCancelOk(originalConsumer, consumerTag); return originalConsumer; } }; rpc(m, k); try { if(_rpcTimeout == NO_RPC_TIMEOUT) { k.getReply(); // discard result } else { try { k.getReply(_rpcTimeout); } catch (TimeoutException e) { throw wrapTimeoutException(m, e); } } } catch(ShutdownSignalException ex) { throw wrap(ex); } metricsCollector.basicCancel(this, consumerTag); } /** Public API - {@inheritDoc} */ @Override public Basic.RecoverOk basicRecover() throws IOException { return basicRecover(true); } /** Public API - {@inheritDoc} */ @Override public Basic.RecoverOk basicRecover(boolean requeue) throws IOException { return (Basic.RecoverOk) exnWrappingRpc(new Basic.Recover(requeue)).getMethod(); } /** Public API - {@inheritDoc} */ @Override public Tx.SelectOk txSelect() throws IOException { return (Tx.SelectOk) exnWrappingRpc(new Tx.Select()).getMethod(); } /** Public API - {@inheritDoc} */ @Override public Tx.CommitOk txCommit() throws IOException { return (Tx.CommitOk) exnWrappingRpc(new Tx.Commit()).getMethod(); } /** Public API - {@inheritDoc} */ @Override public Tx.RollbackOk txRollback() throws IOException { return (Tx.RollbackOk) exnWrappingRpc(new Tx.Rollback()).getMethod(); } /** Public API - {@inheritDoc} */ @Override public Confirm.SelectOk confirmSelect() throws IOException { if (nextPublishSeqNo == 0) nextPublishSeqNo = 1; return (Confirm.SelectOk) exnWrappingRpc(new Confirm.Select(false)).getMethod(); } /** Public API - {@inheritDoc} */ @Override public long getNextPublishSeqNo() { return nextPublishSeqNo; } @Override public void asyncRpc(Method method) throws IOException { transmit(method); } @Override public AMQCommand rpc(Method method) throws IOException { return exnWrappingRpc(method); } @Override public CompletableFuture asyncCompletableRpc(Method method) throws IOException { return exnWrappingAsyncRpc(method); } @Override public void enqueueRpc(RpcContinuation k) { synchronized (_channelMutex) { super.enqueueRpc(k); dispatcher.setUnlimited(true); } } @Override protected void markRpcFinished() { synchronized (_channelMutex) { dispatcher.setUnlimited(false); } } private void handleAckNack(long seqNo, boolean multiple, boolean nack) { if (multiple) { unconfirmedSet.headSet(seqNo + 1).clear(); } else { unconfirmedSet.remove(seqNo); } synchronized (unconfirmedSet) { onlyAcksReceived = onlyAcksReceived && !nack; if (unconfirmedSet.isEmpty()) unconfirmedSet.notifyAll(); } } private static void validateQueueNameLength(String queue) { if(queue.length() > 255) { throw new IllegalArgumentException("queue name must be no more than 255 characters long"); } } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/ClientVersion.java000066400000000000000000000032141316117667700304100ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl; import java.io.IOException; import java.io.InputStream; import java.util.Properties; /** * Publicly available Client Version information */ public class ClientVersion { /** Full version string */ private static final Properties version; public static final String VERSION; static { version = new Properties(); InputStream inputStream = ClientVersion.class.getClassLoader() .getResourceAsStream("version.properties"); try { version.load(inputStream); } catch (IOException e) { } finally { try { if(inputStream != null) { inputStream.close(); } } catch (IOException e) { } } VERSION = version.getProperty("com.rabbitmq.client.version", ClientVersion.class.getPackage().getImplementationVersion()); } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/CommandAssembler.java000066400000000000000000000136031316117667700310430ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl; import java.io.IOException; import java.util.ArrayList; import java.util.List; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.UnexpectedFrameError; /** * Class responsible for piecing together a command from a series of {@link Frame}s. *

Concurrency
* This class is thread-safe, since all methods are synchronised. Callers should not * synchronise on objects of this class unless they are sole owners. * @see AMQCommand */ final class CommandAssembler { private static final byte[] EMPTY_BYTE_ARRAY = new byte[0]; /** Current state, used to decide how to handle each incoming frame. */ private enum CAState { EXPECTING_METHOD, EXPECTING_CONTENT_HEADER, EXPECTING_CONTENT_BODY, COMPLETE } private CAState state; /** The method for this command */ private Method method; /** The content header for this command */ private AMQContentHeader contentHeader; /** The fragments of this command's content body - a list of byte[] */ private final List bodyN; /** sum of the lengths of all fragments */ private int bodyLength; /** No bytes of content body not yet accumulated */ private long remainingBodyBytes; public CommandAssembler(Method method, AMQContentHeader contentHeader, byte[] body) { this.method = method; this.contentHeader = contentHeader; this.bodyN = new ArrayList(2); this.bodyLength = 0; this.remainingBodyBytes = 0; appendBodyFragment(body); if (method == null) { this.state = CAState.EXPECTING_METHOD; } else if (contentHeader == null) { this.state = method.hasContent() ? CAState.EXPECTING_CONTENT_HEADER : CAState.COMPLETE; } else { this.remainingBodyBytes = contentHeader.getBodySize() - this.bodyLength; updateContentBodyState(); } } public synchronized Method getMethod() { return this.method; } public synchronized AMQContentHeader getContentHeader() { return this.contentHeader; } /** @return true if the command is complete */ public synchronized boolean isComplete() { return (this.state == CAState.COMPLETE); } /** Decides whether more body frames are expected */ private void updateContentBodyState() { this.state = (this.remainingBodyBytes > 0) ? CAState.EXPECTING_CONTENT_BODY : CAState.COMPLETE; } private void consumeMethodFrame(Frame f) throws IOException { if (f.type == AMQP.FRAME_METHOD) { this.method = AMQImpl.readMethodFrom(f.getInputStream()); this.state = this.method.hasContent() ? CAState.EXPECTING_CONTENT_HEADER : CAState.COMPLETE; } else { throw new UnexpectedFrameError(f, AMQP.FRAME_METHOD); } } private void consumeHeaderFrame(Frame f) throws IOException { if (f.type == AMQP.FRAME_HEADER) { this.contentHeader = AMQImpl.readContentHeaderFrom(f.getInputStream()); this.remainingBodyBytes = this.contentHeader.getBodySize(); updateContentBodyState(); } else { throw new UnexpectedFrameError(f, AMQP.FRAME_HEADER); } } private void consumeBodyFrame(Frame f) { if (f.type == AMQP.FRAME_BODY) { byte[] fragment = f.getPayload(); this.remainingBodyBytes -= fragment.length; updateContentBodyState(); if (this.remainingBodyBytes < 0) { throw new UnsupportedOperationException("%%%%%% FIXME unimplemented"); } appendBodyFragment(fragment); } else { throw new UnexpectedFrameError(f, AMQP.FRAME_BODY); } } /** Stitches together a fragmented content body into a single byte array */ private byte[] coalesceContentBody() { if (this.bodyLength == 0) return EMPTY_BYTE_ARRAY; if (this.bodyN.size() == 1) return this.bodyN.get(0); byte[] body = new byte[bodyLength]; int offset = 0; for (byte[] fragment : this.bodyN) { System.arraycopy(fragment, 0, body, offset, fragment.length); offset += fragment.length; } this.bodyN.clear(); this.bodyN.add(body); return body; } public synchronized byte[] getContentBody() { return coalesceContentBody(); } private void appendBodyFragment(byte[] fragment) { if (fragment == null || fragment.length == 0) return; bodyN.add(fragment); bodyLength += fragment.length; } /** * @param f frame to be incorporated * @return true if command becomes complete * @throws IOException if error reading frame */ public synchronized boolean handleFrame(Frame f) throws IOException { switch (this.state) { case EXPECTING_METHOD: consumeMethodFrame(f); break; case EXPECTING_CONTENT_HEADER: consumeHeaderFrame(f); break; case EXPECTING_CONTENT_BODY: consumeBodyFrame(f); break; default: throw new IllegalStateException("Bad Command State " + this.state); } return isComplete(); } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/CompletableFutureRpcWrapper.java000066400000000000000000000032671316117667700332640ustar00rootroot00000000000000// Copyright (c) 2017-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl; import com.rabbitmq.client.*; import com.rabbitmq.client.Method; import java.util.concurrent.CompletableFuture; /** * */ public class CompletableFutureRpcWrapper implements RpcWrapper { private final com.rabbitmq.client.Method request; private final CompletableFuture completableFuture; public CompletableFutureRpcWrapper(Method method, CompletableFuture completableFuture) { this.request = method; this.completableFuture = completableFuture; } @Override public boolean canHandleReply(AMQCommand command) { return AMQChannel.SimpleBlockingRpcContinuation.isResponseCompatibleWithRequest(request, command.getMethod()); } @Override public void complete(AMQCommand command) { completableFuture.complete(command); } @Override public void shutdown(ShutdownSignalException signal) { completableFuture.completeExceptionally(signal); } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/ConnectionParams.java000066400000000000000000000133261316117667700310740ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl; import com.rabbitmq.client.ExceptionHandler; import com.rabbitmq.client.SaslConfig; import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ThreadFactory; public class ConnectionParams { private String username; private String password; private ExecutorService consumerWorkServiceExecutor; private ScheduledExecutorService heartbeatExecutor; private ExecutorService shutdownExecutor; private String virtualHost; private Map clientProperties; private int requestedFrameMax; private int requestedChannelMax; private int requestedHeartbeat; private int handshakeTimeout; private int shutdownTimeout; private SaslConfig saslConfig; private long networkRecoveryInterval; private boolean topologyRecovery; private int channelRpcTimeout; private boolean channelShouldCheckRpcResponseType; private ExceptionHandler exceptionHandler; private ThreadFactory threadFactory; public ConnectionParams() {} public String getUsername() { return username; } public String getPassword() { return password; } public ExecutorService getConsumerWorkServiceExecutor() { return consumerWorkServiceExecutor; } public String getVirtualHost() { return virtualHost; } public Map getClientProperties() { return clientProperties; } public int getRequestedFrameMax() { return requestedFrameMax; } public int getRequestedChannelMax() { return requestedChannelMax; } public int getRequestedHeartbeat() { return requestedHeartbeat; } public int getHandshakeTimeout() { return handshakeTimeout; } public void setHandshakeTimeout(int timeout) { this.handshakeTimeout = timeout; } public int getShutdownTimeout() { return shutdownTimeout; } public SaslConfig getSaslConfig() { return saslConfig; } public ExceptionHandler getExceptionHandler() { return exceptionHandler; } public long getNetworkRecoveryInterval() { return networkRecoveryInterval; } public boolean isTopologyRecoveryEnabled() { return topologyRecovery; } public ThreadFactory getThreadFactory() { return threadFactory; } public int getChannelRpcTimeout() { return channelRpcTimeout; } public boolean channelShouldCheckRpcResponseType() { return channelShouldCheckRpcResponseType; } public void setUsername(String username) { this.username = username; } public void setPassword(String password) { this.password = password; } public void setConsumerWorkServiceExecutor(ExecutorService consumerWorkServiceExecutor) { this.consumerWorkServiceExecutor = consumerWorkServiceExecutor; } public void setVirtualHost(String virtualHost) { this.virtualHost = virtualHost; } public void setClientProperties(Map clientProperties) { this.clientProperties = clientProperties; } public void setRequestedFrameMax(int requestedFrameMax) { this.requestedFrameMax = requestedFrameMax; } public void setRequestedChannelMax(int requestedChannelMax) { this.requestedChannelMax = requestedChannelMax; } public void setRequestedHeartbeat(int requestedHeartbeat) { this.requestedHeartbeat = requestedHeartbeat; } public void setShutdownTimeout(int shutdownTimeout) { this.shutdownTimeout = shutdownTimeout; } public void setSaslConfig(SaslConfig saslConfig) { this.saslConfig = saslConfig; } public void setNetworkRecoveryInterval(long networkRecoveryInterval) { this.networkRecoveryInterval = networkRecoveryInterval; } public void setTopologyRecovery(boolean topologyRecovery) { this.topologyRecovery = topologyRecovery; } public void setExceptionHandler(ExceptionHandler exceptionHandler) { this.exceptionHandler = exceptionHandler; } public void setThreadFactory(ThreadFactory threadFactory) { this.threadFactory = threadFactory; } public ExecutorService getShutdownExecutor() { return shutdownExecutor; } public void setShutdownExecutor(ExecutorService shutdownExecutor) { this.shutdownExecutor = shutdownExecutor; } public ScheduledExecutorService getHeartbeatExecutor() { return heartbeatExecutor; } public void setHeartbeatExecutor(ScheduledExecutorService heartbeatExecutor) { this.heartbeatExecutor = heartbeatExecutor; } public void setChannelRpcTimeout(int channelRpcTimeout) { this.channelRpcTimeout = channelRpcTimeout; } public void setChannelShouldCheckRpcResponseType(boolean channelShouldCheckRpcResponseType) { this.channelShouldCheckRpcResponseType = channelShouldCheckRpcResponseType; } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/ConsumerDispatcher.java000066400000000000000000000176561316117667700314450ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.Channel; import com.rabbitmq.client.Consumer; import com.rabbitmq.client.Envelope; import com.rabbitmq.client.ShutdownSignalException; import com.rabbitmq.utility.Utility; import java.io.IOException; import java.util.Map; import java.util.concurrent.CountDownLatch; /** * Dispatches notifications to a {@link Consumer} on an internally-managed executor service and work * pool. *

* Each {@link Channel} has a single ConsumerDispatcher, but the executor service and work * pool may be shared with other channels, typically those on the same {@link AMQConnection}. */ final class ConsumerDispatcher { private final ConsumerWorkService workService; private final AMQConnection connection; private final Channel channel; private volatile boolean shuttingDown = false; private volatile boolean shutdownConsumersDriven = false; private volatile CountDownLatch shutdownConsumersComplete; private volatile ShutdownSignalException shutdownSignal = null; public ConsumerDispatcher(AMQConnection connection, Channel channel, ConsumerWorkService workService) { this.connection = connection; this.channel = channel; workService.registerKey(channel); this.workService = workService; } /** Prepare for shutdown of all consumers on this channel */ public void quiesce() { // Prevent any more items being put on the queue (except the shutdown item) this.shuttingDown = true; } public void setUnlimited(boolean unlimited) { this.workService.setUnlimited(channel, unlimited); } public void handleConsumeOk(final Consumer delegate, final String consumerTag) { executeUnlessShuttingDown( new Runnable() { @Override public void run() { try { delegate.handleConsumeOk(consumerTag); } catch (Throwable ex) { connection.getExceptionHandler().handleConsumerException( channel, ex, delegate, consumerTag, "handleConsumeOk"); } } }); } public void handleCancelOk(final Consumer delegate, final String consumerTag) { executeUnlessShuttingDown( new Runnable() { @Override public void run() { try { delegate.handleCancelOk(consumerTag); } catch (Throwable ex) { connection.getExceptionHandler().handleConsumerException( channel, ex, delegate, consumerTag, "handleCancelOk"); } } }); } public void handleCancel(final Consumer delegate, final String consumerTag) { executeUnlessShuttingDown( new Runnable() { @Override public void run() { try { delegate.handleCancel(consumerTag); } catch (Throwable ex) { connection.getExceptionHandler().handleConsumerException( channel, ex, delegate, consumerTag, "handleCancel"); } } }); } public void handleRecoverOk(final Consumer delegate, final String consumerTag) { executeUnlessShuttingDown( new Runnable() { @Override public void run() { delegate.handleRecoverOk(consumerTag); } }); } public void handleDelivery(final Consumer delegate, final String consumerTag, final Envelope envelope, final AMQP.BasicProperties properties, final byte[] body) throws IOException { executeUnlessShuttingDown( new Runnable() { @Override public void run() { try { delegate.handleDelivery(consumerTag, envelope, properties, body); } catch (Throwable ex) { connection.getExceptionHandler().handleConsumerException( channel, ex, delegate, consumerTag, "handleDelivery"); } } }); } public CountDownLatch handleShutdownSignal(final Map consumers, final ShutdownSignalException signal) { // ONLY CASE WHERE WE IGNORE shuttingDown if (!this.shutdownConsumersDriven) { final CountDownLatch latch = new CountDownLatch(1); this.shutdownConsumersComplete = latch; this.shutdownConsumersDriven = true; // Execute shutdown processing even if there are no consumers. execute(new Runnable() { @Override public void run() { ConsumerDispatcher.this.notifyConsumersOfShutdown(consumers, signal); ConsumerDispatcher.this.shutdown(signal); ConsumerDispatcher.this.workService.stopWork(ConsumerDispatcher.this.channel); latch.countDown(); } }); } return this.shutdownConsumersComplete; } private void notifyConsumersOfShutdown(Map consumers, ShutdownSignalException signal) { for (Map.Entry consumerEntry : consumers.entrySet()) { notifyConsumerOfShutdown(consumerEntry.getKey(), consumerEntry.getValue(), signal); } } private void notifyConsumerOfShutdown(String consumerTag, Consumer consumer, ShutdownSignalException signal) { try { consumer.handleShutdownSignal(consumerTag, signal); } catch (Throwable ex) { connection.getExceptionHandler().handleConsumerException( channel, ex, consumer, consumerTag, "handleShutdownSignal"); } } private void executeUnlessShuttingDown(Runnable r) { if (!this.shuttingDown) execute(r); } private void execute(Runnable r) { checkShutdown(); this.workService.addWork(this.channel, r); } private void shutdown(ShutdownSignalException signal) { this.shutdownSignal = signal; } private void checkShutdown() { if (this.shutdownSignal != null) { throw Utility.fixStackTrace(this.shutdownSignal); } } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/ConsumerWorkService.java000066400000000000000000000075551316117667700316170ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; import com.rabbitmq.client.Channel; final public class ConsumerWorkService { private static final int MAX_RUNNABLE_BLOCK_SIZE = 16; private static final int DEFAULT_NUM_THREADS = Runtime.getRuntime().availableProcessors() * 2; private final ExecutorService executor; private final boolean privateExecutor; private final WorkPool workPool; private final int shutdownTimeout; public ConsumerWorkService(ExecutorService executor, ThreadFactory threadFactory, int shutdownTimeout) { this.privateExecutor = (executor == null); this.executor = (executor == null) ? Executors.newFixedThreadPool(DEFAULT_NUM_THREADS, threadFactory) : executor; this.workPool = new WorkPool(); this.shutdownTimeout = shutdownTimeout; } public int getShutdownTimeout() { return shutdownTimeout; } /** * Stop executing all consumer work */ public void shutdown() { this.workPool.unregisterAllKeys(); if (privateExecutor) this.executor.shutdown(); } /** * Stop executing all consumer work for a particular channel * @param channel to stop consumer work for */ public void stopWork(Channel channel) { this.workPool.unregisterKey(channel); } public void registerKey(Channel channel) { this.workPool.registerKey(channel); } public void setUnlimited(Channel channel, boolean unlimited) { if (unlimited) { this.workPool.unlimit(channel); } else { this.workPool.limit(channel); } } public void addWork(Channel channel, Runnable runnable) { if (this.workPool.addWorkItem(channel, runnable)) { this.executor.execute(new WorkPoolRunnable()); } } /** * @return true if executor used by this work service is managed * by it and wasn't provided by the user */ public boolean usesPrivateExecutor() { return privateExecutor; } private final class WorkPoolRunnable implements Runnable { @Override public void run() { int size = MAX_RUNNABLE_BLOCK_SIZE; List block = new ArrayList(size); try { Channel key = ConsumerWorkService.this.workPool.nextWorkBlock(block, size); if (key == null) return; // nothing ready to run try { for (Runnable runnable : block) { runnable.run(); } } finally { if (ConsumerWorkService.this.workPool.finishWorkBlock(key)) { ConsumerWorkService.this.executor.execute(new WorkPoolRunnable()); } } } catch (RuntimeException e) { Thread.currentThread().interrupt(); } } } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/ContentHeaderPropertyReader.java000066400000000000000000000073761316117667700332540ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl; import java.io.DataInputStream; import java.io.IOException; import java.util.Date; import java.util.Map; import com.rabbitmq.client.ContentHeader; import com.rabbitmq.client.LongString; /** * Parses an AMQP wire-protocol {@link ContentHeader} from a * DataInputStream. Methods on this object are usually called from * autogenerated code. */ public class ContentHeaderPropertyReader { /** Stream we are reading from */ private final ValueReader in; /** Current field flag word */ public int flagWord; /** Current flag position counter */ public int bitCount; /** * Protected API - Constructs a reader from the given input stream */ public ContentHeaderPropertyReader(DataInputStream in) throws IOException { this.in = new ValueReader(in); this.flagWord = 1; // just the continuation bit this.bitCount = 15; // forces a flagWord read } private boolean isContinuationBitSet() { return (flagWord & 1) != 0; } public void readFlagWord() throws IOException { if (!isContinuationBitSet()) { // FIXME: Proper exception class! throw new IOException("Attempted to read flag word when none advertised"); } flagWord = in.readShort(); bitCount = 0; } public boolean readPresence() throws IOException { if (bitCount == 15) { readFlagWord(); } int bit = 15 - bitCount; bitCount++; return (flagWord & (1 << bit)) != 0; } public void finishPresence() throws IOException { if (isContinuationBitSet()) { // FIXME: Proper exception class! throw new IOException("Unexpected continuation flag word"); } } /** Reads and returns an AMQP short string content header field. */ public String readShortstr() throws IOException { return in.readShortstr(); } /** Reads and returns an AMQP "long string" (binary) content header field. */ public LongString readLongstr() throws IOException { return in.readLongstr(); } /** Reads and returns an AMQP short integer content header field. */ public Integer readShort() throws IOException { return in.readShort(); } /** Reads and returns an AMQP integer content header field. */ public Integer readLong() throws IOException { return in.readLong(); } /** Reads and returns an AMQP long integer content header field. */ public Long readLonglong() throws IOException { return in.readLonglong(); } /** Reads and returns an AMQP table content header field. */ public Map readTable() throws IOException { return in.readTable(); } /** Reads and returns an AMQP octet content header field. */ public int readOctet() throws IOException { return in.readOctet(); } /** Reads and returns an AMQP timestamp content header field. */ public Date readTimestamp() throws IOException { return in.readTimestamp(); } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/ContentHeaderPropertyWriter.java000066400000000000000000000061641316117667700333200ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl; import java.io.DataOutputStream; import java.io.IOException; import java.util.Date; import java.util.Map; import com.rabbitmq.client.ContentHeader; import com.rabbitmq.client.LongString; /** * Generates an AMQP wire-protocol packet from a {@link ContentHeader}. * Methods on this object are usually called from autogenerated code. */ public class ContentHeaderPropertyWriter { /** Accumulates our output */ private final ValueWriter out; /** Current flags word being accumulated */ public int flagWord; /** Position within current flags word */ public int bitCount; /** * Constructs a fresh ContentHeaderPropertyWriter. */ public ContentHeaderPropertyWriter(DataOutputStream out) { this.out = new ValueWriter(out); this.flagWord = 0; this.bitCount = 0; } private void emitFlagWord(boolean continuationBit) throws IOException { out.writeShort(continuationBit ? (flagWord | 1) : flagWord); flagWord = 0; bitCount = 0; } public void writePresence(boolean present) throws IOException { if (bitCount == 15) { emitFlagWord(true); } if (present) { int bit = 15 - bitCount; flagWord = flagWord | (1 << bit); } bitCount++; } public void finishPresence() throws IOException { emitFlagWord(false); } public void writeShortstr(String str) throws IOException { out.writeShortstr(str); } public void writeLongstr(String str) throws IOException { out.writeLongstr(str); } public void writeLongstr(LongString str) throws IOException { out.writeLongstr(str); } public void writeShort(Integer s) throws IOException { out.writeShort(s); } public void writeLong(Integer l) throws IOException { out.writeLong(l); } public void writeLonglong(Long ll) throws IOException { out.writeLonglong(ll); } public void writeTable(Map table) throws IOException { out.writeTable(table); } public void writeOctet(Integer octet) throws IOException { out.writeOctet(octet); } public void writeOctet(int octet) throws IOException { out.writeOctet(octet); } public void writeTimestamp(Date timestamp) throws IOException { out.writeTimestamp(timestamp); } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/DefaultExceptionHandler.java000066400000000000000000000020071316117667700323640ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl; import com.rabbitmq.client.ExceptionHandler; /** * Default implementation of {@link com.rabbitmq.client.ExceptionHandler} * used by {@link AMQConnection}. */ public class DefaultExceptionHandler extends StrictExceptionHandler implements ExceptionHandler { } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/Environment.java000066400000000000000000000035771316117667700301440ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl; import java.util.concurrent.ThreadFactory; /** * Infers information about the execution environment, e.g. * security permissions. * Package-protected API. */ public class Environment { public static boolean isAllowedToModifyThreads() { try { SecurityManager sm = System.getSecurityManager(); if(sm != null) { sm.checkPermission(new RuntimePermission("modifyThread")); sm.checkPermission(new RuntimePermission("modifyThreadGroup")); } return true; } catch (SecurityException se) { return false; } } public static Thread newThread(ThreadFactory factory, Runnable runnable, String name) { Thread t = factory.newThread(runnable); if(isAllowedToModifyThreads()) { t.setName(name); } return t; } public static Thread newThread(ThreadFactory factory, Runnable runnable, String name, boolean isDaemon) { Thread t = newThread(factory, runnable, name); if(isAllowedToModifyThreads()) { t.setDaemon(isDaemon); } return t; } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/ExternalMechanism.java000066400000000000000000000022521316117667700312340ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl; import com.rabbitmq.client.LongString; import com.rabbitmq.client.SaslMechanism; /** * The EXTERNAL auth mechanism */ public class ExternalMechanism implements SaslMechanism { @Override public String getName() { return "EXTERNAL"; } @Override public LongString handleChallenge(LongString challenge, String username, String password) { return LongStringHelper.asLongString(""); } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/ForgivingExceptionHandler.java000066400000000000000000000117751316117667700327460ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl; import com.rabbitmq.client.*; import org.slf4j.LoggerFactory; import java.io.IOException; import java.net.ConnectException; /** * An implementation of {@link com.rabbitmq.client.ExceptionHandler} that does not * close channels on unhandled consumer and listener exception. * * Used by {@link AMQConnection}. * * @see ExceptionHandler * @see com.rabbitmq.client.ConnectionFactory#setExceptionHandler(com.rabbitmq.client.ExceptionHandler) */ public class ForgivingExceptionHandler implements ExceptionHandler { @Override public void handleUnexpectedConnectionDriverException(Connection conn, Throwable exception) { log("An unexpected connection driver error occured", exception); } @Override public void handleReturnListenerException(Channel channel, Throwable exception) { handleChannelKiller(channel, exception, "ReturnListener.handleReturn"); } @Override public void handleConfirmListenerException(Channel channel, Throwable exception) { handleChannelKiller(channel, exception, "ConfirmListener.handle{N,A}ck"); } @Override public void handleBlockedListenerException(Connection connection, Throwable exception) { handleConnectionKiller(connection, exception, "BlockedListener"); } @Override public void handleConsumerException(Channel channel, Throwable exception, Consumer consumer, String consumerTag, String methodName) { handleChannelKiller(channel, exception, "Consumer " + consumer + " (" + consumerTag + ")" + " method " + methodName + " for channel " + channel); } /** * @since 3.3.0 */ @Override public void handleConnectionRecoveryException(Connection conn, Throwable exception) { // ignore java.net.ConnectException as those are // expected during recovery and will only produce noisy // traces if (exception instanceof ConnectException) { // no-op } else { log("Caught an exception during connection recovery!", exception); } } /** * @since 3.3.0 */ @Override public void handleChannelRecoveryException(Channel ch, Throwable exception) { log("Caught an exception when recovering channel " + ch.getChannelNumber(), exception); } /** * @since 3.3.0 */ @Override public void handleTopologyRecoveryException(Connection conn, Channel ch, TopologyRecoveryException exception) { log("Caught an exception when recovering topology " + exception.getMessage(), exception); } protected void handleChannelKiller(Channel channel, Throwable exception, String what) { log(what + "threw an exception for channel "+channel, exception); } protected void handleConnectionKiller(Connection connection, Throwable exception, String what) { log(what + " threw an exception for connection " + connection, exception); try { connection.close(AMQP.REPLY_SUCCESS, "Closed due to exception from " + what); } catch (AlreadyClosedException ace) { // noop } catch (IOException ioe) { log("Failure during close of connection " + connection + " after " + exception, ioe); connection.abort(AMQP.INTERNAL_ERROR, "Internal error closing connection for " + what); } } protected void log(String message, Throwable e) { if(isSocketClosedOrConnectionReset(e)) { // we don't want to get too dramatic about those LoggerFactory.getLogger(ForgivingExceptionHandler.class).warn( message + " (Exception message: "+e.getMessage() + ")" ); } else { LoggerFactory.getLogger(ForgivingExceptionHandler.class).error( message, e ); } } private static boolean isSocketClosedOrConnectionReset(Throwable e) { return e instanceof IOException && ("Connection reset".equals(e.getMessage()) || "Socket closed".equals(e.getMessage()) || "Connection reset by peer".equals(e.getMessage()) ); } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/Frame.java000066400000000000000000000266651316117667700266750ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.LongString; import com.rabbitmq.client.MalformedFrameException; import java.io.*; import java.math.BigDecimal; import java.net.SocketTimeoutException; import java.sql.Timestamp; import java.util.Date; import java.util.List; import java.util.Map; /** * Represents an AMQP wire-protocol frame, with frame type, channel number, and payload bytes. * TODO: make state private */ public class Frame { /** Frame type code */ public final int type; /** Frame channel number, 0-65535 */ public final int channel; /** Frame payload bytes (for inbound frames) */ private final byte[] payload; /** Frame payload (for outbound frames) */ private final ByteArrayOutputStream accumulator; private static final int NON_BODY_SIZE = 1 /* type */ + 2 /* channel */ + 4 /* payload size */ + 1 /* end character */; /** * Constructs a frame for output with a type and a channel number and a * fresh accumulator waiting for payload. */ public Frame(int type, int channel) { this.type = type; this.channel = channel; this.payload = null; this.accumulator = new ByteArrayOutputStream(); } /** * Constructs a frame for input with a type, a channel number and a * payload byte array. */ public Frame(int type, int channel, byte[] payload) { this.type = type; this.channel = channel; this.payload = payload; this.accumulator = null; } public static Frame fromBodyFragment(int channelNumber, byte[] body, int offset, int length) throws IOException { Frame frame = new Frame(AMQP.FRAME_BODY, channelNumber); DataOutputStream bodyOut = frame.getOutputStream(); bodyOut.write(body, offset, length); return frame; } /** * Protected API - Factory method to instantiate a Frame by reading an * AMQP-wire-protocol frame from the given input stream. * * @return a new Frame if we read a frame successfully, otherwise null */ public static Frame readFrom(DataInputStream is) throws IOException { int type; int channel; try { type = is.readUnsignedByte(); } catch (SocketTimeoutException ste) { // System.err.println("Timed out waiting for a frame."); return null; // failed } if (type == 'A') { /* * Probably an AMQP.... header indicating a version * mismatch. */ /* * Otherwise meaningless, so try to read the version, * and throw an exception, whether we read the version * okay or not. */ protocolVersionMismatch(is); } channel = is.readUnsignedShort(); int payloadSize = is.readInt(); byte[] payload = new byte[payloadSize]; is.readFully(payload); int frameEndMarker = is.readUnsignedByte(); if (frameEndMarker != AMQP.FRAME_END) { throw new MalformedFrameException("Bad frame end marker: " + frameEndMarker); } return new Frame(type, channel, payload); } /** * Private API - A protocol version mismatch is detected by checking the * three next bytes if a frame type of (int)'A' is read from an input * stream. If the next three bytes are 'M', 'Q' and 'P', then it's * likely the broker is trying to tell us we are speaking the wrong AMQP * protocol version. * * @throws MalformedFrameException * if an AMQP protocol version mismatch is detected * @throws MalformedFrameException * if a corrupt AMQP protocol identifier is read */ public static void protocolVersionMismatch(DataInputStream is) throws IOException { MalformedFrameException x; // We expect the letters M, Q, P in that order: generate an informative error if they're not found byte[] expectedBytes = new byte[] { 'M', 'Q', 'P' }; for (byte expectedByte : expectedBytes) { int nextByte = is.readUnsignedByte(); if (nextByte != expectedByte) { throw new MalformedFrameException("Invalid AMQP protocol header from server: expected character " + expectedByte + ", got " + nextByte); } } try { int[] signature = new int[4]; for (int i = 0; i < 4; i++) { signature[i] = is.readUnsignedByte(); } if (signature[0] == 1 && signature[1] == 1 && signature[2] == 8 && signature[3] == 0) { x = new MalformedFrameException("AMQP protocol version mismatch; we are version " + AMQP.PROTOCOL.MAJOR + "-" + AMQP.PROTOCOL.MINOR + "-" + AMQP.PROTOCOL.REVISION + ", server is 0-8"); } else { String sig = ""; for (int i = 0; i < 4; i++) { if (i != 0) sig += ","; sig += signature[i]; } x = new MalformedFrameException("AMQP protocol version mismatch; we are version " + AMQP.PROTOCOL.MAJOR + "-" + AMQP.PROTOCOL.MINOR + "-" + AMQP.PROTOCOL.REVISION + ", server sent signature " + sig); } } catch (IOException ex) { x = new MalformedFrameException("Invalid AMQP protocol header from server"); } throw x; } /** * Public API - writes this Frame to the given DataOutputStream */ public void writeTo(DataOutputStream os) throws IOException { os.writeByte(type); os.writeShort(channel); if (accumulator != null) { os.writeInt(accumulator.size()); accumulator.writeTo(os); } else { os.writeInt(payload.length); os.write(payload); } os.write(AMQP.FRAME_END); } public int size() { if(accumulator != null) { return accumulator.size() + NON_BODY_SIZE; } else { return payload.length + NON_BODY_SIZE; } } /** * Public API - retrieves the frame payload */ public byte[] getPayload() { if (payload != null) return payload; // This is a Frame we've constructed ourselves. For some reason (e.g. // testing), we're acting as if we received it even though it // didn't come in off the wire. return accumulator.toByteArray(); } /** * Public API - retrieves a new DataInputStream streaming over the payload */ public DataInputStream getInputStream() { return new DataInputStream(new ByteArrayInputStream(getPayload())); } /** * Public API - retrieves a fresh DataOutputStream streaming into the accumulator */ public DataOutputStream getOutputStream() { return new DataOutputStream(accumulator); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("Frame(type=").append(type).append(", channel=").append(channel).append(", "); if (accumulator == null) { sb.append(payload.length).append(" bytes of payload)"); } else { sb.append(accumulator.size()).append(" bytes of accumulator)"); } return sb.toString(); } /** Computes the AMQP wire-protocol length of protocol-encoded table entries. */ public static long tableSize(Map table) throws UnsupportedEncodingException { long acc = 0; for(Map.Entry entry: table.entrySet()) { acc += shortStrSize(entry.getKey()); acc += fieldValueSize(entry.getValue()); } return acc; } /** Computes the AMQP wire-protocol length of a protocol-encoded field-value. */ private static long fieldValueSize(Object value) throws UnsupportedEncodingException { long acc = 1; // for the type tag if(value instanceof String) { acc += longStrSize((String)value); } else if(value instanceof LongString) { acc += 4 + ((LongString)value).length(); } else if(value instanceof Integer) { acc += 4; } else if(value instanceof BigDecimal) { acc += 5; } else if(value instanceof Date || value instanceof Timestamp) { acc += 8; } else if(value instanceof Map) { @SuppressWarnings("unchecked") Map map = (Map) value; acc += 4 + tableSize(map); } else if (value instanceof Byte) { acc += 1; } else if(value instanceof Double) { acc += 8; } else if(value instanceof Float) { acc += 4; } else if(value instanceof Long) { acc += 8; } else if(value instanceof Short) { acc += 2; } else if(value instanceof Boolean) { acc += 1; } else if(value instanceof byte[]) { acc += 4 + ((byte[])value).length; } else if(value instanceof List) { acc += 4 + arraySize((List)value); } else if(value instanceof Object[]) { acc += 4 + arraySize((Object[])value); } else if(value == null) { } else { throw new IllegalArgumentException("invalid value in table"); } return acc; } /** Computes the AMQP 0-9-1 wire-protocol length of an encoded field-array of type List */ public static long arraySize(List values) throws UnsupportedEncodingException { long acc = 0; for (Object value : values) { acc += fieldValueSize(value); } return acc; } /** Computes the AMQP wire-protocol length of an encoded field-array of type Object[] */ public static long arraySize(Object[] values) throws UnsupportedEncodingException { long acc = 0; for (Object value : values) { acc += fieldValueSize(value); } return acc; } /** Computes the AMQP wire-protocol length of a protocol-encoded long string. */ private static int longStrSize(String str) throws UnsupportedEncodingException { return str.getBytes("utf-8").length + 4; } /** Computes the AMQP wire-protocol length of a protocol-encoded short string. */ private static int shortStrSize(String str) throws UnsupportedEncodingException { return str.getBytes("utf-8").length + 1; } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/FrameHandler.java000066400000000000000000000052641316117667700301630ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl; import java.io.IOException; import java.net.SocketException; import java.net.SocketTimeoutException; /** * Interface to a frame handler. *

Concurrency

* Implementations must be thread-safe, and not allow frames to be interleaved, either while reading or writing. */ public interface FrameHandler extends NetworkConnection { /** * Set the underlying socket's read timeout in milliseconds, if applicable. * @param timeoutMs The timeout in milliseconds */ void setTimeout(int timeoutMs) throws SocketException; /** * Get the underlying socket's read timeout in milliseconds. * @return The timeout in milliseconds */ int getTimeout() throws SocketException; /** * Send the initial connection header, thus kickstarting the AMQP * protocol version negotiation process and putting the underlying * connection in a state such that the next layer of startup can * proceed. * @throws IOException if there is a problem accessing the connection */ void sendHeader() throws IOException; void initialize(AMQConnection connection); /** * Read a {@link Frame} from the underlying data connection. * @return an incoming Frame, or null if there is none * @throws IOException if there is a problem accessing the connection * @throws SocketTimeoutException if the underlying read times out */ Frame readFrame() throws IOException; /** * Write a {@link Frame} to the underlying data connection. * @param frame the Frame to transmit * @throws IOException if there is a problem accessing the connection */ void writeFrame(Frame frame) throws IOException; /** * Flush the underlying data connection. * @throws IOException if there is a problem accessing the connection */ void flush() throws IOException; /** Close the underlying data connection (complaint not permitted). */ void close(); } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/FrameHandlerFactory.java000066400000000000000000000003541316117667700315060ustar00rootroot00000000000000package com.rabbitmq.client.impl; import com.rabbitmq.client.Address; import java.io.IOException; /** * */ public interface FrameHandlerFactory { FrameHandler create(Address addr, String connectionName) throws IOException; } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/HeartbeatSender.java000066400000000000000000000112201316117667700306600ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl; import com.rabbitmq.client.AMQP; import java.util.concurrent.ExecutorService; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; import java.util.concurrent.ScheduledFuture; import java.io.IOException; import static java.util.concurrent.TimeUnit.SECONDS; /** * Manages heartbeat sending for a {@link AMQConnection}. *

* Heartbeats are sent in a dedicated thread that is separate * from the main loop thread used for the connection. */ final class HeartbeatSender { private final Object monitor = new Object(); private final FrameHandler frameHandler; private final ThreadFactory threadFactory; private ScheduledExecutorService executor; private final boolean privateExecutor; private ScheduledFuture future; private boolean shutdown = false; private volatile long lastActivityTime; HeartbeatSender(FrameHandler frameHandler, ScheduledExecutorService heartbeatExecutor, ThreadFactory threadFactory) { this.frameHandler = frameHandler; this.privateExecutor = (heartbeatExecutor == null); this.executor = heartbeatExecutor; this.threadFactory = threadFactory; } public void signalActivity() { this.lastActivityTime = System.nanoTime(); } /** * Sets the heartbeat in seconds. */ public void setHeartbeat(int heartbeatSeconds) { synchronized(this.monitor) { if(this.shutdown) { return; } // cancel any existing heartbeat task if(this.future != null) { this.future.cancel(true); this.future = null; } if (heartbeatSeconds > 0) { // wake every heartbeatSeconds / 2 to avoid the worst case // where the last activity comes just after the last heartbeat long interval = SECONDS.toNanos(heartbeatSeconds) / 2; ScheduledExecutorService executor = createExecutorIfNecessary(); Runnable task = new HeartbeatRunnable(interval); this.future = executor.scheduleAtFixedRate( task, interval, interval, TimeUnit.NANOSECONDS); } } } private ScheduledExecutorService createExecutorIfNecessary() { synchronized (this.monitor) { if (this.executor == null) { this.executor = Executors.newSingleThreadScheduledExecutor(threadFactory); } return this.executor; } } /** * Shutdown the heartbeat process, if any. */ public void shutdown() { ExecutorService executorToShutdown = null; synchronized (this.monitor) { if (this.future != null) { this.future.cancel(true); this.future = null; } if (this.privateExecutor) { // to be safe, we shouldn't call shutdown holding the // monitor. executorToShutdown = this.executor; } this.executor = null; this.shutdown = true; } if(executorToShutdown != null) { executorToShutdown.shutdown(); } } private final class HeartbeatRunnable implements Runnable { private final long heartbeatNanos; private HeartbeatRunnable(long heartbeatNanos) { this.heartbeatNanos = heartbeatNanos; } @Override public void run() { try { long now = System.nanoTime(); if (now > (lastActivityTime + this.heartbeatNanos)) { frameHandler.writeFrame(new Frame(AMQP.FRAME_HEARTBEAT, 0)); frameHandler.flush(); } } catch (IOException e) { // ignore } } } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/LongStringHelper.java000066400000000000000000000062361316117667700310610ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl; import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.nio.charset.Charset; import java.util.Arrays; import com.rabbitmq.client.LongString; /** * Utility for working with {@link LongString}s. */ public class LongStringHelper { /** * Private API - Implementation of {@link LongString}. When * interpreting bytes as a string, uses UTF-8 encoding. */ private static class ByteArrayLongString implements LongString { private final byte [] bytes; public ByteArrayLongString(byte[] bytes) { this.bytes = bytes; } @Override public boolean equals(Object o) { if(o instanceof LongString) { LongString other = (LongString)o; return Arrays.equals(this.bytes, other.getBytes()); } return false; } @Override public int hashCode() { return Arrays.hashCode(this.bytes); } /** {@inheritDoc} */ @Override public byte[] getBytes() { return bytes; } /** {@inheritDoc} */ @Override public DataInputStream getStream() throws IOException { return new DataInputStream(new ByteArrayInputStream(bytes)); } /** {@inheritDoc} */ @Override public long length() { return bytes.length; } @Override public String toString() { return new String(bytes, Charset.forName("utf-8")); } } /** * Converts a String to a LongString using UTF-8 encoding. * @param string the string to wrap * @return a LongString wrapping it */ public static LongString asLongString(String string) { if (string == null) return null; return new ByteArrayLongString(string.getBytes(Charset.forName("utf-8"))); } /** * Converts a binary block to a LongString. * @param bytes the data to wrap * @return a LongString wrapping it */ public static LongString asLongString(byte [] bytes) { if (bytes==null) return null; return new ByteArrayLongString(bytes); } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/Method.java000066400000000000000000000061631316117667700270520ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl; import java.io.DataOutputStream; import java.io.IOException; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.impl.AMQImpl.MethodVisitor; /** * Base class for AMQP method objects, specialized by autogenerated * code in AMQP.java. */ public abstract class Method implements com.rabbitmq.client.Method { /** {@inheritDoc} */ @Override public abstract int protocolClassId(); /* properly an unsigned short */ /** {@inheritDoc} */ @Override public abstract int protocolMethodId(); /* properly an unsigned short */ /** {@inheritDoc} */ @Override public abstract String protocolMethodName(); /** * Tell if content is present. * @return true if the wire-protocol for this method should involve a content header and body, * or false if it should just involve a single method frame. */ public abstract boolean hasContent(); /** * Visitor support (double-dispatch mechanism). * @param visitor the visitor object * @return the result of the "visit" operation * @throws IOException if an error is encountered */ public abstract Object visit(MethodVisitor visitor) throws IOException; /** * Private API - Autogenerated writer for this method. * @param writer interface to an object to write the method arguments * @throws IOException if an error is encountered */ public abstract void writeArgumentsTo(MethodArgumentWriter writer) throws IOException; /** * Public API - debugging utility * @param buffer the buffer to append debug data to */ public void appendArgumentDebugStringTo(StringBuilder buffer) { buffer.append("(?)"); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("#method<").append(protocolMethodName()).append(">"); this.appendArgumentDebugStringTo(sb); return sb.toString(); } public Frame toFrame(int channelNumber) throws IOException { Frame frame = new Frame(AMQP.FRAME_METHOD, channelNumber); DataOutputStream bodyOut = frame.getOutputStream(); bodyOut.writeShort(protocolClassId()); bodyOut.writeShort(protocolMethodId()); MethodArgumentWriter argWriter = new MethodArgumentWriter(new ValueWriter(bodyOut)); writeArgumentsTo(argWriter); argWriter.flush(); return frame; } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/MethodArgumentReader.java000066400000000000000000000072021316117667700316730ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl; import java.io.IOException; import java.util.Date; import java.util.Map; import com.rabbitmq.client.LongString; /** * Parses AMQP wire-protocol {@link Method} arguments from a * DataInputStream. Methods on this object are usually called from * generated code. */ public class MethodArgumentReader { /** The stream we are reading from. */ private final ValueReader in; /** If we are reading one or more bits, holds the current packed collection of bits */ private int bits; /** If we are reading one or more bits, keeps track of which bit position we will read from next. * (reading least to most significant order) */ private int nextBitMask; /** * Resets the bit group accumulator variables when * some non-bit argument value is to be read. */ private void clearBits() { bits = 0; nextBitMask = 0x100; // triggers readOctet first time } /** * Construct a MethodArgumentReader from the given {@link ValueReader}. */ public MethodArgumentReader(ValueReader in) { this.in = in; clearBits(); } /** Public API - reads a short string argument. */ public final String readShortstr() throws IOException { clearBits(); return in.readShortstr(); } /** Public API - reads a long string argument. */ public final LongString readLongstr() throws IOException { clearBits(); return in.readLongstr(); } /** Public API - reads a short integer argument. */ public final int readShort() throws IOException { clearBits(); return in.readShort(); } /** Public API - reads an integer argument. */ public final int readLong() throws IOException { clearBits(); return in.readLong(); } /** Public API - reads a long integer argument. */ public final long readLonglong() throws IOException { clearBits(); return in.readLonglong(); } /** Public API - reads a bit/boolean argument. */ public final boolean readBit() throws IOException { if (nextBitMask > 0x80) { bits = in.readOctet(); nextBitMask = 0x01; } boolean result = (bits&nextBitMask) != 0; nextBitMask = nextBitMask << 1; return result; } /** Public API - reads a table argument. */ public final Map readTable() throws IOException { clearBits(); return in.readTable(); } /** Public API - reads an octet argument. */ public final int readOctet() throws IOException { clearBits(); return in.readOctet(); } /** Public API - reads an timestamp argument. */ public final Date readTimestamp() throws IOException { clearBits(); return in.readTimestamp(); } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/MethodArgumentWriter.java000066400000000000000000000112121316117667700317410ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl; import java.io.IOException; import java.util.Date; import java.util.Map; import com.rabbitmq.client.LongString; /** * Generates AMQP wire-protocol encoded arguments. Methods on this * object are usually called from autogenerated code. */ public class MethodArgumentWriter { /** Writes our output */ private final ValueWriter out; /** When encoding one or more bits, records whether a group of bits is waiting to be written */ private boolean needBitFlush; /** The current group of bits */ private byte bitAccumulator; /** The current position within the group of bits */ private int bitMask; /** * Constructs a MethodArgumentWriter targetting the given DataOutputStream. */ public MethodArgumentWriter(ValueWriter out) { this.out = out; resetBitAccumulator(); } /** Private API - called to reset the bit group variables. */ private void resetBitAccumulator() { needBitFlush = false; bitAccumulator = 0; bitMask = 1; } /** * Private API - called when we may be transitioning from encoding * a group of bits to encoding a non-bit value. */ private final void bitflush() throws IOException { if (needBitFlush) { out.writeOctet(bitAccumulator); resetBitAccumulator(); } } /** Public API - encodes a short string argument. */ public final void writeShortstr(String str) throws IOException { bitflush(); out.writeShortstr(str); } /** Public API - encodes a long string argument from a LongString. */ public final void writeLongstr(LongString str) throws IOException { bitflush(); out.writeLongstr(str); } /** Public API - encodes a long string argument from a String. */ public final void writeLongstr(String str) throws IOException { bitflush(); out.writeLongstr(str); } /** Public API - encodes a short integer argument. */ public final void writeShort(int s) throws IOException { bitflush(); out.writeShort(s); } /** Public API - encodes an integer argument. */ public final void writeLong(int l) throws IOException { bitflush(); out.writeLong(l); } /** Public API - encodes a long integer argument. */ public final void writeLonglong(long ll) throws IOException { bitflush(); out.writeLonglong(ll); } /** Public API - encodes a boolean/bit argument. */ public final void writeBit(boolean b) throws IOException { if (bitMask > 0x80) { bitflush(); } if (b) { bitAccumulator |= bitMask; } else { // um, don't set the bit. } bitMask = bitMask << 1; needBitFlush = true; } /** Public API - encodes a table argument. */ public final void writeTable(Map table) throws IOException { bitflush(); out.writeTable(table); } /** Public API - encodes an octet argument from an int. */ public final void writeOctet(int octet) throws IOException { bitflush(); out.writeOctet(octet); } /** Public API - encodes an octet argument from a byte. */ public final void writeOctet(byte octet) throws IOException { bitflush(); out.writeOctet(octet); } /** Public API - encodes a timestamp argument. */ public final void writeTimestamp(Date timestamp) throws IOException { bitflush(); out.writeTimestamp(timestamp); } /** * Public API - call this to ensure all accumulated argument * values are correctly written to the output stream. */ public void flush() throws IOException { bitflush(); out.flush(); } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/NetworkConnection.java000066400000000000000000000023021316117667700312720ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl; import java.net.InetAddress; public interface NetworkConnection { /** * Retrieve the local host. * @return the client socket address. */ InetAddress getLocalAddress(); /** * Retrieve the local port number. * @return the client socket port number */ int getLocalPort(); /** Retrieve address of peer. */ InetAddress getAddress(); /** Retrieve port number of peer. */ int getPort(); } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/PlainMechanism.java000066400000000000000000000024711316117667700305200ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl; import com.rabbitmq.client.LongString; import com.rabbitmq.client.SaslMechanism; /** * The PLAIN auth mechanism */ public class PlainMechanism implements SaslMechanism { @Override public String getName() { return "PLAIN"; } @Override public LongString handleChallenge(LongString challenge, String username, String password) { return LongStringHelper.asLongString("\0" + username + "\0" + password); } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/RpcContinuationRpcWrapper.java000066400000000000000000000026651316117667700327620ustar00rootroot00000000000000// Copyright (c) 2017-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl; import com.rabbitmq.client.ShutdownSignalException; /** * */ public class RpcContinuationRpcWrapper implements RpcWrapper { private final AMQChannel.RpcContinuation continuation; public RpcContinuationRpcWrapper(AMQChannel.RpcContinuation continuation) { this.continuation = continuation; } @Override public boolean canHandleReply(AMQCommand command) { return continuation.canHandleReply(command); } @Override public void complete(AMQCommand command) { continuation.handleCommand(command); } @Override public void shutdown(ShutdownSignalException signal) { continuation.handleShutdownSignal(signal); } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/RpcWrapper.java000066400000000000000000000017571316117667700277230ustar00rootroot00000000000000// Copyright (c) 2017-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl; import com.rabbitmq.client.ShutdownSignalException; /** * */ public interface RpcWrapper { boolean canHandleReply(AMQCommand command); void complete(AMQCommand command); void shutdown(ShutdownSignalException signal); } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/SetQueue.java000066400000000000000000000061651316117667700273740ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl; import java.util.HashSet; import java.util.LinkedList; import java.util.Queue; import java.util.Set; /** *

A generic queue-like implementation (supporting operations addIfNotPresent, * poll, contains, and isEmpty) * which restricts a queue element to appear at most once. * If the element is already present {@link #addIfNotPresent} returns false. *

* Elements must not be null. *

Concurrent Semantics

* This implementation is not thread-safe. * @param type of elements in the queue */ public class SetQueue { private final Set members = new HashSet(); private final Queue queue = new LinkedList(); /** Add an element to the back of the queue and return true, or else return false. * @param item to add * @return true if the element was added, false if it is already present. */ public boolean addIfNotPresent(T item) { if (this.members.contains(item)) { return false; } this.members.add(item); this.queue.offer(item); return true; } /** Remove the head of the queue and return it. * @return head element of the queue, or null if the queue is empty. */ public T poll() { T item = this.queue.poll(); if (item != null) { this.members.remove(item); } return item; } /** @param item to look for in queue * @return true if and only if item is in the queue.*/ public boolean contains(T item) { return this.members.contains(item); } /** @return true if and only if the queue is empty.*/ public boolean isEmpty() { return this.members.isEmpty(); } /** Remove item from queue, if present. * @param item to remove * @return true if and only if item was initially present and was removed. */ public boolean remove(T item) { this.queue.remove(item); // there can only be one such item in the queue return this.members.remove(item); } /** Remove all items from the queue. */ public void clear() { this.queue.clear(); this.members.clear(); } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/ShutdownNotifierComponent.java000066400000000000000000000071671316117667700330350ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl; import java.util.ArrayList; import java.util.List; import com.rabbitmq.client.ShutdownListener; import com.rabbitmq.client.ShutdownNotifier; import com.rabbitmq.client.ShutdownSignalException; /** * A class that manages {@link ShutdownListener}s and remembers the reason for a shutdown. Both * {@link com.rabbitmq.client.Channel Channel}s and {@link com.rabbitmq.client.Connection * Connection}s have shutdown listeners. */ public class ShutdownNotifierComponent implements ShutdownNotifier { /** Monitor for shutdown listeners and shutdownCause */ private final Object monitor = new Object(); /** List of all shutdown listeners associated with the component */ private final List shutdownListeners = new ArrayList(); /** * When this value is null, the component is in an "open" * state. When non-null, the component is in "closed" state, and * this value indicates the circumstances of the shutdown. */ private volatile ShutdownSignalException shutdownCause = null; @Override public void addShutdownListener(ShutdownListener listener) { ShutdownSignalException sse = null; synchronized(this.monitor) { sse = this.shutdownCause; this.shutdownListeners.add(listener); } if (sse != null) // closed listener.shutdownCompleted(sse); } @Override public ShutdownSignalException getCloseReason() { synchronized(this.monitor) { return this.shutdownCause; } } @Override public void notifyListeners() { ShutdownSignalException sse = null; ShutdownListener[] sdls = null; synchronized(this.monitor) { sdls = this.shutdownListeners .toArray(new ShutdownListener[this.shutdownListeners.size()]); sse = this.shutdownCause; } for (ShutdownListener l: sdls) { try { l.shutdownCompleted(sse); } catch (Exception e) { // FIXME: proper logging } } } @Override public void removeShutdownListener(ShutdownListener listener) { synchronized(this.monitor) { this.shutdownListeners.remove(listener); } } @Override public boolean isOpen() { synchronized(this.monitor) { return this.shutdownCause == null; } } /** * Internal: this is the means of registering shutdown. * @param sse the reason for the shutdown * @return true if the component is open; false otherwise. */ public boolean setShutdownCauseIfOpen(ShutdownSignalException sse) { synchronized (this.monitor) { if (isOpen()) { this.shutdownCause = sse; return true; } return false; } } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/SocketFrameHandler.java000066400000000000000000000144201316117667700313260ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl; import com.rabbitmq.client.AMQP; import java.io.*; import java.net.InetAddress; import java.net.Socket; import java.net.SocketException; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; /** * A socket-based frame handler. */ public class SocketFrameHandler implements FrameHandler { /** The underlying socket */ private final Socket _socket; /** * Optional {@link ExecutorService} for final flush. */ private final ExecutorService _shutdownExecutor; /** Socket's inputstream - data from the broker - synchronized on */ private final DataInputStream _inputStream; /** Socket's outputstream - data to the broker - synchronized on */ private final DataOutputStream _outputStream; /** Time to linger before closing the socket forcefully. */ public static final int SOCKET_CLOSING_TIMEOUT = 1; /** * @param socket the socket to use */ public SocketFrameHandler(Socket socket) throws IOException { this(socket, null); } /** * @param socket the socket to use */ public SocketFrameHandler(Socket socket, ExecutorService shutdownExecutor) throws IOException { _socket = socket; _shutdownExecutor = shutdownExecutor; _inputStream = new DataInputStream(new BufferedInputStream(socket.getInputStream())); _outputStream = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream())); } @Override public InetAddress getAddress() { return _socket.getInetAddress(); } @Override public InetAddress getLocalAddress() { return _socket.getLocalAddress(); } // For testing only public DataInputStream getInputStream() { return _inputStream; } @Override public int getPort() { return _socket.getPort(); } @Override public int getLocalPort() { return _socket.getLocalPort(); } @Override public void setTimeout(int timeoutMs) throws SocketException { _socket.setSoTimeout(timeoutMs); } @Override public int getTimeout() throws SocketException { return _socket.getSoTimeout(); } /** * Write a 0-8-style connection header to the underlying socket, * containing the specified version information, kickstarting the * AMQP protocol version negotiation process. * * @param major major protocol version number * @param minor minor protocol version number * @throws IOException if there is a problem accessing the connection * @see #sendHeader() */ public void sendHeader(int major, int minor) throws IOException { synchronized (_outputStream) { _outputStream.write("AMQP".getBytes("US-ASCII")); _outputStream.write(1); _outputStream.write(1); _outputStream.write(major); _outputStream.write(minor); _outputStream.flush(); } } /** * Write a 0-9-1-style connection header to the underlying socket, * containing the specified version information, kickstarting the * AMQP protocol version negotiation process. * * @param major major protocol version number * @param minor minor protocol version number * @param revision protocol revision number * @throws IOException if there is a problem accessing the connection * @see #sendHeader() */ public void sendHeader(int major, int minor, int revision) throws IOException { synchronized (_outputStream) { _outputStream.write("AMQP".getBytes("US-ASCII")); _outputStream.write(0); _outputStream.write(major); _outputStream.write(minor); _outputStream.write(revision); _outputStream.flush(); } } @Override public void sendHeader() throws IOException { sendHeader(AMQP.PROTOCOL.MAJOR, AMQP.PROTOCOL.MINOR, AMQP.PROTOCOL.REVISION); } @Override public void initialize(AMQConnection connection) { connection.startMainLoop(); } @Override public Frame readFrame() throws IOException { synchronized (_inputStream) { return Frame.readFrom(_inputStream); } } @Override public void writeFrame(Frame frame) throws IOException { synchronized (_outputStream) { frame.writeTo(_outputStream); } } @Override public void flush() throws IOException { _outputStream.flush(); } @Override public void close() { try { _socket.setSoLinger(true, SOCKET_CLOSING_TIMEOUT); } catch (Exception _e) {} // async flush if possible // see https://github.com/rabbitmq/rabbitmq-java-client/issues/194 Callable flushCallable = new Callable() { @Override public Void call() throws Exception { flush(); return null; } }; Future flushTask = null; try { if(this._shutdownExecutor == null) { flushCallable.call(); } else { flushTask = this._shutdownExecutor.submit(flushCallable); flushTask.get(SOCKET_CLOSING_TIMEOUT, TimeUnit.SECONDS); } } catch(Exception e) { if(flushTask != null) { flushTask.cancel(true); } } try { _socket.close(); } catch (Exception _e) {} } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/SocketFrameHandlerFactory.java000066400000000000000000000072651316117667700326670ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl; import com.rabbitmq.client.Address; import com.rabbitmq.client.ConnectionFactory; import com.rabbitmq.client.SocketConfigurator; import com.rabbitmq.client.SslContextFactory; import javax.net.SocketFactory; import java.io.IOException; import java.net.InetSocketAddress; import java.net.Socket; import java.util.concurrent.ExecutorService; public class SocketFrameHandlerFactory extends AbstractFrameHandlerFactory { private final SocketFactory socketFactory; private final ExecutorService shutdownExecutor; private final SslContextFactory sslContextFactory; public SocketFrameHandlerFactory(int connectionTimeout, SocketFactory socketFactory, SocketConfigurator configurator, boolean ssl) { this(connectionTimeout, socketFactory, configurator, ssl, null); } public SocketFrameHandlerFactory(int connectionTimeout, SocketFactory socketFactory, SocketConfigurator configurator, boolean ssl, ExecutorService shutdownExecutor) { this(connectionTimeout, socketFactory, configurator, ssl, shutdownExecutor, null); } public SocketFrameHandlerFactory(int connectionTimeout, SocketFactory socketFactory, SocketConfigurator configurator, boolean ssl, ExecutorService shutdownExecutor, SslContextFactory sslContextFactory) { super(connectionTimeout, configurator, ssl); this.socketFactory = socketFactory; this.shutdownExecutor = shutdownExecutor; this.sslContextFactory = sslContextFactory; } public FrameHandler create(Address addr, String connectionName) throws IOException { String hostName = addr.getHost(); int portNumber = ConnectionFactory.portOrDefault(addr.getPort(), ssl); Socket socket = null; try { socket = createSocket(connectionName); configurator.configure(socket); socket.connect(new InetSocketAddress(hostName, portNumber), connectionTimeout); return create(socket); } catch (IOException ioe) { quietTrySocketClose(socket); throw ioe; } } protected Socket createSocket(String connectionName) throws IOException { // SocketFactory takes precedence if specified if (socketFactory != null) { return socketFactory.createSocket(); } else { if (ssl) { return sslContextFactory.create(connectionName).getSocketFactory().createSocket(); } else { return SocketFactory.getDefault().createSocket(); } } } public FrameHandler create(Socket sock) throws IOException { return new SocketFrameHandler(sock, this.shutdownExecutor); } private static void quietTrySocketClose(Socket socket) { if (socket != null) try { socket.close(); } catch (Exception _e) {/*ignore exceptions*/} } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/StandardMetricsCollector.java000066400000000000000000000074631316117667700325740ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl; import com.codahale.metrics.Counter; import com.codahale.metrics.Meter; import com.codahale.metrics.MetricRegistry; import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; import com.rabbitmq.client.MetricsCollector; /** * Dropwizard Metrics implementation of {@link MetricsCollector}. * Note transactions are not supported (see {@link MetricsCollector}. * Metrics provides out-of-the-box support for report backends like JMX, * Graphite, Ganglia, or plain HTTP. See Metrics documentation for * more details. * * @see MetricsCollector */ public class StandardMetricsCollector extends AbstractMetricsCollector { private final MetricRegistry registry; private final Counter connections; private final Counter channels; private final Meter publishedMessages; private final Meter consumedMessages; private final Meter acknowledgedMessages; private final Meter rejectedMessages; public StandardMetricsCollector(MetricRegistry registry, String metricsPrefix) { this.registry = registry; this.connections = registry.counter(metricsPrefix+".connections"); this.channels = registry.counter(metricsPrefix+".channels"); this.publishedMessages = registry.meter(metricsPrefix+".published"); this.consumedMessages = registry.meter(metricsPrefix+".consumed"); this.acknowledgedMessages = registry.meter(metricsPrefix+".acknowledged"); this.rejectedMessages = registry.meter(metricsPrefix+".rejected"); } public StandardMetricsCollector() { this(new MetricRegistry()); } public StandardMetricsCollector(MetricRegistry metricRegistry) { this(metricRegistry, "rabbitmq"); } @Override protected void incrementConnectionCount(Connection connection) { connections.inc(); } @Override protected void decrementConnectionCount(Connection connection) { connections.dec(); } @Override protected void incrementChannelCount(Channel channel) { channels.inc(); } @Override protected void decrementChannelCount(Channel channel) { channels.dec(); } @Override protected void markPublishedMessage() { publishedMessages.mark(); } @Override protected void markConsumedMessage() { consumedMessages.mark(); } @Override protected void markAcknowledgedMessage() { acknowledgedMessages.mark(); } @Override protected void markRejectedMessage() { rejectedMessages.mark(); } public MetricRegistry getMetricRegistry() { return registry; } public Counter getConnections() { return connections; } public Counter getChannels() { return channels; } public Meter getPublishedMessages() { return publishedMessages; } public Meter getConsumedMessages() { return consumedMessages; } public Meter getAcknowledgedMessages() { return acknowledgedMessages; } public Meter getRejectedMessages() { return rejectedMessages; } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/StrictExceptionHandler.java000066400000000000000000000057651316117667700322660ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl; import com.rabbitmq.client.*; import java.io.IOException; import java.util.concurrent.TimeoutException; /** * An implementation of {@link com.rabbitmq.client.ExceptionHandler} that does * close channels on unhandled consumer exception. * * Used by {@link AMQConnection}. * * @see ExceptionHandler * @see com.rabbitmq.client.ConnectionFactory#setExceptionHandler(ExceptionHandler) */ public class StrictExceptionHandler extends ForgivingExceptionHandler implements ExceptionHandler { @Override public void handleReturnListenerException(Channel channel, Throwable exception) { handleChannelKiller(channel, exception, "ReturnListener.handleReturn"); } @Override public void handleConfirmListenerException(Channel channel, Throwable exception) { handleChannelKiller(channel, exception, "ConfirmListener.handle{N,A}ck"); } @Override public void handleBlockedListenerException(Connection connection, Throwable exception) { handleConnectionKiller(connection, exception, "BlockedListener"); } @Override public void handleConsumerException(Channel channel, Throwable exception, Consumer consumer, String consumerTag, String methodName) { handleChannelKiller(channel, exception, "Consumer " + consumer + " (" + consumerTag + ")" + " method " + methodName + " for channel " + channel); } @Override protected void handleChannelKiller(Channel channel, Throwable exception, String what) { log(what + " threw an exception for channel " + channel, exception); try { channel.close(AMQP.REPLY_SUCCESS, "Closed due to exception from " + what); } catch (AlreadyClosedException ace) { // noop } catch (TimeoutException ace) { // noop } catch (IOException ioe) { log("Failure during close of channel " + channel + " after " + exception, ioe); channel.getConnection().abort(AMQP.INTERNAL_ERROR, "Internal error closing channel for " + what); } } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/TruncatedInputStream.java000066400000000000000000000045301316117667700317530ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl; import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; /** * Utility stream: proxies another stream, making it appear to be no * longer than a preset limit. */ public class TruncatedInputStream extends FilterInputStream { private final long limit; private long counter = 0L; private long mark = 0L; public TruncatedInputStream(InputStream in, long limit) { super(in); this.limit = limit; } @Override public int available() throws IOException { return (int) Math.min(limit - counter, super.available()); } @Override public synchronized void mark(int readlimit) { super.mark(readlimit); mark = counter; } @Override public int read() throws IOException { if (counter < limit) { int result = super.read(); if (result >= 0) counter++; return result; } return -1; } @Override public int read(byte[] b, int off, int len) throws IOException { if (limit > counter) { int result = super.read(b, off, (int) Math.min(len, limit - counter)); if (result > 0) counter += result; return result; } return -1; } @Override public synchronized void reset() throws IOException { super.reset(); counter = mark; } @Override public long skip(long n) throws IOException { long result = super.skip(Math.min(n, limit - counter)); counter += result; return result; } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/UnknownChannelException.java000066400000000000000000000022531316117667700324350ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl; class UnknownChannelException extends RuntimeException { /** Default for non-checking. */ private static final long serialVersionUID = 1L; private final int channelNumber; public UnknownChannelException(int channelNumber) { super("Unknown channel number " + channelNumber); this.channelNumber = channelNumber; } public int getChannelNumber() { return channelNumber; } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/ValueReader.java000066400000000000000000000162751316117667700300360ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl; import java.io.DataInputStream; import java.io.IOException; import java.math.BigDecimal; import java.math.BigInteger; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.List; import java.util.ArrayList; import com.rabbitmq.client.LongString; import com.rabbitmq.client.MalformedFrameException; /** * Helper class to read AMQP wire-protocol encoded values. */ public class ValueReader { private static final long INT_MASK = 0xffffffffL; /** * Protected API - Cast an int to a long without extending the * sign bit of the int out into the high half of the long. */ private static long unsignedExtend(int value) { long extended = value; return extended & INT_MASK; } /** The stream we are reading from. */ private final DataInputStream in; /** * Construct a MethodArgumentReader streaming over the given DataInputStream. */ public ValueReader(DataInputStream in) { this.in = in; } /** Convenience method - reads a short string from a DataInput * Stream. */ private static String readShortstr(DataInputStream in) throws IOException { byte [] b = new byte[in.readUnsignedByte()]; in.readFully(b); return new String(b, "utf-8"); } /** Public API - reads a short string. */ public final String readShortstr() throws IOException { return readShortstr(this.in); } /** Convenience method - reads a 32-bit-length-prefix * byte vector from a DataInputStream. */ private static byte[] readBytes(final DataInputStream in) throws IOException { final long contentLength = unsignedExtend(in.readInt()); if(contentLength < Integer.MAX_VALUE) { final byte [] buffer = new byte[(int)contentLength]; in.readFully(buffer); return buffer; } else { throw new UnsupportedOperationException ("Very long byte vectors and strings not currently supported"); } } /** Convenience method - reads a long string argument * from a DataInputStream. */ private static LongString readLongstr(final DataInputStream in) throws IOException { return LongStringHelper.asLongString(readBytes(in)); } /** Public API - reads a long string. */ public final LongString readLongstr() throws IOException { return readLongstr(this.in); } /** Public API - reads a short integer. */ public final int readShort() throws IOException { return in.readUnsignedShort(); } /** Public API - reads an integer. */ public final int readLong() throws IOException { return in.readInt(); } /** Public API - reads a long integer. */ public final long readLonglong() throws IOException { return in.readLong(); } /** * Reads a table argument from a given stream. Also * called by {@link ContentHeaderPropertyReader}. */ private static Map readTable(DataInputStream in) throws IOException { long tableLength = unsignedExtend(in.readInt()); if (tableLength == 0) return Collections.emptyMap(); Map table = new HashMap(); DataInputStream tableIn = new DataInputStream (new TruncatedInputStream(in, tableLength)); while(tableIn.available() > 0) { String name = readShortstr(tableIn); Object value = readFieldValue(tableIn); if(!table.containsKey(name)) table.put(name, value); } return table; } private static Object readFieldValue(DataInputStream in) throws IOException { Object value = null; switch(in.readUnsignedByte()) { case 'S': value = readLongstr(in); break; case 'I': value = in.readInt(); break; case 'D': int scale = in.readUnsignedByte(); byte [] unscaled = new byte[4]; in.readFully(unscaled); value = new BigDecimal(new BigInteger(unscaled), scale); break; case 'T': value = readTimestamp(in); break; case 'F': value = readTable(in); break; case 'A': value = readArray(in); break; case 'b': value = in.readByte(); break; case 'd': value = in.readDouble(); break; case 'f': value = in.readFloat(); break; case 'l': value = in.readLong(); break; case 's': value = in.readShort(); break; case 't': value = in.readBoolean(); break; case 'x': value = readBytes(in); break; case 'V': value = null; break; default: throw new MalformedFrameException ("Unrecognised type in table"); } return value; } /** Read a field-array */ private static List readArray(DataInputStream in) throws IOException { long length = unsignedExtend(in.readInt()); DataInputStream arrayIn = new DataInputStream (new TruncatedInputStream(in, length)); List array = new ArrayList(); while(arrayIn.available() > 0) { Object value = readFieldValue(arrayIn); array.add(value); } return array; } /** Public API - reads a table. */ public final Map readTable() throws IOException { return readTable(this.in); } /** Public API - reads an octet. */ public final int readOctet() throws IOException { return in.readUnsignedByte(); } /** Convenience method - reads a timestamp argument from the DataInputStream. */ private static Date readTimestamp(DataInputStream in) throws IOException { return new Date(in.readLong()*1000); } /** Public API - reads an timestamp. */ public final Date readTimestamp() throws IOException { return readTimestamp(this.in); } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/ValueWriter.java000066400000000000000000000176501316117667700301060ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.math.BigDecimal; import java.math.BigInteger; import java.util.Date; import java.util.Map; import java.util.List; import com.rabbitmq.client.LongString; /** * Helper class to generate AMQP wire-protocol encoded values. */ public class ValueWriter { private final DataOutputStream out; public ValueWriter(DataOutputStream out) { this.out = out; } /** Public API - encodes a short string. */ public final void writeShortstr(String str) throws IOException { byte [] bytes = str.getBytes("utf-8"); int length = bytes.length; if (length > 255) { throw new IllegalArgumentException( "Short string too long; utf-8 encoded length = " + length + ", max = 255."); } out.writeByte(bytes.length); out.write(bytes); } /** Public API - encodes a long string from a LongString. */ public final void writeLongstr(LongString str) throws IOException { writeLong((int)str.length()); copy(str.getStream(), out); } private static final int COPY_BUFFER_SIZE = 4096; private static void copy(InputStream input, OutputStream output) throws IOException { byte[] buffer = new byte[COPY_BUFFER_SIZE]; int biteSize = input.read(buffer); while (-1 != biteSize) { output.write(buffer, 0, biteSize); biteSize = input.read(buffer); } } /** Public API - encodes a long string from a String. */ public final void writeLongstr(String str) throws IOException { byte [] bytes = str.getBytes("utf-8"); writeLong(bytes.length); out.write(bytes); } /** Public API - encodes a short integer. */ public final void writeShort(int s) throws IOException { out.writeShort(s); } /** Public API - encodes an integer. */ public final void writeLong(int l) throws IOException { // java's arithmetic on this type is signed, however it's // reasonable to use ints to represent the unsigned long // type - for values < Integer.MAX_VALUE everything works // as expected out.writeInt(l); } /** Public API - encodes a long integer. */ public final void writeLonglong(long ll) throws IOException { out.writeLong(ll); } /** Public API - encodes a table. */ public final void writeTable(Map table) throws IOException { if (table == null) { // Convenience. out.writeInt(0); } else { out.writeInt((int)Frame.tableSize(table)); for(Map.Entry entry: table.entrySet()) { writeShortstr(entry.getKey()); Object value = entry.getValue(); writeFieldValue(value); } } } public final void writeFieldValue(Object value) throws IOException { if(value instanceof String) { writeOctet('S'); writeLongstr((String)value); } else if(value instanceof LongString) { writeOctet('S'); writeLongstr((LongString)value); } else if(value instanceof Integer) { writeOctet('I'); writeLong((Integer) value); } else if(value instanceof BigDecimal) { writeOctet('D'); BigDecimal decimal = (BigDecimal)value; writeOctet(decimal.scale()); BigInteger unscaled = decimal.unscaledValue(); if(unscaled.bitLength() > 32) /*Integer.SIZE in Java 1.5*/ throw new IllegalArgumentException ("BigDecimal too large to be encoded"); writeLong(decimal.unscaledValue().intValue()); } else if(value instanceof Date) { writeOctet('T'); writeTimestamp((Date)value); } else if(value instanceof Map) { writeOctet('F'); // Ignore the warnings here. We hate erasure // (not even a little respect) // (We even have trouble recognising it.) @SuppressWarnings("unchecked") Map map = (Map) value; writeTable(map); } else if (value instanceof Byte) { writeOctet('b'); out.writeByte((Byte)value); } else if(value instanceof Double) { writeOctet('d'); out.writeDouble((Double)value); } else if(value instanceof Float) { writeOctet('f'); out.writeFloat((Float)value); } else if(value instanceof Long) { writeOctet('l'); out.writeLong((Long)value); } else if(value instanceof Short) { writeOctet('s'); out.writeShort((Short)value); } else if(value instanceof Boolean) { writeOctet('t'); out.writeBoolean((Boolean)value); } else if(value instanceof byte[]) { writeOctet('x'); writeLong(((byte[])value).length); out.write((byte[])value); } else if(value == null) { writeOctet('V'); } else if(value instanceof List) { writeOctet('A'); writeArray((List)value); } else if(value instanceof Object[]) { writeOctet('A'); writeArray((Object[])value); } else { throw new IllegalArgumentException ("Invalid value type: " + value.getClass().getName()); } } public final void writeArray(List value) throws IOException { if (value==null) { out.write(0); } else { out.writeInt((int)Frame.arraySize(value)); for (Object item : value) { writeFieldValue(item); } } } public final void writeArray(Object[] value) throws IOException { if (value==null) { out.write(0); } else { out.writeInt((int)Frame.arraySize(value)); for (Object item : value) { writeFieldValue(item); } } } /** Public API - encodes an octet from an int. */ public final void writeOctet(int octet) throws IOException { out.writeByte(octet); } /** Public API - encodes an octet from a byte. */ public final void writeOctet(byte octet) throws IOException { out.writeByte(octet); } /** Public API - encodes a timestamp. */ public final void writeTimestamp(Date timestamp) throws IOException { // AMQP uses POSIX time_t which is in seconds since the epoch began writeLonglong(timestamp.getTime()/1000); } /** * Public API - call this to ensure all accumulated * values are correctly written to the output stream. */ public void flush() throws IOException { out.flush(); } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/VariableLinkedBlockingQueue.java000066400000000000000000000604361316117667700331670ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. /* * Modifications Copyright 2015 Pivotal Software, Inc and licenced as per * the rest of the RabbitMQ Java client. */ /* * Written by Doug Lea with assistance from members of JCP JSR-166 * Expert Group and released to the public domain, as explained at * http://creativecommons.org/licenses/publicdomain */ package com.rabbitmq.client.impl; import java.util.concurrent.BlockingQueue; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.*; import java.util.concurrent.locks.*; import java.util.*; /** * A clone of {@linkplain java.util.concurrent.LinkedBlockingQueue} * with the addition of a {@link #setCapacity(int)} method, allowing us to * change the capacity of the queue while it is in use.

* * The documentation for LinkedBlockingQueue follows...

* * An optionally-bounded {@linkplain BlockingQueue blocking queue} based on * linked nodes. * This queue orders elements FIFO (first-in-first-out). * The head of the queue is that element that has been on the * queue the longest time. * The tail of the queue is that element that has been on the * queue the shortest time. New elements * are inserted at the tail of the queue, and the queue retrieval * operations obtain elements at the head of the queue. * Linked queues typically have higher throughput than array-based queues but * less predictable performance in most concurrent applications. * *

The optional capacity bound constructor argument serves as a * way to prevent excessive queue expansion. The capacity, if unspecified, * is equal to {@link Integer#MAX_VALUE}. Linked nodes are * dynamically created upon each insertion unless this would bring the * queue above capacity. * *

This class implements all of the optional methods * of the {@link Collection} and {@link Iterator} interfaces. * *

This class is a member of the * * Java Collections Framework. * * @since 1.5 * @author Doug Lea * @param the type of elements held in this collection * **/ public class VariableLinkedBlockingQueue extends AbstractQueue implements BlockingQueue, java.io.Serializable { private static final long serialVersionUID = -6903933977591709194L; /* * A variant of the "two lock queue" algorithm. The putLock gates * entry to put (and offer), and has an associated condition for * waiting puts. Similarly for the takeLock. The "count" field * that they both rely on is maintained as an atomic to avoid * needing to get both locks in most cases. Also, to minimize need * for puts to get takeLock and vice-versa, cascading notifies are * used. When a put notices that it has enabled at least one take, * it signals taker. That taker in turn signals others if more * items have been entered since the signal. And symmetrically for * takes signalling puts. Operations such as remove(Object) and * iterators acquire both locks. */ /** * Linked list node class */ static class Node { /** The item, volatile to ensure barrier separating write and read */ volatile E item; Node next; Node(E x) { item = x; } } /** The capacity bound, or Integer.MAX_VALUE if none */ private int capacity; /** Current number of elements */ private final AtomicInteger count = new AtomicInteger(0); /** Head of linked list */ private transient Node head; /** Tail of linked list */ private transient Node last; /** Lock held by take, poll, etc */ private final ReentrantLock takeLock = new ReentrantLock(); /** Wait queue for waiting takes */ private final Condition notEmpty = takeLock.newCondition(); /** Lock held by put, offer, etc */ private final ReentrantLock putLock = new ReentrantLock(); /** Wait queue for waiting puts */ private final Condition notFull = putLock.newCondition(); /** * Signal a waiting take. Called only from put/offer (which do not * otherwise ordinarily lock takeLock.) */ private void signalNotEmpty() { final ReentrantLock takeLock = this.takeLock; takeLock.lock(); try { notEmpty.signal(); } finally { takeLock.unlock(); } } /** * Signal a waiting put. Called only from take/poll. */ private void signalNotFull() { final ReentrantLock putLock = this.putLock; putLock.lock(); try { notFull.signal(); } finally { putLock.unlock(); } } /** * Create a node and link it at end of queue * @param x the item */ private void insert(E x) { last = last.next = new Node(x); } /** * Remove a node from head of queue, * @return the node */ private E extract() { Node first = head.next; head = first; E x = first.item; first.item = null; return x; } /** * Lock to prevent both puts and takes. */ private void fullyLock() { putLock.lock(); takeLock.lock(); } /** * Unlock to allow both puts and takes. */ private void fullyUnlock() { takeLock.unlock(); putLock.unlock(); } /** * Creates a LinkedBlockingQueue with a capacity of * {@link Integer#MAX_VALUE}. */ public VariableLinkedBlockingQueue() { this(Integer.MAX_VALUE); } /** * Creates a LinkedBlockingQueue with the given (fixed) capacity. * * @param capacity the capacity of this queue. * @throws IllegalArgumentException if capacity is not greater * than zero. */ public VariableLinkedBlockingQueue(int capacity) { if (capacity <= 0) throw new IllegalArgumentException(); this.capacity = capacity; last = head = new Node(null); } /** * Creates a LinkedBlockingQueue with a capacity of * {@link Integer#MAX_VALUE}, initially containing the elements of the * given collection, * added in traversal order of the collection's iterator. * @param c the collection of elements to initially contain * @throws NullPointerException if c or any element within it * is null */ public VariableLinkedBlockingQueue(Collection c) { this(Integer.MAX_VALUE); for (Iterator it = c.iterator(); it.hasNext();) add(it.next()); } // this doc comment is overridden to remove the reference to collections // greater in size than Integer.MAX_VALUE /** * Returns the number of elements in this queue. * * @return the number of elements in this queue. */ @Override public int size() { return count.get(); } /** * Set a new capacity for the queue. Increasing the capacity can * cause any waiting {@link #put(Object)} invocations to succeed if the new * capacity is larger than the queue. * @param capacity the new capacity for the queue */ public void setCapacity(int capacity) { final int oldCapacity = this.capacity; this.capacity = capacity; final int size = count.get(); if (capacity > size && size >= oldCapacity) { signalNotFull(); } } // this doc comment is a modified copy of the inherited doc comment, // without the reference to unlimited queues. /** * Returns the number of elements that this queue can ideally (in * the absence of memory or resource constraints) accept without * blocking. This is always equal to the initial capacity of this queue * less the current size of this queue. *

Note that you cannot always tell if * an attempt to add an element will succeed by * inspecting remainingCapacity because it may be the * case that a waiting consumer is ready to take an * element out of an otherwise full queue. */ @Override public int remainingCapacity() { return capacity - count.get(); } /** * Adds the specified element to the tail of this queue, waiting if * necessary for space to become available. * @param o the element to add * @throws InterruptedException if interrupted while waiting. * @throws NullPointerException if the specified element is null. */ @Override public void put(E o) throws InterruptedException { if (o == null) throw new NullPointerException(); // Note: convention in all put/take/etc is to preset // local var holding count negative to indicate failure unless set. int c = -1; final ReentrantLock putLock = this.putLock; final AtomicInteger count = this.count; putLock.lockInterruptibly(); try { /* * Note that count is used in wait guard even though it is * not protected by lock. This works because count can * only decrease at this point (all other puts are shut * out by lock), and we (or some other waiting put) are * signalled if it ever changes from * capacity. Similarly for all other uses of count in * other wait guards. */ try { while (count.get() >= capacity) notFull.await(); } catch (InterruptedException ie) { notFull.signal(); // propagate to a non-interrupted thread throw ie; } insert(o); c = count.getAndIncrement(); if (c + 1 < capacity) notFull.signal(); } finally { putLock.unlock(); } if (c == 0) signalNotEmpty(); } /** * Inserts the specified element at the tail of this queue, waiting if * necessary up to the specified wait time for space to become available. * @param o the element to add * @param timeout how long to wait before giving up, in units of * unit * @param unit a TimeUnit determining how to interpret the * timeout parameter * @return true if successful, or false if * the specified waiting time elapses before space is available. * @throws InterruptedException if interrupted while waiting. * @throws NullPointerException if the specified element is null. */ @Override public boolean offer(E o, long timeout, TimeUnit unit) throws InterruptedException { if (o == null) throw new NullPointerException(); long nanos = unit.toNanos(timeout); int c = -1; final ReentrantLock putLock = this.putLock; final AtomicInteger count = this.count; putLock.lockInterruptibly(); try { for (;;) { if (count.get() < capacity) { insert(o); c = count.getAndIncrement(); if (c + 1 < capacity) notFull.signal(); break; } if (nanos <= 0) return false; try { nanos = notFull.awaitNanos(nanos); } catch (InterruptedException ie) { notFull.signal(); // propagate to a non-interrupted thread throw ie; } } } finally { putLock.unlock(); } if (c == 0) signalNotEmpty(); return true; } /** * Inserts the specified element at the tail of this queue if possible, * returning immediately if this queue is full. * * @param o the element to add. * @return true if it was possible to add the element to * this queue, else false * @throws NullPointerException if the specified element is null */ @Override public boolean offer(E o) { if (o == null) throw new NullPointerException(); final AtomicInteger count = this.count; if (count.get() >= capacity) return false; int c = -1; final ReentrantLock putLock = this.putLock; putLock.lock(); try { if (count.get() < capacity) { insert(o); c = count.getAndIncrement(); if (c + 1 < capacity) notFull.signal(); } } finally { putLock.unlock(); } if (c == 0) signalNotEmpty(); return c >= 0; } @Override public E take() throws InterruptedException { E x; int c = -1; final AtomicInteger count = this.count; final ReentrantLock takeLock = this.takeLock; takeLock.lockInterruptibly(); try { try { while (count.get() == 0) notEmpty.await(); } catch (InterruptedException ie) { notEmpty.signal(); // propagate to a non-interrupted thread throw ie; } x = extract(); c = count.getAndDecrement(); if (c > 1) notEmpty.signal(); } finally { takeLock.unlock(); } if (c >= capacity) signalNotFull(); return x; } @Override public E poll(long timeout, TimeUnit unit) throws InterruptedException { E x = null; int c = -1; long nanos = unit.toNanos(timeout); final AtomicInteger count = this.count; final ReentrantLock takeLock = this.takeLock; takeLock.lockInterruptibly(); try { for (;;) { if (count.get() > 0) { x = extract(); c = count.getAndDecrement(); if (c > 1) notEmpty.signal(); break; } if (nanos <= 0) return null; try { nanos = notEmpty.awaitNanos(nanos); } catch (InterruptedException ie) { notEmpty.signal(); // propagate to a non-interrupted thread throw ie; } } } finally { takeLock.unlock(); } if (c >= capacity) signalNotFull(); return x; } @Override public E poll() { final AtomicInteger count = this.count; if (count.get() == 0) return null; E x = null; int c = -1; final ReentrantLock takeLock = this.takeLock; takeLock.lock(); try { if (count.get() > 0) { x = extract(); c = count.getAndDecrement(); if (c > 1) notEmpty.signal(); } } finally { takeLock.unlock(); } if (c >= capacity) signalNotFull(); return x; } @Override public E peek() { if (count.get() == 0) return null; final ReentrantLock takeLock = this.takeLock; takeLock.lock(); try { Node first = head.next; if (first == null) return null; else return first.item; } finally { takeLock.unlock(); } } @Override public boolean remove(Object o) { if (o == null) return false; boolean removed = false; fullyLock(); try { Node trail = head; Node p = head.next; while (p != null) { if (o.equals(p.item)) { removed = true; break; } trail = p; p = p.next; } if (removed) { p.item = null; trail.next = p.next; if (count.getAndDecrement() >= capacity) notFull.signalAll(); } } finally { fullyUnlock(); } return removed; } @Override public Object[] toArray() { fullyLock(); try { int size = count.get(); Object[] a = new Object[size]; int k = 0; for (Node p = head.next; p != null; p = p.next) a[k++] = p.item; return a; } finally { fullyUnlock(); } } @Override @SuppressWarnings("unchecked") public T[] toArray(T[] a) { fullyLock(); try { int size = count.get(); if (a.length < size) a = (T[])java.lang.reflect.Array.newInstance (a.getClass().getComponentType(), size); int k = 0; for (Node p = head.next; p != null; p = p.next) a[k++] = (T)p.item; return a; } finally { fullyUnlock(); } } @Override public String toString() { fullyLock(); try { return super.toString(); } finally { fullyUnlock(); } } @Override public void clear() { fullyLock(); try { head.next = null; if (count.getAndSet(0) >= capacity) notFull.signalAll(); } finally { fullyUnlock(); } } @Override public int drainTo(Collection c) { if (c == null) throw new NullPointerException(); if (c == this) throw new IllegalArgumentException(); Node first; fullyLock(); try { first = head.next; head.next = null; if (count.getAndSet(0) >= capacity) notFull.signalAll(); } finally { fullyUnlock(); } // Transfer the elements outside of locks int n = 0; for (Node p = first; p != null; p = p.next) { c.add(p.item); p.item = null; ++n; } return n; } @Override public int drainTo(Collection c, int maxElements) { if (c == null) throw new NullPointerException(); if (c == this) throw new IllegalArgumentException(); if (maxElements <= 0) return 0; fullyLock(); try { int n = 0; Node p = head.next; while (p != null && n < maxElements) { c.add(p.item); p.item = null; p = p.next; ++n; } if (n != 0) { head.next = p; if (count.getAndAdd(-n) >= capacity) notFull.signalAll(); } return n; } finally { fullyUnlock(); } } /** * Returns an iterator over the elements in this queue in proper sequence. * The returned Iterator is a "weakly consistent" iterator that * will never throw {@link java.util.ConcurrentModificationException}, * and guarantees to traverse elements as they existed upon * construction of the iterator, and may (but is not guaranteed to) * reflect any modifications subsequent to construction. * * @return an iterator over the elements in this queue in proper sequence. */ @Override public Iterator iterator() { return new Itr(); } private class Itr implements Iterator { /* * Basic weak-consistent iterator. At all times hold the next * item to hand out so that if hasNext() reports true, we will * still have it to return even if lost race with a take etc. */ private Node current; private Node lastRet; private E currentElement; Itr() { final ReentrantLock putLock = VariableLinkedBlockingQueue.this.putLock; final ReentrantLock takeLock = VariableLinkedBlockingQueue.this.takeLock; putLock.lock(); takeLock.lock(); try { current = head.next; if (current != null) currentElement = current.item; } finally { takeLock.unlock(); putLock.unlock(); } } @Override public boolean hasNext() { return current != null; } @Override public E next() { final ReentrantLock putLock = VariableLinkedBlockingQueue.this.putLock; final ReentrantLock takeLock = VariableLinkedBlockingQueue.this.takeLock; putLock.lock(); takeLock.lock(); try { if (current == null) throw new NoSuchElementException(); E x = currentElement; lastRet = current; current = current.next; if (current != null) currentElement = current.item; return x; } finally { takeLock.unlock(); putLock.unlock(); } } @Override public void remove() { if (lastRet == null) throw new IllegalStateException(); final ReentrantLock putLock = VariableLinkedBlockingQueue.this.putLock; final ReentrantLock takeLock = VariableLinkedBlockingQueue.this.takeLock; putLock.lock(); takeLock.lock(); try { Node node = lastRet; lastRet = null; Node trail = head; Node p = head.next; while (p != null && p != node) { trail = p; p = p.next; } if (p == node) { p.item = null; trail.next = p.next; int c = count.getAndDecrement(); if (c >= capacity) notFull.signalAll(); } } finally { takeLock.unlock(); putLock.unlock(); } } } /** * Save the state to a stream (that is, serialize it). * * @serialData The capacity is emitted (int), followed by all of * its elements (each an Object) in the proper order, * followed by a null * @param s the stream */ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException { fullyLock(); try { // Write out any hidden stuff, plus capacity s.defaultWriteObject(); // Write out all elements in the proper order. for (Node p = head.next; p != null; p = p.next) s.writeObject(p.item); // Use trailing null as sentinel s.writeObject(null); } finally { fullyUnlock(); } } /** * Reconstitute this queue instance from a stream (that is, * deserialize it). * @param s the stream */ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { // Read in capacity, and any hidden stuff s.defaultReadObject(); count.set(0); last = head = new Node(null); // Read in all elements and place in queue for (;;) { @SuppressWarnings("unchecked") E item = (E)s.readObject(); if (item == null) break; add(item); } } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/Version.java000066400000000000000000000060071316117667700272540ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl; /** * Encapsulation of AMQP protocol version */ public class Version { private final int _major; private final int _minor; /** * Creates a new Version instance. * * @param major the AMQP major version number * @param minor the AMQP minor version number */ public Version(int major, int minor) { _major = major; _minor = minor; } /** * Retrieve the major version number. * @return the major version number */ public int getMajor() { return _major; } /** * Retrieve the minor version number. * @return the minor version number */ public int getMinor() { return _minor; } /** * Retrieve a String representation of the version in the standard * AMQP version format of major-minor. * * @return a String representation of the version * @see Object#toString() */ @Override public String toString() { return "" + getMajor() + "-" + getMinor(); } @Override public boolean equals(Object o) { if(o instanceof Version) { Version other = (Version)o; return this.getMajor() == other.getMajor() && this.getMinor() == other.getMinor(); } else { return false; } } @Override public int hashCode() { return 31 * getMajor()+ getMinor(); } /** * Adjust a version for spec weirdness. * * The AMQP 0-8 spec confusingly defines the version as 8-0. This * method maps the latter to the former. * * @return the adjusted Version */ public Version adjust() { return (getMajor() == 8 && getMinor() == 0) ? new Version(0, 8) : this; } /** * Check compatibility of a client and server version, from the * client's perspective. * * @param clientVersion the client Version * @param serverVersion the server Version * @return a boolean value */ public static boolean checkVersion(Version clientVersion, Version serverVersion) { return clientVersion.adjust().equals(serverVersion.adjust()); } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/WorkPool.java000066400000000000000000000231471316117667700274070ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; /** *

This is a generic implementation of the channels specification * in Channeling Work, Nov 2010 (channels.pdf). * Objects of type K must be registered, with registerKey(K), * and then they become clients and a queue of * items (type W) is stored for each client. *

* Each client has a state which is exactly one of dormant, * in progress or ready. Immediately after registration a client is dormant. * Items may be (singly) added to (the end of) a client's queue with {@link WorkPool#addWorkItem(Object, Object)}. * If the client is dormant it becomes ready thereby. All other states remain unchanged. * The next ready client, together with a collection of its items, * may be retrieved with nextWorkBlock(collection,max) * (making that client in progress). * An in progress client can finish (processing a batch of items) with finishWorkBlock(K). * It then becomes either dormant or ready, depending if its queue of work items is empty or no. * If a client has items queued, it is either in progress or ready but cannot be both. * When work is finished it may be marked ready if there is further work, * or dormant if there is not. * There is never any work for a dormant client. * A client may be unregistered, with unregisterKey(K), which removes the client from * all parts of the state, and any queue of items stored with it. * All clients may be unregistered with unregisterAllKeys(). *

Concurrent Semantics

* This implementation is thread-safe. * @param Key -- type of client * @param Work -- type of work item */ public class WorkPool { private static final int MAX_QUEUE_LENGTH = 1000; /** An injective queue of ready clients. */ private final SetQueue ready = new SetQueue(); /** The set of clients which have work in progress. */ private final Set inProgress = new HashSet(); /** The pool of registered clients, with their work queues. */ private final Map> pool = new HashMap>(); /** Those keys which want limits to be removed. We do not limit queue size if this is non-empty. */ private final Set unlimited = new HashSet(); /** * Add client key to pool of item queues, with an empty queue. * A client is initially dormant. * No-op if key already present. * @param key client to add to pool */ public void registerKey(K key) { synchronized (this) { if (!this.pool.containsKey(key)) { int initialCapacity = unlimited.isEmpty() ? MAX_QUEUE_LENGTH : Integer.MAX_VALUE; this.pool.put(key, new VariableLinkedBlockingQueue(initialCapacity)); } } } public synchronized void limit(K key) { unlimited.remove(key); if (unlimited.isEmpty()) { setCapacities(MAX_QUEUE_LENGTH); } } public synchronized void unlimit(K key) { unlimited.add(key); if (!unlimited.isEmpty()) { setCapacities(Integer.MAX_VALUE); } } private void setCapacities(int capacity) { Iterator> it = pool.values().iterator(); while (it.hasNext()) { it.next().setCapacity(capacity); } } /** * Remove client from pool and from any other state. Has no effect if client already absent. * @param key of client to unregister */ public void unregisterKey(K key) { synchronized (this) { this.pool.remove(key); this.ready.remove(key); this.inProgress.remove(key); this.unlimited.remove(key); } } /** * Remove all clients from pool and from any other state. */ public void unregisterAllKeys() { synchronized (this) { this.pool.clear(); this.ready.clear(); this.inProgress.clear(); this.unlimited.clear(); } } /** * Return the next ready client, * and transfer a collection of that client's items to process. * Mark client in progress. * If there is no ready client, return null. * @param to collection object in which to transfer items * @param size max number of items to transfer * @return key of client to whom items belong, or null if there is none. */ public K nextWorkBlock(Collection to, int size) { synchronized (this) { K nextKey = readyToInProgress(); if (nextKey != null) { VariableLinkedBlockingQueue queue = this.pool.get(nextKey); drainTo(queue, to, size); } return nextKey; } } /** * Private implementation of drainTo (not implemented for LinkedList<W>s). * @param deList to take (poll) elements from * @param c to add elements to * @param maxElements to take from deList * @return number of elements actually taken */ private int drainTo(VariableLinkedBlockingQueue deList, Collection c, int maxElements) { int n = 0; while (n < maxElements) { W first = deList.poll(); if (first == null) break; c.add(first); ++n; } return n; } /** * Add (enqueue) an item for a specific client. * No change and returns false if client not registered. * If dormant, the client will be marked ready. * @param key the client to add to the work item to * @param item the work item to add to the client queue * @return true if and only if the client is marked ready * — as a result of this work item */ public boolean addWorkItem(K key, W item) { VariableLinkedBlockingQueue queue; synchronized (this) { queue = this.pool.get(key); } // The put operation may block. We need to make sure we are not holding the lock while that happens. if (queue != null) { try { queue.put(item); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } synchronized (this) { if (isDormant(key)) { dormantToReady(key); return true; } } } return false; } /** * Set client no longer in progress. * Ignore unknown clients (and return false). * @param key client that has finished work * @return true if and only if client becomes ready * @throws IllegalStateException if registered client not in progress */ public boolean finishWorkBlock(K key) { synchronized (this) { if (!this.isRegistered(key)) return false; if (!this.inProgress.contains(key)) { throw new IllegalStateException("Client " + key + " not in progress"); } if (moreWorkItems(key)) { inProgressToReady(key); return true; } else { inProgressToDormant(key); return false; } } } private boolean moreWorkItems(K key) { VariableLinkedBlockingQueue leList = this.pool.get(key); return leList != null && !leList.isEmpty(); } /* State identification functions */ private boolean isInProgress(K key){ return this.inProgress.contains(key); } private boolean isReady(K key){ return this.ready.contains(key); } private boolean isRegistered(K key) { return this.pool.containsKey(key); } private boolean isDormant(K key){ return !isInProgress(key) && !isReady(key) && isRegistered(key); } /* State transition methods - all assume key registered */ private void inProgressToReady(K key){ this.inProgress.remove(key); this.ready.addIfNotPresent(key); } private void inProgressToDormant(K key){ this.inProgress.remove(key); } private void dormantToReady(K key){ this.ready.addIfNotPresent(key); } /* Basic work selector and state transition step */ private K readyToInProgress() { K key = this.ready.poll(); if (key != null) { this.inProgress.add(key); } return key; } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/nio/000077500000000000000000000000001316117667700255465ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/nio/ByteBufferInputStream.java000066400000000000000000000035461316117667700326520ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl.nio; import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; import java.nio.channels.ReadableByteChannel; /** * Bridge between the byte buffer and stream worlds. */ public class ByteBufferInputStream extends InputStream { private final ReadableByteChannel channel; private final ByteBuffer buffer; public ByteBufferInputStream(ReadableByteChannel channel, ByteBuffer buffer) { this.channel = channel; this.buffer = buffer; } @Override public int read() throws IOException { readFromNetworkIfNecessary(channel, buffer); return readFromBuffer(buffer); } private int readFromBuffer(ByteBuffer buffer) { return buffer.get() & 0xff; } private static void readFromNetworkIfNecessary(ReadableByteChannel channel, ByteBuffer buffer) throws IOException { if(!buffer.hasRemaining()) { buffer.clear(); int read = NioHelper.read(channel, buffer); if(read <= 0) { NioHelper.retryRead(channel, buffer); } buffer.flip(); } } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/nio/ByteBufferOutputStream.java000066400000000000000000000033521316117667700330460ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl.nio; import java.io.IOException; import java.io.OutputStream; import java.nio.ByteBuffer; import java.nio.channels.WritableByteChannel; /** * Bridge between the byte buffer and stream worlds. */ public class ByteBufferOutputStream extends OutputStream { private final WritableByteChannel channel; private final ByteBuffer buffer; public ByteBufferOutputStream(WritableByteChannel channel, ByteBuffer buffer) { this.buffer = buffer; this.channel = channel; } @Override public void write(int b) throws IOException { if(!buffer.hasRemaining()) { drain(channel, buffer); } buffer.put((byte) b); } @Override public void flush() throws IOException { drain(channel, buffer); } public static void drain(WritableByteChannel channel, ByteBuffer buffer) throws IOException { buffer.flip(); while(buffer.hasRemaining() && channel.write(buffer) != -1); buffer.clear(); } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/nio/FrameWriteRequest.java000066400000000000000000000022351316117667700320310ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl.nio; import com.rabbitmq.client.impl.Frame; import java.io.DataOutputStream; import java.io.IOException; /** * */ public class FrameWriteRequest implements WriteRequest { final Frame frame; public FrameWriteRequest(Frame frame) { this.frame = frame; } @Override public void handle(DataOutputStream outputStream) throws IOException { frame.writeTo(outputStream); } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/nio/HeaderWriteRequest.java000066400000000000000000000023721316117667700321710ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl.nio; import com.rabbitmq.client.AMQP; import java.io.DataOutputStream; import java.io.IOException; /** * */ public class HeaderWriteRequest implements WriteRequest { @Override public void handle(DataOutputStream outputStream) throws IOException { outputStream.write("AMQP".getBytes("US-ASCII")); outputStream.write(0); outputStream.write(AMQP.PROTOCOL.MAJOR); outputStream.write(AMQP.PROTOCOL.MINOR); outputStream.write(AMQP.PROTOCOL.REVISION); } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/nio/NioHelper.java000066400000000000000000000031431316117667700302770ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl.nio; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.ReadableByteChannel; public class NioHelper { static int read(ReadableByteChannel channel, ByteBuffer buffer) throws IOException { int read = channel.read(buffer); if(read < 0) { throw new IOException("I/O thread: reached EOF"); } return read; } static int retryRead(ReadableByteChannel channel, ByteBuffer buffer) throws IOException { int attempt = 0; int read = 0; while(attempt < 3) { try { Thread.sleep(100L); } catch (InterruptedException e) { // ignore } read = read(channel, buffer); if(read > 0) { break; } attempt++; } return read; } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/nio/NioLoop.java000066400000000000000000000326561316117667700300040ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl.nio; import com.rabbitmq.client.impl.Environment; import com.rabbitmq.client.impl.Frame; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.util.Iterator; import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.concurrent.ThreadFactory; /** * Logic of the NIO loop. */ public class NioLoop implements Runnable { private static final Logger LOGGER = LoggerFactory.getLogger(NioLoop.class); private final NioLoopContext context; private final NioParams nioParams; public NioLoop(NioParams nioParams, NioLoopContext loopContext) { this.nioParams = nioParams; this.context = loopContext; } @Override public void run() { final SelectorHolder selectorState = context.readSelectorState; final Selector selector = selectorState.selector; final Set registrations = selectorState.registrations; final ByteBuffer buffer = context.readBuffer; final SelectorHolder writeSelectorState = context.writeSelectorState; final Selector writeSelector = writeSelectorState.selector; final Set writeRegistrations = writeSelectorState.registrations; // whether there have been write registrations in the previous loop // registrations are done after Selector.select(), to work on clean keys // thus, any write operation is performed in the next loop // we don't want to wait in the read Selector.select() if there are // pending writes boolean writeRegistered = false; try { while (true && !Thread.currentThread().isInterrupted()) { for (SelectionKey selectionKey : selector.keys()) { SocketChannelFrameHandlerState state = (SocketChannelFrameHandlerState) selectionKey.attachment(); if (state.getConnection() != null && state.getConnection().getHeartbeat() > 0) { long now = System.currentTimeMillis(); if ((now - state.getLastActivity()) > state.getConnection().getHeartbeat() * 1000 * 2) { try { state.getConnection().handleHeartbeatFailure(); } catch (Exception e) { LOGGER.warn("Error after heartbeat failure of connection {}", state.getConnection()); } finally { selectionKey.cancel(); } } } } int select; if (!writeRegistered && registrations.isEmpty() && writeRegistrations.isEmpty()) { // we can block, registrations will call Selector.wakeup() select = selector.select(1000); if (selector.keys().size() == 0) { // we haven't been doing anything for a while, shutdown state boolean clean = context.cleanUp(); if (clean) { // we stop this thread return; } // there may be incoming connections, keep going } } else { // we don't have to block, we need to select and clean cancelled keys before registration select = selector.selectNow(); } writeRegistered = false; // registrations should be done after select, // once the cancelled keys have been actually removed SocketChannelRegistration registration; Iterator registrationIterator = registrations.iterator(); while (registrationIterator.hasNext()) { registration = registrationIterator.next(); registrationIterator.remove(); int operations = registration.operations; registration.state.getChannel().register(selector, operations, registration.state); } if (select > 0) { Set readyKeys = selector.selectedKeys(); Iterator iterator = readyKeys.iterator(); while (iterator.hasNext()) { SelectionKey key = iterator.next(); iterator.remove(); if (!key.isValid()) { continue; } if (key.isReadable()) { final SocketChannelFrameHandlerState state = (SocketChannelFrameHandlerState) key.attachment(); try { if (!state.getChannel().isOpen()) { key.cancel(); continue; } if(state.getConnection() == null) { // we're in AMQConnection#start, between the header sending and the FrameHandler#initialize // let's wait a bit more continue; } DataInputStream inputStream = state.inputStream; state.prepareForReadSequence(); while (state.continueReading()) { Frame frame = Frame.readFrom(inputStream); try { boolean noProblem = state.getConnection().handleReadFrame(frame); if (noProblem && (!state.getConnection().isRunning() || state.getConnection().hasBrokerInitiatedShutdown())) { // looks like the frame was Close-Ok or Close dispatchShutdownToConnection(state); key.cancel(); break; } } catch (Throwable ex) { // problem during frame processing, tell connection, and // we can stop for this channel handleIoError(state, ex); key.cancel(); break; } } state.setLastActivity(System.currentTimeMillis()); } catch (final Exception e) { LOGGER.warn("Error during reading frames", e); handleIoError(state, e); key.cancel(); } finally { buffer.clear(); } } } } // write loop select = writeSelector.selectNow(); // registrations should be done after select, // once the cancelled keys have been actually removed SocketChannelRegistration writeRegistration; Iterator writeRegistrationIterator = writeRegistrations.iterator(); while (writeRegistrationIterator.hasNext()) { writeRegistration = writeRegistrationIterator.next(); writeRegistrationIterator.remove(); int operations = writeRegistration.operations; try { if (writeRegistration.state.getChannel().isOpen()) { writeRegistration.state.getChannel().register(writeSelector, operations, writeRegistration.state); writeRegistered = true; } } catch (Exception e) { // can happen if the channel has been closed since the operation has been enqueued LOGGER.info("Error while registering socket channel for write: {}", e.getMessage()); } } if (select > 0) { Set readyKeys = writeSelector.selectedKeys(); Iterator iterator = readyKeys.iterator(); while (iterator.hasNext()) { SelectionKey key = iterator.next(); iterator.remove(); SocketChannelFrameHandlerState state = (SocketChannelFrameHandlerState) key.attachment(); if (!key.isValid()) { continue; } if (key.isWritable()) { boolean cancelKey = true; try { if (!state.getChannel().isOpen()) { key.cancel(); continue; } state.prepareForWriteSequence(); int toBeWritten = state.getWriteQueue().size(); int written = 0; DataOutputStream outputStream = state.outputStream; WriteRequest request; while (written <= toBeWritten && (request = state.getWriteQueue().poll()) != null) { request.handle(outputStream); written++; } outputStream.flush(); if (!state.getWriteQueue().isEmpty()) { cancelKey = true; } } catch (Exception e) { handleIoError(state, e); } finally { state.endWriteSequence(); if (cancelKey) { key.cancel(); } } } } } } } catch (Exception e) { LOGGER.error("Error in NIO loop", e); } } protected void handleIoError(SocketChannelFrameHandlerState state, Throwable ex) { if (needToDispatchIoError(state)) { dispatchIoErrorToConnection(state, ex); } else { try { state.close(); } catch (IOException e) { } } } protected boolean needToDispatchIoError(final SocketChannelFrameHandlerState state) { return state.getConnection().isOpen(); } protected void dispatchIoErrorToConnection(final SocketChannelFrameHandlerState state, final Throwable ex) { // In case of recovery after the shutdown, // the new connection shouldn't be initialized in // the NIO thread, to avoid a deadlock. Runnable shutdown = () -> state.getConnection().handleIoError(ex); if (executorService() == null) { String name = "rabbitmq-connection-shutdown-" + state.getConnection(); Thread shutdownThread = Environment.newThread(threadFactory(), shutdown, name); shutdownThread.start(); } else { executorService().submit(shutdown); } } protected void dispatchShutdownToConnection(final SocketChannelFrameHandlerState state) { Runnable shutdown = new Runnable() { @Override public void run() { state.getConnection().doFinalShutdown(); } }; if (executorService() == null) { String name = "rabbitmq-connection-shutdown-" + state.getConnection(); Thread shutdownThread = Environment.newThread(threadFactory(), shutdown, name); shutdownThread.start(); } else { executorService().submit(shutdown); } } private ExecutorService executorService() { return nioParams.getNioExecutor(); } private ThreadFactory threadFactory() { return nioParams.getThreadFactory(); } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/nio/NioLoopContext.java000066400000000000000000000060111316117667700313330ustar00rootroot00000000000000package com.rabbitmq.client.impl.nio; import com.rabbitmq.client.impl.Environment; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.Selector; import java.util.concurrent.ExecutorService; import java.util.concurrent.ThreadFactory; /** * */ public class NioLoopContext { private static final Logger LOGGER = LoggerFactory.getLogger(NioLoopContext.class); private final SocketChannelFrameHandlerFactory socketChannelFrameHandlerFactory; private final ExecutorService executorService; private final ThreadFactory threadFactory; final ByteBuffer readBuffer, writeBuffer; SelectorHolder readSelectorState; SelectorHolder writeSelectorState; public NioLoopContext(SocketChannelFrameHandlerFactory socketChannelFrameHandlerFactory, NioParams nioParams) { this.socketChannelFrameHandlerFactory = socketChannelFrameHandlerFactory; this.executorService = nioParams.getNioExecutor(); this.threadFactory = nioParams.getThreadFactory(); this.readBuffer = ByteBuffer.allocate(nioParams.getReadByteBufferSize()); this.writeBuffer = ByteBuffer.allocate(nioParams.getWriteByteBufferSize()); } void initStateIfNecessary() throws IOException { if (this.readSelectorState == null) { this.readSelectorState = new SelectorHolder(Selector.open()); this.writeSelectorState = new SelectorHolder(Selector.open()); startIoLoops(); } } private void startIoLoops() { if (executorService == null) { Thread nioThread = Environment.newThread( threadFactory, new NioLoop(socketChannelFrameHandlerFactory.nioParams, this), "rabbitmq-nio" ); nioThread.start(); } else { this.executorService.submit(new NioLoop(socketChannelFrameHandlerFactory.nioParams, this)); } } protected boolean cleanUp() { int readRegistrationsCount = readSelectorState.registrations.size(); if(readRegistrationsCount != 0) { return false; } socketChannelFrameHandlerFactory.lock(); try { if (readRegistrationsCount != readSelectorState.registrations.size()) { // a connection request has come in meanwhile, don't do anything return false; } try { readSelectorState.selector.close(); } catch (IOException e) { LOGGER.warn("Could not close read selector: {}", e.getMessage()); } try { writeSelectorState.selector.close(); } catch (IOException e) { LOGGER.warn("Could not close write selector: {}", e.getMessage()); } this.readSelectorState = null; this.writeSelectorState = null; } finally { socketChannelFrameHandlerFactory.unlock(); } return true; } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/nio/NioParams.java000066400000000000000000000243211316117667700303040ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl.nio; import com.rabbitmq.client.DefaultSocketChannelConfigurator; import com.rabbitmq.client.SocketChannelConfigurator; import com.rabbitmq.client.SslEngineConfigurator; import javax.net.ssl.SSLEngine; import java.io.IOException; import java.util.concurrent.ExecutorService; import java.util.concurrent.ThreadFactory; /** * Parameters used to configure the NIO mode of a {@link com.rabbitmq.client.ConnectionFactory}. * */ public class NioParams { /** size of the byte buffer used for inbound data */ private int readByteBufferSize = 32768; /** size of the byte buffer used for outbound data */ private int writeByteBufferSize = 32768; /** the max number of IO threads */ private int nbIoThreads = 1; /** the timeout to enqueue outbound frames */ private int writeEnqueuingTimeoutInMs = 10 * 1000; /** the capacity of the queue used for outbound frames */ private int writeQueueCapacity = 10000; /** the executor service used for IO threads and connections shutdown */ private ExecutorService nioExecutor; /** the thread factory used for IO threads and connections shutdown */ private ThreadFactory threadFactory; /** the hook to configure the socket channel before it's open */ private SocketChannelConfigurator socketChannelConfigurator = new DefaultSocketChannelConfigurator(); /** the hook to configure the SSL engine before the connection is open */ private SslEngineConfigurator sslEngineConfigurator = new SslEngineConfigurator() { @Override public void configure(SSLEngine sslEngine) throws IOException { } }; public NioParams() { } public NioParams(NioParams nioParams) { setReadByteBufferSize(nioParams.getReadByteBufferSize()); setWriteByteBufferSize(nioParams.getWriteByteBufferSize()); setNbIoThreads(nioParams.getNbIoThreads()); setWriteEnqueuingTimeoutInMs(nioParams.getWriteEnqueuingTimeoutInMs()); setWriteQueueCapacity(nioParams.getWriteQueueCapacity()); setNioExecutor(nioParams.getNioExecutor()); setThreadFactory(nioParams.getThreadFactory()); setSslEngineConfigurator(nioParams.getSslEngineConfigurator()); } public int getReadByteBufferSize() { return readByteBufferSize; } /** * Sets the size in byte of the read {@link java.nio.ByteBuffer} used in the NIO loop. * Default is 32768. * * This parameter isn't used when using SSL/TLS, where {@link java.nio.ByteBuffer} * size is set up according to the {@link javax.net.ssl.SSLSession} packet size. * * @param readByteBufferSize size of the {@link java.nio.ByteBuffer} for inbound data * @return this {@link NioParams} instance */ public NioParams setReadByteBufferSize(int readByteBufferSize) { if (readByteBufferSize <= 0) { throw new IllegalArgumentException("Buffer size must be greater than 0"); } this.readByteBufferSize = readByteBufferSize; return this; } public int getWriteByteBufferSize() { return writeByteBufferSize; } /** * Sets the size in byte of the write {@link java.nio.ByteBuffer} used in the NIO loop. * Default is 32768. * * This parameter isn't used when using SSL/TLS, where {@link java.nio.ByteBuffer} * size is set up according to the {@link javax.net.ssl.SSLSession} packet size. * * @param writeByteBufferSize size of the {@link java.nio.ByteBuffer} used for outbound data * @return this {@link NioParams} instance */ public NioParams setWriteByteBufferSize(int writeByteBufferSize) { if (readByteBufferSize <= 0) { throw new IllegalArgumentException("Buffer size must be greater than 0"); } this.writeByteBufferSize = writeByteBufferSize; return this; } public int getNbIoThreads() { return nbIoThreads; } /** * Sets the max number of threads/tasks used for NIO. Default is 1. * Set this number according to the number of simultaneous connections * and their activity. * Threads/tasks are created as necessary (e.g. with 10 threads, when * 10 connections have been created). * Once a connection is created, it's assigned to a thread/task and * all its IO activity is handled by this thread/task. * * When idle for a few seconds (i.e. without any connection to perform IO for), * a thread/task stops and is recreated if necessary. * * @param nbIoThreads * @return this {@link NioParams} instance */ public NioParams setNbIoThreads(int nbIoThreads) { if (nbIoThreads <= 0) { throw new IllegalArgumentException("Number of threads must be greater than 0"); } this.nbIoThreads = nbIoThreads; return this; } public int getWriteEnqueuingTimeoutInMs() { return writeEnqueuingTimeoutInMs; } /** * Sets the timeout for queuing outbound frames. Default is 10,000 ms. * Every requests to the server is divided into frames * that are then queued in a {@link java.util.concurrent.BlockingQueue} before * being sent on the network by a IO thread. * * If the IO thread cannot cope with the frames dispatch, the * {@link java.util.concurrent.BlockingQueue} gets filled up and blocks * (blocking the calling thread by the same occasion). This timeout is the * time the {@link java.util.concurrent.BlockingQueue} will wait before * rejecting the outbound frame. The calling thread will then received * an exception. * * The appropriate value depends on the application scenarios: * rate of outbound data (published messages, acknowledgment, etc), network speed... * * @param writeEnqueuingTimeoutInMs * @return this {@link NioParams} instance * @see NioParams#setWriteQueueCapacity(int) */ public NioParams setWriteEnqueuingTimeoutInMs(int writeEnqueuingTimeoutInMs) { this.writeEnqueuingTimeoutInMs = writeEnqueuingTimeoutInMs; return this; } public ExecutorService getNioExecutor() { return nioExecutor; } /** * Sets the {@link ExecutorService} to use for NIO threads/tasks. * Default is to use the thread factory. * * The {@link ExecutorService} should be able to run the * number of requested IO threads, plus a few more, as it's also * used to dispatch the shutdown of connections. * * It's developer's responsibility to shut down the executor * when it is no longer needed. * * The thread factory isn't used if an executor service is set up. * * @param nioExecutor {@link ExecutorService} used for IO threads and connection shutdown * @return this {@link NioParams} instance * @see NioParams#setNbIoThreads(int) * @see NioParams#setThreadFactory(ThreadFactory) */ public NioParams setNioExecutor(ExecutorService nioExecutor) { this.nioExecutor = nioExecutor; return this; } public ThreadFactory getThreadFactory() { return threadFactory; } /** * Sets the {@link ThreadFactory} to use for NIO threads/tasks. * Default is to use the {@link com.rabbitmq.client.ConnectionFactory}'s * {@link ThreadFactory}. * * The {@link ThreadFactory} is used to spawn the IO threads * and dispatch the shutdown of connections. * * @param threadFactory {@link ThreadFactory} used for IO threads and connection shutdown * @return this {@link NioParams} instance * @see NioParams#setNbIoThreads(int) * @see NioParams#setNioExecutor(ExecutorService) */ public NioParams setThreadFactory(ThreadFactory threadFactory) { this.threadFactory = threadFactory; return this; } public int getWriteQueueCapacity() { return writeQueueCapacity; } /** * Set the capacity of the queue used for outbound frames. * Default capacity is 10,000. * * @param writeQueueCapacity * @return this {@link NioParams} instance * @see NioParams#setWriteEnqueuingTimeoutInMs(int) */ public NioParams setWriteQueueCapacity(int writeQueueCapacity) { if (writeQueueCapacity <= 0) { throw new IllegalArgumentException("Write queue capacity must be greater than 0"); } this.writeQueueCapacity = writeQueueCapacity; return this; } /** * Set the {@link java.nio.channels.SocketChannel} configurator. * This gets a chance to "configure" a socket channel * before it has been opened. The default implementation disables * Nagle's algorithm. * * @param configurator the configurator to use */ public void setSocketChannelConfigurator(SocketChannelConfigurator configurator) { this.socketChannelConfigurator = configurator; } public SocketChannelConfigurator getSocketChannelConfigurator() { return socketChannelConfigurator; } /** * Set the {@link SSLEngine} configurator. * This gets a change to "configure" the SSL engine * before the connection has been opened. This can be * used e.g. to set {@link javax.net.ssl.SSLParameters}. * The default implementation doesn't do anything. * * @param configurator the configurator to use */ public void setSslEngineConfigurator(SslEngineConfigurator configurator) { this.sslEngineConfigurator = configurator; } public SslEngineConfigurator getSslEngineConfigurator() { return sslEngineConfigurator; } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/nio/SelectorHolder.java000066400000000000000000000026221316117667700313310ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl.nio; import java.nio.channels.Selector; import java.util.Collections; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; /** * */ public class SelectorHolder { final Selector selector; final Set registrations = Collections .newSetFromMap(new ConcurrentHashMap()); SelectorHolder(Selector selector) { this.selector = selector; } public void registerFrameHandlerState(SocketChannelFrameHandlerState state, int operations) { registrations.add(new SocketChannelRegistration(state, operations)); selector.wakeup(); } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/nio/SocketChannelFrameHandler.java000066400000000000000000000055731316117667700334150ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl.nio; import com.rabbitmq.client.impl.AMQConnection; import com.rabbitmq.client.impl.Frame; import com.rabbitmq.client.impl.FrameHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.net.InetAddress; import java.net.SocketException; /** * */ public class SocketChannelFrameHandler implements FrameHandler { private static final Logger LOGGER = LoggerFactory.getLogger(SocketChannelFrameHandler.class); private final SocketChannelFrameHandlerState state; public SocketChannelFrameHandler(SocketChannelFrameHandlerState state) { this.state = state; } @Override public InetAddress getLocalAddress() { return state.getChannel().socket().getLocalAddress(); } @Override public int getLocalPort() { return state.getChannel().socket().getLocalPort(); } @Override public InetAddress getAddress() { return state.getChannel().socket().getInetAddress(); } @Override public int getPort() { return state.getChannel().socket().getPort(); } @Override public void setTimeout(int timeoutMs) throws SocketException { state.getChannel().socket().setSoTimeout(timeoutMs); } @Override public int getTimeout() throws SocketException { return state.getChannel().socket().getSoTimeout(); } @Override public void sendHeader() throws IOException { state.sendHeader(); } @Override public void initialize(AMQConnection connection) { state.setConnection(connection); } @Override public Frame readFrame() throws IOException { throw new UnsupportedOperationException(); } @Override public void writeFrame(Frame frame) throws IOException { state.write(frame); } @Override public void flush() throws IOException { } @Override public void close() { try { state.close(); } catch (IOException e) { LOGGER.warn("Error while closing SocketChannel", e); } } public SocketChannelFrameHandlerState getState() { return state; } } SocketChannelFrameHandlerFactory.java000066400000000000000000000117041316117667700346570ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/nio// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl.nio; import com.rabbitmq.client.Address; import com.rabbitmq.client.ConnectionFactory; import com.rabbitmq.client.SslContextFactory; import com.rabbitmq.client.impl.AbstractFrameHandlerFactory; import com.rabbitmq.client.impl.FrameHandler; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLException; import java.io.IOException; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.nio.channels.SocketChannel; import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * */ public class SocketChannelFrameHandlerFactory extends AbstractFrameHandlerFactory { final NioParams nioParams; private final SslContextFactory sslContextFactory; private final Lock stateLock = new ReentrantLock(); private final AtomicLong globalConnectionCount = new AtomicLong(); private final List nioLoopContexts; public SocketChannelFrameHandlerFactory(int connectionTimeout, NioParams nioParams, boolean ssl, SslContextFactory sslContextFactory) throws IOException { super(connectionTimeout, null, ssl); this.nioParams = new NioParams(nioParams); this.sslContextFactory = sslContextFactory; this.nioLoopContexts = new ArrayList(this.nioParams.getNbIoThreads()); for (int i = 0; i < this.nioParams.getNbIoThreads(); i++) { this.nioLoopContexts.add(new NioLoopContext(this, this.nioParams)); } } @Override public FrameHandler create(Address addr, String connectionName) throws IOException { int portNumber = ConnectionFactory.portOrDefault(addr.getPort(), ssl); SSLEngine sslEngine = null; SocketChannel channel = null; try { if (ssl) { SSLContext sslContext = sslContextFactory.create(connectionName); sslEngine = sslContext.createSSLEngine(addr.getHost(), portNumber); sslEngine.setUseClientMode(true); if (nioParams.getSslEngineConfigurator() != null) { nioParams.getSslEngineConfigurator().configure(sslEngine); } } SocketAddress address = new InetSocketAddress(addr.getHost(), portNumber); channel = SocketChannel.open(); channel.configureBlocking(true); if(nioParams.getSocketChannelConfigurator() != null) { nioParams.getSocketChannelConfigurator().configure(channel); } channel.connect(address); if (ssl) { sslEngine.beginHandshake(); boolean handshake = SslEngineHelper.doHandshake(channel, sslEngine); if (!handshake) { throw new SSLException("TLS handshake failed"); } } channel.configureBlocking(false); // lock stateLock.lock(); NioLoopContext nioLoopContext = null; try { long modulo = globalConnectionCount.getAndIncrement() % nioParams.getNbIoThreads(); nioLoopContext = nioLoopContexts.get((int) modulo); nioLoopContext.initStateIfNecessary(); SocketChannelFrameHandlerState state = new SocketChannelFrameHandlerState( channel, nioLoopContext, nioParams, sslEngine ); state.startReading(); SocketChannelFrameHandler frameHandler = new SocketChannelFrameHandler(state); return frameHandler; } finally { stateLock.unlock(); } } catch(IOException e) { try { if(sslEngine != null && channel != null) { SslEngineHelper.close(channel, sslEngine); } channel.close(); } catch(IOException closingException) { // ignore } throw e; } } void lock() { stateLock.lock(); } void unlock() { stateLock.unlock(); } } SocketChannelFrameHandlerState.java000066400000000000000000000162701316117667700343330ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/nio// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl.nio; import com.rabbitmq.client.impl.AMQConnection; import com.rabbitmq.client.impl.Frame; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.net.ssl.SSLEngine; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.SocketChannel; import java.util.Queue; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.TimeUnit; /** * */ public class SocketChannelFrameHandlerState { private static final Logger LOGGER = LoggerFactory.getLogger(SocketChannelFrameHandlerState.class); /** Time to linger before closing the socket forcefully. */ private static final int SOCKET_CLOSING_TIMEOUT = 1; private final SocketChannel channel; private final BlockingQueue writeQueue; private volatile AMQConnection connection; /** should be used only in the NIO read thread */ private long lastActivity; private final SelectorHolder writeSelectorState; private final SelectorHolder readSelectorState; private final int writeEnqueuingTimeoutInMs; final boolean ssl; final SSLEngine sslEngine; /** outbound app data (to be crypted if TLS is on) */ final ByteBuffer plainOut; /** inbound app data (deciphered if TLS is on) */ final ByteBuffer plainIn; /** outbound net data (ciphered if TLS is on) */ final ByteBuffer cipherOut; /** inbound data (ciphered if TLS is on) */ final ByteBuffer cipherIn; final DataOutputStream outputStream; final DataInputStream inputStream; public SocketChannelFrameHandlerState(SocketChannel channel, NioLoopContext nioLoopsState, NioParams nioParams, SSLEngine sslEngine) { this.channel = channel; this.readSelectorState = nioLoopsState.readSelectorState; this.writeSelectorState = nioLoopsState.writeSelectorState; this.writeQueue = new ArrayBlockingQueue(nioParams.getWriteQueueCapacity(), true); this.writeEnqueuingTimeoutInMs = nioParams.getWriteEnqueuingTimeoutInMs(); this.sslEngine = sslEngine; if(this.sslEngine == null) { this.ssl = false; this.plainOut = nioLoopsState.writeBuffer; this.cipherOut = null; this.plainIn = nioLoopsState.readBuffer; this.cipherIn = null; this.outputStream = new DataOutputStream( new ByteBufferOutputStream(channel, plainOut) ); this.inputStream = new DataInputStream( new ByteBufferInputStream(channel, plainIn) ); } else { this.ssl = true; this.plainOut = ByteBuffer.allocate(sslEngine.getSession().getApplicationBufferSize()); this.cipherOut = ByteBuffer.allocate(sslEngine.getSession().getPacketBufferSize()); this.plainIn = ByteBuffer.allocate(sslEngine.getSession().getApplicationBufferSize()); this.cipherIn = ByteBuffer.allocate(sslEngine.getSession().getPacketBufferSize()); this.outputStream = new DataOutputStream( new SslEngineByteBufferOutputStream(sslEngine, plainOut, cipherOut, channel) ); this.inputStream = new DataInputStream( new SslEngineByteBufferInputStream(sslEngine, plainIn, cipherIn, channel) ); } } public SocketChannel getChannel() { return channel; } public Queue getWriteQueue() { return writeQueue; } public void sendHeader() throws IOException { sendWriteRequest(new HeaderWriteRequest()); } public void write(Frame frame) throws IOException { sendWriteRequest(new FrameWriteRequest(frame)); } private void sendWriteRequest(WriteRequest writeRequest) throws IOException { try { boolean offered = this.writeQueue.offer(writeRequest, writeEnqueuingTimeoutInMs, TimeUnit.MILLISECONDS); if(offered) { this.writeSelectorState.registerFrameHandlerState(this, SelectionKey.OP_WRITE); this.readSelectorState.selector.wakeup(); } else { throw new IOException("Frame enqueuing failed"); } } catch (InterruptedException e) { LOGGER.warn("Thread interrupted during enqueuing frame in write queue"); } } public void startReading() { this.readSelectorState.registerFrameHandlerState(this, SelectionKey.OP_READ); } public AMQConnection getConnection() { return connection; } public void setConnection(AMQConnection connection) { this.connection = connection; } public void setLastActivity(long lastActivity) { this.lastActivity = lastActivity; } public long getLastActivity() { return lastActivity; } void prepareForWriteSequence() { if(ssl) { plainOut.clear(); cipherOut.clear(); } } void endWriteSequence() { if(!ssl) { plainOut.clear(); } } void prepareForReadSequence() throws IOException { if(ssl) { cipherIn.clear(); plainIn.clear(); cipherIn.flip(); plainIn.flip(); } else { NioHelper.read(channel, plainIn); plainIn.flip(); } } boolean continueReading() throws IOException { if(ssl) { if (!plainIn.hasRemaining() && !cipherIn.hasRemaining()) { // need to try to read something cipherIn.clear(); int bytesRead = NioHelper.read(channel, cipherIn); if (bytesRead <= 0) { return false; } else { cipherIn.flip(); return true; } } else { return true; } } else { if (!plainIn.hasRemaining()) { plainIn.clear(); NioHelper.read(channel, plainIn); plainIn.flip(); } return plainIn.hasRemaining(); } } void close() throws IOException { if(ssl) { SslEngineHelper.close(channel, sslEngine); } if(channel.isOpen()) { channel.socket().setSoLinger(true, SOCKET_CLOSING_TIMEOUT); channel.close(); } } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/nio/SocketChannelRegistration.java000066400000000000000000000027221316117667700335300ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl.nio; /** * */ public class SocketChannelRegistration { final SocketChannelFrameHandlerState state; final int operations; public SocketChannelRegistration(SocketChannelFrameHandlerState state, int operations) { this.state = state; this.operations = operations; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; SocketChannelRegistration that = (SocketChannelRegistration) o; return state.getChannel().equals(that.state.getChannel()); } @Override public int hashCode() { return state.getChannel().hashCode(); } } SslEngineByteBufferInputStream.java000066400000000000000000000070261316117667700344000ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/nio// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl.nio; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLEngineResult; import javax.net.ssl.SSLException; import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; import java.nio.channels.ReadableByteChannel; /** * Bridge between the byte buffer and stream worlds. */ public class SslEngineByteBufferInputStream extends InputStream { private final SSLEngine sslEngine; private final ByteBuffer plainIn, cipherIn; private final ReadableByteChannel channel; public SslEngineByteBufferInputStream(SSLEngine sslEngine, ByteBuffer plainIn, ByteBuffer cipherIn, ReadableByteChannel channel) { this.sslEngine = sslEngine; this.plainIn = plainIn; this.cipherIn = cipherIn; this.channel = channel; } @Override public int read() throws IOException { if (plainIn.hasRemaining()) { return readFromBuffer(plainIn); } else { plainIn.clear(); SSLEngineResult result = sslEngine.unwrap(cipherIn, plainIn); switch (result.getStatus()) { case OK: plainIn.flip(); if (plainIn.hasRemaining()) { return readFromBuffer(plainIn); } break; case BUFFER_OVERFLOW: throw new SSLException("buffer overflow in read"); case BUFFER_UNDERFLOW: if (cipherIn.hasRemaining()) { cipherIn.compact(); } else { cipherIn.clear(); } int bytesRead = NioHelper.read(channel, cipherIn); // see https://github.com/rabbitmq/rabbitmq-java-client/issues/307 if (bytesRead <= 0) { bytesRead = NioHelper.retryRead(channel, cipherIn); if(bytesRead <= 0) { throw new IllegalStateException("Should be reading something from the network"); } } cipherIn.flip(); plainIn.clear(); result = sslEngine.unwrap(cipherIn, plainIn); if (result.getStatus() != SSLEngineResult.Status.OK) { throw new SSLException("Unexpected result: " + result); } plainIn.flip(); if (plainIn.hasRemaining()) { return readFromBuffer(plainIn); } break; case CLOSED: throw new SSLException("closed in read"); default: throw new IllegalStateException("Invalid SSL status: " + result.getStatus()); } } return -1; } private int readFromBuffer(ByteBuffer buffer) { return buffer.get() & 0xff; } } SslEngineByteBufferOutputStream.java000066400000000000000000000036761316117667700346100ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/nio// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl.nio; import javax.net.ssl.SSLEngine; import java.io.IOException; import java.io.OutputStream; import java.nio.ByteBuffer; import java.nio.channels.WritableByteChannel; /** * Bridge between the byte buffer and stream worlds. */ public class SslEngineByteBufferOutputStream extends OutputStream { private final SSLEngine sslEngine; private final ByteBuffer plainOut, cypherOut; private final WritableByteChannel channel; public SslEngineByteBufferOutputStream(SSLEngine sslEngine, ByteBuffer plainOut, ByteBuffer cypherOut, WritableByteChannel channel) { this.sslEngine = sslEngine; this.plainOut = plainOut; this.cypherOut = cypherOut; this.channel = channel; } @Override public void write(int b) throws IOException { if (!plainOut.hasRemaining()) { doFlush(); } plainOut.put((byte) b); } @Override public void flush() throws IOException { if (plainOut.position() > 0) { doFlush(); } } private void doFlush() throws IOException { plainOut.flip(); SslEngineHelper.write(channel, sslEngine, plainOut, cypherOut); plainOut.clear(); } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/nio/SslEngineHelper.java000066400000000000000000000161161316117667700314450ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl.nio; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLEngineResult; import javax.net.ssl.SSLException; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.ReadableByteChannel; import java.nio.channels.SocketChannel; import java.nio.channels.WritableByteChannel; import static javax.net.ssl.SSLEngineResult.HandshakeStatus.FINISHED; import static javax.net.ssl.SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING; /** * */ public class SslEngineHelper { public static boolean doHandshake(SocketChannel socketChannel, SSLEngine engine) throws IOException { ByteBuffer plainOut = ByteBuffer.allocate(engine.getSession().getApplicationBufferSize()); ByteBuffer plainIn = ByteBuffer.allocate(engine.getSession().getApplicationBufferSize()); ByteBuffer cipherOut = ByteBuffer.allocate(engine.getSession().getPacketBufferSize()); ByteBuffer cipherIn = ByteBuffer.allocate(engine.getSession().getPacketBufferSize()); SSLEngineResult.HandshakeStatus handshakeStatus = engine.getHandshakeStatus(); while (handshakeStatus != FINISHED && handshakeStatus != NOT_HANDSHAKING) { switch (handshakeStatus) { case NEED_TASK: handshakeStatus = runDelegatedTasks(engine); break; case NEED_UNWRAP: handshakeStatus = unwrap(cipherIn, plainIn, socketChannel, engine); break; case NEED_WRAP: handshakeStatus = wrap(plainOut, cipherOut, socketChannel, engine); break; } } return true; } private static SSLEngineResult.HandshakeStatus runDelegatedTasks(SSLEngine sslEngine) { // FIXME run in executor? Runnable runnable; while ((runnable = sslEngine.getDelegatedTask()) != null) { runnable.run(); } return sslEngine.getHandshakeStatus(); } private static SSLEngineResult.HandshakeStatus unwrap(ByteBuffer cipherIn, ByteBuffer plainIn, ReadableByteChannel channel, SSLEngine sslEngine) throws IOException { SSLEngineResult.HandshakeStatus handshakeStatus = sslEngine.getHandshakeStatus(); if (channel.read(cipherIn) < 0) { throw new SSLException("Could not read from socket channel"); } cipherIn.flip(); SSLEngineResult.Status status; do { SSLEngineResult unwrapResult = sslEngine.unwrap(cipherIn, plainIn); status = unwrapResult.getStatus(); switch (status) { case OK: plainIn.clear(); handshakeStatus = runDelegatedTasks(sslEngine); break; case BUFFER_OVERFLOW: throw new SSLException("Buffer overflow during handshake"); case BUFFER_UNDERFLOW: cipherIn.compact(); int read = NioHelper.read(channel, cipherIn); if(read <= 0) { NioHelper.retryRead(channel, cipherIn); } cipherIn.flip(); break; case CLOSED: sslEngine.closeInbound(); break; default: throw new SSLException("Unexpected status from " + unwrapResult); } } while (cipherIn.hasRemaining()); cipherIn.compact(); return handshakeStatus; } private static SSLEngineResult.HandshakeStatus wrap(ByteBuffer plainOut, ByteBuffer cipherOut, WritableByteChannel channel, SSLEngine sslEngine) throws IOException { SSLEngineResult.HandshakeStatus handshakeStatus = sslEngine.getHandshakeStatus(); SSLEngineResult.Status status = sslEngine.wrap(plainOut, cipherOut).getStatus(); switch (status) { case OK: handshakeStatus = runDelegatedTasks(sslEngine); cipherOut.flip(); while (cipherOut.hasRemaining()) { channel.write(cipherOut); } cipherOut.clear(); break; case BUFFER_OVERFLOW: throw new SSLException("Buffer overflow during handshake"); default: throw new SSLException("Unexpected status " + status); } return handshakeStatus; } static int bufferCopy(ByteBuffer from, ByteBuffer to) { int maxTransfer = Math.min(to.remaining(), from.remaining()); ByteBuffer temporaryBuffer = from.duplicate(); temporaryBuffer.limit(temporaryBuffer.position() + maxTransfer); to.put(temporaryBuffer); from.position(from.position() + maxTransfer); return maxTransfer; } public static void write(WritableByteChannel socketChannel, SSLEngine engine, ByteBuffer plainOut, ByteBuffer cypherOut) throws IOException { while (plainOut.hasRemaining()) { cypherOut.clear(); SSLEngineResult result = engine.wrap(plainOut, cypherOut); switch (result.getStatus()) { case OK: cypherOut.flip(); while (cypherOut.hasRemaining()) { socketChannel.write(cypherOut); } break; case BUFFER_OVERFLOW: throw new SSLException("Buffer overflow occured after a wrap."); case BUFFER_UNDERFLOW: throw new SSLException("Buffer underflow occured after a wrap."); case CLOSED: throw new SSLException("Buffer closed"); default: throw new IllegalStateException("Invalid SSL status: " + result.getStatus()); } } } public static void close(WritableByteChannel channel, SSLEngine engine) throws IOException { ByteBuffer plainOut = ByteBuffer.allocate(engine.getSession().getApplicationBufferSize()); ByteBuffer cipherOut = ByteBuffer.allocate(engine.getSession().getPacketBufferSize()); // won't be sending any more data engine.closeOutbound(); while (!engine.isOutboundDone()) { engine.wrap(plainOut, cipherOut); cipherOut.flip(); while (cipherOut.hasRemaining()) { int num = channel.write(cipherOut); if (num == -1) { // the channel has been closed break; } } cipherOut.clear(); } } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/nio/WriteRequest.java000066400000000000000000000016711316117667700310610ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl.nio; import java.io.DataOutputStream; import java.io.IOException; /** * */ public interface WriteRequest { void handle(DataOutputStream dataOutputStream) throws IOException; } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/package.html000066400000000000000000000003171316117667700272430ustar00rootroot00000000000000 Implementations of interfaces specified in the client API, and their supporting classes. rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/recovery/000077500000000000000000000000001316117667700266175ustar00rootroot00000000000000AutorecoveringChannel.java000066400000000000000000001064161316117667700337000ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/recovery// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl.recovery; import com.rabbitmq.client.*; import com.rabbitmq.client.RecoverableChannel; import java.io.IOException; import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.TimeoutException; /** * {@link com.rabbitmq.client.Channel} implementation that is automatically * recovered during connection recovery. * * @since 3.3.0 */ public class AutorecoveringChannel implements RecoverableChannel { private volatile RecoveryAwareChannelN delegate; private volatile AutorecoveringConnection connection; private final List shutdownHooks = new CopyOnWriteArrayList(); private final List recoveryListeners = new CopyOnWriteArrayList(); private final List returnListeners = new CopyOnWriteArrayList(); private final List confirmListeners = new CopyOnWriteArrayList(); private final Set consumerTags = Collections.synchronizedSet(new HashSet()); private int prefetchCountConsumer; private int prefetchCountGlobal; private boolean usesPublisherConfirms; private boolean usesTransactions; public AutorecoveringChannel(AutorecoveringConnection connection, RecoveryAwareChannelN delegate) { this.connection = connection; this.delegate = delegate; } @Override public int getChannelNumber() { return delegate.getChannelNumber(); } @Override public Connection getConnection() { return delegate.getConnection(); } public Channel getDelegate() { return delegate; } @Override public void close() throws IOException, TimeoutException { try { delegate.close(); } finally { for (String consumerTag : consumerTags) { this.connection.deleteRecordedConsumer(consumerTag); } this.connection.unregisterChannel(this); } } @Override public void close(int closeCode, String closeMessage) throws IOException, TimeoutException { try { delegate.close(closeCode, closeMessage); } finally { this.connection.unregisterChannel(this); } } @Override public void abort() throws IOException { delegate.abort(); } @Override public void abort(int closeCode, String closeMessage) throws IOException { delegate.abort(closeCode, closeMessage); } @Override public void addReturnListener(ReturnListener listener) { this.returnListeners.add(listener); delegate.addReturnListener(listener); } @Override public ReturnListener addReturnListener(ReturnCallback returnCallback) { ReturnListener returnListener = (replyCode, replyText, exchange, routingKey, properties, body) -> returnCallback.handle(new Return( replyCode, replyText, exchange, routingKey, properties, body )); this.addReturnListener(returnListener); return returnListener; } @Override public boolean removeReturnListener(ReturnListener listener) { this.returnListeners.remove(listener); return delegate.removeReturnListener(listener); } @Override public void clearReturnListeners() { this.returnListeners.clear(); delegate.clearReturnListeners(); } @Override public void addConfirmListener(ConfirmListener listener) { this.confirmListeners.add(listener); delegate.addConfirmListener(listener); } @Override public ConfirmListener addConfirmListener(ConfirmCallback ackCallback, ConfirmCallback nackCallback) { ConfirmListener confirmListener = new ConfirmListener() { @Override public void handleAck(long deliveryTag, boolean multiple) throws IOException { ackCallback.handle(deliveryTag, multiple); } @Override public void handleNack(long deliveryTag, boolean multiple) throws IOException { nackCallback.handle(deliveryTag, multiple); } }; this.addConfirmListener(confirmListener); return confirmListener; } @Override public boolean removeConfirmListener(ConfirmListener listener) { this.confirmListeners.remove(listener); return delegate.removeConfirmListener(listener); } @Override public void clearConfirmListeners() { this.confirmListeners.clear(); delegate.clearConfirmListeners(); } @Override public Consumer getDefaultConsumer() { return delegate.getDefaultConsumer(); } @Override public void setDefaultConsumer(Consumer consumer) { delegate.setDefaultConsumer(consumer); } @Override public void basicQos(int prefetchSize, int prefetchCount, boolean global) throws IOException { if (global) { this.prefetchCountGlobal = prefetchCount; } else { this.prefetchCountConsumer = prefetchCount; } delegate.basicQos(prefetchSize, prefetchCount, global); } @Override public void basicQos(int prefetchCount) throws IOException { basicQos(0, prefetchCount, false); } @Override public void basicQos(int prefetchCount, boolean global) throws IOException { basicQos(0, prefetchCount, global); } @Override public void basicPublish(String exchange, String routingKey, AMQP.BasicProperties props, byte[] body) throws IOException { delegate.basicPublish(exchange, routingKey, props, body); } @Override public void basicPublish(String exchange, String routingKey, boolean mandatory, AMQP.BasicProperties props, byte[] body) throws IOException { delegate.basicPublish(exchange, routingKey, mandatory, props, body); } @Override public void basicPublish(String exchange, String routingKey, boolean mandatory, boolean immediate, AMQP.BasicProperties props, byte[] body) throws IOException { delegate.basicPublish(exchange, routingKey, mandatory, immediate, props, body); } @Override public AMQP.Exchange.DeclareOk exchangeDeclare(String exchange, String type) throws IOException { return exchangeDeclare(exchange, type, false, false, null); } @Override public AMQP.Exchange.DeclareOk exchangeDeclare(String exchange, BuiltinExchangeType type) throws IOException { return exchangeDeclare(exchange, type.getType()); } @Override public AMQP.Exchange.DeclareOk exchangeDeclare(String exchange, String type, boolean durable) throws IOException { return exchangeDeclare(exchange, type, durable, false, null); } @Override public AMQP.Exchange.DeclareOk exchangeDeclare(String exchange, BuiltinExchangeType type, boolean durable) throws IOException { return exchangeDeclare(exchange, type.getType(), durable); } @Override public AMQP.Exchange.DeclareOk exchangeDeclare(String exchange, String type, boolean durable, boolean autoDelete, Map arguments) throws IOException { return exchangeDeclare(exchange, type, durable, autoDelete, false, arguments); } @Override public AMQP.Exchange.DeclareOk exchangeDeclare(String exchange, BuiltinExchangeType type, boolean durable, boolean autoDelete, Map arguments) throws IOException { return exchangeDeclare(exchange, type.getType(), durable, autoDelete, arguments); } @Override public AMQP.Exchange.DeclareOk exchangeDeclare(String exchange, String type, boolean durable, boolean autoDelete, boolean internal, Map arguments) throws IOException { final AMQP.Exchange.DeclareOk ok = delegate.exchangeDeclare(exchange, type, durable, autoDelete, internal, arguments); RecordedExchange x = new RecordedExchange(this, exchange). type(type). durable(durable). autoDelete(autoDelete). arguments(arguments); recordExchange(exchange, x); return ok; } @Override public AMQP.Exchange.DeclareOk exchangeDeclare(String exchange, BuiltinExchangeType type, boolean durable, boolean autoDelete, boolean internal, Map arguments) throws IOException { return exchangeDeclare(exchange, type.getType(), durable, autoDelete, internal, arguments); } @Override public void exchangeDeclareNoWait(String exchange, String type, boolean durable, boolean autoDelete, boolean internal, Map arguments) throws IOException { RecordedExchange x = new RecordedExchange(this, exchange). type(type). durable(durable). autoDelete(autoDelete). arguments(arguments); recordExchange(exchange, x); delegate.exchangeDeclareNoWait(exchange, type, durable, autoDelete, internal, arguments); } @Override public void exchangeDeclareNoWait(String exchange, BuiltinExchangeType type, boolean durable, boolean autoDelete, boolean internal, Map arguments) throws IOException { exchangeDeclareNoWait(exchange, type.getType(), durable, autoDelete, internal, arguments); } @Override public AMQP.Exchange.DeclareOk exchangeDeclarePassive(String name) throws IOException { return delegate.exchangeDeclarePassive(name); } @Override public AMQP.Exchange.DeleteOk exchangeDelete(String exchange, boolean ifUnused) throws IOException { deleteRecordedExchange(exchange); return delegate.exchangeDelete(exchange, ifUnused); } @Override public void exchangeDeleteNoWait(String exchange, boolean ifUnused) throws IOException { deleteRecordedExchange(exchange); delegate.exchangeDeleteNoWait(exchange, ifUnused); } @Override public AMQP.Exchange.DeleteOk exchangeDelete(String exchange) throws IOException { return exchangeDelete(exchange, false); } @Override public AMQP.Exchange.BindOk exchangeBind(String destination, String source, String routingKey) throws IOException { return exchangeBind(destination, source, routingKey, null); } @Override public AMQP.Exchange.BindOk exchangeBind(String destination, String source, String routingKey, Map arguments) throws IOException { final AMQP.Exchange.BindOk ok = delegate.exchangeBind(destination, source, routingKey, arguments); recordExchangeBinding(destination, source, routingKey, arguments); return ok; } @Override public void exchangeBindNoWait(String destination, String source, String routingKey, Map arguments) throws IOException { delegate.exchangeBindNoWait(destination, source, routingKey, arguments); recordExchangeBinding(destination, source, routingKey, arguments); } @Override public AMQP.Exchange.UnbindOk exchangeUnbind(String destination, String source, String routingKey) throws IOException { return exchangeUnbind(destination, source, routingKey, null); } @Override public AMQP.Exchange.UnbindOk exchangeUnbind(String destination, String source, String routingKey, Map arguments) throws IOException { deleteRecordedExchangeBinding(destination, source, routingKey, arguments); this.maybeDeleteRecordedAutoDeleteExchange(source); return delegate.exchangeUnbind(destination, source, routingKey, arguments); } @Override public void exchangeUnbindNoWait(String destination, String source, String routingKey, Map arguments) throws IOException { delegate.exchangeUnbindNoWait(destination, source, routingKey, arguments); deleteRecordedExchangeBinding(destination, source, routingKey, arguments); } @Override public AMQP.Queue.DeclareOk queueDeclare() throws IOException { return queueDeclare("", false, true, true, null); } @Override public AMQP.Queue.DeclareOk queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete, Map arguments) throws IOException { final AMQP.Queue.DeclareOk ok = delegate.queueDeclare(queue, durable, exclusive, autoDelete, arguments); RecordedQueue q = new RecordedQueue(this, ok.getQueue()). durable(durable). exclusive(exclusive). autoDelete(autoDelete). arguments(arguments); if (queue.equals(RecordedQueue.EMPTY_STRING)) { q.serverNamed(true); } recordQueue(ok, q); return ok; } @Override public void queueDeclareNoWait(String queue, boolean durable, boolean exclusive, boolean autoDelete, Map arguments) throws IOException { RecordedQueue meta = new RecordedQueue(this, queue). durable(durable). exclusive(exclusive). autoDelete(autoDelete). arguments(arguments); delegate.queueDeclareNoWait(queue, durable, exclusive, autoDelete, arguments); recordQueue(queue, meta); } @Override public AMQP.Queue.DeclareOk queueDeclarePassive(String queue) throws IOException { return delegate.queueDeclarePassive(queue); } @Override public long messageCount(String queue) throws IOException { return delegate.messageCount(queue); } @Override public long consumerCount(String queue) throws IOException { return delegate.consumerCount(queue); } @Override public AMQP.Queue.DeleteOk queueDelete(String queue) throws IOException { return queueDelete(queue, false, false); } @Override public AMQP.Queue.DeleteOk queueDelete(String queue, boolean ifUnused, boolean ifEmpty) throws IOException { deleteRecordedQueue(queue); return delegate.queueDelete(queue, ifUnused, ifEmpty); } @Override public void queueDeleteNoWait(String queue, boolean ifUnused, boolean ifEmpty) throws IOException { deleteRecordedQueue(queue); delegate.queueDeleteNoWait(queue, ifUnused, ifEmpty); } @Override public AMQP.Queue.BindOk queueBind(String queue, String exchange, String routingKey) throws IOException { return queueBind(queue, exchange, routingKey, null); } @Override public AMQP.Queue.BindOk queueBind(String queue, String exchange, String routingKey, Map arguments) throws IOException { AMQP.Queue.BindOk ok = delegate.queueBind(queue, exchange, routingKey, arguments); recordQueueBinding(queue, exchange, routingKey, arguments); return ok; } @Override public void queueBindNoWait(String queue, String exchange, String routingKey, Map arguments) throws IOException { delegate.queueBindNoWait(queue, exchange, routingKey, arguments); recordQueueBinding(queue, exchange, routingKey, arguments); } @Override public AMQP.Queue.UnbindOk queueUnbind(String queue, String exchange, String routingKey) throws IOException { return queueUnbind(queue, exchange, routingKey, null); } @Override public AMQP.Queue.UnbindOk queueUnbind(String queue, String exchange, String routingKey, Map arguments) throws IOException { deleteRecordedQueueBinding(queue, exchange, routingKey, arguments); this.maybeDeleteRecordedAutoDeleteExchange(exchange); return delegate.queueUnbind(queue, exchange, routingKey, arguments); } @Override public AMQP.Queue.PurgeOk queuePurge(String queue) throws IOException { return delegate.queuePurge(queue); } @Override public GetResponse basicGet(String queue, boolean autoAck) throws IOException { return delegate.basicGet(queue, autoAck); } @Override public void basicAck(long deliveryTag, boolean multiple) throws IOException { delegate.basicAck(deliveryTag, multiple); } @Override public void basicNack(long deliveryTag, boolean multiple, boolean requeue) throws IOException { delegate.basicNack(deliveryTag, multiple, requeue); } @Override public void basicReject(long deliveryTag, boolean requeue) throws IOException { delegate.basicReject(deliveryTag, requeue); } @Override public String basicConsume(String queue, Consumer callback) throws IOException { return basicConsume(queue, false, callback); } @Override public String basicConsume(String queue, DeliverCallback deliverCallback, CancelCallback cancelCallback) throws IOException { return basicConsume(queue, consumerFromDeliverCancelCallbacks(deliverCallback, cancelCallback)); } @Override public String basicConsume(String queue, DeliverCallback deliverCallback, ConsumerShutdownSignalCallback shutdownSignalCallback) throws IOException { return basicConsume(queue, consumerFromDeliverShutdownCallbacks(deliverCallback, shutdownSignalCallback)); } @Override public String basicConsume(String queue, DeliverCallback deliverCallback, CancelCallback cancelCallback, ConsumerShutdownSignalCallback shutdownSignalCallback) throws IOException { return basicConsume(queue, false, consumerFromDeliverCancelShutdownCallbacks(deliverCallback, cancelCallback, shutdownSignalCallback)); } @Override public String basicConsume(String queue, boolean autoAck, Consumer callback) throws IOException { return basicConsume(queue, autoAck, "", callback); } @Override public String basicConsume(String queue, boolean autoAck, DeliverCallback deliverCallback, CancelCallback cancelCallback) throws IOException { return basicConsume(queue, autoAck, "", consumerFromDeliverCancelCallbacks(deliverCallback, cancelCallback)); } @Override public String basicConsume(String queue, boolean autoAck, DeliverCallback deliverCallback, ConsumerShutdownSignalCallback shutdownSignalCallback) throws IOException { return basicConsume(queue, autoAck, "", consumerFromDeliverShutdownCallbacks(deliverCallback, shutdownSignalCallback)); } @Override public String basicConsume(String queue, boolean autoAck, DeliverCallback deliverCallback, CancelCallback cancelCallback, ConsumerShutdownSignalCallback shutdownSignalCallback) throws IOException { return basicConsume(queue, autoAck, "", consumerFromDeliverCancelShutdownCallbacks(deliverCallback, cancelCallback, shutdownSignalCallback)); } @Override public String basicConsume(String queue, boolean autoAck, String consumerTag, Consumer callback) throws IOException { return basicConsume(queue, autoAck, consumerTag, false, false, null, callback); } @Override public String basicConsume(String queue, boolean autoAck, String consumerTag, DeliverCallback deliverCallback, CancelCallback cancelCallback) throws IOException { return basicConsume(queue, autoAck, consumerTag, false, false, null, consumerFromDeliverCancelCallbacks(deliverCallback, cancelCallback)); } @Override public String basicConsume(String queue, boolean autoAck, String consumerTag, DeliverCallback deliverCallback, ConsumerShutdownSignalCallback shutdownSignalCallback) throws IOException { return basicConsume(queue, autoAck, consumerTag, false, false, null, consumerFromDeliverShutdownCallbacks(deliverCallback, shutdownSignalCallback)); } @Override public String basicConsume(String queue, boolean autoAck, String consumerTag, DeliverCallback deliverCallback, CancelCallback cancelCallback, ConsumerShutdownSignalCallback shutdownSignalCallback) throws IOException { return basicConsume(queue, autoAck, consumerTag, false, false, null, consumerFromDeliverCancelShutdownCallbacks(deliverCallback, cancelCallback, shutdownSignalCallback)); } @Override public String basicConsume(String queue, boolean autoAck, Map arguments, Consumer callback) throws IOException { return basicConsume(queue, autoAck, "", false, false, arguments, callback); } @Override public String basicConsume(String queue, boolean autoAck, Map arguments, DeliverCallback deliverCallback, CancelCallback cancelCallback) throws IOException { return basicConsume(queue, autoAck, "", false, false, arguments, consumerFromDeliverCancelCallbacks(deliverCallback, cancelCallback)); } @Override public String basicConsume(String queue, boolean autoAck, Map arguments, DeliverCallback deliverCallback, ConsumerShutdownSignalCallback shutdownSignalCallback) throws IOException { return basicConsume(queue, autoAck, "", false, false, arguments, consumerFromDeliverShutdownCallbacks(deliverCallback, shutdownSignalCallback)); } @Override public String basicConsume(String queue, boolean autoAck, Map arguments, DeliverCallback deliverCallback, CancelCallback cancelCallback, ConsumerShutdownSignalCallback shutdownSignalCallback) throws IOException { return basicConsume(queue, autoAck, "", false, false, arguments, consumerFromDeliverCancelShutdownCallbacks(deliverCallback, cancelCallback, shutdownSignalCallback)); } @Override public String basicConsume(String queue, boolean autoAck, String consumerTag, boolean noLocal, boolean exclusive, Map arguments, Consumer callback) throws IOException { final String result = delegate.basicConsume(queue, autoAck, consumerTag, noLocal, exclusive, arguments, callback); recordConsumer(result, queue, autoAck, exclusive, arguments, callback); return result; } @Override public String basicConsume(String queue, boolean autoAck, String consumerTag, boolean noLocal, boolean exclusive, Map arguments, DeliverCallback deliverCallback, CancelCallback cancelCallback) throws IOException { return basicConsume(queue, autoAck, consumerTag, noLocal, exclusive, arguments, consumerFromDeliverCancelCallbacks(deliverCallback, cancelCallback)); } @Override public String basicConsume(String queue, boolean autoAck, String consumerTag, boolean noLocal, boolean exclusive, Map arguments, DeliverCallback deliverCallback, ConsumerShutdownSignalCallback shutdownSignalCallback) throws IOException { return basicConsume(queue, autoAck, consumerTag, noLocal, exclusive, arguments, consumerFromDeliverShutdownCallbacks(deliverCallback, shutdownSignalCallback)); } @Override public String basicConsume(String queue, boolean autoAck, String consumerTag, boolean noLocal, boolean exclusive, Map arguments, DeliverCallback deliverCallback, CancelCallback cancelCallback, ConsumerShutdownSignalCallback shutdownSignalCallback) throws IOException { return basicConsume(queue, autoAck, consumerTag, noLocal, exclusive, arguments, consumerFromDeliverCancelShutdownCallbacks(deliverCallback, cancelCallback, shutdownSignalCallback)); } private Consumer consumerFromDeliverCancelCallbacks(final DeliverCallback deliverCallback, final CancelCallback cancelCallback) { return new Consumer() { @Override public void handleConsumeOk(String consumerTag) { } @Override public void handleCancelOk(String consumerTag) { } @Override public void handleCancel(String consumerTag) throws IOException { cancelCallback.handle(consumerTag); } @Override public void handleShutdownSignal(String consumerTag, ShutdownSignalException sig) { } @Override public void handleRecoverOk(String consumerTag) { } @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { deliverCallback.handle(consumerTag, new Delivery(envelope, properties, body)); } }; } private Consumer consumerFromDeliverShutdownCallbacks(final DeliverCallback deliverCallback, final ConsumerShutdownSignalCallback shutdownSignalCallback) { return new Consumer() { @Override public void handleConsumeOk(String consumerTag) { } @Override public void handleCancelOk(String consumerTag) { } @Override public void handleCancel(String consumerTag) throws IOException { } @Override public void handleShutdownSignal(String consumerTag, ShutdownSignalException sig) { shutdownSignalCallback.handleShutdownSignal(consumerTag, sig); } @Override public void handleRecoverOk(String consumerTag) { } @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { deliverCallback.handle(consumerTag, new Delivery(envelope, properties, body)); } }; } private Consumer consumerFromDeliverCancelShutdownCallbacks(final DeliverCallback deliverCallback, final CancelCallback cancelCallback, final ConsumerShutdownSignalCallback shutdownSignalCallback) { return new Consumer() { @Override public void handleConsumeOk(String consumerTag) { } @Override public void handleCancelOk(String consumerTag) { } @Override public void handleCancel(String consumerTag) throws IOException { cancelCallback.handle(consumerTag); } @Override public void handleShutdownSignal(String consumerTag, ShutdownSignalException sig) { shutdownSignalCallback.handleShutdownSignal(consumerTag, sig); } @Override public void handleRecoverOk(String consumerTag) { } @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { deliverCallback.handle(consumerTag, new Delivery(envelope, properties, body)); } }; } @Override public void basicCancel(String consumerTag) throws IOException { RecordedConsumer c = this.deleteRecordedConsumer(consumerTag); if(c != null) { this.maybeDeleteRecordedAutoDeleteQueue(c.getQueue()); } delegate.basicCancel(consumerTag); } @Override public AMQP.Basic.RecoverOk basicRecover() throws IOException { return delegate.basicRecover(); } @Override public AMQP.Basic.RecoverOk basicRecover(boolean requeue) throws IOException { return delegate.basicRecover(requeue); } @Override public AMQP.Tx.SelectOk txSelect() throws IOException { this.usesTransactions = true; return delegate.txSelect(); } @Override public AMQP.Tx.CommitOk txCommit() throws IOException { return delegate.txCommit(); } @Override public AMQP.Tx.RollbackOk txRollback() throws IOException { return delegate.txRollback(); } @Override public AMQP.Confirm.SelectOk confirmSelect() throws IOException { this.usesPublisherConfirms = true; return delegate.confirmSelect(); } @Override public long getNextPublishSeqNo() { return delegate.getNextPublishSeqNo(); } @Override public boolean waitForConfirms() throws InterruptedException { return delegate.waitForConfirms(); } @Override public boolean waitForConfirms(long timeout) throws InterruptedException, TimeoutException { return delegate.waitForConfirms(timeout); } @Override public void waitForConfirmsOrDie() throws IOException, InterruptedException { delegate.waitForConfirmsOrDie(); } @Override public void waitForConfirmsOrDie(long timeout) throws IOException, InterruptedException, TimeoutException { delegate.waitForConfirmsOrDie(timeout); } @Override public void asyncRpc(Method method) throws IOException { delegate.asyncRpc(method); } @Override public Command rpc(Method method) throws IOException { return delegate.rpc(method); } /** * @see Connection#addShutdownListener(com.rabbitmq.client.ShutdownListener) */ @Override public void addShutdownListener(ShutdownListener listener) { this.shutdownHooks.add(listener); delegate.addShutdownListener(listener); } @Override public void removeShutdownListener(ShutdownListener listener) { this.shutdownHooks.remove(listener); delegate.removeShutdownListener(listener); } @Override public ShutdownSignalException getCloseReason() { return delegate.getCloseReason(); } @Override public void notifyListeners() { delegate.notifyListeners(); } @Override public boolean isOpen() { return delegate.isOpen(); } @Override public void addRecoveryListener(RecoveryListener listener) { this.recoveryListeners.add(listener); } @Override public void removeRecoveryListener(RecoveryListener listener) { this.recoveryListeners.remove(listener); } // // Recovery // public void automaticallyRecover(AutorecoveringConnection connection, Connection connDelegate) throws IOException { RecoveryAwareChannelN defunctChannel = this.delegate; this.connection = connection; final RecoveryAwareChannelN newChannel = (RecoveryAwareChannelN) connDelegate.createChannel(this.getChannelNumber()); if (newChannel == null) throw new IOException("Failed to create new channel for channel number=" + this.getChannelNumber() + " during recovery"); this.delegate = newChannel; this.delegate.inheritOffsetFrom(defunctChannel); this.notifyRecoveryListenersStarted(); this.recoverShutdownListeners(); this.recoverReturnListeners(); this.recoverConfirmListeners(); this.recoverState(); this.notifyRecoveryListenersComplete(); } private void recoverShutdownListeners() { for (ShutdownListener sh : this.shutdownHooks) { this.delegate.addShutdownListener(sh); } } private void recoverReturnListeners() { for(ReturnListener rl : this.returnListeners) { this.delegate.addReturnListener(rl); } } private void recoverConfirmListeners() { for(ConfirmListener cl : this.confirmListeners) { this.delegate.addConfirmListener(cl); } } private void recoverState() throws IOException { if (this.prefetchCountConsumer != 0) { basicQos(this.prefetchCountConsumer, false); } if (this.prefetchCountGlobal != 0) { basicQos(this.prefetchCountGlobal, true); } if(this.usesPublisherConfirms) { this.confirmSelect(); } if(this.usesTransactions) { this.txSelect(); } } private void notifyRecoveryListenersComplete() { for (RecoveryListener f : this.recoveryListeners) { f.handleRecovery(this); } } private void notifyRecoveryListenersStarted() { for (RecoveryListener f : this.recoveryListeners) { f.handleRecoveryStarted(this); } } private void recordQueueBinding(String queue, String exchange, String routingKey, Map arguments) { this.connection.recordQueueBinding(this, queue, exchange, routingKey, arguments); } private boolean deleteRecordedQueueBinding(String queue, String exchange, String routingKey, Map arguments) { return this.connection.deleteRecordedQueueBinding(this, queue, exchange, routingKey, arguments); } private void recordExchangeBinding(String destination, String source, String routingKey, Map arguments) { this.connection.recordExchangeBinding(this, destination, source, routingKey, arguments); } private boolean deleteRecordedExchangeBinding(String destination, String source, String routingKey, Map arguments) { return this.connection.deleteRecordedExchangeBinding(this, destination, source, routingKey, arguments); } private void recordQueue(AMQP.Queue.DeclareOk ok, RecordedQueue q) { this.connection.recordQueue(ok, q); } private void recordQueue(String queue, RecordedQueue meta) { this.connection.recordQueue(queue, meta); } private void deleteRecordedQueue(String queue) { this.connection.deleteRecordedQueue(queue); } private void recordExchange(String exchange, RecordedExchange x) { this.connection.recordExchange(exchange, x); } private void deleteRecordedExchange(String exchange) { this.connection.deleteRecordedExchange(exchange); } private void recordConsumer(String result, String queue, boolean autoAck, boolean exclusive, Map arguments, Consumer callback) { RecordedConsumer consumer = new RecordedConsumer(this, queue). autoAck(autoAck). consumerTag(result). exclusive(exclusive). arguments(arguments). consumer(callback); this.consumerTags.add(result); this.connection.recordConsumer(result, consumer); } private RecordedConsumer deleteRecordedConsumer(String consumerTag) { this.consumerTags.remove(consumerTag); return this.connection.deleteRecordedConsumer(consumerTag); } private void maybeDeleteRecordedAutoDeleteQueue(String queue) { this.connection.maybeDeleteRecordedAutoDeleteQueue(queue); } private void maybeDeleteRecordedAutoDeleteExchange(String exchange) { this.connection.maybeDeleteRecordedAutoDeleteExchange(exchange); } void updateConsumerTag(String tag, String newTag) { synchronized (this.consumerTags) { consumerTags.remove(tag); consumerTags.add(newTag); } } @Override public CompletableFuture asyncCompletableRpc(Method method) throws IOException { return this.delegate.asyncCompletableRpc(method); } @Override public String toString() { return this.delegate.toString(); } } AutorecoveringConnection.java000066400000000000000000000763701316117667700344340ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/recovery// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl.recovery; import com.rabbitmq.client.*; import com.rabbitmq.client.impl.AMQConnection; import com.rabbitmq.client.impl.ConnectionParams; import com.rabbitmq.client.impl.FrameHandlerFactory; import com.rabbitmq.client.impl.NetworkConnection; import com.rabbitmq.utility.Utility; import java.io.IOException; import java.net.InetAddress; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.TimeoutException; /** * Connection implementation that performs automatic recovery when * connection shutdown is not initiated by the application (e.g. due to * an I/O exception). * * Topology (exchanges, queues, bindings, and consumers) can be (and by default is) recovered * as well, in this order: * *
    *
  1. Exchanges
  2. *
  3. Queues
  4. *
  5. Bindings (both queue and exchange-to-exchange)
  6. *
  7. Consumers
  8. *
* * @see com.rabbitmq.client.Connection * @see com.rabbitmq.client.Recoverable * @see com.rabbitmq.client.ConnectionFactory#setAutomaticRecoveryEnabled(boolean) * @see com.rabbitmq.client.ConnectionFactory#setTopologyRecoveryEnabled(boolean) * @since 3.3.0 */ public class AutorecoveringConnection implements RecoverableConnection, NetworkConnection { private final RecoveryAwareAMQConnectionFactory cf; private final Map channels; private final ConnectionParams params; private volatile RecoveryAwareAMQConnection delegate; private final List shutdownHooks = Collections.synchronizedList(new ArrayList()); private final List recoveryListeners = Collections.synchronizedList(new ArrayList()); private final List blockedListeners = Collections.synchronizedList(new ArrayList()); // Records topology changes private final Map recordedQueues = Collections.synchronizedMap(new LinkedHashMap()); private final List recordedBindings = Collections.synchronizedList(new ArrayList()); private final Map recordedExchanges = Collections.synchronizedMap(new LinkedHashMap()); private final Map consumers = Collections.synchronizedMap(new LinkedHashMap()); private final List consumerRecoveryListeners = Collections.synchronizedList(new ArrayList()); private final List queueRecoveryListeners = Collections.synchronizedList(new ArrayList()); // Used to block connection recovery attempts after close() is invoked. private volatile boolean manuallyClosed = false; // This lock guards the manuallyClosed flag and the delegate connection. Guarding these two ensures that a new connection can never // be created after application code has initiated shutdown. private final Object recoveryLock = new Object(); public AutorecoveringConnection(ConnectionParams params, FrameHandlerFactory f, List
addrs) { this(params, f, new ListAddressResolver(addrs)); } public AutorecoveringConnection(ConnectionParams params, FrameHandlerFactory f, AddressResolver addressResolver) { this(params, f, addressResolver, new NoOpMetricsCollector()); } public AutorecoveringConnection(ConnectionParams params, FrameHandlerFactory f, AddressResolver addressResolver, MetricsCollector metricsCollector) { this.cf = new RecoveryAwareAMQConnectionFactory(params, f, addressResolver, metricsCollector); this.params = params; this.channels = new ConcurrentHashMap(); } /** * Private API. * @throws IOException * @see com.rabbitmq.client.ConnectionFactory#newConnection(java.util.concurrent.ExecutorService) */ public void init() throws IOException, TimeoutException { this.delegate = this.cf.newConnection(); this.addAutomaticRecoveryListener(delegate); } /** * @see com.rabbitmq.client.Connection#createChannel() */ @Override public Channel createChannel() throws IOException { RecoveryAwareChannelN ch = (RecoveryAwareChannelN) delegate.createChannel(); if (ch == null) { return null; } else { return this.wrapChannel(ch); } } /** * @see com.rabbitmq.client.Connection#createChannel(int) */ @Override public Channel createChannel(int channelNumber) throws IOException { return delegate.createChannel(channelNumber); } /** * Creates a recovering channel from a regular channel and registers it. * If the regular channel cannot be created (e.g. too many channels are open * already), returns null. * * @param delegateChannel Channel to wrap. * @return Recovering channel. */ private Channel wrapChannel(RecoveryAwareChannelN delegateChannel) { if (delegateChannel == null) { return null; } else { final AutorecoveringChannel channel = new AutorecoveringChannel(this, delegateChannel); this.registerChannel(channel); return channel; } } void registerChannel(AutorecoveringChannel channel) { this.channels.put(channel.getChannelNumber(), channel); } void unregisterChannel(AutorecoveringChannel channel) { this.channels.remove(channel.getChannelNumber()); } /** * @see com.rabbitmq.client.Connection#getServerProperties() */ @Override public Map getServerProperties() { return delegate.getServerProperties(); } /** * @see com.rabbitmq.client.Connection#getClientProperties() */ @Override public Map getClientProperties() { return delegate.getClientProperties(); } /** * @see com.rabbitmq.client.Connection#getClientProvidedName() * @see ConnectionFactory#newConnection(Address[], String) * @see ConnectionFactory#newConnection(ExecutorService, Address[], String) */ @Override public String getClientProvidedName() { return delegate.getClientProvidedName(); } /** * @see com.rabbitmq.client.Connection#getFrameMax() */ @Override public int getFrameMax() { return delegate.getFrameMax(); } /** * @see com.rabbitmq.client.Connection#getHeartbeat() */ @Override public int getHeartbeat() { return delegate.getHeartbeat(); } /** * @see com.rabbitmq.client.Connection#getChannelMax() */ @Override public int getChannelMax() { return delegate.getChannelMax(); } /** * @see com.rabbitmq.client.Connection#isOpen() */ @Override public boolean isOpen() { return delegate.isOpen(); } /** * @see com.rabbitmq.client.Connection#close() */ @Override public void close() throws IOException { synchronized(recoveryLock) { this.manuallyClosed = true; } delegate.close(); } /** * @see Connection#close(int) */ @Override public void close(int timeout) throws IOException { synchronized(recoveryLock) { this.manuallyClosed = true; } delegate.close(timeout); } /** * @see Connection#close(int, String, int) */ @Override public void close(int closeCode, String closeMessage, int timeout) throws IOException { synchronized(recoveryLock) { this.manuallyClosed = true; } delegate.close(closeCode, closeMessage, timeout); } /** * @see com.rabbitmq.client.Connection#abort() */ @Override public void abort() { synchronized(recoveryLock) { this.manuallyClosed = true; } delegate.abort(); } /** * @see Connection#abort(int, String, int) */ @Override public void abort(int closeCode, String closeMessage, int timeout) { synchronized(recoveryLock) { this.manuallyClosed = true; } delegate.abort(closeCode, closeMessage, timeout); } /** * @see Connection#abort(int, String) */ @Override public void abort(int closeCode, String closeMessage) { synchronized(recoveryLock) { this.manuallyClosed = true; } delegate.abort(closeCode, closeMessage); } /** * @see Connection#abort(int) */ @Override public void abort(int timeout) { synchronized(recoveryLock) { this.manuallyClosed = true; } delegate.abort(timeout); } /** * Not supposed to be used outside of automated tests. */ public AMQConnection getDelegate() { return delegate; } /** * @see com.rabbitmq.client.Connection#getCloseReason() */ @Override public ShutdownSignalException getCloseReason() { return delegate.getCloseReason(); } /** * @see com.rabbitmq.client.ShutdownNotifier#addShutdownListener(com.rabbitmq.client.ShutdownListener) */ @Override public void addBlockedListener(BlockedListener listener) { this.blockedListeners.add(listener); delegate.addBlockedListener(listener); } @Override public BlockedListener addBlockedListener(BlockedCallback blockedCallback, UnblockedCallback unblockedCallback) { BlockedListener blockedListener = new BlockedListener() { @Override public void handleBlocked(String reason) throws IOException { blockedCallback.handle(reason); } @Override public void handleUnblocked() throws IOException { unblockedCallback.handle(); } }; this.addBlockedListener(blockedListener); return blockedListener; } /** * @see Connection#removeBlockedListener(com.rabbitmq.client.BlockedListener) */ @Override public boolean removeBlockedListener(BlockedListener listener) { this.blockedListeners.remove(listener); return delegate.removeBlockedListener(listener); } /** * @see com.rabbitmq.client.Connection#clearBlockedListeners() */ @Override public void clearBlockedListeners() { this.blockedListeners.clear(); delegate.clearBlockedListeners(); } /** * @see com.rabbitmq.client.Connection#close(int, String) */ @Override public void close(int closeCode, String closeMessage) throws IOException { synchronized(recoveryLock) { this.manuallyClosed = true; } delegate.close(closeCode, closeMessage); } /** * @see Connection#addShutdownListener(com.rabbitmq.client.ShutdownListener) */ @Override public void addShutdownListener(ShutdownListener listener) { this.shutdownHooks.add(listener); delegate.addShutdownListener(listener); } /** * @see com.rabbitmq.client.ShutdownNotifier#removeShutdownListener(com.rabbitmq.client.ShutdownListener) */ @Override public void removeShutdownListener(ShutdownListener listener) { this.shutdownHooks.remove(listener); delegate.removeShutdownListener(listener); } /** * @see com.rabbitmq.client.ShutdownNotifier#notifyListeners() */ @Override public void notifyListeners() { delegate.notifyListeners(); } /** * Adds the recovery listener * @param listener {@link com.rabbitmq.client.RecoveryListener} to execute after this connection recovers from network failure */ @Override public void addRecoveryListener(RecoveryListener listener) { this.recoveryListeners.add(listener); } /** * Removes the recovery listener * @param listener {@link com.rabbitmq.client.RecoveryListener} to remove */ @Override public void removeRecoveryListener(RecoveryListener listener) { this.recoveryListeners.remove(listener); } /** * @see com.rabbitmq.client.impl.AMQConnection#getExceptionHandler() */ @Override public ExceptionHandler getExceptionHandler() { return this.delegate.getExceptionHandler(); } /** * @see com.rabbitmq.client.Connection#getPort() */ @Override public int getPort() { return delegate.getPort(); } /** * @see com.rabbitmq.client.Connection#getAddress() */ @Override public InetAddress getAddress() { return delegate.getAddress(); } /** * @return client socket address */ @Override public InetAddress getLocalAddress() { return this.delegate.getLocalAddress(); } /** * @return client socket port */ @Override public int getLocalPort() { return this.delegate.getLocalPort(); } // // Recovery // private void addAutomaticRecoveryListener(final RecoveryAwareAMQConnection newConn) { final AutorecoveringConnection c = this; // this listener will run after shutdown listeners, // see https://github.com/rabbitmq/rabbitmq-java-client/issues/135 RecoveryCanBeginListener starter = new RecoveryCanBeginListener() { @Override public void recoveryCanBegin(ShutdownSignalException cause) { try { if (shouldTriggerConnectionRecovery(cause)) { c.beginAutomaticRecovery(); } } catch (Exception e) { newConn.getExceptionHandler().handleConnectionRecoveryException(c, e); } } }; synchronized (this) { newConn.addRecoveryCanBeginListener(starter); } } protected boolean shouldTriggerConnectionRecovery(ShutdownSignalException cause) { return !cause.isInitiatedByApplication() || (cause.getCause() instanceof MissedHeartbeatException); } /** * Not part of the public API. Mean to be used by JVM RabbitMQ clients that build on * top of the Java client and need to be notified when server-named queue name changes * after recovery. * * @param listener listener that observes queue name changes after recovery */ public void addQueueRecoveryListener(QueueRecoveryListener listener) { this.queueRecoveryListeners.add(listener); } /** * @see com.rabbitmq.client.impl.recovery.AutorecoveringConnection#addQueueRecoveryListener * @param listener listener to be removed */ public void removeQueueRecoveryListener(QueueRecoveryListener listener) { this.queueRecoveryListeners.remove(listener); } /** * Not part of the public API. Mean to be used by JVM RabbitMQ clients that build on * top of the Java client and need to be notified when consumer tag changes * after recovery. * * @param listener listener that observes consumer tag changes after recovery */ public void addConsumerRecoveryListener(ConsumerRecoveryListener listener) { this.consumerRecoveryListeners.add(listener); } /** * @see com.rabbitmq.client.impl.recovery.AutorecoveringConnection#addConsumerRecoveryListener(ConsumerRecoveryListener) * @param listener listener to be removed */ public void removeConsumerRecoveryListener(ConsumerRecoveryListener listener) { this.consumerRecoveryListeners.remove(listener); } synchronized private void beginAutomaticRecovery() throws InterruptedException { Thread.sleep(this.params.getNetworkRecoveryInterval()); this.notifyRecoveryListenersStarted(); final RecoveryAwareAMQConnection newConn = this.recoverConnection(); if (newConn == null) { return; } this.addAutomaticRecoveryListener(newConn); this.recoverShutdownListeners(newConn); this.recoverBlockedListeners(newConn); this.recoverChannels(newConn); // don't assign new delegate connection until channel recovery is complete this.delegate = newConn; if(this.params.isTopologyRecoveryEnabled()) { this.recoverEntities(); this.recoverConsumers(); } this.notifyRecoveryListenersComplete(); } private void recoverShutdownListeners(final RecoveryAwareAMQConnection newConn) { for (ShutdownListener sh : Utility.copy(this.shutdownHooks)) { newConn.addShutdownListener(sh); } } private void recoverBlockedListeners(final RecoveryAwareAMQConnection newConn) { for (BlockedListener bl : Utility.copy(this.blockedListeners)) { newConn.addBlockedListener(bl); } } // Returns new connection if the connection was recovered, // null if application initiated shutdown while attempting recovery. private RecoveryAwareAMQConnection recoverConnection() throws InterruptedException { while (!manuallyClosed) { try { RecoveryAwareAMQConnection newConn = this.cf.newConnection(); synchronized(recoveryLock) { if (!manuallyClosed) { // This is the standard case. return newConn; } } // This is the once in a blue moon case. // Application code just called close as the connection // was being re-established. So we attempt to close the newly created connection. newConn.abort(); return null; } catch (Exception e) { // TODO: exponential back-off Thread.sleep(this.params.getNetworkRecoveryInterval()); this.getExceptionHandler().handleConnectionRecoveryException(this, e); } } return null; } private void recoverChannels(final RecoveryAwareAMQConnection newConn) { for (AutorecoveringChannel ch : this.channels.values()) { try { ch.automaticallyRecover(this, newConn); } catch (Throwable t) { newConn.getExceptionHandler().handleChannelRecoveryException(ch, t); } } } private void notifyRecoveryListenersComplete() { for (RecoveryListener f : this.recoveryListeners) { f.handleRecovery(this); } } private void notifyRecoveryListenersStarted() { for (RecoveryListener f : this.recoveryListeners) { f.handleRecoveryStarted(this); } } private void recoverEntities() { // The recovery sequence is the following: // // 1. Recover exchanges // 2. Recover queues // 3. Recover bindings // 4. Recover consumers recoverExchanges(); recoverQueues(); recoverBindings(); } private void recoverExchanges() { // recorded exchanges are guaranteed to be // non-predefined (we filter out predefined ones // in exchangeDeclare). MK. for (RecordedExchange x : Utility.copy(this.recordedExchanges).values()) { try { x.recover(); } catch (Exception cause) { final String message = "Caught an exception while recovering exchange " + x.getName() + ": " + cause.getMessage(); TopologyRecoveryException e = new TopologyRecoveryException(message, cause); this.getExceptionHandler().handleTopologyRecoveryException(delegate, x.getDelegateChannel(), e); } } } private void recoverQueues() { for (Map.Entry entry : Utility.copy(this.recordedQueues).entrySet()) { String oldName = entry.getKey(); RecordedQueue q = entry.getValue(); try { q.recover(); String newName = q.getName(); if (!oldName.equals(newName)) { // make sure server-named queues are re-added with // their new names. MK. synchronized (this.recordedQueues) { this.propagateQueueNameChangeToBindings(oldName, newName); this.propagateQueueNameChangeToConsumers(oldName, newName); // bug26552: // remove old name after we've updated the bindings and consumers, // plus only for server-named queues, both to make sure we don't lose // anything to recover. MK. if(q.isServerNamed()) { deleteRecordedQueue(oldName); } this.recordedQueues.put(newName, q); } } for(QueueRecoveryListener qrl : Utility.copy(this.queueRecoveryListeners)) { qrl.queueRecovered(oldName, newName); } } catch (Exception cause) { final String message = "Caught an exception while recovering queue " + oldName + ": " + cause.getMessage(); TopologyRecoveryException e = new TopologyRecoveryException(message, cause); this.getExceptionHandler().handleTopologyRecoveryException(delegate, q.getDelegateChannel(), e); } } } private void recoverBindings() { for (RecordedBinding b : Utility.copy(this.recordedBindings)) { try { b.recover(); } catch (Exception cause) { String message = "Caught an exception while recovering binding between " + b.getSource() + " and " + b.getDestination() + ": " + cause.getMessage(); TopologyRecoveryException e = new TopologyRecoveryException(message, cause); this.getExceptionHandler().handleTopologyRecoveryException(delegate, b.getDelegateChannel(), e); } } } private void recoverConsumers() { for (Map.Entry entry : Utility.copy(this.consumers).entrySet()) { String tag = entry.getKey(); RecordedConsumer consumer = entry.getValue(); try { String newTag = consumer.recover(); // make sure server-generated tags are re-added. MK. if(tag != null && !tag.equals(newTag)) { synchronized (this.consumers) { this.consumers.remove(tag); this.consumers.put(newTag, consumer); } consumer.getChannel().updateConsumerTag(tag, newTag); } for(ConsumerRecoveryListener crl : Utility.copy(this.consumerRecoveryListeners)) { crl.consumerRecovered(tag, newTag); } } catch (Exception cause) { final String message = "Caught an exception while recovering consumer " + tag + ": " + cause.getMessage(); TopologyRecoveryException e = new TopologyRecoveryException(message, cause); this.getExceptionHandler().handleTopologyRecoveryException(delegate, consumer.getDelegateChannel(), e); } } } private void propagateQueueNameChangeToBindings(String oldName, String newName) { for (RecordedBinding b : Utility.copy(this.recordedBindings)) { if (b.getDestination().equals(oldName)) { b.setDestination(newName); } } } private void propagateQueueNameChangeToConsumers(String oldName, String newName) { for (RecordedConsumer c : Utility.copy(this.consumers).values()) { if (c.getQueue().equals(oldName)) { c.setQueue(newName); } } } void recordQueueBinding(AutorecoveringChannel ch, String queue, String exchange, String routingKey, Map arguments) { RecordedBinding binding = new RecordedQueueBinding(ch). source(exchange). destination(queue). routingKey(routingKey). arguments(arguments); this.recordedBindings.remove(binding); this.recordedBindings.add(binding); } boolean deleteRecordedQueueBinding(AutorecoveringChannel ch, String queue, String exchange, String routingKey, Map arguments) { RecordedBinding b = new RecordedQueueBinding(ch). source(exchange). destination(queue). routingKey(routingKey). arguments(arguments); return this.recordedBindings.remove(b); } void recordExchangeBinding(AutorecoveringChannel ch, String destination, String source, String routingKey, Map arguments) { RecordedBinding binding = new RecordedExchangeBinding(ch). source(source). destination(destination). routingKey(routingKey). arguments(arguments); this.recordedBindings.remove(binding); this.recordedBindings.add(binding); } boolean deleteRecordedExchangeBinding(AutorecoveringChannel ch, String destination, String source, String routingKey, Map arguments) { RecordedBinding b = new RecordedExchangeBinding(ch). source(source). destination(destination). routingKey(routingKey). arguments(arguments); return this.recordedBindings.remove(b); } void recordQueue(AMQP.Queue.DeclareOk ok, RecordedQueue q) { this.recordedQueues.put(ok.getQueue(), q); } void recordQueue(String queue, RecordedQueue meta) { this.recordedQueues.put(queue, meta); } void deleteRecordedQueue(String queue) { this.recordedQueues.remove(queue); Set xs = this.removeBindingsWithDestination(queue); for (RecordedBinding b : xs) { this.maybeDeleteRecordedAutoDeleteExchange(b.getSource()); } } void recordExchange(String exchange, RecordedExchange x) { this.recordedExchanges.put(exchange, x); } void deleteRecordedExchange(String exchange) { this.recordedExchanges.remove(exchange); Set xs = this.removeBindingsWithDestination(exchange); for (RecordedBinding b : xs) { this.maybeDeleteRecordedAutoDeleteExchange(b.getSource()); } } void recordConsumer(String result, RecordedConsumer consumer) { this.consumers.put(result, consumer); } RecordedConsumer deleteRecordedConsumer(String consumerTag) { return this.consumers.remove(consumerTag); } void maybeDeleteRecordedAutoDeleteQueue(String queue) { synchronized (this.consumers) { synchronized (this.recordedQueues) { if(!hasMoreConsumersOnQueue(this.consumers.values(), queue)) { RecordedQueue q = this.recordedQueues.get(queue); // last consumer on this connection is gone, remove recorded queue // if it is auto-deleted. See bug 26364. if((q != null) && q.isAutoDelete()) { deleteRecordedQueue(queue); } } } } } void maybeDeleteRecordedAutoDeleteExchange(String exchange) { synchronized (this.consumers) { synchronized (this.recordedExchanges) { if(!hasMoreDestinationsBoundToExchange(Utility.copy(this.recordedBindings), exchange)) { RecordedExchange x = this.recordedExchanges.get(exchange); // last binding where this exchange is the source is gone, remove recorded exchange // if it is auto-deleted. See bug 26364. if((x != null) && x.isAutoDelete()) { deleteRecordedExchange(exchange); } } } } } boolean hasMoreDestinationsBoundToExchange(List bindings, String exchange) { boolean result = false; for (RecordedBinding b : bindings) { if(exchange.equals(b.getSource())) { result = true; break; } } return result; } boolean hasMoreConsumersOnQueue(Collection consumers, String queue) { boolean result = false; for (RecordedConsumer c : consumers) { if(queue.equals(c.getQueue())) { result = true; break; } } return result; } Set removeBindingsWithDestination(String s) { final Set result = new HashSet(); synchronized (this.recordedBindings) { for (Iterator it = this.recordedBindings.iterator(); it.hasNext(); ) { RecordedBinding b = it.next(); if(b.getDestination().equals(s)) { it.remove(); result.add(b); } } } return result; } public Map getRecordedQueues() { return recordedQueues; } public Map getRecordedExchanges() { return recordedExchanges; } @Override public String toString() { return this.delegate.toString(); } /** Public API - {@inheritDoc} */ @Override public String getId() { return this.delegate.getId(); } /** Public API - {@inheritDoc} */ @Override public void setId(String id) { this.delegate.setId(id); } } ConsumerRecoveryListener.java000066400000000000000000000020761316117667700344300ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/recovery// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl.recovery; /** * Not part of the public API. Mean to be used by JVM RabbitMQ clients that build on * top of the Java client and need to be notified when consumer tag changes * after recovery. */ public interface ConsumerRecoveryListener { void consumerRecovered(String oldConsumerTag, String newConsumerTag); } QueueRecoveryListener.java000066400000000000000000000020641316117667700337160ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/recovery// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl.recovery; /** * Not part of the public API. Mean to be used by JVM RabbitMQ clients that build on * top of the Java client and need to be notified when server-name queue name changes * after recovery. */ public interface QueueRecoveryListener { void queueRecovered(String oldName, String newName); } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/recovery/RecordedBinding.java000066400000000000000000000053751316117667700325160ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl.recovery; import java.io.IOException; import java.util.Map; /** * @since 3.3.0 */ public abstract class RecordedBinding extends RecordedEntity { protected String source; protected String destination; protected String routingKey; protected Map arguments; public RecordedBinding(AutorecoveringChannel channel) { super(channel); } public RecordedBinding source(String value) { this.source = value; return this; } public RecordedBinding destination(String value) { this.destination = value; return this; } public RecordedBinding routingKey(String value) { this.routingKey = value; return this; } public RecordedBinding arguments(Map value) { this.arguments = value; return this; } public String getSource() { return source; } public String getDestination() { return destination; } public Map getArguments() { return arguments; } public void setDestination(String destination) { this.destination = destination; } public abstract void recover() throws IOException; @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; RecordedBinding that = (RecordedBinding) o; if (arguments != null ? !arguments.equals(that.arguments) : that.arguments != null) return false; if (!destination.equals(that.destination)) return false; if (!routingKey.equals(that.routingKey)) return false; if (!source.equals(that.source)) return false; return true; } @Override public int hashCode() { int result = source.hashCode(); result = 31 * result + destination.hashCode(); result = 31 * result + routingKey.hashCode(); result = 31 * result + (arguments != null ? arguments.hashCode() : 0); return result; } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/recovery/RecordedConsumer.java000066400000000000000000000044221316117667700327270ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl.recovery; import com.rabbitmq.client.Consumer; import java.io.IOException; import java.util.Map; /** * @since 3.3.0 */ public class RecordedConsumer extends RecordedEntity { private String queue; private String consumerTag; private Consumer consumer; private boolean exclusive; private boolean autoAck; private Map arguments; public RecordedConsumer(AutorecoveringChannel channel, String queue) { super(channel); this.queue = queue; } public RecordedConsumer consumerTag(String value) { this.consumerTag = value; return this; } public RecordedConsumer consumer(Consumer value) { this.consumer = value; return this; } public RecordedConsumer exclusive(boolean value) { this.exclusive = value; return this; } public RecordedConsumer autoAck(boolean value) { this.autoAck = value; return this; } public String recover() throws IOException { this.consumerTag = this.channel.getDelegate().basicConsume(this.queue, this.autoAck, this.consumerTag, false, this.exclusive, this.arguments, this.consumer); return this.consumerTag; } public RecordedConsumer arguments(Map value) { this.arguments = value; return this; } public String getQueue() { return queue; } public void setQueue(String queue) { this.queue = queue; } public String getConsumerTag() { return consumerTag; } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/recovery/RecordedEntity.java000066400000000000000000000022421316117667700324060ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl.recovery; import com.rabbitmq.client.Channel; /** * @since 3.3.0 */ public class RecordedEntity { protected final AutorecoveringChannel channel; public RecordedEntity(AutorecoveringChannel channel) { this.channel = channel; } public AutorecoveringChannel getChannel() { return channel; } public Channel getDelegateChannel() { return channel.getDelegate(); } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/recovery/RecordedExchange.java000066400000000000000000000035031316117667700326550ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl.recovery; import java.io.IOException; import java.util.Map; /** * @since 3.3.0 */ public class RecordedExchange extends RecordedNamedEntity { private boolean durable; private boolean autoDelete; private Map arguments; private String type; public RecordedExchange(AutorecoveringChannel channel, String name) { super(channel, name); } public void recover() throws IOException { this.channel.getDelegate().exchangeDeclare(this.name, this.type, this.durable, this.autoDelete, this.arguments); } public RecordedExchange durable(boolean value) { this.durable = value; return this; } public RecordedExchange autoDelete(boolean value) { this.autoDelete = value; return this; } public RecordedExchange type(String value) { this.type = value; return this; } public RecordedExchange arguments(Map value) { this.arguments = value; return this; } public boolean isAutoDelete() { return autoDelete; } } RecordedExchangeBinding.java000066400000000000000000000022271316117667700340730ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/recovery// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl.recovery; import java.io.IOException; /** * @since 3.3.0 */ public class RecordedExchangeBinding extends RecordedBinding { public RecordedExchangeBinding(AutorecoveringChannel channel) { super(channel); } @Override public void recover() throws IOException { this.channel.getDelegate().exchangeBind(this.destination, this.source, this.routingKey, this.arguments); } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/recovery/RecordedNamedEntity.java000066400000000000000000000020711316117667700333530ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl.recovery; /** * @since 3.3.0 */ public class RecordedNamedEntity extends RecordedEntity { protected String name; public RecordedNamedEntity(AutorecoveringChannel channel, String name) { super(channel); this.name = name; } public String getName() { return name; } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/recovery/RecordedQueue.java000066400000000000000000000047761316117667700322340ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl.recovery; import java.io.IOException; import java.util.Map; /** * @since 3.3.0 */ public class RecordedQueue extends RecordedNamedEntity { public static final String EMPTY_STRING = ""; private boolean durable; private boolean autoDelete; private Map arguments; private boolean exclusive; private boolean serverNamed; public RecordedQueue(AutorecoveringChannel channel, String name) { super(channel, name); } public RecordedQueue exclusive(boolean value) { this.exclusive = value; return this; } public RecordedQueue serverNamed(boolean value) { this.serverNamed = value; return this; } public boolean isServerNamed() { return this.serverNamed; } public boolean isAutoDelete() { return this.autoDelete; } public void recover() throws IOException { this.name = this.channel.getDelegate().queueDeclare(this.getNameToUseForRecovery(), this.durable, this.exclusive, this.autoDelete, this.arguments).getQueue(); } public String getNameToUseForRecovery() { if(isServerNamed()) { return EMPTY_STRING; } else { return this.name; } } public RecordedQueue durable(boolean value) { this.durable = value; return this; } public RecordedQueue autoDelete(boolean value) { this.autoDelete = value; return this; } public RecordedQueue arguments(Map value) { this.arguments = value; return this; } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/recovery/RecordedQueueBinding.java000066400000000000000000000022301316117667700335060ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl.recovery; import java.io.IOException; /** * @since 3.3.0 */ public class RecordedQueueBinding extends RecordedBinding { public RecordedQueueBinding(AutorecoveringChannel channel) { super(channel); } @Override public void recover() throws IOException { this.channel.getDelegate().queueBind(this.getDestination(), this.getSource(), this.routingKey, this.arguments); } } RecoveryAwareAMQConnection.java000066400000000000000000000036561316117667700345520ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/recovery// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl.recovery; import com.rabbitmq.client.MetricsCollector; import com.rabbitmq.client.impl.AMQConnection; import com.rabbitmq.client.impl.ConnectionParams; import com.rabbitmq.client.impl.FrameHandler; import java.util.concurrent.ThreadFactory; /** * {@link com.rabbitmq.client.impl.AMQConnection} modification that uses {@link com.rabbitmq.client.impl.recovery.RecoveryAwareChannelN} * @since 3.3.0 */ public class RecoveryAwareAMQConnection extends AMQConnection { public RecoveryAwareAMQConnection(ConnectionParams params, FrameHandler handler, MetricsCollector metricsCollector) { super(params, handler, metricsCollector); } public RecoveryAwareAMQConnection(ConnectionParams params, FrameHandler handler) { super(params, handler); } @Override protected RecoveryAwareChannelManager instantiateChannelManager(int channelMax, ThreadFactory threadFactory) { RecoveryAwareChannelManager recoveryAwareChannelManager = new RecoveryAwareChannelManager(super._workService, channelMax, threadFactory, this.metricsCollector); configureChannelManager(recoveryAwareChannelManager); return recoveryAwareChannelManager; } } RecoveryAwareAMQConnectionFactory.java000066400000000000000000000102001316117667700360610ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/recovery// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl.recovery; import com.rabbitmq.client.*; import com.rabbitmq.client.impl.ConnectionParams; import com.rabbitmq.client.impl.FrameHandler; import com.rabbitmq.client.impl.FrameHandlerFactory; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.concurrent.TimeoutException; public class RecoveryAwareAMQConnectionFactory { private final ConnectionParams params; private final FrameHandlerFactory factory; private final AddressResolver addressResolver; private final MetricsCollector metricsCollector; public RecoveryAwareAMQConnectionFactory(ConnectionParams params, FrameHandlerFactory factory, List
addrs) { this(params, factory, new ListAddressResolver(addrs), new NoOpMetricsCollector()); } public RecoveryAwareAMQConnectionFactory(ConnectionParams params, FrameHandlerFactory factory, AddressResolver addressResolver) { this(params, factory, addressResolver, new NoOpMetricsCollector()); } public RecoveryAwareAMQConnectionFactory(ConnectionParams params, FrameHandlerFactory factory, AddressResolver addressResolver, MetricsCollector metricsCollector) { this.params = params; this.factory = factory; this.addressResolver = addressResolver; this.metricsCollector = metricsCollector; } /** * @return an interface to the connection * @throws java.io.IOException if it encounters a problem */ // package protected API, made public for testing only public RecoveryAwareAMQConnection newConnection() throws IOException, TimeoutException { Exception lastException = null; List
shuffled = shuffle(addressResolver.getAddresses()); for (Address addr : shuffled) { try { FrameHandler frameHandler = factory.create(addr, connectionName()); RecoveryAwareAMQConnection conn = createConnection(params, frameHandler, metricsCollector); conn.start(); metricsCollector.newConnection(conn); return conn; } catch (IOException e) { lastException = e; } catch (TimeoutException te) { lastException = te; } } if (lastException != null) { if (lastException instanceof IOException) { throw (IOException) lastException; } else if (lastException instanceof TimeoutException) { throw (TimeoutException) lastException; } } throw new IOException("failed to connect"); } private static List
shuffle(List
addrs) { List
list = new ArrayList
(addrs); Collections.shuffle(list); return list; } protected RecoveryAwareAMQConnection createConnection(ConnectionParams params, FrameHandler handler, MetricsCollector metricsCollector) { return new RecoveryAwareAMQConnection(params, handler, metricsCollector); } private String connectionName() { Map clientProperties = params.getClientProperties(); if (clientProperties == null) { return null; } else { Object connectionName = clientProperties.get("connection_name"); return connectionName == null ? null : connectionName.toString(); } } } RecoveryAwareChannelManager.java000066400000000000000000000040621316117667700347470ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/recovery// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl.recovery; import com.rabbitmq.client.NoOpMetricsCollector; import com.rabbitmq.client.MetricsCollector; import com.rabbitmq.client.impl.AMQConnection; import com.rabbitmq.client.impl.ChannelManager; import com.rabbitmq.client.impl.ChannelN; import com.rabbitmq.client.impl.ConsumerWorkService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; /** * @since 3.3.0 */ public class RecoveryAwareChannelManager extends ChannelManager { public RecoveryAwareChannelManager(ConsumerWorkService workService, int channelMax) { this(workService, channelMax, Executors.defaultThreadFactory()); } public RecoveryAwareChannelManager(ConsumerWorkService workService, int channelMax, ThreadFactory threadFactory) { super(workService, channelMax, threadFactory, new NoOpMetricsCollector()); } public RecoveryAwareChannelManager(ConsumerWorkService workService, int channelMax, ThreadFactory threadFactory, MetricsCollector metricsCollector) { super(workService, channelMax, threadFactory, metricsCollector); } @Override protected ChannelN instantiateChannel(AMQConnection connection, int channelNumber, ConsumerWorkService workService) { return new RecoveryAwareChannelN(connection, channelNumber, workService, this.metricsCollector); } } RecoveryAwareChannelN.java000066400000000000000000000114741316117667700335770ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/recovery// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl.recovery; import com.rabbitmq.client.Command; import com.rabbitmq.client.NoOpMetricsCollector; import com.rabbitmq.client.MetricsCollector; import com.rabbitmq.client.impl.AMQConnection; import com.rabbitmq.client.impl.AMQImpl; import com.rabbitmq.client.impl.ChannelN; import com.rabbitmq.client.impl.ConsumerWorkService; import java.io.IOException; /** * {@link com.rabbitmq.client.impl.ChannelN} modification that keeps track of delivery * tags and avoids sending
basic.ack
,
basic.nack
, and
basic.reject
* for stale tags. * * @since 3.3.0 */ public class RecoveryAwareChannelN extends ChannelN { private long maxSeenDeliveryTag = 0; private long activeDeliveryTagOffset = 0; /** * Construct a new channel on the given connection with the given * channel number. Usually not called directly - call * Connection.createChannel instead. * * @param connection The connection associated with this channel * @param channelNumber The channel number to be associated with this channel * @param workService service for managing this channel's consumer callbacks */ public RecoveryAwareChannelN(AMQConnection connection, int channelNumber, ConsumerWorkService workService) { this(connection, channelNumber, workService, new NoOpMetricsCollector()); } /** * Construct a new channel on the given connection with the given * channel number. Usually not called directly - call * Connection.createChannel instead. * * @param connection The connection associated with this channel * @param channelNumber The channel number to be associated with this channel * @param workService service for managing this channel's consumer callbacks * @param metricsCollector service for managing metrics */ public RecoveryAwareChannelN(AMQConnection connection, int channelNumber, ConsumerWorkService workService, MetricsCollector metricsCollector) { super(connection, channelNumber, workService, metricsCollector); } @Override protected void processDelivery(Command command, AMQImpl.Basic.Deliver method) { long tag = method.getDeliveryTag(); if(tag > maxSeenDeliveryTag) { maxSeenDeliveryTag = tag; } super.processDelivery(command, offsetDeliveryTag(method)); } private AMQImpl.Basic.Deliver offsetDeliveryTag(AMQImpl.Basic.Deliver method) { return new AMQImpl.Basic.Deliver(method.getConsumerTag(), method.getDeliveryTag() + activeDeliveryTagOffset, method.getRedelivered(), method.getExchange(), method.getRoutingKey()); } @Override public void basicAck(long deliveryTag, boolean multiple) throws IOException { // FIXME no check if deliveryTag = 0 (ack all) long realTag = deliveryTag - activeDeliveryTagOffset; // 0 tag means ack all if (realTag >= 0) { super.basicAck(realTag, multiple); } } @Override public void basicNack(long deliveryTag, boolean multiple, boolean requeue) throws IOException { // FIXME no check if deliveryTag = 0 (nack all) long realTag = deliveryTag - activeDeliveryTagOffset; // 0 tag means nack all if (realTag >= 0) { super.basicNack(realTag, multiple, requeue); } } @Override public void basicReject(long deliveryTag, boolean requeue) throws IOException { long realTag = deliveryTag - activeDeliveryTagOffset; if (realTag > 0) { super.basicReject(realTag, requeue); } } void inheritOffsetFrom(RecoveryAwareChannelN other) { activeDeliveryTagOffset = other.getActiveDeliveryTagOffset() + other.getMaxSeenDeliveryTag(); maxSeenDeliveryTag = 0; } public long getMaxSeenDeliveryTag() { return maxSeenDeliveryTag; } public long getActiveDeliveryTagOffset() { return activeDeliveryTagOffset; } } RecoveryCanBeginListener.java000066400000000000000000000022021316117667700342720ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/impl/recovery// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl.recovery; import com.rabbitmq.client.ShutdownSignalException; /** * Used internally to indicate when connection recovery can * begin. * This is package-local by design. * * @see Issue 135 on GitHub */ public interface RecoveryCanBeginListener { void recoveryCanBegin(ShutdownSignalException cause); } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/client/package.html000066400000000000000000000003701316117667700263010ustar00rootroot00000000000000 The client API proper: classes and interfaces representing the AMQP connections, channels, and wire-protocol framing descriptors. rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/tools/000077500000000000000000000000001316117667700237025ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/tools/json/000077500000000000000000000000001316117667700246535ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/tools/json/JSONReader.java000066400000000000000000000176771316117667700274340ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. /* Copyright (c) 2006-2007 Frank Carver Copyright (c) 2007-2016 Pivotal Software, Inc. All Rights Reserved 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. */ /* * Based on org.stringtree.json.JSONReader, licensed under APL and * LGPL. We've chosen APL (see above). The original code was written * by Frank Carver. Tony Garnock-Jones has made many changes to it * since then. */ package com.rabbitmq.tools.json; import java.text.CharacterIterator; import java.text.StringCharacterIterator; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class JSONReader { private static final Object OBJECT_END = new Object(); private static final Object ARRAY_END = new Object(); private static final Object COLON = new Object(); private static final Object COMMA = new Object(); private static final Map escapes = new HashMap(); static { escapes.put(Character.valueOf('"'), Character.valueOf('"')); escapes.put(Character.valueOf('\\'), Character.valueOf('\\')); escapes.put(Character.valueOf('/'), Character.valueOf('/')); escapes.put(Character.valueOf('b'), Character.valueOf('\b')); escapes.put(Character.valueOf('f'), Character.valueOf('\f')); escapes.put(Character.valueOf('n'), Character.valueOf('\n')); escapes.put(Character.valueOf('r'), Character.valueOf('\r')); escapes.put(Character.valueOf('t'), Character.valueOf('\t')); } private CharacterIterator it; private char c; private Object token; private final StringBuilder buf = new StringBuilder(); private char next() { c = it.next(); return c; } private void skipWhiteSpace() { boolean cont; do { cont = true; if (Character.isWhitespace(c)) { next(); } else if (c == '/' && next() == '/') { while (c != '\n') { next(); } } else { cont = false; } } while (cont); } public Object read(String string) { it = new StringCharacterIterator(string); c = it.first(); return read(); } private Object read() { Object ret = null; skipWhiteSpace(); if (c == '"' || c == '\'') { char sep = c; next(); ret = string(sep); } else if (c == '[') { next(); ret = array(); } else if (c == ']') { ret = ARRAY_END; next(); } else if (c == ',') { ret = COMMA; next(); } else if (c == '{') { next(); ret = object(); } else if (c == '}') { ret = OBJECT_END; next(); } else if (c == ':') { ret = COLON; next(); } else if (c == 't' && next() == 'r' && next() == 'u' && next() == 'e') { ret = Boolean.TRUE; next(); } else if (c == 'f' && next() == 'a' && next() == 'l' && next() == 's' && next() == 'e') { ret = Boolean.FALSE; next(); } else if (c == 'n' && next() == 'u' && next() == 'l' && next() == 'l') { next(); } else if (Character.isDigit(c) || c == '-') { ret = number(); } else { throw new IllegalStateException("Found invalid token while parsing JSON (around character "+(it.getIndex()-it.getBeginIndex())+"): " + ret); } token = ret; return ret; } private Object object() { Map ret = new HashMap(); String key = (String) read(); // JSON keys must be strings while (token != OBJECT_END) { read(); // should be a colon if (token != OBJECT_END) { ret.put(key, read()); if (read() == COMMA) { key = (String) read(); } } } return ret; } private Object array() { List ret = new ArrayList(); Object value = read(); while (token != ARRAY_END) { ret.add(value); if (read() == COMMA) { value = read(); } } return ret; } private Object number() { buf.setLength(0); if (c == '-') { add(); } addDigits(); if (c == '.') { add(); addDigits(); } if (c == 'e' || c == 'E') { add(); if (c == '+' || c == '-') { add(); } addDigits(); } String result = buf.toString(); try { return Integer.valueOf(result); } catch (NumberFormatException nfe) { return Double.valueOf(result); } } /** * Read a string with a specific delimiter (either ' or ") */ private Object string(char sep) { buf.setLength(0); while (c != sep) { if (c == '\\') { next(); if (c == 'u') { add(unicode()); } else { Object value = escapes.get(Character.valueOf(c)); if (value != null) { add(((Character) value).charValue()); } // if escaping is invalid, if we're going to ignore the error, // it makes more sense to put in the literal character instead // of just skipping it, so we do that else { add(); } } } else { add(); } } next(); return buf.toString(); } private void add(char cc) { buf.append(cc); next(); } private void add() { add(c); } private void addDigits() { while (Character.isDigit(c)) { add(); } } private char unicode() { int value = 0; for (int i = 0; i < 4; ++i) { switch (next()) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': value = (value << 4) + c - '0'; break; case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': value = (value << 4) + c - 'a' + 10; break; case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': value = (value << 4) + c - 'A' + 10; break; } } return (char) value; } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/tools/json/JSONSerializable.java000066400000000000000000000017301316117667700306170ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.tools.json; /** * Interface for classes that wish to control their own serialization. */ public interface JSONSerializable { /** * Called during serialization to JSON. */ void jsonSerialize(JSONWriter w); } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/tools/json/JSONUtil.java000066400000000000000000000071211316117667700271260ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.tools.json; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.beans.BeanInfo; import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.Map; /** * Utility methods for working with JSON objects in Java. */ public class JSONUtil { private static final Logger LOGGER = LoggerFactory.getLogger(JSONUtil.class); /** * Uses reflection to fill public fields and Bean properties of * the target object from the source Map. */ public static Object fill(Object target, Map source) throws IntrospectionException, IllegalAccessException, InvocationTargetException { return fill(target, source, true); } /** * Uses reflection to fill public fields and optionally Bean * properties of the target object from the source Map. */ public static Object fill(Object target, Map source, boolean useProperties) throws IntrospectionException, IllegalAccessException, InvocationTargetException { if (useProperties) { BeanInfo info = Introspector.getBeanInfo(target.getClass()); PropertyDescriptor[] props = info.getPropertyDescriptors(); for (int i = 0; i < props.length; ++i) { PropertyDescriptor prop = props[i]; String name = prop.getName(); Method setter = prop.getWriteMethod(); if (setter != null && !Modifier.isStatic(setter.getModifiers())) { //System.out.println(target + " " + name + " <- " + source.get(name)); setter.invoke(target, source.get(name)); } } } Field[] ff = target.getClass().getDeclaredFields(); for (int i = 0; i < ff.length; ++i) { Field field = ff[i]; int fieldMod = field.getModifiers(); if (Modifier.isPublic(fieldMod) && !(Modifier.isFinal(fieldMod) || Modifier.isStatic(fieldMod))) { //System.out.println(target + " " + field.getName() + " := " + source.get(field.getName())); try { field.set(target, source.get(field.getName())); } catch (IllegalArgumentException iae) { // no special error processing required } } } return target; } /** * Ignores reflection exceptions while using reflection to fill * public fields and Bean properties of the target object from the * source Map. */ public static void tryFill(Object target, Map source) { try { fill(target, source); } catch (IntrospectionException ie) { LOGGER.error("Error in tryFill", ie); } catch (IllegalAccessException iae) { LOGGER.error("Error in tryFill", iae); } catch (InvocationTargetException ite) { LOGGER.error("Error in tryFill", ite); } } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/tools/json/JSONWriter.java000066400000000000000000000221551316117667700274710ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. /* Copyright (c) 2006-2007 Frank Carver Copyright (c) 2007-2016 Pivotal Software, Inc. All Rights Reserved 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. */ /* * Based on org.stringtree.json.JSONWriter, licensed under APL and * LGPL. We've chosen APL (see above). The original code was written * by Frank Carver. Tony Garnock-Jones has made many changes to it * since then. */ package com.rabbitmq.tools.json; import java.beans.BeanInfo; import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.lang.reflect.Array; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.text.CharacterIterator; import java.text.StringCharacterIterator; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; public class JSONWriter { private boolean indentMode = false; private int indentLevel = 0; private final StringBuilder buf = new StringBuilder(); public JSONWriter() {} public JSONWriter(boolean indenting) { indentMode = indenting; } public boolean getIndentMode() { return indentMode; } public void setIndentMode(boolean value) { indentMode = value; } private void newline() { if (indentMode) { add('\n'); for (int i = 0; i < indentLevel; i++) add(' '); } } public String write(Object object) { buf.setLength(0); value(object); return buf.toString(); } public String write(long n) { return write(Long.valueOf(n)); } public Object write(double d) { return write(Double.valueOf(d)); } public String write(char c) { return write(Character.valueOf(c)); } public String write(boolean b) { return write(Boolean.valueOf(b)); } @SuppressWarnings("unchecked") private void value(Object object) { if (object == null) add("null"); else if (object instanceof JSONSerializable) { ((JSONSerializable) object).jsonSerialize(this); } else if (object instanceof Class) string(object); else if (object instanceof Boolean) bool(((Boolean) object).booleanValue()); else if (object instanceof Number) add(object); else if (object instanceof String) string(object); else if (object instanceof Character) string(object); else if (object instanceof Map) map((Map) object); else if (object.getClass().isArray()) array(object); else if (object instanceof Collection) array(((Collection) object).iterator()); else bean(object); } private void bean(Object object) { writeLimited(object.getClass(), object, null); } /** * Write only a certain subset of the object's properties and fields. * @param klass the class to look up properties etc in * @param object the object * @param properties explicit list of property/field names to include - may be null for "all" */ public void writeLimited(Class klass, Object object, String[] properties) { Set propertiesSet = null; if (properties != null) { propertiesSet = new HashSet(); for (String p: properties) { propertiesSet.add(p); } } add('{'); indentLevel += 2; newline(); boolean needComma = false; BeanInfo info; try { info = Introspector.getBeanInfo(klass); } catch (IntrospectionException ie) { info = null; } if (info != null) { PropertyDescriptor[] props = info.getPropertyDescriptors(); for (int i = 0; i < props.length; ++i) { PropertyDescriptor prop = props[i]; String name = prop.getName(); if (propertiesSet == null && name.equals("class")) { // We usually don't want the class in there. continue; } if (propertiesSet == null || propertiesSet.contains(name)) { Method accessor = prop.getReadMethod(); if (accessor != null && !Modifier.isStatic(accessor.getModifiers())) { try { Object value = accessor.invoke(object, (Object[])null); if (needComma) { add(','); newline(); } needComma = true; add(name, value); } catch (Exception e) { // Ignore it. } } } } } Field[] ff = object.getClass().getDeclaredFields(); for (int i = 0; i < ff.length; ++i) { Field field = ff[i]; int fieldMod = field.getModifiers(); String name = field.getName(); if (propertiesSet == null || propertiesSet.contains(name)) { if (!Modifier.isStatic(fieldMod)) { try { Object v = field.get(object); if (needComma) { add(','); newline(); } needComma = true; add(name, v); } catch (Exception e) { // Ignore it. } } } } indentLevel -= 2; newline(); add('}'); } private void add(String name, Object value) { add('"'); add(name); add("\":"); value(value); } private void map(Map map) { add('{'); indentLevel += 2; newline(); Iterator it = map.keySet().iterator(); if (it.hasNext()) { mapEntry(it.next(), map); } while (it.hasNext()) { add(','); newline(); Object key = it.next(); value(key); add(':'); value(map.get(key)); } indentLevel -= 2; newline(); add('}'); } private void mapEntry(Object key, Map map) { value(key); add(':'); value(map.get(key)); } private void array(Iterator it) { add('['); if (it.hasNext()) value(it.next()); while (it.hasNext()) { add(','); value(it.next()); } add(']'); } private void array(Object object) { add('['); int length = Array.getLength(object); if (length > 0) value(Array.get(object, 0)); for (int i = 1; i < length; ++i) { add(','); value(Array.get(object, i)); } add(']'); } private void bool(boolean b) { add(b ? "true" : "false"); } private void string(Object obj) { add('"'); CharacterIterator it = new StringCharacterIterator(obj.toString()); for (char c = it.first(); c != CharacterIterator.DONE; c = it.next()) { if (c == '"') add("\\\""); else if (c == '\\') add("\\\\"); else if (c == '/') add("\\/"); else if (c == '\b') add("\\b"); else if (c == '\f') add("\\f"); else if (c == '\n') add("\\n"); else if (c == '\r') add("\\r"); else if (c == '\t') add("\\t"); else if (Character.isISOControl(c)) { unicode(c); } else { add(c); } } add('"'); } private void add(Object obj) { buf.append(obj); } private void add(char c) { buf.append(c); } static final char[] hex = "0123456789ABCDEF".toCharArray(); private void unicode(char c) { add("\\u"); int n = c; for (int i = 0; i < 4; ++i) { int digit = (n & 0xf000) >> 12; add(hex[digit]); n <<= 4; } } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/tools/json/package.html000066400000000000000000000002361316117667700271350ustar00rootroot00000000000000 JSON reader/writer and utility classes. rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/tools/jsonrpc/000077500000000000000000000000001316117667700253605ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/tools/jsonrpc/JsonRpcClient.java000066400000000000000000000213041316117667700307400ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.tools.jsonrpc; import java.io.IOException; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeoutException; import com.rabbitmq.client.Channel; import com.rabbitmq.client.RpcClient; import com.rabbitmq.client.ShutdownSignalException; import com.rabbitmq.tools.json.JSONReader; import com.rabbitmq.tools.json.JSONWriter; /** JSON-RPC is a lightweight RPC mechanism using JSON as a data language for request and reply messages. It is rapidly becoming a standard in web development, where it is used to make RPC requests over HTTP. RabbitMQ provides an AMQP transport binding for JSON-RPC in the form of the JsonRpcClient class. JSON-RPC services are self-describing - each service is able to list its supported procedures, and each procedure describes its parameters and types. An instance of JsonRpcClient retrieves its service description using the standard system.describe procedure when it is constructed, and uses the information to coerce parameter types appropriately. A JSON service description is parsed into instances of ServiceDescription. Client code can access the service description by reading the serviceDescription field of JsonRpcClient instances. @see #call(String, Object[]) @see #call(String[]) */ public class JsonRpcClient extends RpcClient implements InvocationHandler { /** Holds the JSON-RPC service description for this client. */ private ServiceDescription serviceDescription; /** * Construct a new JsonRpcClient, passing the parameters through * to RpcClient's constructor. The service description record is * retrieved from the server during construction. * @throws TimeoutException if a response is not received within the timeout specified, if any */ public JsonRpcClient(Channel channel, String exchange, String routingKey, int timeout) throws IOException, JsonRpcException, TimeoutException { super(channel, exchange, routingKey, timeout); retrieveServiceDescription(); } public JsonRpcClient(Channel channel, String exchange, String routingKey) throws IOException, JsonRpcException, TimeoutException { this(channel, exchange, routingKey, RpcClient.NO_TIMEOUT); } /** * Private API - parses a JSON-RPC reply object, checking it for exceptions. * @return the result contained within the reply, if no exception is found * Throws JsonRpcException if the reply object contained an exception */ public static Object checkReply(Map reply) throws JsonRpcException { if (reply.containsKey("error")) { @SuppressWarnings("unchecked") Map map = (Map) reply.get("error"); // actually a Map throw new JsonRpcException(map); } Object result = reply.get("result"); //System.out.println(new JSONWriter().write(result)); return result; } /** * Public API - builds, encodes and sends a JSON-RPC request, and * waits for the response. * @return the result contained within the reply, if no exception is found * @throws JsonRpcException if the reply object contained an exception * @throws TimeoutException if a response is not received within the timeout specified, if any */ public Object call(String method, Object[] params) throws IOException, JsonRpcException, TimeoutException { HashMap request = new HashMap(); request.put("id", null); request.put("method", method); request.put("version", ServiceDescription.JSON_RPC_VERSION); request.put("params", (params == null) ? new Object[0] : params); String requestStr = new JSONWriter().write(request); try { String replyStr = this.stringCall(requestStr); @SuppressWarnings("unchecked") Map map = (Map) (new JSONReader().read(replyStr)); return checkReply(map); } catch(ShutdownSignalException ex) { throw new IOException(ex.getMessage()); // wrap, re-throw } } /** * Public API - implements InvocationHandler.invoke. This is * useful for constructing dynamic proxies for JSON-RPC * interfaces. */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return call(method.getName(), args); } /** * Public API - gets a dynamic proxy for a particular interface class. */ public Object createProxy(Class klass) throws IllegalArgumentException { return Proxy.newProxyInstance(klass.getClassLoader(), new Class[] { klass }, this); } /** * Private API - used by {@link #call(String[])} to ad-hoc convert * strings into the required data types for a call. */ public static Object coerce(String val, String type) throws NumberFormatException { if ("bit".equals(type)) { return Boolean.getBoolean(val) ? Boolean.TRUE : Boolean.FALSE; } else if ("num".equals(type)) { try { return Integer.valueOf(val); } catch (NumberFormatException nfe) { return Double.valueOf(val); } } else if ("str".equals(type)) { return val; } else if ("arr".equals(type) || "obj".equals(type) || "any".equals(type)) { return new JSONReader().read(val); } else if ("nil".equals(type)) { return null; } else { throw new IllegalArgumentException("Bad type: " + type); } } /** * Public API - as {@link #call(String,Object[])}, but takes the * method name from the first entry in args, and the * parameters from subsequent entries. All parameter values are * passed through coerce() to attempt to make them the types the * server is expecting. * @return the result contained within the reply, if no exception is found * @throws JsonRpcException if the reply object contained an exception * @throws NumberFormatException if a coercion failed * @throws TimeoutException if a response is not received within the timeout specified, if any * @see #coerce */ public Object call(String[] args) throws NumberFormatException, IOException, JsonRpcException, TimeoutException { if (args.length == 0) { throw new IllegalArgumentException("First string argument must be method name"); } String method = args[0]; int arity = args.length - 1; ProcedureDescription proc = serviceDescription.getProcedure(method, arity); ParameterDescription[] params = proc.getParams(); Object[] actuals = new Object[arity]; for (int count = 0; count < params.length; count++) { actuals[count] = coerce(args[count + 1], params[count].type); } return call(method, actuals); } /** * Public API - gets the service description record that this * service loaded from the server itself at construction time. */ public ServiceDescription getServiceDescription() { return serviceDescription; } /** * Private API - invokes the "system.describe" method on the * server, and parses and stores the resulting service description * in this object. * TODO: Avoid calling this from the constructor. * @throws TimeoutException if a response is not received within the timeout specified, if any */ private void retrieveServiceDescription() throws IOException, JsonRpcException, TimeoutException { @SuppressWarnings("unchecked") Map rawServiceDescription = (Map) call("system.describe", null); serviceDescription = new ServiceDescription(rawServiceDescription); } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/tools/jsonrpc/JsonRpcException.java000066400000000000000000000033451316117667700314650ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.tools.jsonrpc; import java.util.Map; import com.rabbitmq.tools.json.JSONWriter; /** * Thrown when a JSON-RPC service indicates an error occurred during a call. */ public class JsonRpcException extends Exception { /** * Default serialized version ID */ private static final long serialVersionUID = 1L; /** Usually the constant string, "JSONRPCError" */ public String name; /** Error code */ public int code; /** Error message */ public String message; /** Error detail object - may not always be present or meaningful */ public Object error; public JsonRpcException() { // no work needed in default no-arg constructor } public JsonRpcException(Map errorMap) { super(new JSONWriter().write(errorMap)); name = (String) errorMap.get("name"); code = 0; if (errorMap.get("code") != null) { code = ((Integer) errorMap.get("code")); } message = (String) errorMap.get("message"); error = errorMap.get("error"); } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/tools/jsonrpc/JsonRpcServer.java000066400000000000000000000171461316117667700310010ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.tools.jsonrpc; import java.io.IOException; import java.lang.reflect.Method; import java.util.HashMap; import java.util.List; import java.util.Map; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.Channel; import com.rabbitmq.client.StringRpcServer; import com.rabbitmq.tools.json.JSONReader; import com.rabbitmq.tools.json.JSONWriter; /** * JSON-RPC Server class. * * Given a Java {@link Class}, representing an interface, and an * implementation of that interface, JsonRpcServer will reflect on the * class to construct the {@link ServiceDescription}, and will route * incoming requests for methods on the interface to the * implementation object while the mainloop() is running. * * @see com.rabbitmq.client.RpcServer * @see JsonRpcClient */ public class JsonRpcServer extends StringRpcServer { /** Holds the JSON-RPC service description for this client. */ public ServiceDescription serviceDescription; /** The interface this server implements. */ public Class interfaceClass; /** The instance backing this server. */ public Object interfaceInstance; /** * Construct a server that talks to the outside world using the * given channel, and constructs a fresh temporary * queue. Use getQueueName() to discover the created queue name. * @param channel AMQP channel to use * @param interfaceClass Java interface that this server is exposing to the world * @param interfaceInstance Java instance (of interfaceClass) that is being exposed * @throws IOException if something goes wrong during an AMQP operation */ public JsonRpcServer(Channel channel, Class interfaceClass, Object interfaceInstance) throws IOException { super(channel); init(interfaceClass, interfaceInstance); } private void init(Class interfaceClass, Object interfaceInstance) { this.interfaceClass = interfaceClass; this.interfaceInstance = interfaceInstance; this.serviceDescription = new ServiceDescription(interfaceClass); } /** * Construct a server that talks to the outside world using the * given channel and queue name. Our superclass, * RpcServer, expects the queue to exist at the time of * construction. * @param channel AMQP channel to use * @param queueName AMQP queue name to listen for requests on * @param interfaceClass Java interface that this server is exposing to the world * @param interfaceInstance Java instance (of interfaceClass) that is being exposed * @throws IOException if something goes wrong during an AMQP operation */ public JsonRpcServer(Channel channel, String queueName, Class interfaceClass, Object interfaceInstance) throws IOException { super(channel, queueName); init(interfaceClass, interfaceInstance); } /** * Override our superclass' method, dispatching to doCall. */ @Override public String handleStringCall(String requestBody, AMQP.BasicProperties replyProperties) { String replyBody = doCall(requestBody); return replyBody; } /** * Runs a single JSON-RPC request. * @param requestBody the JSON-RPC request string (a JSON encoded value) * @return a JSON-RPC response string (a JSON encoded value) */ public String doCall(String requestBody) { Object id; String method; Object[] params; try { @SuppressWarnings("unchecked") Map request = (Map) new JSONReader().read(requestBody); if (request == null) { return errorResponse(null, 400, "Bad Request", null); } if (!ServiceDescription.JSON_RPC_VERSION.equals(request.get("version"))) { return errorResponse(null, 505, "JSONRPC version not supported", null); } id = request.get("id"); method = (String) request.get("method"); List parmList = (List) request.get("params"); params = parmList.toArray(); } catch (ClassCastException cce) { // Bogus request! return errorResponse(null, 400, "Bad Request", null); } if (method.equals("system.describe")) { return resultResponse(id, serviceDescription); } else if (method.startsWith("system.")) { return errorResponse(id, 403, "System methods forbidden", null); } else { Object result; try { result = matchingMethod(method, params).invoke(interfaceInstance, params); } catch (Throwable t) { return errorResponse(id, 500, "Internal Server Error", t); } return resultResponse(id, result); } } /** * Retrieves the best matching method for the given method name and parameters. * * Subclasses may override this if they have specialised * dispatching requirements, so long as they continue to honour * their ServiceDescription. */ public Method matchingMethod(String methodName, Object[] params) { ProcedureDescription proc = serviceDescription.getProcedure(methodName, params.length); return proc.internal_getMethod(); } /** * Construct and encode a JSON-RPC error response for the request * ID given, using the code, message, and possible * (JSON-encodable) argument passed in. */ public static String errorResponse(Object id, int code, String message, Object errorArg) { Map err = new HashMap(); err.put("name", "JSONRPCError"); err.put("code", code); err.put("message", message); err.put("error", errorArg); return response(id, "error", err); } /** * Construct and encode a JSON-RPC success response for the * request ID given, using the result value passed in. */ public static String resultResponse(Object id, Object result) { return response(id, "result", result); } /** * Private API - used by errorResponse and resultResponse. */ public static String response(Object id, String label, Object value) { Map resp = new HashMap(); resp.put("version", ServiceDescription.JSON_RPC_VERSION); if (id != null) { resp.put("id", id); } resp.put(label, value); String respStr = new JSONWriter().write(resp); //System.err.println(respStr); return respStr; } /** * Public API - gets the service description record that this * service built from interfaceClass at construction time. */ public ServiceDescription getServiceDescription() { return serviceDescription; } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/tools/jsonrpc/ParameterDescription.java000066400000000000000000000035721316117667700323560ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.tools.jsonrpc; import java.util.Collection; import java.util.Map; import com.rabbitmq.tools.json.JSONUtil; /** * Description of a single JSON-RPC procedure parameter. */ public class ParameterDescription { /** The parameter name. */ public String name; /** * The parameter type - one of "bit", "num", "str", "arr", * "obj", "any" or "nil". */ public String type; public ParameterDescription() { // Nothing to do here. } public ParameterDescription(Map pm) { JSONUtil.tryFill(this, pm); } public ParameterDescription(int index, Class c) { name = "param" + index; type = lookup(c); } public static String lookup(Class c) { if (c == Void.class) return "nil"; if (c == Boolean.class) return "bit"; if (c == Integer.class) return "num"; if (c == Double.class) return "num"; if (c == String.class) return "str"; if (c.isArray()) return "arr"; if (Map.class.isAssignableFrom(c)) return "obj"; if (Collection.class.isAssignableFrom(c)) return "arr"; return "any"; } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/tools/jsonrpc/ProcedureDescription.java000066400000000000000000000065711316117667700323700ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.tools.jsonrpc; import java.lang.reflect.Method; import java.util.List; import java.util.Map; import com.rabbitmq.tools.json.JSONUtil; /** * Description of a single JSON-RPC procedure. */ public class ProcedureDescription { /** Procedure name */ public String name; /** Human-readable procedure summary */ public String summary; /** Human-readable instructions for how to get information on the procedure's operation */ public String help; /** True if this procedure is idempotent, that is, can be accessed via HTTP GET */ public boolean idempotent; /** Descriptions of parameters for this procedure */ private ParameterDescription[] params; /** Return type for this procedure */ private String returnType; /** Reflected method object, used for service invocation */ private Method method; public ProcedureDescription(Map pm) { JSONUtil.tryFill(this, pm); @SuppressWarnings("unchecked") List> p = (List>) pm.get("params"); params = new ParameterDescription[p.size()]; int count = 0; for (Map param_map: p) { ParameterDescription param = new ParameterDescription(param_map); params[count++] = param; } } public ProcedureDescription(Method m) { this.method = m; this.name = m.getName(); this.summary = ""; this.help = ""; this.idempotent = false; Class[] parameterTypes = m.getParameterTypes(); this.params = new ParameterDescription[parameterTypes.length]; for (int i = 0; i < parameterTypes.length; i++) { params[i] = new ParameterDescription(i, parameterTypes[i]); } this.returnType = ParameterDescription.lookup(m.getReturnType()); } public ProcedureDescription() { // no work to do here } /** Getter for return type */ public String getReturn() { return returnType; } /** Private API - used via reflection during parsing/loading */ public void setReturn(String value) { returnType = value; } /** Private API - used to get the reflected method object, for servers */ public Method internal_getMethod() { return method; } /** Gets an array of parameter descriptions for all this procedure's parameters */ public ParameterDescription[] internal_getParams() { return params; } /** Retrieves the parameter count for this procedure */ public int arity() { return (params == null) ? 0 : params.length; } public ParameterDescription[] getParams() { return params; } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/tools/jsonrpc/ServiceDescription.java000066400000000000000000000064041316117667700320330ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.tools.jsonrpc; import java.lang.reflect.Method; import java.util.Collection; import java.util.HashMap; import java.util.Map; import com.rabbitmq.tools.json.JSONUtil; /** * Description of a JSON-RPC service. */ public class ServiceDescription { public static final String JSON_RPC_VERSION = "1.1"; /** The service name */ public String name; /** ID for the service */ public String id; /** Version of the service */ public String version; /** Human-readable summary for the service */ public String summary; /** Human-readable instructions for how to get information on the service's operation */ public String help; /** Map from procedure name to {@link ProcedureDescription} */ private Map procedures; public ServiceDescription(Map rawServiceDescription) { JSONUtil.tryFill(this, rawServiceDescription); } public ServiceDescription(Class klass) { this.procedures = new HashMap(); for (Method m: klass.getMethods()) { ProcedureDescription proc = new ProcedureDescription(m); addProcedure(proc); } } public ServiceDescription() { // No work to do here } /** Gets a collection of all {@link ProcedureDescription} for this service */ public Collection getProcs() { return procedures.values(); } /** Private API - used via reflection during parsing/loading */ public void setProcs(Collection> p) { procedures = new HashMap(); for (Map pm: p) { ProcedureDescription proc = new ProcedureDescription(pm); addProcedure(proc); } } /** Private API - used during initialization */ private void addProcedure(ProcedureDescription proc) { procedures.put(proc.name + "/" + proc.arity(), proc); } /** * Looks up a single ProcedureDescription by name and arity. * @return non-null ProcedureDescription if a match is found * @throws IllegalArgumentException if no match is found */ public ProcedureDescription getProcedure(String newname, int arity) { ProcedureDescription proc = procedures.get(newname + "/" + arity); if (proc == null) { throw new IllegalArgumentException("Procedure not found: " + newname + ", arity " + arity); } return proc; } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/tools/jsonrpc/package.html000066400000000000000000000003111316117667700276340ustar00rootroot00000000000000 JSON-RPC client and server classes for supporting JSON-RPC over an AMQP transport. rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/tools/package.html000066400000000000000000000002431316117667700261620ustar00rootroot00000000000000 Non-core utilities and administration tools. rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/utility/000077500000000000000000000000001316117667700242455ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/utility/BlockingCell.java000066400000000000000000000127421316117667700274460ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.utility; import java.util.concurrent.TimeoutException; /** * Simple one-shot IPC mechanism. Essentially a one-place buffer that cannot be emptied once filled. */ public class BlockingCell { /** Indicator of not-yet-filledness */ private boolean _filled = false; /** Will be null until a value is supplied, and possibly still then. */ private T _value; private static final long NANOS_IN_MILLI = 1000 * 1000; private static final long INFINITY = -1; /** Instantiate a new BlockingCell waiting for a value of the specified type. */ public BlockingCell() { // no special handling required in default constructor } /** * Wait for a value, and when one arrives, return it (without clearing it). If there's already a value present, there's no need to wait - the existing value * is returned. * @return the waited-for value * * @throws InterruptedException if this thread is interrupted */ public synchronized T get() throws InterruptedException { while (!_filled) { wait(); } return _value; } /** * Wait for a value, and when one arrives, return it (without clearing it). If there's * already a value present, there's no need to wait - the existing value is returned. * If timeout is reached and value hasn't arrived, TimeoutException is thrown. * * @param timeout timeout in milliseconds. -1 effectively means infinity * @return the waited-for value * @throws InterruptedException if this thread is interrupted */ public synchronized T get(long timeout) throws InterruptedException, TimeoutException { if (timeout == INFINITY) return get(); if (timeout < 0) { throw new IllegalArgumentException("Timeout cannot be less than zero"); } long now = System.nanoTime() / NANOS_IN_MILLI; long maxTime = now + timeout; while (!_filled && (now = (System.nanoTime() / NANOS_IN_MILLI)) < maxTime) { wait(maxTime - now); } if (!_filled) throw new TimeoutException(); return _value; } /** * As get(), but catches and ignores InterruptedException, retrying until a value appears. * @return the waited-for value */ public synchronized T uninterruptibleGet() { boolean wasInterrupted = false; try { while (true) { try { return get(); } catch (InterruptedException ex) { // no special handling necessary wasInterrupted = true; } } } finally { if (wasInterrupted) { Thread.currentThread().interrupt(); } } } /** * As get(long timeout), but catches and ignores InterruptedException, retrying until * a value appears or until specified timeout is reached. If timeout is reached, * TimeoutException is thrown. * We also use System.nanoTime() to behave correctly when system clock jumps around. * * @param timeout timeout in milliseconds. -1 means 'infinity': never time out * @return the waited-for value */ public synchronized T uninterruptibleGet(int timeout) throws TimeoutException { long now = System.nanoTime() / NANOS_IN_MILLI; long runTime = now + timeout; boolean wasInterrupted = false; try { do { try { return get(runTime - now); } catch (InterruptedException e) { // Ignore. wasInterrupted = true; } } while ((timeout == INFINITY) || ((now = System.nanoTime() / NANOS_IN_MILLI) < runTime)); } finally { if (wasInterrupted) { Thread.currentThread().interrupt(); } } throw new TimeoutException(); } /** * Store a value in this BlockingCell, throwing {@link IllegalStateException} if the cell already has a value. * @param newValue the new value to store */ public synchronized void set(T newValue) { if (_filled) { throw new IllegalStateException("BlockingCell can only be set once"); } _value = newValue; _filled = true; notifyAll(); } /** * Store a value in this BlockingCell if it doesn't already have a value. * @return true if this call to setIfUnset actually updated the BlockingCell; false if the cell already had a value. * @param newValue the new value to store */ public synchronized boolean setIfUnset(T newValue) { if (_filled) { return false; } set(newValue); return true; } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/utility/BlockingValueOrException.java000066400000000000000000000025521316117667700320210ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.utility; import java.util.concurrent.TimeoutException; public class BlockingValueOrException> extends BlockingCell> { public void setValue(V v) { super.set(ValueOrException.makeValue(v)); } public void setException(E e) { super.set(ValueOrException.makeException(e)); } public V uninterruptibleGetValue() throws E { return uninterruptibleGet().getValue(); } public V uninterruptibleGetValue(int timeout) throws E, TimeoutException { return uninterruptibleGet(timeout).getValue(); } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/utility/IntAllocator.java000066400000000000000000000127501316117667700275100ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.utility; import java.util.BitSet; /** *

* A class for allocating integers from a given range that uses a * {@link BitSet} representation of the free integers. *

* *

Concurrecy Semantics:

* This class is not thread safe. * *

Implementation notes:

*

This was originally an ordered chain of non-overlapping Intervals, * together with a fixed size array cache for freed integers. *

*

* {@link #reserve(int)} was expensive in this scheme, whereas in the * present implementation it is O(1), as is {@link #free(int)}. *

*

Although {@link #allocate()} is slightly slower than O(1) and in the * worst case could be O(N), the use of a "lastIndex" field * for starting the next scan for free integers means this is negligible. *

*

The data representation overhead is O(N) where N is the size of the * allocation range. One long is used for every 64 integers in the * range. *

*

Very little Object creation and destruction occurs in use.

*/ public class IntAllocator { private final int loRange; // the integer bit 0 represents private final int hiRange; // one more than the integer the highest bit represents private final int numberOfBits; // relevant in freeSet private int lastIndex = 0; // for searching for FREE integers /** A bit is SET in freeSet if the corresponding integer is FREE *
A bit is UNSET in freeSet if the corresponding integer is ALLOCATED */ private final BitSet freeSet; /** * Creates an IntAllocator allocating integer IDs within the * inclusive range [bottom, top]. * @param bottom lower end of range * @param top upper end of range (inclusive) */ public IntAllocator(int bottom, int top) { this.loRange = bottom; this.hiRange = top + 1; this.numberOfBits = hiRange - loRange; this.freeSet = new BitSet(this.numberOfBits); this.freeSet.set(0, this.numberOfBits); // All integers FREE initially } /** * Allocate an unallocated integer from the range, or return -1 if no * more integers are available. * @return the allocated integer, or -1 */ public int allocate() { int setIndex = this.freeSet.nextSetBit(this.lastIndex); if (setIndex<0) { // means none found in trailing part setIndex = this.freeSet.nextSetBit(0); } if (setIndex<0) return -1; this.lastIndex = setIndex; this.freeSet.clear(setIndex); return setIndex + this.loRange; } /** * Make the provided integer available for allocation again. This operation * runs in O(1) time. * No error checking is performed, so if you double free or free an * integer that was not originally allocated the results are undefined. * @param reservation the previously allocated integer to free */ public void free(int reservation) { this.freeSet.set(reservation - this.loRange); } /** * Attempt to reserve the provided ID as if it had been allocated. Returns * true if it is available, false otherwise. * This operation runs in O(1) time. * @param reservation the integer to be allocated, if possible * @return true if allocated, false * if already allocated */ public boolean reserve(int reservation) { int index = reservation - this.loRange; if (this.freeSet.get(index)) { // FREE this.freeSet.clear(index); return true; } else { return false; } } @Override public String toString() { StringBuilder sb = new StringBuilder("IntAllocator{allocated = ["); int firstClearBit = this.freeSet.nextClearBit(0); if (firstClearBit < this.numberOfBits) { int firstSetAfterThat = this.freeSet.nextSetBit(firstClearBit+1); if (firstSetAfterThat < 0) firstSetAfterThat = this.numberOfBits; stringInterval(sb, firstClearBit, firstSetAfterThat); for (int i = this.freeSet.nextClearBit(firstSetAfterThat+1); i < this.numberOfBits; i = this.freeSet.nextClearBit(i+1)) { int nextSet = this.freeSet.nextSetBit(i); if (nextSet<0) nextSet = this.numberOfBits; stringInterval(sb.append(", "), i, nextSet); i = nextSet; } } sb.append("]}"); return sb.toString(); } private void stringInterval(StringBuilder sb, int i1, int i2) { sb.append(i1 + this.loRange); if (i1+1 != i2) { sb.append("..").append(i2-1 + this.loRange); } } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/utility/SensibleClone.java000066400000000000000000000024761316117667700276460ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.utility; /** * This interface exists as a workaround for the annoyingness of java.lang.Cloneable. * It is used for generic methods which need to accept something they can actually clone * (Object.clone is protected and java.lang.Cloneable does not define a public clone method) * and want to provide some guarantees of the type of the cloned object. */ public interface SensibleClone> extends Cloneable { /** * Like Object.clone but sensible; in particular, public and declared to return * the right type. */ public T sensibleClone(); } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/utility/Utility.java000066400000000000000000000107601316117667700265570ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.utility; import java.io.ByteArrayOutputStream; import java.io.PrintStream; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; /** * Catch-all holder class for static helper methods. */ public class Utility { static class ThrowableCreatedElsewhere extends Throwable { /** Default for non-checking. */ private static final long serialVersionUID = 1L; public ThrowableCreatedElsewhere(Throwable throwable) { super(throwable.getClass() + " created elsewhere"); this.setStackTrace(throwable.getStackTrace()); } @Override public synchronized Throwable fillInStackTrace(){ return this; } } public static > T fixStackTrace(T throwable) { throwable = throwable.sensibleClone(); if(throwable.getCause() == null) { // We'd like to preserve the original stack trace in the cause. // Unfortunately Java doesn't let you set the cause once it's been // set once. This means we have to choose between either // - not preserving the type // - sometimes losing the original stack trace // - performing nasty reflective voodoo which may or may not work // We only lose the original stack trace when there's a root cause // which will hopefully be enlightening enough on its own that it // doesn't matter too much. try { throwable.initCause(new ThrowableCreatedElsewhere(throwable)); } catch(IllegalStateException e) { // This exception was explicitly initialised with a null cause. // Alas this means we can't set the cause even though it has none. // Thanks. } } throwable.fillInStackTrace(); // We want to remove fixStackTrace from the trace. StackTraceElement[] existing = throwable.getStackTrace(); StackTraceElement[] newTrace = new StackTraceElement[existing.length - 1]; System.arraycopy(existing, 1, newTrace, 0, newTrace.length); throwable.setStackTrace(newTrace); return throwable; } /** * * @param throwable * @return * @deprecated use logging library instead for logging stack traces somewhere */ public static String makeStackTrace(Throwable throwable) { ByteArrayOutputStream baOutStream = new ByteArrayOutputStream(); PrintStream printStream = new PrintStream(baOutStream, false); throwable.printStackTrace(printStream); printStream.flush(); // since we don't automatically do so String text = baOutStream.toString(); printStream.close(); // closes baOutStream return text; } /** * Synchronizes on the list and then returns a copy of the list that is safe to iterate over. Useful when wanting to do thread-safe iteration over * a List wrapped in {@link Collections#synchronizedList(List)}. * * @param list * The list, which may not be {@code null} * @return ArrayList copy of the list */ public static List copy(final List list) { synchronized (list) { return new ArrayList(list); } } /** * Synchronizes on the map and then returns a copy of the map that is safe to iterate over. Useful when wanting to do thread-safe iteration over a * Map wrapped in {@link Collections#synchronizedMap(Map)} * * @param map * The map, which may not be {@code null} * @return LinkedHashMap copy of the map */ public static Map copy(final Map map) { synchronized (map) { return new LinkedHashMap(map); } } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/utility/ValueOrException.java000066400000000000000000000047311316117667700303510ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.utility; public class ValueOrException> { private final boolean _useValue; private final V _value; private final E _exception; /** * dual-purpose private constructor: one will be null, and the flag tells which to use * @param value the value to wrap, if applicable * @param exception the exception to wrap, if applicable * @param useValue true if we should use the value, rather than the exception */ private ValueOrException(V value, E exception, boolean useValue) { _useValue = useValue; if (useValue) { _value = value; _exception = null; } else { _value = null; _exception = exception; } } /** * Factory method for values * @param value the value to wrap as a ValueOrException * @return the wrapped value */ public static > ValueOrException makeValue(V value) { return new ValueOrException(value, null, true); } /** * Factory method for exceptions * @param exception the exception to wrap as a ValueOrException * @return the wrapped exception */ public static > ValueOrException makeException(E exception) { return new ValueOrException(null, exception, false); } /** Retrieve value or throw exception * @return the wrapped value, if it's a value * @throws E the wrapped exception, if it's an exception */ public V getValue() throws E { if (_useValue) { return _value; } else { throw Utility.fixStackTrace(_exception); } } } rabbitmq-java-client-5.0.0/src/main/java/com/rabbitmq/utility/package.html000066400000000000000000000003011316117667700265200ustar00rootroot00000000000000 Utility package of helper classes, mostly used in the implementation code. rabbitmq-java-client-5.0.0/src/main/resources/000077500000000000000000000000001316117667700212545ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/main/resources/version.properties000066400000000000000000000000611316117667700250540ustar00rootroot00000000000000com.rabbitmq.client.version = ${project.version} rabbitmq-java-client-5.0.0/src/main/scripts/000077500000000000000000000000001316117667700207315ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/main/scripts/generate_amqp_sources.groovy000066400000000000000000000026461316117667700265630ustar00rootroot00000000000000import java.security.MessageDigest def md5(final file) { MessageDigest digest = MessageDigest.getInstance("MD5") file.withInputStream() { is -> byte[] buffer = new byte[8192] int read = 0 while ((read = is.read(buffer)) > 0) { digest.update(buffer, 0, read); } } byte[] md5sum = digest.digest() BigInteger bigInt = new BigInteger(1, md5sum) return bigInt.toString(16) } def generate_source(final type, final filename) { String[] command = [ 'python', properties['script'], type, properties['spec'], filename ] def pb = new ProcessBuilder(command) pb.environment().put('PYTHONPATH', properties['codegen.dir']) pb.redirectErrorStream(true) def process = pb.start() process.waitFor() if (process.exitValue() != 0) { println(process.in.text.trim()) fail("Failed to generate ${filename} with command: ${command.join(' ')}") } } def maybe_regen_source(final type, final filename) { def file = new File(filename) if (file.exists()) { def tmp_filename = filename + '.new' def tmp_file = new File(tmp_filename) generate_source(type, tmp_filename) old_md5 = md5(file) new_md5 = md5(tmp_file) if (old_md5 == new_md5) { tmp_file.delete() } else { tmp_file.renameTo(file) } } else { generate_source(type, filename) } } maybe_regen_source('header', properties['header']) maybe_regen_source('body', properties['body']) rabbitmq-java-client-5.0.0/src/main/scripts/manage_test_broker.groovy000066400000000000000000000031471316117667700260400ustar00rootroot00000000000000String[] command def nodename = properties['nodename'] if (nodename == null || nodename.length() == 0) { fail("Node name required") } switch (mojo.getExecutionId()) { case ~/^start-test-broker-.*/: def node_port = properties['node_port'] if (node_port == null || node_port.length() == 0) { fail("Node TCP port required") } command = [ properties['make.bin'], '-C', properties['rabbitmq.dir'], '--no-print-directory', 'virgin-node-tmpdir', 'start-background-broker', "DEPS_DIR=${properties['deps.dir']}", "RABBITMQ_NODENAME=${nodename}", "RABBITMQ_NODE_PORT=${node_port}", "RABBITMQ_CONFIG_FILE=${project.build.directory}/test-classes/${nodename}" ] break case ~/^create-test-cluster$/: def target = properties['target'] if (target == null || target.length() == 0) { fail("Target node name required") } command = [ properties['make.bin'], '--no-print-directory', 'cluster-other-node', "RABBITMQCTL=${properties['rabbitmqctl.bin']}", "DEPS_DIR=${properties['deps.dir']}", "OTHER_NODE=${nodename}", "MAIN_NODE=${target}" ] break case ~/^stop-test-broker-.*/: command = [ properties['make.bin'], '-C', properties['rabbitmq.dir'], '--no-print-directory', 'stop-node', "DEPS_DIR=${properties['deps.dir']}", "RABBITMQ_NODENAME=${nodename}" ] break } def pb = new ProcessBuilder(command) pb.redirectErrorStream(true) def process = pb.start() process.waitFor() if (process.exitValue() != 0) { println(process.in.text.trim()) fail("Failed to manage broker '${nodename}' with command: ${command.join(' ')}") } rabbitmq-java-client-5.0.0/src/main/scripts/query_test_tls_certs_dir.groovy000066400000000000000000000013071316117667700273250ustar00rootroot00000000000000String[] command = [ properties['make.bin'], '-C', properties['rabbitmq.dir'], '--no-print-directory', 'show-test-tls-certs-dir', "DEPS_DIR=${properties['deps.dir']}", ] def pb = new ProcessBuilder(command) pb.redirectErrorStream(true) def process = pb.start() // We are only interested in the last line of output. Previous lines, if // any, are related to the generation of the test certificates. def whole_output = "" process.inputStream.eachLine { whole_output += it project.properties['test-tls-certs.dir'] = it.trim() } process.waitFor() if (process.exitValue() != 0) { println(whole_output.trim()) fail("Failed to query test TLS certs directory with command: ${command.join(' ')}") } rabbitmq-java-client-5.0.0/src/main/scripts/remove_old_test_keystores.groovy000066400000000000000000000004021316117667700274760ustar00rootroot00000000000000def dir = new File(project.build.directory) // This pattern starts with `.*`. This is normally useless and even // inefficient but the matching doesn't work without it... def pattern = ~/.*\.keystore$/ dir.eachFileMatch(pattern) { file -> file.delete() } rabbitmq-java-client-5.0.0/src/test/000077500000000000000000000000001316117667700172755ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/test/java/000077500000000000000000000000001316117667700202165ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/test/java/com/000077500000000000000000000000001316117667700207745ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/000077500000000000000000000000001316117667700225755ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/000077500000000000000000000000001316117667700240535ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/QueueingConsumer.java000066400000000000000000000221161316117667700302160ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client; import java.io.IOException; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import com.rabbitmq.client.AMQP.BasicProperties; import com.rabbitmq.utility.Utility; /** * Convenience class: an implementation of {@link Consumer} with * straightforward blocking semantics. It is meant to be using in * tests. * * Deprecated in favor of {@link DefaultConsumer} (see below for background). * Will be removed in next major release. * * The general pattern for using QueueingConsumer is as follows: * *
 * // Create connection and channel.
 * {@link ConnectionFactory} factory = new ConnectionFactory();
 * Connection conn = factory.newConnection();
 * {@link Channel} ch1 = conn.createChannel();
 *
 * // Declare a queue and bind it to an exchange.
 * String queueName = ch1.queueDeclare().{@link AMQP.Queue.DeclareOk#getQueue getQueue}();
 * ch1.{@link Channel#queueBind queueBind}(queueName, exchangeName, queueName);
 *
 * // Create the QueueingConsumer and have it consume from the queue
 * QueueingConsumer consumer = new {@link QueueingConsumer#QueueingConsumer(Channel) QueueingConsumer}(ch1);
 * ch1.{@link Channel#basicConsume basicConsume}(queueName, false, consumer);
 *
 * // Process deliveries
 * while (/* some condition * /) {
 *     {@link QueueingConsumer.Delivery} delivery = consumer.{@link QueueingConsumer#nextDelivery nextDelivery}();
 *     // process delivery
 *     ch1.{@link Channel#basicAck basicAck}(delivery.{@link QueueingConsumer.Delivery#getEnvelope getEnvelope}().{@link Envelope#getDeliveryTag getDeliveryTag}(), false);
 * }
 * 
* * *

For a more complete example, see LogTail in the test/src/com/rabbitmq/examples * directory of the source distribution.

* *

Historical Perspective

* *

QueueingConsumer was introduced to allow * applications to overcome a limitation in the way Connection * managed threads and consumer dispatching. When QueueingConsumer * was introduced, callbacks to Consumers were made on the * Connection's thread. This had two main drawbacks. Firstly, the * Consumer could stall the processing of all * Channels on the Connection. Secondly, if a * Consumer made a recursive synchronous call into its * Channel the client would deadlock. *

*

* QueueingConsumer provided client code with an easy way to * obviate this problem by queueing incoming messages and processing them on * a separate, application-managed thread. *

*

* The threading behaviour of Connection and Channel * has been changed so that each Channel uses a distinct thread * for dispatching to Consumers. This prevents * Consumers on one Channel holding up * Consumers on another and it also prevents recursive calls from * deadlocking the client. * As such, it is now safe to implement Consumer directly or * to extend DefaultConsumer and QueueingConsumer * is a lot less relevant.

* */ public class QueueingConsumer extends DefaultConsumer { private final BlockingQueue _queue; // When this is non-null the queue is in shutdown mode and nextDelivery should // throw a shutdown signal exception. private volatile ShutdownSignalException _shutdown; private volatile ConsumerCancelledException _cancelled; // Marker object used to signal the queue is in shutdown mode. // It is only there to wake up consumers. The canonical representation // of shutting down is the presence of _shutdown. // Invariant: This is never on _queue unless _shutdown != null. private static final Delivery POISON = new Delivery(null, null, null); public QueueingConsumer(Channel ch) { this(ch, new LinkedBlockingQueue()); } public QueueingConsumer(Channel ch, BlockingQueue q) { super(ch); this._queue = q; } @Override public void handleShutdownSignal(String consumerTag, ShutdownSignalException sig) { _shutdown = sig; _queue.add(POISON); } @Override public void handleCancel(String consumerTag) throws IOException { _cancelled = new ConsumerCancelledException(); _queue.add(POISON); } @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { checkShutdown(); this._queue.add(new Delivery(envelope, properties, body)); } /** * Encapsulates an arbitrary message - simple "bean" holder structure. */ public static class Delivery { private final Envelope _envelope; private final AMQP.BasicProperties _properties; private final byte[] _body; public Delivery(Envelope envelope, AMQP.BasicProperties properties, byte[] body) { _envelope = envelope; _properties = properties; _body = body; } /** * Retrieve the message envelope. * @return the message envelope */ public Envelope getEnvelope() { return _envelope; } /** * Retrieve the message properties. * @return the message properties */ public BasicProperties getProperties() { return _properties; } /** * Retrieve the message body. * @return the message body */ public byte[] getBody() { return _body; } } /** * Check if we are in shutdown mode and if so throw an exception. */ private void checkShutdown() { if (_shutdown != null) throw Utility.fixStackTrace(_shutdown); } /** * If delivery is not POISON nor null, return it. *

* If delivery, _shutdown and _cancelled are all null, return null. *

* If delivery is POISON re-insert POISON into the queue and * throw an exception if POISONed for no reason. *

* Otherwise, if we are in shutdown mode or cancelled, * throw a corresponding exception. */ private Delivery handle(Delivery delivery) { if (delivery == POISON || delivery == null && (_shutdown != null || _cancelled != null)) { if (delivery == POISON) { _queue.add(POISON); if (_shutdown == null && _cancelled == null) { throw new IllegalStateException( "POISON in queue, but null _shutdown and null _cancelled. " + "This should never happen, please report as a BUG"); } } if (null != _shutdown) throw Utility.fixStackTrace(_shutdown); if (null != _cancelled) throw Utility.fixStackTrace(_cancelled); } return delivery; } /** * Main application-side API: wait for the next message delivery and return it. * @return the next message * @throws InterruptedException if an interrupt is received while waiting * @throws ShutdownSignalException if the connection is shut down while waiting * @throws ConsumerCancelledException if this consumer is cancelled while waiting */ public Delivery nextDelivery() throws InterruptedException, ShutdownSignalException, ConsumerCancelledException { return handle(_queue.take()); } /** * Main application-side API: wait for the next message delivery and return it. * @param timeout timeout in millisecond * @return the next message or null if timed out * @throws InterruptedException if an interrupt is received while waiting * @throws ShutdownSignalException if the connection is shut down while waiting * @throws ConsumerCancelledException if this consumer is cancelled while waiting */ public Delivery nextDelivery(long timeout) throws InterruptedException, ShutdownSignalException, ConsumerCancelledException { return handle(_queue.poll(timeout, TimeUnit.MILLISECONDS)); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/impl/000077500000000000000000000000001316117667700250145ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/impl/WorkPoolTests.java000066400000000000000000000133171316117667700304630ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.impl; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.util.ArrayList; import java.util.List; import org.junit.Test; /** * Unit tests for {@link WorkPool} */ public class WorkPoolTests { private final WorkPool pool = new WorkPool(); /** * Test unknown key tolerated silently * @throws Exception untested */ @Test public void unknownKey() throws Exception{ assertFalse(this.pool.addWorkItem("test", new Object())); } /** * Test add work and remove work * @throws Exception untested */ @Test public void basicInOut() throws Exception { Object one = new Object(); Object two = new Object(); this.pool.registerKey("test"); assertTrue(this.pool.addWorkItem("test", one)); assertFalse(this.pool.addWorkItem("test", two)); List workList = new ArrayList(16); String key = this.pool.nextWorkBlock(workList, 1); assertEquals("test", key); assertEquals(1, workList.size()); assertEquals(one, workList.get(0)); assertTrue("Should be made ready", this.pool.finishWorkBlock(key)); workList.clear(); key = this.pool.nextWorkBlock(workList, 1); assertEquals("Work client key wrong", "test", key); assertEquals("Wrong work delivered", two, workList.get(0)); assertFalse("Should not be made ready after this.", this.pool.finishWorkBlock(key)); assertNull("Shouldn't be more work", this.pool.nextWorkBlock(workList, 1)); } /** * Test add work when work in progress. * @throws Exception untested */ @Test public void workInWhileInProgress() throws Exception { Object one = new Object(); Object two = new Object(); this.pool.registerKey("test"); assertTrue(this.pool.addWorkItem("test", one)); List workList = new ArrayList(16); String key = this.pool.nextWorkBlock(workList, 1); assertEquals("test", key); assertEquals(1, workList.size()); assertEquals(one, workList.get(0)); assertFalse(this.pool.addWorkItem("test", two)); assertTrue(this.pool.finishWorkBlock(key)); workList.clear(); key = this.pool.nextWorkBlock(workList, 1); assertEquals("test", key); assertEquals(1, workList.size()); assertEquals(two, workList.get(0)); } /** * Test multiple work keys. * @throws Exception untested */ @Test public void interleavingKeys() throws Exception { Object one = new Object(); Object two = new Object(); Object three = new Object(); this.pool.registerKey("test1"); this.pool.registerKey("test2"); assertTrue(this.pool.addWorkItem("test1", one)); assertTrue(this.pool.addWorkItem("test2", two)); assertFalse(this.pool.addWorkItem("test1", three)); List workList = new ArrayList(16); String key = this.pool.nextWorkBlock(workList, 3); assertEquals("test1", key); assertEquals(2, workList.size()); assertEquals(one, workList.get(0)); assertEquals(three, workList.get(1)); workList.clear(); key = this.pool.nextWorkBlock(workList, 2); assertEquals("test2", key); assertEquals(1, workList.size()); assertEquals(two, workList.get(0)); } /** * Test removal of key (with work) * @throws Exception untested */ @Test public void unregisterKey() throws Exception { Object one = new Object(); Object two = new Object(); Object three = new Object(); this.pool.registerKey("test1"); this.pool.registerKey("test2"); assertTrue(this.pool.addWorkItem("test1", one)); assertTrue(this.pool.addWorkItem("test2", two)); assertFalse(this.pool.addWorkItem("test1", three)); this.pool.unregisterKey("test1"); List workList = new ArrayList(16); String key = this.pool.nextWorkBlock(workList, 3); assertEquals("test2", key); assertEquals(1, workList.size()); assertEquals(two, workList.get(0)); } /** * Test removal of all keys (with work). * @throws Exception untested */ @Test public void unregisterAllKeys() throws Exception { Object one = new Object(); Object two = new Object(); Object three = new Object(); this.pool.registerKey("test1"); this.pool.registerKey("test2"); assertTrue(this.pool.addWorkItem("test1", one)); assertTrue(this.pool.addWorkItem("test2", two)); assertFalse(this.pool.addWorkItem("test1", three)); this.pool.unregisterAllKeys(); List workList = new ArrayList(16); assertNull(this.pool.nextWorkBlock(workList, 1)); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/000077500000000000000000000000001316117667700250325ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/AMQBuilderApiTest.java000066400000000000000000000055611316117667700311230ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.IOException; import org.junit.Test; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.Method; public class AMQBuilderApiTest extends BrokerTestCase { private static final String XCHG_NAME = "builder_test_xchg"; @Test public void particularBuilderForBasicSanityWithRpc() throws IOException { Method retVal = channel.rpc(new AMQP.Exchange.Declare.Builder() .exchange(XCHG_NAME) .type("direct") .durable(false) .build() ).getMethod(); assertTrue("Channel should still be open.", channel.isOpen()); assertTrue(retVal instanceof AMQP.Exchange.DeclareOk); retVal = channel.rpc(new AMQP.Exchange.Delete.Builder() .exchange(XCHG_NAME) .build() ).getMethod(); assertTrue("Channel should still be open.", channel.isOpen()); assertTrue(retVal instanceof AMQP.Exchange.DeleteOk); } @Test public void particularBuilderForBasicSanityWithAsyncRpc() throws IOException { channel.asyncRpc(new AMQP.Exchange.Declare.Builder() .exchange(XCHG_NAME) .type("direct") .durable(false) .build() ); assertTrue("Channel should still be open.", channel.isOpen()); channel.asyncRpc(new AMQP.Exchange.Delete.Builder() .exchange(XCHG_NAME) .build() ); assertTrue("Channel should still be open.", channel.isOpen()); } @Test public void illFormedBuilder() { try { new AMQP.Exchange.Declare.Builder().build(); fail("Should have thrown IllegalStateException"); } catch (Exception e) { assertTrue(e instanceof IllegalStateException); } } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/AMQChannelTest.java000066400000000000000000000144211316117667700304460ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test; import com.rabbitmq.client.ChannelContinuationTimeoutException; import com.rabbitmq.client.Command; import com.rabbitmq.client.Method; import com.rabbitmq.client.impl.AMQChannel; import com.rabbitmq.client.impl.AMQCommand; import com.rabbitmq.client.impl.AMQConnection; import com.rabbitmq.client.impl.AMQImpl; import org.junit.After; import org.junit.Before; import org.junit.Test; import java.io.IOException; import java.util.concurrent.Callable; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; import static org.mockito.Mockito.*; public class AMQChannelTest { ScheduledExecutorService scheduler; @Before public void init() { scheduler = Executors.newSingleThreadScheduledExecutor(); } @After public void tearDown() { scheduler.shutdownNow(); } @Test public void rpcTimesOutWhenResponseDoesNotCome() throws IOException { int rpcTimeout = 100; AMQConnection connection = mock(AMQConnection.class); when(connection.getChannelRpcTimeout()).thenReturn(rpcTimeout); DummyAmqChannel channel = new DummyAmqChannel(connection, 1); Method method = new AMQImpl.Queue.Declare.Builder() .queue("") .durable(false) .exclusive(true) .autoDelete(true) .arguments(null) .build(); try { channel.rpc(method); fail("Should time out and throw an exception"); } catch(ChannelContinuationTimeoutException e) { // OK assertThat((DummyAmqChannel) e.getChannel(), is(channel)); assertThat(e.getChannelNumber(), is(channel.getChannelNumber())); assertThat(e.getMethod(), is(method)); assertNull("outstanding RPC should have been cleaned", channel.nextOutstandingRpc()); } } @Test public void rpcReturnsResultWhenResponseHasCome() throws IOException { int rpcTimeout = 1000; AMQConnection connection = mock(AMQConnection.class); when(connection.getChannelRpcTimeout()).thenReturn(rpcTimeout); final DummyAmqChannel channel = new DummyAmqChannel(connection, 1); Method method = new AMQImpl.Queue.Declare.Builder() .queue("") .durable(false) .exclusive(true) .autoDelete(true) .arguments(null) .build(); final Method response = new AMQImpl.Queue.DeclareOk.Builder() .queue("whatever") .consumerCount(0) .messageCount(0).build(); scheduler.schedule(new Callable() { @Override public Void call() throws Exception { channel.handleCompleteInboundCommand(new AMQCommand(response)); return null; } }, (long) (rpcTimeout / 2.0), TimeUnit.MILLISECONDS); AMQCommand rpcResponse = channel.rpc(method); assertThat(rpcResponse.getMethod(), is(response)); } @Test public void testRpcTimeoutReplyComesDuringNexRpc() throws Exception { int rpcTimeout = 100; AMQConnection connection = mock(AMQConnection.class); when(connection.getChannelRpcTimeout()).thenReturn(rpcTimeout); when(connection.willCheckRpcResponseType()).thenReturn(Boolean.TRUE); final DummyAmqChannel channel = new DummyAmqChannel(connection, 1); Method method = new AMQImpl.Queue.Declare.Builder() .queue("123") .durable(false) .exclusive(true) .autoDelete(true) .arguments(null) .build(); try { channel.rpc(method); fail("Should time out and throw an exception"); } catch(final ChannelContinuationTimeoutException e) { // OK assertThat((DummyAmqChannel) e.getChannel(), is(channel)); assertThat(e.getChannelNumber(), is(channel.getChannelNumber())); assertThat(e.getMethod(), is(method)); assertNull("outstanding RPC should have been cleaned", channel.nextOutstandingRpc()); } // now do a basic.consume request and have the queue.declareok returned instead method = new AMQImpl.Basic.Consume.Builder() .queue("123") .consumerTag("") .arguments(null) .build(); final Method response1 = new AMQImpl.Queue.DeclareOk.Builder() .queue("123") .consumerCount(0) .messageCount(0).build(); final Method response2 = new AMQImpl.Basic.ConsumeOk.Builder() .consumerTag("456").build(); scheduler.schedule(new Callable() { @Override public Void call() throws Exception { channel.handleCompleteInboundCommand(new AMQCommand(response1)); Thread.sleep(10); channel.handleCompleteInboundCommand(new AMQCommand(response2)); return null; } }, (long) (rpcTimeout / 2.0), TimeUnit.MILLISECONDS); AMQCommand rpcResponse = channel.rpc(method); assertThat(rpcResponse.getMethod(), is(response2)); } static class DummyAmqChannel extends AMQChannel { public DummyAmqChannel(AMQConnection connection, int channelNumber) { super(connection, channelNumber); } @Override public boolean processAsync(Command command) throws IOException { return false; } } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/AMQConnectionTest.java000066400000000000000000000273321316117667700312020ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test; import com.rabbitmq.client.*; import com.rabbitmq.client.impl.AMQConnection; import com.rabbitmq.client.impl.ConnectionParams; import com.rabbitmq.client.impl.Frame; import com.rabbitmq.client.impl.FrameHandler; import org.junit.After; import org.junit.Before; import org.junit.Test; import java.io.IOException; import java.net.InetAddress; import java.net.SocketException; import java.net.SocketTimeoutException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeoutException; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; /** * Test suite for AMQConnection. */ public class AMQConnectionTest { // private static final String CLOSE_MESSAGE = "terminated by test"; /** The mock frame handler used to test connection behaviour. */ private MockFrameHandler _mockFrameHandler; private ConnectionFactory factory; private MyExceptionHandler exceptionHandler; @Before public void setUp() throws Exception { _mockFrameHandler = new MockFrameHandler(); factory = TestUtils.connectionFactory(); exceptionHandler = new MyExceptionHandler(); factory.setExceptionHandler(exceptionHandler); } @After public void tearDown() throws Exception { factory = null; _mockFrameHandler = null; } @Test public void negativeTCPConnectionTimeout() { ConnectionFactory cf = TestUtils.connectionFactory(); try { cf.setConnectionTimeout(-10); fail("expected an exception"); } catch (IllegalArgumentException _ignored) { // expected } } @Test public void negativeProtocolHandshakeTimeout() { ConnectionFactory cf = TestUtils.connectionFactory(); try { cf.setHandshakeTimeout(-10); fail("expected an exception"); } catch (IllegalArgumentException _ignored) { // expected } } @Test public void tcpConnectionTimeoutGreaterThanHandShakeTimeout() { ConnectionFactory cf = TestUtils.connectionFactory(); cf.setHandshakeTimeout(3000); cf.setConnectionTimeout(5000); } @Test public void protocolHandshakeTimeoutGreaterThanTCPConnectionTimeout() { ConnectionFactory cf = TestUtils.connectionFactory(); cf.setConnectionTimeout(5000); cf.setHandshakeTimeout(7000); cf.setConnectionTimeout(0); cf.setHandshakeTimeout(7000); } @Test public void negativeRpcTimeoutIsForbidden() { ConnectionFactory cf = TestUtils.connectionFactory(); try { cf.setChannelRpcTimeout(-10); fail("expected an exception"); } catch (IllegalArgumentException _ignored) { // expected } } /** Check the AMQConnection does send exactly 1 initial header, and deal correctly with * the frame handler throwing an exception when we try to read data */ @Test public void connectionSendsSingleHeaderAndTimesOut() throws TimeoutException { IOException exception = new SocketTimeoutException(); _mockFrameHandler.setExceptionOnReadingFrames(exception); assertEquals(0, _mockFrameHandler.countHeadersSent()); try { ConnectionParams params = factory.params(Executors.newFixedThreadPool(1)); new AMQConnection(params, _mockFrameHandler).start(); fail("Connection should have thrown exception"); } catch(IOException signal) { // As expected } assertEquals(1, _mockFrameHandler.countHeadersSent()); // _connection.close(0, CLOSE_MESSAGE); List exceptionList = exceptionHandler.getHandledExceptions(); assertEquals(Collections.singletonList(exception), exceptionList); } /** Check we can open a connection once, but not twice. * @throws IOException */ // public void testCanOpenConnectionOnceOnly() throws IOException { // AMQConnection connection = new AMQConnection(_mockFrameHandler); // connection.open(); // try { // connection.open(); // fail("We shouldn't have been able to open this connection more than once."); // } catch(IOException ex) { // // as expected // } // } /** * Test that we catch timeout between connect and negotiation of the connection being finished. */ @Test public void connectionHangInNegotiation() { this._mockFrameHandler.setTimeoutCount(10); // to limit hang assertEquals(0, this._mockFrameHandler.countHeadersSent()); try { ConnectionParams params = factory.params(Executors.newFixedThreadPool(1)); new AMQConnection(params, this._mockFrameHandler).start(); fail("Connection should have thrown exception"); } catch(IOException signal) { // expected } catch(TimeoutException te) { // also fine: continuation timed out first } assertEquals(1, this._mockFrameHandler.countHeadersSent()); List exceptionList = exceptionHandler.getHandledExceptions(); assertEquals("Only one exception expected", 1, exceptionList.size()); assertEquals("Wrong type of exception returned.", SocketTimeoutException.class, exceptionList.get(0).getClass()); } @Test public void clientProvidedConnectionName() throws IOException, TimeoutException { String providedName = "event consumers connection"; Connection connection = factory.newConnection(providedName); assertEquals(providedName, connection.getClientProvidedName()); connection.close(); List
addrs1 = Arrays.asList(new Address("127.0.0.1"), new Address("127.0.0.1", 5672)); connection = factory.newConnection(addrs1, providedName); assertEquals(providedName, connection.getClientProvidedName()); connection.close(); Address[] addrs2 = {new Address("127.0.0.1"), new Address("127.0.0.1", 5672)}; connection = factory.newConnection(addrs2, providedName); assertEquals(providedName, connection.getClientProvidedName()); connection.close(); ExecutorService xs = Executors.newSingleThreadExecutor(); connection = factory.newConnection(xs, providedName); assertEquals(providedName, connection.getClientProvidedName()); connection.close(); connection = factory.newConnection(xs, addrs1, providedName); assertEquals(providedName, connection.getClientProvidedName()); connection.close(); connection = factory.newConnection(xs, addrs2, providedName); assertEquals(providedName, connection.getClientProvidedName()); connection.close(); } /** Mock frame handler to facilitate testing. */ private static class MockFrameHandler implements FrameHandler { /** How many times has sendHeader() been called? */ private int _numHeadersSent; private int timeout; /** An optional exception for us to throw on reading frames */ private IOException _exceptionOnReadingFrames; private int timeoutCount = 0; /** count how many headers we've sent * @return the number of sent headers */ public int countHeadersSent() { return _numHeadersSent; } public void setExceptionOnReadingFrames(IOException exception) { _exceptionOnReadingFrames = exception; } public void setTimeoutCount(int timeoutCount) { this.timeoutCount = timeoutCount; } public Frame readFrame() throws IOException { if (_exceptionOnReadingFrames != null) { throw _exceptionOnReadingFrames; } if (this.timeoutCount > 0) { if (--this.timeoutCount == 0) throw new IOException("Mock Framehandler: too many timeouts."); } return null; // simulate a socket timeout } public void sendHeader() throws IOException { _numHeadersSent++; } @Override public void initialize(AMQConnection connection) { connection.startMainLoop(); } public void setTimeout(int timeoutMs) throws SocketException { this.timeout = timeoutMs; } public void writeFrame(Frame frame) throws IOException { // no need to implement this: don't bother writing the frame } public void close() { // nothing to do } public int getTimeout() throws SocketException { return this.timeout; } public InetAddress getAddress() { return null; } public int getPort() { return -1; } public void flush() throws IOException { // no need to implement this: don't bother writing the frame } public InetAddress getLocalAddress() { return null; } public int getLocalPort() { return -1; } } /** Exception handler to facilitate testing. */ private class MyExceptionHandler implements ExceptionHandler { private final List _handledExceptions = new ArrayList(); public void handleUnexpectedConnectionDriverException(Connection conn, Throwable ex) { _handledExceptions.add(ex); } public void handleReturnListenerException(Channel ch, Throwable ex) { fail("handleReturnListenerException: " + ex); } public void handleFlowListenerException(Channel ch, Throwable ex) { fail("handleFlowListenerException: " + ex); } public void handleConfirmListenerException(Channel ch, Throwable ex) { fail("handleConfirmListenerException: " + ex); } public void handleBlockedListenerException(Connection conn, Throwable ex) { fail("handleBlockedListenerException: " + ex); } public void handleConsumerException(Channel ch, Throwable ex, Consumer c, String consumerTag, String methodName) { fail("handleConsumerException " + consumerTag + " " + methodName + ": " + ex); } public void handleConnectionRecoveryException(Connection conn, Throwable ex) { _handledExceptions.add(ex); } public void handleChannelRecoveryException(Channel ch, Throwable ex) { _handledExceptions.add(ex); } public void handleTopologyRecoveryException(Connection conn, Channel ch, TopologyRecoveryException ex) { _handledExceptions.add(ex); } public List getHandledExceptions() { return _handledExceptions; } } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/AbstractRMQTestSuite.java000066400000000000000000000072401316117667700316750ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test; import com.rabbitmq.tools.Host; import java.io.File; import java.io.IOException; import java.net.Socket; import java.util.Properties; public abstract class AbstractRMQTestSuite { static { Properties TESTS_PROPS = new Properties(System.getProperties()); String make = System.getenv("MAKE"); if (make != null) TESTS_PROPS.setProperty("make.bin", make); try { TESTS_PROPS.load(Host.class.getClassLoader().getResourceAsStream("config.properties")); } catch (Exception e) { System.out.println( "\"build.properties\" or \"config.properties\" not found" + " in classpath. Please copy \"build.properties\" and" + " \"config.properties\" into src/test/resources. Ignore" + " this message if running with ant."); } finally { System.setProperties(TESTS_PROPS); } } public static boolean requiredProperties() { /* GNU Make. */ String make = Host.makeCommand(); boolean isGNUMake = false; if (make != null) { try { Process makeProc = Host.executeCommandIgnoringErrors(make + " --version"); String makeVersion = Host.capture(makeProc.getInputStream()); isGNUMake = makeVersion.startsWith("GNU Make"); } catch (IOException e) {} } if (!isGNUMake) { System.err.println( "GNU Make required; please set \"make.bin\" system property" + " or \"$MAKE\" environment variable"); return false; } /* Path to RabbitMQ. */ String rabbitmq = Host.rabbitmqDir(); if (rabbitmq == null || !new File(rabbitmq).isDirectory()) { System.err.println( "RabbitMQ required; please set \"rabbitmq.dir\" system" + " property"); return false; } /* Path to rabbitmqctl. */ String rabbitmqctl = Host.rabbitmqctlCommand(); if (rabbitmqctl == null || !new File(rabbitmqctl).isFile()) { System.err.println( "rabbitmqctl required; please set \"rabbitmqctl.bin\" system" + " property"); return false; } return true; } public static boolean isSSLAvailable() { String sslClientCertsDir = System.getProperty("test-client-cert.path"); String hostname = System.getProperty("broker.hostname"); String port = System.getProperty("broker.sslport"); if (sslClientCertsDir == null || hostname == null || port == null) return false; // If certificate is present and some server is listening on port 5671 if (new File(sslClientCertsDir).exists() && checkServerListening(hostname, Integer.parseInt(port))) { return true; } else return false; } private static boolean checkServerListening(String host, int port) { Socket s = null; try { s = new Socket(host, port); return true; } catch (Exception e) { return false; } finally { if (s != null) try { s.close(); } catch (Exception e) { } } } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/AmqpUriTest.java000066400000000000000000000076211316117667700301210ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import java.net.URISyntaxException; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import org.junit.Test; import com.rabbitmq.client.ConnectionFactory; public class AmqpUriTest extends BrokerTestCase { @Test public void uriParsing() throws URISyntaxException, NoSuchAlgorithmException, KeyManagementException { /* From the spec (subset of the tests) */ parseSuccess("amqp://user:pass@host:10000/vhost", "user", "pass", "host", 10000, "vhost"); parseSuccess("aMQps://user%61:%61pass@host:10000/v%2fhost", "usera", "apass", "host", 10000, "v/host"); parseSuccess("amqp://host", "guest", "guest", "host", 5672, "/"); parseSuccess("amqp:///vhost", "guest", "guest", "localhost", 5672, "vhost"); parseSuccess("amqp://host/", "guest", "guest", "host", 5672, ""); parseSuccess("amqp://host/%2f", "guest", "guest", "host", 5672, "/"); parseSuccess("amqp://[::1]", "guest", "guest", "[::1]", 5672, "/"); /* Various other success cases */ parseSuccess("amqp://host:100", "guest", "guest", "host", 100, "/"); parseSuccess("amqp://[::1]:100", "guest", "guest", "[::1]", 100, "/"); parseSuccess("amqp://host/blah", "guest", "guest", "host", 5672, "blah"); parseSuccess("amqp://host:100/blah", "guest", "guest", "host", 100, "blah"); parseSuccess("amqp://[::1]/blah", "guest", "guest", "[::1]", 5672, "blah"); parseSuccess("amqp://[::1]:100/blah", "guest", "guest", "[::1]", 100, "blah"); parseSuccess("amqp://user:pass@host", "user", "pass", "host", 5672, "/"); parseSuccess("amqp://user:pass@[::1]", "user", "pass", "[::1]", 5672, "/"); parseSuccess("amqp://user:pass@[::1]:100", "user", "pass", "[::1]", 100, "/"); /* Various failure cases */ parseFail("http://www.rabbitmq.com"); parseFail("amqp://foo[::1]"); parseFail("amqp://foo:[::1]"); parseFail("amqp://[::1]foo"); parseFail("amqp://foo%1"); parseFail("amqp://foo%1x"); parseFail("amqp://foo%xy"); } private void parseSuccess(String uri, String user, String password, String host, int port, String vhost) throws URISyntaxException, NoSuchAlgorithmException, KeyManagementException { ConnectionFactory cf = TestUtils.connectionFactory(); cf.setUri(uri); assertEquals(user, cf.getUsername()); assertEquals(password, cf.getPassword()); assertEquals(host, cf.getHost()); assertEquals(port, cf.getPort()); assertEquals(vhost, cf.getVirtualHost()); } private void parseFail(String uri) { try { (TestUtils.connectionFactory()).setUri(uri); fail("URI parse didn't fail: '" + uri + "'"); } catch (Exception e) { // whoosh! } } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/BlockingCellTest.java000066400000000000000000000120431316117667700310650ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test; import com.rabbitmq.utility.BlockingCell; import org.junit.Test; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import static org.junit.Assert.*; public class BlockingCellTest { @Test public void doubleSet() throws InterruptedException { BlockingCell cell = new BlockingCell(); cell.set("one"); assertEquals("one", cell.get()); try { cell.set("two"); } catch (IllegalStateException ae) { return; } fail("Expected IllegalStateException"); } @Test public void multiGet() throws InterruptedException { final BlockingCell cell = new BlockingCell(); cell.set("one"); assertEquals("one", cell.get()); assertEquals("one", cell.get()); } @Test public void nullSet() throws InterruptedException { BlockingCell c = new BlockingCell(); c.set(null); assertNull(c.get()); } @Test public void earlySet() throws InterruptedException { final BlockingCell cell = new BlockingCell(); final AtomicReference holder = new AtomicReference(); Thread getterThread = new Thread(new Runnable() { public void run() { try { Thread.sleep(300); holder.set(cell.get()); } catch (InterruptedException ie) { // no special handling required } } }); Thread setterThread = new Thread(new Runnable() { public void run() { cell.set("hello"); } }); getterThread.start(); setterThread.start(); getterThread.join(); setterThread.join(); assertEquals("hello", holder.get()); } @Test public void lateSet() throws InterruptedException { final BlockingCell cell = new BlockingCell(); final AtomicReference holder = new AtomicReference(); Thread getterThread = new Thread(new Runnable() { public void run() { try { holder.set(cell.get()); } catch (InterruptedException ie) { // no special handling required } } }); Thread setterThread = new Thread(new Runnable() { public void run() { try { Thread.sleep(300); cell.set("hello"); } catch (InterruptedException ie) { // no special handling required } } }); getterThread.start(); setterThread.start(); getterThread.join(); setterThread.join(); assertEquals("hello", holder.get()); } @Test public void getWaitsUntilSet() throws InterruptedException { final BlockingCell cell = new BlockingCell(); final String value = "foo"; final AtomicReference valueHolder = new AtomicReference(); final AtomicBoolean doneHolder = new AtomicBoolean(false); Thread getterThread = new Thread() { @Override public void run() { try { valueHolder.set(cell.get()); } catch (InterruptedException ex) { fail("hit InterruptedException"); ex.printStackTrace(); } doneHolder.set(true); } }; getterThread.start(); Thread.sleep(300); assertFalse(doneHolder.get()); cell.set(value); getterThread.join(); assertTrue(doneHolder.get()); assertTrue(value == valueHolder.get()); } @Test public void setIfUnset() throws InterruptedException { final BlockingCell cell = new BlockingCell(); assertTrue(cell.setIfUnset("foo")); assertEquals("foo", cell.get()); assertFalse(cell.setIfUnset("bar")); assertEquals("foo", cell.get()); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/BrokenFramesTest.java000066400000000000000000000122561316117667700311210ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.ConnectionFactory; import com.rabbitmq.client.UnexpectedFrameError; import com.rabbitmq.client.impl.AMQConnection; import com.rabbitmq.client.impl.AMQImpl.Basic.Publish; import com.rabbitmq.client.impl.Frame; import com.rabbitmq.client.impl.FrameHandler; import org.junit.After; import org.junit.Before; import org.junit.Test; import java.io.IOException; import java.net.InetAddress; import java.net.SocketException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.concurrent.Executors; import static org.junit.Assert.*; public class BrokenFramesTest { private MyFrameHandler myFrameHandler; private ConnectionFactory factory; @Before public void setUp() throws Exception { myFrameHandler = new MyFrameHandler(); factory = TestUtils.connectionFactory(); } @After public void tearDown() throws Exception { factory = null; myFrameHandler = null; } @Test public void noMethod() throws Exception { List frames = new ArrayList(); frames.add(new Frame(AMQP.FRAME_HEADER, 0)); myFrameHandler.setFrames(frames.iterator()); try { new AMQConnection(factory.params(Executors.newFixedThreadPool(1)), myFrameHandler).start(); } catch (IOException e) { UnexpectedFrameError unexpectedFrameError = findUnexpectedFrameError(e); assertNotNull(unexpectedFrameError); assertEquals(AMQP.FRAME_HEADER, unexpectedFrameError.getReceivedFrame().type); assertEquals(AMQP.FRAME_METHOD, unexpectedFrameError.getExpectedFrameType()); return; } fail("No UnexpectedFrameError thrown"); } @Test public void methodThenBody() throws Exception { List frames = new ArrayList(); byte[] contentBody = new byte[10]; int channelNumber = 0; Publish method = new Publish(1, "test", "test", false, false); frames.add(method.toFrame(0)); frames.add(Frame.fromBodyFragment(channelNumber, contentBody, 0, contentBody.length)); myFrameHandler.setFrames(frames.iterator()); try { new AMQConnection(factory.params(Executors.newFixedThreadPool(1)), myFrameHandler).start(); } catch (IOException e) { UnexpectedFrameError unexpectedFrameError = findUnexpectedFrameError(e); assertNotNull(unexpectedFrameError); assertEquals(AMQP.FRAME_BODY, unexpectedFrameError.getReceivedFrame().type); assertEquals(AMQP.FRAME_HEADER, unexpectedFrameError.getExpectedFrameType()); return; } fail("No UnexpectedFrameError thrown"); } private UnexpectedFrameError findUnexpectedFrameError(Exception e) { Throwable t = e; while ((t = t.getCause()) != null) { if (t instanceof UnexpectedFrameError) { // This is what we wanted return (UnexpectedFrameError) t; } } return null; } private static class MyFrameHandler implements FrameHandler { private Iterator frames; public void setFrames(Iterator frames) { this.frames = frames; } public Frame readFrame() throws IOException { return frames.next(); } public void sendHeader() throws IOException { } @Override public void initialize(AMQConnection connection) { connection.startMainLoop(); } public void setTimeout(int timeoutMs) throws SocketException { // no need to implement this: don't bother changing the timeout } public void writeFrame(Frame frame) throws IOException { // no need to implement this: don't bother writing the frame } public void close() { // nothing to do } public int getTimeout() throws SocketException { return 0; } public InetAddress getAddress() { return null; } public int getPort() { return -1; } public void flush() throws IOException { // no need to implement this: don't bother writing the frame } public InetAddress getLocalAddress() { return null; } public int getLocalPort() { return -1; } } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/BrokerTestCase.java000066400000000000000000000267001316117667700305620ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test; import com.rabbitmq.client.*; import com.rabbitmq.client.impl.nio.NioParams; import com.rabbitmq.tools.Host; import org.junit.After; import org.junit.Assume; import org.junit.Before; import org.junit.Rule; import org.junit.rules.TestRule; import org.junit.rules.TestWatcher; import org.junit.runner.Description; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.net.ssl.SSLContext; import java.io.IOException; import java.security.NoSuchAlgorithmException; import java.util.Arrays; import java.util.Map; import java.util.UUID; import java.util.concurrent.TimeoutException; import static org.junit.Assert.*; import static org.junit.Assume.*; public class BrokerTestCase { private static final Logger LOGGER = LoggerFactory.getLogger(BrokerTestCase.class); @Rule public TestRule watcher = new TestWatcher() { protected void starting(Description description) { LOGGER.info( "Starting test: {}.{} (nio? {})", description.getTestClass().getSimpleName(), description.getMethodName(), TestUtils.USE_NIO ); } @Override protected void finished(Description description) { LOGGER.info("Test finished: {}.{}", description.getTestClass().getSimpleName(), description.getMethodName()); } }; protected ConnectionFactory connectionFactory = newConnectionFactory(); protected ConnectionFactory newConnectionFactory() { ConnectionFactory connectionFactory = TestUtils.connectionFactory(); if(TestUtils.USE_NIO) { connectionFactory.setNioParams(nioParams()); } connectionFactory.setAutomaticRecoveryEnabled(isAutomaticRecoveryEnabled()); return connectionFactory; } protected NioParams nioParams() { return new NioParams(); } protected boolean isAutomaticRecoveryEnabled() { return true; } protected Connection connection; protected Channel channel; @Before public void setUp() throws IOException, TimeoutException { assumeTrue(shouldRun()); openConnection(); openChannel(); createResources(); } @After public void tearDown() throws IOException, TimeoutException { if(shouldRun()) { closeChannel(); closeConnection(); openConnection(); openChannel(); releaseResources(); closeChannel(); closeConnection(); } } /** * Whether to run the test or not. * Subclasses can check whether some broker features * are available or not, and choose not to run the test. * @return */ protected boolean shouldRun() throws IOException { return true; } /** * Should create any AMQP resources needed by the test. Will be * called by BrokerTestCase's implementation of setUp, after the * connection and channel have been opened. */ protected void createResources() throws IOException, TimeoutException { } /** * Should destroy any AMQP resources that were created by the * test. Will be called by BrokerTestCase's implementation of * tearDown, after the connection and channel have been closed and * reopened specifically for this method. After this method * completes, the connection and channel will be closed again. */ protected void releaseResources() throws IOException { } protected void restart() throws IOException, TimeoutException { tearDown(); bareRestart(); setUp(); } protected void bareRestart() throws IOException { Host.invokeMakeTarget( "stop-rabbit-on-node start-rabbit-on-node"); } public void openConnection() throws IOException, TimeoutException { if (connection == null) { connection = connectionFactory.newConnection(); } } public void closeConnection() throws IOException { if (connection != null) { connection.abort(); connection = null; } } public void openChannel() throws IOException { channel = connection.createChannel(); } public void closeChannel() throws IOException { if (channel != null) { channel.abort(); channel = null; } } public void checkShutdownSignal(int expectedCode, IOException ioe) { ShutdownSignalException sse = (ShutdownSignalException) ioe.getCause(); checkShutdownSignal(expectedCode, sse); } public void checkShutdownSignal(int expectedCode, ShutdownSignalException sse) { Method method = sse.getReason(); channel = null; if (sse.isHardError()) { connection = null; AMQP.Connection.Close closeMethod = (AMQP.Connection.Close) method; assertEquals(expectedCode, closeMethod.getReplyCode()); } else { AMQP.Channel.Close closeMethod = (AMQP.Channel.Close) method; assertEquals(expectedCode, closeMethod.getReplyCode()); } } public void expectError(int error) { try { channel.basicQos(0); fail("Expected channel error " + error); } catch (IOException ioe) { // If we get a channel close back when flushing it with the // synchronous basicQos above. checkShutdownSignal(error, ioe); } catch (AlreadyClosedException ace) { // If it has already closed of its own accord before we got there. checkShutdownSignal(error, ace); } } protected void assertDelivered(String q, int count) throws IOException { assertDelivered(q, count, false); } protected void assertDelivered(String q, int count, boolean redelivered) throws IOException { GetResponse r; for (int i = 0; i < count; i++) { r = basicGet(q); assertNotNull(r); assertEquals(redelivered, r.getEnvelope().isRedeliver()); } assertNull(basicGet(q)); } protected GetResponse basicGet(String q) throws IOException { return channel.basicGet(q, true); } protected void basicPublishPersistent(String q) throws IOException { basicPublishPersistent("persistent message".getBytes(), q); } protected void basicPublishPersistent(byte[] msg, String q) throws IOException { basicPublishPersistent(msg, "", q); } protected void basicPublishPersistent(String x, String routingKey) throws IOException { basicPublishPersistent("persistent message".getBytes(), x, routingKey); } protected void basicPublishPersistent(byte[] msg, String x, String routingKey) throws IOException { channel.basicPublish(x, routingKey, MessageProperties.PERSISTENT_TEXT_PLAIN, msg); } protected void basicPublishVolatile(String q) throws IOException { basicPublishVolatile("not persistent message".getBytes(), q); } protected void basicPublishVolatile(byte[] msg, String q) throws IOException { basicPublishVolatile(msg, "", q); } protected void basicPublishVolatile(String x, String routingKey) throws IOException { basicPublishVolatile("not persistent message".getBytes(), x, routingKey); } protected void basicPublishVolatile(byte[] msg, String x, String routingKey) throws IOException { basicPublishVolatile(msg, x, routingKey, MessageProperties.TEXT_PLAIN); } public void basicPublishVolatile(byte[] msg, String x, String routingKey, AMQP.BasicProperties properties) throws IOException { channel.basicPublish(x, routingKey, properties, msg); } protected void declareAndBindDurableQueue(String q, String x, String r) throws IOException { declareDurableQueue(q); channel.queueBind(q, x, r); } protected void declareDurableDirectExchange(String x) throws IOException { channel.exchangeDeclare(x, "direct", true); } protected void declareDurableQueue(String q) throws IOException { channel.queueDeclare(q, true, false, false, null); } protected void declareTransientQueue(String q) throws IOException { channel.queueDeclare(q, false, false, false, null); } protected void declareTransientQueue(String q, Map args) throws IOException { channel.queueDeclare(q, false, false, false, args); } protected void declareDurableTopicExchange(String x) throws IOException { channel.exchangeDeclare(x, "topic", true); } protected void declareTransientTopicExchange(String x) throws IOException { channel.exchangeDeclare(x, "topic", false); } protected void declareTransientFanoutExchange(String x) throws IOException { channel.exchangeDeclare(x, "fanout", false); } protected void deleteExchange(String x) throws IOException { channel.exchangeDelete(x); } protected void deleteQueue(String q) throws IOException { channel.queueDelete(q); } protected void clearAllResourceAlarms() throws IOException, InterruptedException { clearResourceAlarm("memory"); clearResourceAlarm("disk"); } protected void setResourceAlarm(String source) throws IOException, InterruptedException { Host.invokeMakeTarget("set-resource-alarm SOURCE=" + source); } protected void clearResourceAlarm(String source) throws IOException, InterruptedException { Host.invokeMakeTarget("clear-resource-alarm SOURCE=" + source); } protected void block() throws IOException, InterruptedException { Host.rabbitmqctl("set_vm_memory_high_watermark 0.000000001"); setResourceAlarm("disk"); } protected void unblock() throws IOException, InterruptedException { Host.rabbitmqctl("set_vm_memory_high_watermark 0.4"); clearResourceAlarm("disk"); } protected String generateQueueName() { return "queue" + UUID.randomUUID().toString(); } protected String generateExchangeName() { return "exchange" + UUID.randomUUID().toString(); } protected SSLContext getSSLContext() throws NoSuchAlgorithmException { SSLContext c = null; // pick the first protocol available, preferring TLSv1.2, then TLSv1, // falling back to SSLv3 if running on an ancient/crippled JDK for(String proto : Arrays.asList("TLSv1.2", "TLSv1", "SSLv3")) { try { c = SSLContext.getInstance(proto); return c; } catch (NoSuchAlgorithmException x) { // keep trying } } throw new NoSuchAlgorithmException(); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/Bug20004Test.java000066400000000000000000000053301316117667700276410ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test; import org.junit.Test; import java.io.IOException; import static org.junit.Assert.*; /** * Test for bug 20004 - deadlock through internal synchronization on * the channel object. This is more properly a unit test, but since it * requires a connection to a broker, it's grouped with the functional * tests. *

* Test calls channel.queueDeclare, while synchronising on channel, from * an independent thread. */ public class Bug20004Test extends BrokerTestCase { private volatile Exception caughtException = null; private volatile boolean completed = false; private volatile boolean created = false; protected void releaseResources() throws IOException { if (created) { channel.queueDelete("Bug20004Test"); } } @SuppressWarnings("deprecation") @Test public void bug20004() throws IOException { final Bug20004Test testInstance = this; Thread declaringThread = new Thread(new Runnable() { public void run() { try { synchronized (channel) { channel.queueDeclare("Bug20004Test", false, false, false, null); testInstance.created = true; } } catch (Exception e) { testInstance.caughtException = e; } testInstance.completed = true; } }); declaringThread.start(); // poll (100ms) for `completed`, up to 5s long endTime = System.currentTimeMillis() + 5000; while (!completed && (System.currentTimeMillis() < endTime)) { try { Thread.sleep(100); } catch (InterruptedException ie) {} } declaringThread.stop(); // see bug 20012. assertTrue("Deadlock detected?", completed); assertNull("queueDeclare threw an exception", caughtException); assertTrue("unknown sequence of events", created); } } ChannelAsyncCompletableFutureTest.java000066400000000000000000000101201316117667700343610ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test// Copyright (c) 2017-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.DefaultConsumer; import com.rabbitmq.client.Envelope; import com.rabbitmq.client.impl.AMQImpl; import org.junit.After; import org.junit.Before; import org.junit.Test; import java.io.IOException; import java.util.UUID; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import static org.junit.Assert.assertTrue; public class ChannelAsyncCompletableFutureTest extends BrokerTestCase { ExecutorService executor; String queue; String exchange; @Before public void init() { executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); queue = UUID.randomUUID().toString(); exchange = UUID.randomUUID().toString(); } @After public void tearDown() throws IOException { executor.shutdownNow(); channel.queueDelete(queue); channel.exchangeDelete(exchange); } @Test public void async() throws Exception { channel.confirmSelect(); CountDownLatch latch = new CountDownLatch(1); AMQP.Queue.Declare queueDeclare = new AMQImpl.Queue.Declare.Builder() .queue(queue) .durable(true) .exclusive(false) .autoDelete(false) .arguments(null) .build(); channel.asyncCompletableRpc(queueDeclare) .thenComposeAsync(action -> { try { return channel.asyncCompletableRpc(new AMQImpl.Exchange.Declare.Builder() .exchange(exchange) .type("fanout") .durable(false) .autoDelete(false) .arguments(null) .build()); } catch (IOException e) { throw new RuntimeException(e); } }, executor).thenComposeAsync(action -> { try { return channel.asyncCompletableRpc(new AMQImpl.Queue.Bind.Builder() .queue(queue) .exchange(exchange) .routingKey("") .arguments(null) .build()); } catch (IOException e) { throw new RuntimeException(e); } }, executor).thenAcceptAsync(action -> { try { channel.basicPublish("", queue, null, "dummy".getBytes()); } catch (IOException e) { throw new RuntimeException(e); } }, executor).thenAcceptAsync((whatever) -> { try { channel.basicConsume(queue, true, new DefaultConsumer(channel) { @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { latch.countDown(); } }); } catch (IOException e) { throw new RuntimeException(e); } }, executor); channel.waitForConfirmsOrDie(1000); assertTrue(latch.await(2, TimeUnit.SECONDS)); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/ChannelNumberAllocationTests.java000066400000000000000000000077131316117667700334570ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test; import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; import com.rabbitmq.client.ConnectionFactory; import org.junit.After; import org.junit.Before; import org.junit.Test; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import static org.junit.Assert.*; public class ChannelNumberAllocationTests { static final int CHANNEL_COUNT = 100; static final Comparator COMPARATOR = new Comparator(){ public int compare(Channel x, Channel y){ if(x.getChannelNumber() < y.getChannelNumber()) return -1; if(x.getChannelNumber() == y.getChannelNumber()) return 0; return 1; } }; Connection connection; @Before public void setUp() throws Exception{ connection = TestUtils.connectionFactory().newConnection(); } @After public void tearDown() throws Exception{ connection.close(); connection = null; } @Test public void allocateInOrder() throws Exception{ for(int i = 1; i <= CHANNEL_COUNT; i++) assertEquals(i, connection.createChannel().getChannelNumber()); } @Test public void allocateAfterFreeingLast() throws Exception{ Channel ch = connection.createChannel(); assertEquals(1, ch.getChannelNumber()); ch.close(); ch = connection.createChannel(); assertEquals(1, ch.getChannelNumber()); } @Test public void allocateAfterFreeingMany() throws Exception{ List channels = new ArrayList(); for(int i = 1; i <= CHANNEL_COUNT; i++) channels.add(connection.createChannel()); for(Channel channel : channels){ channel.close(); } channels = new ArrayList(); for(int i = 1; i <= CHANNEL_COUNT; i++) channels.add(connection.createChannel()); // In the current implementation the allocated numbers need not be increasing Collections.sort(channels, COMPARATOR); assertEquals("Didn't create the right number of channels!", CHANNEL_COUNT, channels.size()); for(int i = 1; i < CHANNEL_COUNT; ++i) { assertTrue("Channel numbers should be distinct." , channels.get(i-1).getChannelNumber() < channels.get(i).getChannelNumber() ); } } @Test public void allocateAfterManualAssign() throws Exception{ connection.createChannel(10); for(int i = 0; i < 20; i++) assertTrue(10 != connection.createChannel().getChannelNumber()); } @Test public void manualAllocationDoesntBreakThings() throws Exception{ connection.createChannel((1 << 16) - 1); Channel ch = connection.createChannel(); assertNotNull(ch); } @Test public void reuseManuallyAllocatedChannelNumber1() throws Exception{ connection.createChannel(1).close(); assertNotNull(connection.createChannel(1)); } @Test public void reuseManuallyAllocatedChannelNumber2() throws Exception{ connection.createChannel(2).close(); assertNotNull(connection.createChannel(3)); } @Test public void reserveOnBoundaries() throws Exception{ assertNotNull(connection.createChannel(3)); assertNotNull(connection.createChannel(4)); assertNotNull(connection.createChannel(2)); assertNotNull(connection.createChannel(5)); assertNotNull(connection.createChannel(1)); } } ChannelRpcTimeoutIntegrationTest.java000066400000000000000000000121041316117667700342440ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test; import com.rabbitmq.client.*; import com.rabbitmq.client.impl.*; import org.junit.After; import org.junit.Before; import org.junit.Test; import javax.net.SocketFactory; import java.io.IOException; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeoutException; import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; public class ChannelRpcTimeoutIntegrationTest { static long waitTimeOnSomeResponses = 1000L; ConnectionFactory factory; @Before public void setUp() throws Exception { factory = TestUtils.connectionFactory(); } @After public void tearDown() throws Exception { factory = null; } @Test public void channelWaitsWhenNoTimeoutSet() throws IOException, TimeoutException { FrameHandler frameHandler = createFrameHandler(); ConnectionParams params = factory.params(Executors.newFixedThreadPool(1)); WaitingAmqConnection connection = new WaitingAmqConnection(params, frameHandler); try { connection.start(); Channel channel = connection.createChannel(); channel.queueDeclare(); } finally { connection.close(); } } @Test public void channelThrowsExceptionWhenTimeoutIsSet() throws IOException, TimeoutException { FrameHandler frameHandler = createFrameHandler(); ConnectionParams params = factory.params(Executors.newFixedThreadPool(1)); params.setChannelRpcTimeout((int) (waitTimeOnSomeResponses / 5.0)); WaitingAmqConnection connection = new WaitingAmqConnection(params, frameHandler); try { connection.start(); Channel channel = connection.createChannel(); try { channel.queueDeclare(); fail("Should time out and throw an exception"); } catch(ChannelContinuationTimeoutException e) { // OK assertThat((Channel) e.getChannel(), is(channel)); assertThat(e.getChannelNumber(), is(channel.getChannelNumber())); assertThat(e.getMethod(), instanceOf(AMQP.Queue.Declare.class)); } } finally { connection.close(); } } private FrameHandler createFrameHandler() throws IOException { SocketFrameHandlerFactory socketFrameHandlerFactory = new SocketFrameHandlerFactory(ConnectionFactory.DEFAULT_CONNECTION_TIMEOUT, SocketFactory.getDefault(), new DefaultSocketConfigurator(), false, null); return socketFrameHandlerFactory.create(new Address("localhost"), null); } static class WaitingChannel extends ChannelN { public WaitingChannel(AMQConnection connection, int channelNumber, ConsumerWorkService workService) { super(connection, channelNumber, workService); } @Override public void handleCompleteInboundCommand(AMQCommand command) throws IOException { if(command.getMethod() instanceof AMQImpl.Queue.DeclareOk) { try { Thread.sleep(waitTimeOnSomeResponses); } catch (InterruptedException e) { throw new IOException(e); } } super.handleCompleteInboundCommand(command); } } static class WaitingChannelManager extends ChannelManager { public WaitingChannelManager(ConsumerWorkService workService, int channelMax, ThreadFactory threadFactory) { super(workService, channelMax, threadFactory); } @Override protected ChannelN instantiateChannel(AMQConnection connection, int channelNumber, ConsumerWorkService workService) { return new WaitingChannel(connection, channelNumber, workService); } } static class WaitingAmqConnection extends AMQConnection { public WaitingAmqConnection(ConnectionParams params, FrameHandler frameHandler) { super(params, frameHandler); } @Override protected ChannelManager instantiateChannelManager(int channelMax, ThreadFactory threadFactory) { WaitingChannelManager channelManager = new WaitingChannelManager(_workService, channelMax, threadFactory); configureChannelManager(channelManager); return channelManager; } } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/ClientTests.java000066400000000000000000000037311316117667700301420ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test; import com.rabbitmq.utility.IntAllocatorTests; import org.junit.runner.RunWith; import org.junit.runners.Suite; @RunWith(Suite.class) @Suite.SuiteClasses({ TableTest.class, LongStringTest.class, BlockingCellTest.class, TruncatedInputStreamTest.class, AMQConnectionTest.class, AMQChannelTest.class, ChannelRpcTimeoutIntegrationTest.class, ValueOrExceptionTest.class, BrokenFramesTest.class, ClonePropertiesTest.class, Bug20004Test.class, CloseInMainLoop.class, ChannelNumberAllocationTests.class, QueueingConsumerTests.class, MultiThreadedChannel.class, IntAllocatorTests.class, AMQBuilderApiTest.class, AmqpUriTest.class, JSONReadWriteTest.class, SharedThreadPoolTest.class, DnsRecordIpAddressResolverTests.class, StandardMetricsCollectorTest.class, DnsSrvRecordAddressResolverTest.class, JavaNioTest.class, ConnectionFactoryTest.class, RecoveryAwareAMQConnectionFactoryTest.class, RpcTest.class, SslContextFactoryTest.class, LambdaCallbackTest.class, ChannelAsyncCompletableFutureTest.class }) public class ClientTests { // initialize system properties static{ new AbstractRMQTestSuite(){}; } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/ClonePropertiesTest.java000066400000000000000000000032701316117667700316540ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test; import com.rabbitmq.client.AMQP.BasicProperties; import com.rabbitmq.client.MessageProperties; import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; public class ClonePropertiesTest { @Test public void propertyCloneIsDistinct() throws CloneNotSupportedException { assertTrue(MessageProperties.MINIMAL_PERSISTENT_BASIC != MessageProperties.MINIMAL_PERSISTENT_BASIC.clone()); } @Test public void propertyClonePreservesValues() throws CloneNotSupportedException { assertEquals(MessageProperties.MINIMAL_PERSISTENT_BASIC.getDeliveryMode(), ((BasicProperties) MessageProperties.MINIMAL_PERSISTENT_BASIC.clone()) .getDeliveryMode()); assertEquals(Integer.valueOf(2), ((BasicProperties) MessageProperties.MINIMAL_PERSISTENT_BASIC.clone()) .getDeliveryMode()); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/CloseInMainLoop.java000066400000000000000000000115471316117667700307000ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test; import static org.junit.Assert.assertTrue; import java.io.IOException; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import javax.net.SocketFactory; import org.junit.Test; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.Channel; import com.rabbitmq.client.Command; import com.rabbitmq.client.ConnectionFactory; import com.rabbitmq.client.Consumer; import com.rabbitmq.client.DefaultConsumer; import com.rabbitmq.client.Envelope; import com.rabbitmq.client.impl.AMQConnection; import com.rabbitmq.client.impl.DefaultExceptionHandler; import com.rabbitmq.client.impl.SocketFrameHandler; public class CloseInMainLoop extends BrokerTestCase{ private final CountDownLatch closeLatch = new CountDownLatch(1); private ConnectionFactory specialConnectionFactory() { ConnectionFactory f = TestUtils.connectionFactory(); f.setExceptionHandler(new DefaultExceptionHandler(){ @Override public void handleConsumerException(Channel channel, Throwable exception, Consumer consumer, String consumerTag, String methodName) { try { // TODO: change this to call 4-parameter close and make 6-parm one private ((AMQConnection) channel.getConnection()) .close(AMQP.INTERNAL_ERROR, "Internal error in Consumer " + consumerTag, false, exception, -1, false); } catch (Throwable e) { // Man, this clearly isn't our day. // TODO: Log the nested failure } finally { closeLatch.countDown(); } } }); return f; } class SpecialConnection extends AMQConnection{ private final AtomicBoolean validShutdown = new AtomicBoolean(false); public boolean hadValidShutdown(){ if(isOpen()) throw new IllegalStateException("hadValidShutdown called while connection is still open"); return validShutdown.get(); } public SpecialConnection() throws Exception { super(specialConnectionFactory().params(Executors.newFixedThreadPool(1)), new SocketFrameHandler(SocketFactory.getDefault().createSocket("localhost", AMQP.PROTOCOL.PORT))); this.start(); } @Override public boolean processControlCommand(Command c) throws IOException{ if(c.getMethod() instanceof AMQP.Connection.CloseOk) validShutdown.set(true); return super.processControlCommand(c); } } @Test public void closeOKNormallyReceived() throws Exception{ SpecialConnection connection = new SpecialConnection(); connection.close(); assertTrue(connection.hadValidShutdown()); } // The thrown runtime exception should get intercepted by the // consumer exception handler, and result in a clean shut down. @Test public void closeWithFaultyConsumer() throws Exception{ SpecialConnection connection = new SpecialConnection(); Channel channel = connection.createChannel(); channel.exchangeDeclare("x", "direct"); channel.queueDeclare("q", false, false, false, null); channel.queueBind("q", "x", "k"); channel.basicConsume("q", true, new DefaultConsumer(channel){ @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) { throw new RuntimeException("I am a bad consumer"); } }); channel.basicPublish("x", "k", null, new byte[10]); assertTrue(closeLatch.await(1000, TimeUnit.MILLISECONDS)); assertTrue(connection.hadValidShutdown()); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/ConfirmBase.java000066400000000000000000000046111316117667700300670ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test; import static org.junit.Assert.fail; import java.io.IOException; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executors; import java.util.concurrent.FutureTask; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import com.rabbitmq.client.ShutdownSignalException; import junit.framework.AssertionFailedError; public class ConfirmBase extends BrokerTestCase { protected void waitForConfirms() throws Exception { waitForConfirms("ConfirmBase.waitForConfirms"); } protected void waitForConfirms(final String testTitle) throws Exception { try { FutureTask waiter = new FutureTask(new Runnable() { public void run() { try { channel.waitForConfirmsOrDie(); } catch (IOException e) { throw (ShutdownSignalException)e.getCause(); } catch (InterruptedException _e) { fail(testTitle + ": interrupted"); } } }, null); (Executors.newSingleThreadExecutor()).execute(waiter); waiter.get(10, TimeUnit.SECONDS); } catch (ExecutionException ee) { Throwable t = ee.getCause(); if (t instanceof ShutdownSignalException) throw (ShutdownSignalException) t; if (t instanceof AssertionFailedError) throw (AssertionFailedError) t; throw (Exception)t; } catch (TimeoutException _e) { fail(testTitle + ": timeout"); } } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/ConnectionFactoryTest.java000066400000000000000000000055211316117667700321670ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test; import com.rabbitmq.client.Address; import com.rabbitmq.client.Connection; import com.rabbitmq.client.ConnectionFactory; import com.rabbitmq.client.MetricsCollector; import com.rabbitmq.client.impl.AMQConnection; import com.rabbitmq.client.impl.ConnectionParams; import com.rabbitmq.client.impl.FrameHandler; import com.rabbitmq.client.impl.FrameHandlerFactory; import org.junit.Test; import java.io.IOException; import java.util.Queue; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.TimeoutException; import static org.junit.Assert.assertSame; import static org.mockito.Mockito.*; public class ConnectionFactoryTest { // see https://github.com/rabbitmq/rabbitmq-java-client/issues/262 @Test public void tryNextAddressIfTimeoutExceptionNoAutoRecovery() throws IOException, TimeoutException { final AMQConnection connectionThatThrowsTimeout = mock(AMQConnection.class); final AMQConnection connectionThatSucceeds = mock(AMQConnection.class); final Queue connections = new ArrayBlockingQueue(10); connections.add(connectionThatThrowsTimeout); connections.add(connectionThatSucceeds); ConnectionFactory connectionFactory = new ConnectionFactory() { @Override protected AMQConnection createConnection(ConnectionParams params, FrameHandler frameHandler, MetricsCollector metricsCollector) { return connections.poll(); } @Override protected synchronized FrameHandlerFactory createFrameHandlerFactory() throws IOException { return mock(FrameHandlerFactory.class); } }; connectionFactory.setAutomaticRecoveryEnabled(false); doThrow(TimeoutException.class).when(connectionThatThrowsTimeout).start(); doNothing().when(connectionThatSucceeds).start(); Connection returnedConnection = connectionFactory.newConnection( new Address[] { new Address("host1"), new Address("host2") } ); assertSame(connectionThatSucceeds, returnedConnection); } } DnsRecordIpAddressResolverTests.java000066400000000000000000000033741316117667700340540ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/testpackage com.rabbitmq.client.test; import com.rabbitmq.client.Connection; import com.rabbitmq.client.ConnectionFactory; import com.rabbitmq.client.DnsRecordIpAddressResolver; import org.junit.Test; import java.io.IOException; import java.net.UnknownHostException; import java.util.concurrent.TimeoutException; import static org.junit.Assert.fail; /** * */ public class DnsRecordIpAddressResolverTests extends BrokerTestCase { @Test public void localhostResolution() throws IOException, TimeoutException { DnsRecordIpAddressResolver addressResolver = new DnsRecordIpAddressResolver("localhost"); ConnectionFactory connectionFactory = newConnectionFactory(); Connection connection = connectionFactory.newConnection(addressResolver); try { connection.createChannel(); } finally { connection.abort(); } } @Test public void loopbackInterfaceResolution() throws IOException, TimeoutException { DnsRecordIpAddressResolver addressResolver = new DnsRecordIpAddressResolver("127.0.0.1"); ConnectionFactory connectionFactory = newConnectionFactory(); Connection connection = connectionFactory.newConnection(addressResolver); try { connection.createChannel(); } finally { connection.abort(); } } @Test public void resolutionFails() throws IOException, TimeoutException { DnsRecordIpAddressResolver addressResolver = new DnsRecordIpAddressResolver( "afancyandunlikelyhostname" ); try { connectionFactory.newConnection(addressResolver); fail("The host resolution should have failed"); } catch (UnknownHostException e) { // expected } } } DnsSrvRecordAddressResolverTest.java000066400000000000000000000051061316117667700340660ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test; import com.rabbitmq.client.Address; import com.rabbitmq.client.DnsSrvRecordAddressResolver; import org.junit.Test; import java.io.IOException; import java.util.Arrays; import java.util.List; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; /** * */ public class DnsSrvRecordAddressResolverTest { @Test public void recordsParsedAndSorted() throws IOException { DnsSrvRecordAddressResolver resolver = new DnsSrvRecordAddressResolver("rabbitmq") { @Override protected List lookupSrvRecords(String service, String dnsUrls) throws IOException { return Arrays.asList( DnsSrvRecordAddressResolver.SrvRecord.fromSrvQueryResult("20 0 5269 alt2.xmpp-server.l.google.com."), DnsSrvRecordAddressResolver.SrvRecord.fromSrvQueryResult("30 0 5269 alt3.xmpp-server.l.google.com."), DnsSrvRecordAddressResolver.SrvRecord.fromSrvQueryResult("10 0 5269 alt1.xmpp-server.l.google.com."), DnsSrvRecordAddressResolver.SrvRecord.fromSrvQueryResult("50 0 5269 alt5.xmpp-server.l.google.com."), DnsSrvRecordAddressResolver.SrvRecord.fromSrvQueryResult("40 0 5269 alt4.xmpp-server.l.google.com.") ); } }; List
addresses = resolver.getAddresses(); assertThat(addresses.size(), is(5)); assertThat(addresses.get(0).getHost(), is("alt1.xmpp-server.l.google.com")); assertThat(addresses.get(1).getHost(), is("alt2.xmpp-server.l.google.com")); assertThat(addresses.get(2).getHost(), is("alt3.xmpp-server.l.google.com")); assertThat(addresses.get(3).getHost(), is("alt4.xmpp-server.l.google.com")); assertThat(addresses.get(4).getHost(), is("alt5.xmpp-server.l.google.com")); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/FrameTest.java000066400000000000000000000153071316117667700275750ustar00rootroot00000000000000package com.rabbitmq.client.test; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.impl.Frame; import com.rabbitmq.client.impl.nio.ByteBufferInputStream; import com.rabbitmq.client.impl.nio.ByteBufferOutputStream; import org.junit.Test; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.ReadableByteChannel; import java.nio.channels.WritableByteChannel; import java.util.*; import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; /** * */ public class FrameTest { @Test public void readFrames() throws IOException { Random random = new Random(); int nbOfFrames = 100; AccumulatorReadableByteChannel channel = new AccumulatorReadableByteChannel(); for(int i = 0; i < nbOfFrames; i++) { byte[] payload = new byte[random.nextInt(2000) + 1]; Frame frame = new Frame(AMQP.FRAME_METHOD, 1, payload); channel.add(frame); } ByteBuffer buffer = ByteBuffer.allocate(8192); DataInputStream inputStream = new DataInputStream( new ByteBufferInputStream(channel, buffer) ); int nbReadFrames = 0; channel.read(buffer); buffer.flip(); while(buffer.hasRemaining()) { Frame.readFrom(inputStream); nbReadFrames++; if(!buffer.hasRemaining()) { buffer.clear(); channel.read(buffer); buffer.flip(); } } assertThat(nbReadFrames, equalTo(nbOfFrames)); } @Test public void readLargeFrame() throws IOException { AccumulatorReadableByteChannel channel = new AccumulatorReadableByteChannel(); int [] framesSize = new int [] {100, 75, 20000, 150}; for (int frameSize : framesSize) { Frame frame = new Frame(AMQP.FRAME_METHOD, 1, new byte[frameSize]); channel.add(frame); } ByteBuffer buffer = ByteBuffer.allocate(8192); DataInputStream inputStream = new DataInputStream( new ByteBufferInputStream(channel, buffer) ); int nbReadFrames = 0; channel.read(buffer); buffer.flip(); while(buffer.hasRemaining()) { Frame.readFrom(inputStream); nbReadFrames++; if(!buffer.hasRemaining()) { buffer.clear(); channel.read(buffer); buffer.flip(); } } assertThat(nbReadFrames, equalTo(framesSize.length)); } @Test public void writeFrames() throws IOException { List frames = new ArrayList(); Random random = new Random(); int totalFrameSize = 0; for(int i = 0; i < 100; i++) { byte[] payload = new byte[random.nextInt(2000) + 1]; Frame frame = new Frame(AMQP.FRAME_METHOD, 1, payload); frames.add(frame); totalFrameSize += frame.size(); } AccumulatorWritableByteChannel channel = new AccumulatorWritableByteChannel(); ByteBuffer buffer = ByteBuffer.allocate(8192); for (Frame frame : frames) { frame.writeTo(new DataOutputStream(new ByteBufferOutputStream(channel, buffer))); } drain(channel, buffer); checkWrittenChunks(totalFrameSize, channel); } @Test public void writeLargeFrame() throws IOException { List frames = new ArrayList(); int totalFrameSize = 0; int [] framesSize = new int [] {100, 75, 20000, 150}; for (int frameSize : framesSize) { Frame frame = new Frame(AMQP.FRAME_METHOD, 1, new byte[frameSize]); frames.add(frame); totalFrameSize += frame.size(); } AccumulatorWritableByteChannel channel = new AccumulatorWritableByteChannel(); ByteBuffer buffer = ByteBuffer.allocate(8192); for (Frame frame : frames) { frame.writeTo(new DataOutputStream(new ByteBufferOutputStream(channel, buffer))); } drain(channel, buffer); checkWrittenChunks(totalFrameSize, channel); } private void checkWrittenChunks(int totalFrameSize, AccumulatorWritableByteChannel channel) { int totalWritten = 0; for (byte[] chunk : channel.chunks) { totalWritten += chunk.length; } assertThat(totalWritten, equalTo(totalFrameSize)); } private static class AccumulatorWritableByteChannel implements WritableByteChannel { List chunks = new ArrayList(); Random random = new Random(); @Override public int write(ByteBuffer src) throws IOException { int remaining = src.remaining(); if(remaining > 0) { int toRead = random.nextInt(remaining) + 1; byte [] chunk = new byte[toRead]; src.get(chunk); chunks.add(chunk); return toRead; } else { return remaining; } } @Override public boolean isOpen() { return false; } @Override public void close() throws IOException { } } private static class AccumulatorReadableByteChannel implements ReadableByteChannel { private List bytesOfFrames = new LinkedList(); @Override public int read(ByteBuffer dst) throws IOException { int remaining = dst.remaining(); int read = 0; if(remaining > 0) { Iterator iterator = bytesOfFrames.iterator(); while(iterator.hasNext() && read < remaining) { dst.put(iterator.next()); iterator.remove(); read++; } } return read; } @Override public boolean isOpen() { return false; } @Override public void close() throws IOException { } void add(Frame frame) throws IOException { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(frame.size()); DataOutputStream outputStream = new DataOutputStream(byteArrayOutputStream); frame.writeTo(outputStream); outputStream.flush(); for (byte b : byteArrayOutputStream.toByteArray()) { bytesOfFrames.add(b); } } } public static void drain(WritableByteChannel channel, ByteBuffer buffer) throws IOException { buffer.flip(); while(buffer.hasRemaining() && channel.write(buffer) != -1); buffer.clear(); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/JSONReadWriteTest.java000066400000000000000000000075111316117667700311210ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test; import com.rabbitmq.tools.json.JSONReader; import com.rabbitmq.tools.json.JSONWriter; import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; public class JSONReadWriteTest { @Test public void readWriteSimple() throws Exception { Object myRet; String myJson; // simple string myRet = new JSONReader().read(myJson = new JSONWriter().write("blah")); assertEquals("blah", myRet); // simple int myRet = new JSONReader().read(myJson = new JSONWriter().write(1)); assertEquals(1, myRet); // string with double quotes myRet = new JSONReader().read(myJson = new JSONWriter().write("t1-blah\"blah")); assertEquals("t1-blah\"blah", myRet); // string with single quotes myRet = new JSONReader().read(myJson = new JSONWriter().write("t2-blah'blah")); assertEquals("t2-blah'blah", myRet); // string with two double quotes myRet = new JSONReader().read(myJson = new JSONWriter().write("t3-blah\"n\"blah")); assertEquals("t3-blah\"n\"blah", myRet); // string with two single quotes myRet = new JSONReader().read(myJson = new JSONWriter().write("t4-blah'n'blah")); assertEquals("t4-blah'n'blah", myRet); // string with a single and a double quote myRet = new JSONReader().read(myJson = new JSONWriter().write("t4-blah'n\"blah")); assertEquals("t4-blah'n\"blah", myRet); // UTF-8 character myRet = new JSONReader().read(myJson = new JSONWriter().write("smile \u9786")); assertEquals("smile \u9786", myRet); // null byte myRet = new JSONReader().read(myJson = new JSONWriter().write("smile \u0000")); assertEquals("smile \u0000", myRet); } @Test public void moreComplicated() throws Exception { String v, s; Object t; s = "[\"foo\",{\"bar\":[\"baz\",null,1.0,2]}]"; v = new JSONWriter().write(new JSONReader().read(s)); assertEquals(s, v); s = "[\"foo\",{\"bar\":[\"b\\\"az\",null,1.0,2]}]"; t = new JSONReader().read(s); v = new JSONWriter().write(t); assertEquals(s, v); s = "[\"foo\",{\"bar\":[\"b'az\",null,1.0,2]}]"; v = new JSONWriter().write(new JSONReader().read(s)); assertEquals(s, v); s = "[\"foo\",{\"bar\":[\"b'a'z\",null,1.0,2]}]"; v = new JSONWriter().write(new JSONReader().read(s)); assertEquals(s, v); s = "[\"foo\",{\"bar\":[\"b\\\"a\\\"z\",null,1.0,2]}]"; v = new JSONWriter().write(new JSONReader().read(s)); assertEquals(s, v); } @Test public void badJSON() throws Exception { try { new JSONReader().read("[\"foo\",{\"bar\":[\"b\"az\",null,1.0,2]}]"); fail("Should not have parsed"); } catch (IllegalStateException e) {} try { new JSONReader().read("[\"foo\",{\"bar\":[\"b\"a\"z\",null,1.0,2]}]"); fail("Should not have parsed"); } catch (IllegalStateException e) {} } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/JavaNioTest.java000066400000000000000000000114331316117667700300660ustar00rootroot00000000000000package com.rabbitmq.client.test; import com.rabbitmq.client.*; import com.rabbitmq.client.impl.nio.NioParams; import org.junit.Test; import java.io.IOException; import java.util.concurrent.*; import static org.junit.Assert.assertTrue; /** * */ public class JavaNioTest { @Test public void connection() throws Exception { CountDownLatch latch = new CountDownLatch(1); ConnectionFactory connectionFactory = new ConnectionFactory(); connectionFactory.useNio(); Connection connection = null; try { connection = basicGetBasicConsume(connectionFactory, "nio.queue", latch); boolean messagesReceived = latch.await(5, TimeUnit.SECONDS); assertTrue("Message has not been received", messagesReceived); } finally { safeClose(connection); } } @Test public void twoConnections() throws IOException, TimeoutException, InterruptedException { CountDownLatch latch = new CountDownLatch(2); ConnectionFactory connectionFactory = new ConnectionFactory(); connectionFactory.useNio(); connectionFactory.setNioParams(new NioParams().setNbIoThreads(4)); Connection connection1 = null; Connection connection2 = null; try { connection1 = basicGetBasicConsume(connectionFactory, "nio.queue.1", latch); connection2 = basicGetBasicConsume(connectionFactory, "nio.queue.2", latch); boolean messagesReceived = latch.await(5, TimeUnit.SECONDS); assertTrue("Messages have not been received", messagesReceived); } finally { safeClose(connection1); safeClose(connection2); } } @Test public void twoConnectionsWithNioExecutor() throws IOException, TimeoutException, InterruptedException { CountDownLatch latch = new CountDownLatch(2); ExecutorService nioExecutor = Executors.newFixedThreadPool(5); ConnectionFactory connectionFactory = new ConnectionFactory(); connectionFactory.useNio(); Connection connection1 = null; Connection connection2 = null; try { connection1 = basicGetBasicConsume(connectionFactory, "nio.queue.1", latch); connection2 = basicGetBasicConsume(connectionFactory, "nio.queue.2", latch); boolean messagesReceived = latch.await(5, TimeUnit.SECONDS); assertTrue("Messages have not been received", messagesReceived); } finally { safeClose(connection1); safeClose(connection2); nioExecutor.shutdownNow(); } } @Test public void shutdownListenerCalled() throws IOException, TimeoutException, InterruptedException { ConnectionFactory connectionFactory = new ConnectionFactory(); connectionFactory.useNio(); Connection connection = connectionFactory.newConnection(); try { final CountDownLatch latch = new CountDownLatch(1); connection.addShutdownListener(new ShutdownListener() { @Override public void shutdownCompleted(ShutdownSignalException cause) { latch.countDown(); } }); safeClose(connection); assertTrue("Shutdown listener should have been called", latch.await(5, TimeUnit.SECONDS)); } finally { safeClose(connection); } } @Test public void nioLoopCleaning() throws Exception { ConnectionFactory connectionFactory = new ConnectionFactory(); connectionFactory.useNio(); for(int i = 0; i < 10; i++) { Connection connection = connectionFactory.newConnection(); connection.abort(); } } private Connection basicGetBasicConsume(ConnectionFactory connectionFactory, String queue, final CountDownLatch latch) throws IOException, TimeoutException { Connection connection = connectionFactory.newConnection(); Channel channel = connection.createChannel(); channel.queueDeclare(queue, false, false, false, null); channel.queuePurge(queue); channel.basicPublish("", queue, null, new byte[20000]); channel.basicConsume(queue, false, new DefaultConsumer(channel) { @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { getChannel().basicAck(envelope.getDeliveryTag(), false); latch.countDown(); } }); return connection; } private void safeClose(Connection connection) { if (connection != null) { try { connection.abort(); } catch (Exception e) { // OK } } } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/LambdaCallbackTest.java000066400000000000000000000147151316117667700313420ustar00rootroot00000000000000// Copyright (c) 2017 Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test; import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; import org.junit.Test; import java.io.IOException; import java.util.UUID; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import static org.junit.Assert.assertTrue; public class LambdaCallbackTest extends BrokerTestCase { String queue; @Override protected void createResources() throws IOException, TimeoutException { queue = channel.queueDeclare(UUID.randomUUID().toString(), true, false, false, null).getQueue(); } @Override protected void releaseResources() throws IOException { channel.queueDelete(queue); try { unblock(); } catch (InterruptedException e) { e.printStackTrace(); } } @Test public void shutdownListener() throws Exception { CountDownLatch latch = new CountDownLatch(2); try(Connection connection = TestUtils.connectionFactory().newConnection()) { connection.addShutdownListener(cause -> latch.countDown()); Channel channel = connection.createChannel(); channel.addShutdownListener(cause -> latch.countDown()); } assertTrue("Connection closed, shutdown listeners should have been called", latch.await(1, TimeUnit.SECONDS)); } @Test public void confirmListener() throws Exception { channel.confirmSelect(); CountDownLatch latch = new CountDownLatch(1); channel.addConfirmListener( (deliveryTag, multiple) -> latch.countDown(), (deliveryTag, multiple) -> {} ); channel.basicPublish("", "whatever", null, "dummy".getBytes()); assertTrue("Should have received publisher confirm", latch.await(1, TimeUnit.SECONDS)); } @Test public void returnListener() throws Exception { CountDownLatch latch = new CountDownLatch(1); channel.addReturnListener(returnMessage -> latch.countDown()); channel.basicPublish("", "notlikelytoexist", true, null, "dummy".getBytes()); assertTrue("Should have received returned message", latch.await(1, TimeUnit.SECONDS)); } @Test public void blockedListener() throws Exception { final CountDownLatch latch = new CountDownLatch(1); try(Connection connection = TestUtils.connectionFactory().newConnection()) { connection.addBlockedListener( reason -> { try { unblock(); } catch (InterruptedException e) { e.printStackTrace(); } }, () -> latch.countDown() ); block(); Channel ch = connection.createChannel(); ch.basicPublish("", "", null, "dummy".getBytes()); assertTrue("Should have been blocked and unblocked", latch.await(10, TimeUnit.SECONDS)); } } @Test public void basicConsumeDeliverCancel() throws Exception { try(Connection connection = TestUtils.connectionFactory().newConnection()) { final CountDownLatch consumingLatch = new CountDownLatch(1); final CountDownLatch cancelLatch = new CountDownLatch(1); Channel consumingChannel = connection.createChannel(); consumingChannel.basicConsume(queue, true, (consumerTag, delivery) -> consumingLatch.countDown(), consumerTag -> cancelLatch.countDown() ); this.channel.basicPublish("", queue, null, "dummy".getBytes()); assertTrue("deliver callback should have been called", consumingLatch.await(1, TimeUnit.SECONDS)); this.channel.queueDelete(queue); assertTrue("cancel callback should have been called", cancelLatch.await(1, TimeUnit.SECONDS)); } } @Test public void basicConsumeDeliverShutdown() throws Exception { final CountDownLatch shutdownLatch = new CountDownLatch(1); try(Connection connection = TestUtils.connectionFactory().newConnection()) { final CountDownLatch consumingLatch = new CountDownLatch(1); Channel consumingChannel = connection.createChannel(); consumingChannel.basicConsume(queue, true, (consumerTag, delivery) -> consumingLatch.countDown(), (consumerTag, sig) -> shutdownLatch.countDown() ); this.channel.basicPublish("", queue, null, "dummy".getBytes()); assertTrue("deliver callback should have been called", consumingLatch.await(1, TimeUnit.SECONDS)); } assertTrue("shutdown callback should have been called", shutdownLatch.await(1, TimeUnit.SECONDS)); } @Test public void basicConsumeCancelDeliverShutdown() throws Exception { final CountDownLatch shutdownLatch = new CountDownLatch(1); try(Connection connection = TestUtils.connectionFactory().newConnection()) { final CountDownLatch consumingLatch = new CountDownLatch(1); Channel consumingChannel = connection.createChannel(); // not both cancel and shutdown callback can be called on the same consumer // testing just shutdown consumingChannel.basicConsume(queue, true, (consumerTag, delivery) -> consumingLatch.countDown(), (consumerTag) -> { }, (consumerTag, sig) -> shutdownLatch.countDown() ); this.channel.basicPublish("", queue, null, "dummy".getBytes()); assertTrue("deliver callback should have been called", consumingLatch.await(1, TimeUnit.SECONDS)); } assertTrue("shutdown callback should have been called", shutdownLatch.await(1, TimeUnit.SECONDS)); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/LongStringTest.java000066400000000000000000000024211316117667700306220ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test; import com.rabbitmq.client.LongString; import com.rabbitmq.client.impl.LongStringHelper; import org.junit.Test; import java.io.UnsupportedEncodingException; import static org.junit.Assert.assertTrue; public class LongStringTest { @Test public void testToString() throws UnsupportedEncodingException { String s = "abcdef"; LongString ls = LongStringHelper.asLongString(s); assertTrue(ls.toString().equals(s)); assertTrue(ls.toString().equals(new String(ls.getBytes(), "UTF-8"))); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/MultiThreadedChannel.java000066400000000000000000000043731316117667700317300ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test; import java.util.concurrent.atomic.AtomicReference; import org.junit.Test; /** * Tests whether a Channel is safe for multi-threaded access */ public class MultiThreadedChannel extends BrokerTestCase { private static final String DUMMY_QUEUE_NAME = "dummy.queue"; private static final String DUMMY_EXCHANGE_NAME = "dummy.exchange"; @Test public void interleavedRpcs() throws Throwable { final AtomicReference throwableRef = new AtomicReference(null); Thread queueDeclare = new Thread(new Runnable() { public void run() { try { for (int x = 0; x < 100; x++) { channel.queueDeclare(DUMMY_QUEUE_NAME, false, false, true, null); } } catch (Throwable e) { throwableRef.set(e); } } }); Thread exchangeDeclare = new Thread(new Runnable() { public void run() { try { for (int x = 0; x < 100; x++) { channel.exchangeDeclare(DUMMY_EXCHANGE_NAME, "direct"); } } catch (Throwable e) { throwableRef.set(e); } } }); queueDeclare.start(); exchangeDeclare.start(); queueDeclare.join(); exchangeDeclare.join(); Throwable t = throwableRef.get(); if (t != null) { throw t; } } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/QueueingConsumerTests.java000066400000000000000000000065531316117667700322270ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test; import static org.junit.Assert.*; import com.rabbitmq.client.ConsumerCancelledException; import org.junit.Test; import java.io.IOException; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import com.rabbitmq.client.Channel; import com.rabbitmq.client.QueueingConsumer; import com.rabbitmq.client.ShutdownSignalException; public class QueueingConsumerTests extends BrokerTestCase{ static final String QUEUE = "some-queue"; static final int THREADS = 5; @Test public void nThreadShutdown() throws Exception{ Channel channel = connection.createChannel(); final QueueingConsumer c = new QueueingConsumer(channel); channel.queueDeclare(QUEUE, false, true, true, null); channel.basicConsume(QUEUE, c); final AtomicInteger count = new AtomicInteger(THREADS); final CountDownLatch latch = new CountDownLatch(THREADS); for(int i = 0; i < THREADS; i++){ new Thread(){ @Override public void run(){ try { while(true){ c.nextDelivery(); } } catch (ShutdownSignalException sig) { count.decrementAndGet(); } catch (Exception e) { throw new RuntimeException(e); } finally { latch.countDown(); } } }.start(); } connection.close(); // Far longer than this could reasonably take assertTrue(latch.await(5, TimeUnit.SECONDS)); assertEquals(0, count.get()); } @Test public void consumerCancellationInterruptsQueuingConsumerWait() throws IOException, InterruptedException { String queue = "cancel_notification_queue_for_queueing_consumer"; final BlockingQueue result = new ArrayBlockingQueue(1); channel.queueDeclare(queue, false, true, false, null); final QueueingConsumer consumer = new QueueingConsumer(channel); Runnable receiver = new Runnable() { public void run() { try { try { consumer.nextDelivery(); } catch (ConsumerCancelledException e) { result.put(true); return; } catch (ShutdownSignalException e) { } catch (InterruptedException e) { } result.put(false); } catch (InterruptedException e) { fail(); } } }; Thread t = new Thread(receiver); t.start(); channel.basicConsume(queue, consumer); channel.queueDelete(queue); assertTrue(result.take()); t.join(); } } RecoveryAwareAMQConnectionFactoryTest.java000066400000000000000000000057141316117667700351520ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test; import com.rabbitmq.client.Address; import com.rabbitmq.client.AddressResolver; import com.rabbitmq.client.Connection; import com.rabbitmq.client.MetricsCollector; import com.rabbitmq.client.impl.ConnectionParams; import com.rabbitmq.client.impl.FrameHandler; import com.rabbitmq.client.impl.FrameHandlerFactory; import com.rabbitmq.client.impl.recovery.RecoveryAwareAMQConnection; import com.rabbitmq.client.impl.recovery.RecoveryAwareAMQConnectionFactory; import org.junit.Test; import java.io.IOException; import java.util.Arrays; import java.util.List; import java.util.Queue; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.TimeoutException; import static org.junit.Assert.assertSame; import static org.mockito.Mockito.*; public class RecoveryAwareAMQConnectionFactoryTest { // see https://github.com/rabbitmq/rabbitmq-java-client/issues/262 @Test public void tryNextAddressIfTimeoutException() throws IOException, TimeoutException { final RecoveryAwareAMQConnection connectionThatThrowsTimeout = mock(RecoveryAwareAMQConnection.class); final RecoveryAwareAMQConnection connectionThatSucceeds = mock(RecoveryAwareAMQConnection.class); final Queue connections = new ArrayBlockingQueue(10); connections.add(connectionThatThrowsTimeout); connections.add(connectionThatSucceeds); AddressResolver addressResolver = () -> Arrays.asList(new Address("host1"), new Address("host2")); RecoveryAwareAMQConnectionFactory connectionFactory = new RecoveryAwareAMQConnectionFactory( new ConnectionParams(), mock(FrameHandlerFactory.class), addressResolver ) { @Override protected RecoveryAwareAMQConnection createConnection(ConnectionParams params, FrameHandler handler, MetricsCollector metricsCollector) { return connections.poll(); } }; doThrow(TimeoutException.class).when(connectionThatThrowsTimeout).start(); doNothing().when(connectionThatSucceeds).start(); Connection returnedConnection = connectionFactory.newConnection(); assertSame(connectionThatSucceeds, returnedConnection); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/RequiredPropertiesSuite.java000066400000000000000000000024411316117667700325450ustar00rootroot00000000000000package com.rabbitmq.client.test; import org.junit.runner.Runner; import org.junit.runners.Suite; import org.junit.runners.model.InitializationError; import org.junit.runners.model.RunnerBuilder; import java.util.ArrayList; import java.util.List; /** * */ public class RequiredPropertiesSuite extends Suite { public RequiredPropertiesSuite(Class klass, RunnerBuilder builder) throws InitializationError { super(klass, builder); } public RequiredPropertiesSuite(RunnerBuilder builder, Class[] classes) throws InitializationError { super(builder, classes); } protected RequiredPropertiesSuite(Class klass, Class[] suiteClasses) throws InitializationError { super(klass, suiteClasses); } protected RequiredPropertiesSuite(RunnerBuilder builder, Class klass, Class[] suiteClasses) throws InitializationError { super(builder, klass, suiteClasses); } protected RequiredPropertiesSuite(Class klass, List runners) throws InitializationError { super(klass, runners); } @Override protected List getChildren() { if(!AbstractRMQTestSuite.requiredProperties()) { return new ArrayList(); } else { return super.getChildren(); } } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/RpcTest.java000066400000000000000000000074501316117667700272670ustar00rootroot00000000000000// Copyright (c) 2017-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test; import com.rabbitmq.client.*; import org.junit.After; import org.junit.Before; import org.junit.Test; import java.io.IOException; import java.util.HashMap; import java.util.Map; import static org.junit.Assert.assertEquals; public class RpcTest { Connection clientConnection, serverConnection; Channel clientChannel, serverChannel; String queue = "rpc.queue"; RpcServer rpcServer; @Before public void init() throws Exception { clientConnection = TestUtils.connectionFactory().newConnection(); clientChannel = clientConnection.createChannel(); serverConnection = TestUtils.connectionFactory().newConnection(); serverChannel = serverConnection.createChannel(); serverChannel.queueDeclare(queue, false, false, false, null); } @After public void tearDown() throws Exception { if(rpcServer != null) { rpcServer.terminateMainloop(); } if(serverChannel != null) { serverChannel.queueDelete(queue); } TestUtils.close(clientConnection); TestUtils.close(serverConnection); } @Test public void rpc() throws Exception { rpcServer = new TestRpcServer(serverChannel, queue); new Thread(() -> { try { rpcServer.mainloop(); } catch (Exception e) { // safe to ignore when loops ends/server is canceled } }).start(); RpcClient client = new RpcClient(clientChannel, "", queue, 1000); RpcClient.Response response = client.doCall(null, "hello".getBytes()); assertEquals("*** hello ***", new String(response.getBody())); assertEquals("pre-hello", response.getProperties().getHeaders().get("pre").toString()); assertEquals("post-hello", response.getProperties().getHeaders().get("post").toString()); client.close(); } private static class TestRpcServer extends RpcServer { public TestRpcServer(Channel channel, String queueName) throws IOException { super(channel, queueName); } @Override protected AMQP.BasicProperties preprocessReplyProperties(Delivery request, AMQP.BasicProperties.Builder builder) { Map headers = new HashMap(); headers.put("pre", "pre-" + new String(request.getBody())); builder.headers(headers); return builder.build(); } @Override public byte[] handleCall(Delivery request, AMQP.BasicProperties replyProperties) { String input = new String(request.getBody()); return ("*** " + input + " ***").getBytes(); } @Override protected AMQP.BasicProperties postprocessReplyProperties(Delivery request, AMQP.BasicProperties.Builder builder) { Map headers = new HashMap(builder.build().getHeaders()); headers.put("post", "post-" + new String(request.getBody())); builder.headers(headers); return builder.build(); } } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/SharedThreadPoolTest.java000066400000000000000000000040551316117667700317310ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import java.io.IOException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeoutException; import org.junit.Test; import com.rabbitmq.client.ConnectionFactory; import com.rabbitmq.client.impl.AMQConnection; public class SharedThreadPoolTest extends BrokerTestCase { @Test public void willShutDownExecutor() throws IOException, TimeoutException { ConnectionFactory cf = TestUtils.connectionFactory(); cf.setAutomaticRecoveryEnabled(false); ExecutorService executor = Executors.newFixedThreadPool(8); cf.setSharedExecutor(executor); AMQConnection conn1 = (AMQConnection)cf.newConnection(); assertFalse(conn1.willShutDownConsumerExecutor()); AMQConnection conn2 = (AMQConnection)cf.newConnection(Executors.newSingleThreadExecutor()); assertFalse(conn2.willShutDownConsumerExecutor()); AMQConnection conn3 = (AMQConnection)cf.newConnection((ExecutorService)null); assertTrue(conn3.willShutDownConsumerExecutor()); cf.setSharedExecutor(null); AMQConnection conn4 = (AMQConnection)cf.newConnection(); assertTrue(conn4.willShutDownConsumerExecutor()); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/SslContextFactoryTest.java000066400000000000000000000143061316117667700321770ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test; import com.rabbitmq.client.Connection; import com.rabbitmq.client.ConnectionFactory; import com.rabbitmq.client.SslContextFactory; import com.rabbitmq.client.TrustEverythingTrustManager; import org.junit.Test; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLHandshakeException; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.HashMap; import java.util.Map; import java.util.function.Supplier; import static org.junit.Assert.fail; /** * */ public class SslContextFactoryTest { @Test public void setSslContextFactory() throws Exception { doTestSetSslContextFactory(() -> { ConnectionFactory connectionFactory = new ConnectionFactory(); connectionFactory.useBlockingIo(); connectionFactory.setAutomaticRecoveryEnabled(true); return connectionFactory; }); doTestSetSslContextFactory(() -> { ConnectionFactory connectionFactory = new ConnectionFactory(); connectionFactory.useNio(); connectionFactory.setAutomaticRecoveryEnabled(true); return connectionFactory; }); doTestSetSslContextFactory(() -> { ConnectionFactory connectionFactory = new ConnectionFactory(); connectionFactory.useBlockingIo(); connectionFactory.setAutomaticRecoveryEnabled(false); return connectionFactory; }); doTestSetSslContextFactory(() -> { ConnectionFactory connectionFactory = new ConnectionFactory(); connectionFactory.useNio(); connectionFactory.setAutomaticRecoveryEnabled(false); return connectionFactory; }); } private void doTestSetSslContextFactory(Supplier supplier) throws Exception { ConnectionFactory connectionFactory = supplier.get(); SslContextFactory sslContextFactory = sslContextFactory(); connectionFactory.setSslContextFactory(sslContextFactory); Connection connection = connectionFactory.newConnection("connection01"); TestUtils.close(connection); try { connectionFactory.newConnection("connection02"); fail("The SSL context of this client should not trust the server"); } catch (SSLHandshakeException e) { // OK } } @Test public void socketFactoryTakesPrecedenceOverSslContextFactoryWithBlockingIo() throws Exception { doTestSocketFactoryTakesPrecedenceOverSslContextFactoryWithBlockingIo(() -> { ConnectionFactory connectionFactory = new ConnectionFactory(); connectionFactory.useBlockingIo(); connectionFactory.setAutomaticRecoveryEnabled(true); return connectionFactory; }); doTestSocketFactoryTakesPrecedenceOverSslContextFactoryWithBlockingIo(() -> { ConnectionFactory connectionFactory = new ConnectionFactory(); connectionFactory.useBlockingIo(); connectionFactory.setAutomaticRecoveryEnabled(false); return connectionFactory; }); } private void doTestSocketFactoryTakesPrecedenceOverSslContextFactoryWithBlockingIo( Supplier supplier ) throws Exception { ConnectionFactory connectionFactory = supplier.get(); connectionFactory.useBlockingIo(); SslContextFactory sslContextFactory = sslContextFactory(); connectionFactory.setSslContextFactory(sslContextFactory); SSLContext contextAcceptAll = sslContextFactory.create("connection01"); connectionFactory.setSocketFactory(contextAcceptAll.getSocketFactory()); Connection connection = connectionFactory.newConnection("connection01"); TestUtils.close(connection); connection = connectionFactory.newConnection("connection02"); TestUtils.close(connection); } private SslContextFactory sslContextFactory() throws Exception { SSLContext contextAcceptAll = SSLContext.getInstance(tlsProtocol()); contextAcceptAll.init(null, new TrustManager[] { new TrustEverythingTrustManager() }, null); SSLContext contextRejectAll = SSLContext.getInstance(tlsProtocol()); contextRejectAll.init(null, new TrustManager[] { new TrustNothingTrustManager() }, null); Map sslContexts = new HashMap<>(); sslContexts.put("connection01", contextAcceptAll); sslContexts.put("connection02", contextRejectAll); SslContextFactory sslContextFactory = name -> sslContexts.get(name); return sslContextFactory; } private String tlsProtocol() throws NoSuchAlgorithmException { return ConnectionFactory.computeDefaultTlsProcotol(SSLContext.getDefault().getSupportedSSLParameters().getProtocols()); } private static class TrustNothingTrustManager implements X509TrustManager { @Override public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { } @Override public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { throw new CertificateException("Doesn't trust any server"); } @Override public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/StandardMetricsCollectorTest.java000066400000000000000000000135501316117667700334770ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test; import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; import com.rabbitmq.client.impl.StandardMetricsCollector; import org.junit.Test; import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; import static org.mockito.Mockito.*; /** * */ public class StandardMetricsCollectorTest { @Test public void basicGetAndAck() { StandardMetricsCollector metrics = new StandardMetricsCollector(); Connection connection = mock(Connection.class); when(connection.getId()).thenReturn("connection-1"); Channel channel = mock(Channel.class); when(channel.getConnection()).thenReturn(connection); when(channel.getChannelNumber()).thenReturn(1); metrics.newConnection(connection); metrics.newChannel(channel); metrics.consumedMessage(channel, 1, true); metrics.consumedMessage(channel, 2, false); metrics.consumedMessage(channel, 3, false); metrics.consumedMessage(channel, 4, true); metrics.consumedMessage(channel, 5, false); metrics.consumedMessage(channel, 6, false); metrics.basicAck(channel, 6, false); assertThat(metrics.getAcknowledgedMessages().getCount(), is(1L)); metrics.basicAck(channel, 3, true); assertThat(metrics.getAcknowledgedMessages().getCount(), is(1L+2L)); metrics.basicAck(channel, 6, true); assertThat(metrics.getAcknowledgedMessages().getCount(), is(1L+2L+1L)); metrics.basicAck(channel, 10, true); assertThat(metrics.getAcknowledgedMessages().getCount(), is(1L+2L+1L)); } @Test public void basicConsumeAndAck() { StandardMetricsCollector metrics = new StandardMetricsCollector(); Connection connection = mock(Connection.class); when(connection.getId()).thenReturn("connection-1"); Channel channel = mock(Channel.class); when(channel.getConnection()).thenReturn(connection); when(channel.getChannelNumber()).thenReturn(1); metrics.newConnection(connection); metrics.newChannel(channel); String consumerTagWithAutoAck = "1"; String consumerTagWithManualAck = "2"; metrics.basicConsume(channel, consumerTagWithAutoAck, true); metrics.basicConsume(channel, consumerTagWithManualAck, false); metrics.consumedMessage(channel, 1, consumerTagWithAutoAck); assertThat(metrics.getConsumedMessages().getCount(), is(1L)); assertThat(metrics.getAcknowledgedMessages().getCount(), is(0L)); metrics.consumedMessage(channel, 2, consumerTagWithManualAck); metrics.consumedMessage(channel, 3, consumerTagWithManualAck); metrics.consumedMessage(channel, 4, consumerTagWithAutoAck); metrics.consumedMessage(channel, 5, consumerTagWithManualAck); metrics.consumedMessage(channel, 6, consumerTagWithManualAck); metrics.basicAck(channel, 6, false); assertThat(metrics.getAcknowledgedMessages().getCount(), is(1L)); metrics.basicAck(channel, 3, true); assertThat(metrics.getAcknowledgedMessages().getCount(), is(1L+2L)); metrics.basicAck(channel, 6, true); assertThat(metrics.getAcknowledgedMessages().getCount(), is(1L+2L+1L)); metrics.basicAck(channel, 10, true); assertThat(metrics.getAcknowledgedMessages().getCount(), is(1L+2L+1L)); } @Test public void cleanStaleState() { StandardMetricsCollector metrics = new StandardMetricsCollector(); Connection openConnection = mock(Connection.class); when(openConnection.getId()).thenReturn("connection-1"); when(openConnection.isOpen()).thenReturn(true); Channel openChannel = mock(Channel.class); when(openChannel.getConnection()).thenReturn(openConnection); when(openChannel.getChannelNumber()).thenReturn(1); when(openChannel.isOpen()).thenReturn(true); Channel closedChannel = mock(Channel.class); when(closedChannel.getConnection()).thenReturn(openConnection); when(closedChannel.getChannelNumber()).thenReturn(2); when(closedChannel.isOpen()).thenReturn(false); Connection closedConnection = mock(Connection.class); when(closedConnection.getId()).thenReturn("connection-2"); when(closedConnection.isOpen()).thenReturn(false); Channel openChannelInClosedConnection = mock(Channel.class); when(openChannelInClosedConnection.getConnection()).thenReturn(closedConnection); when(openChannelInClosedConnection.getChannelNumber()).thenReturn(1); when(openChannelInClosedConnection.isOpen()).thenReturn(true); metrics.newConnection(openConnection); metrics.newConnection(closedConnection); metrics.newChannel(openChannel); metrics.newChannel(closedChannel); metrics.newChannel(openChannelInClosedConnection); assertThat(metrics.getConnections().getCount(), is(2L)); assertThat(metrics.getChannels().getCount(), is(2L+1L)); metrics.cleanStaleState(); assertThat(metrics.getConnections().getCount(), is(1L)); assertThat(metrics.getChannels().getCount(), is(1L)); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/TableTest.java000066400000000000000000000047341316117667700275740ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test; import com.rabbitmq.client.impl.*; import org.junit.Test; import java.io.*; import java.math.BigDecimal; import java.util.Date; import java.util.HashMap; import java.util.Map; import static org.junit.Assert.assertEquals; public class TableTest { public byte [] marshal(Map table) throws IOException { ByteArrayOutputStream buffer = new ByteArrayOutputStream(); MethodArgumentWriter writer = new MethodArgumentWriter(new ValueWriter(new DataOutputStream(buffer))); writer.writeTable(table); writer.flush(); assertEquals(Frame.tableSize(table) + 4, buffer.size()); return buffer.toByteArray(); } public Map unmarshal(byte [] bytes) throws IOException { MethodArgumentReader reader = new MethodArgumentReader (new ValueReader (new DataInputStream (new ByteArrayInputStream(bytes)))); return reader.readTable(); } public Date secondDate() { return new Date((System.currentTimeMillis()/1000)*1000); } @Test public void loop() throws IOException { Map table = new HashMap(); table.put("a", 1); assertEquals(table, unmarshal(marshal(table))); table.put("b", secondDate()); assertEquals(table, unmarshal(marshal(table))); table.put("c", new BigDecimal("1.1")); assertEquals(table, unmarshal(marshal(table))); table.put("d", LongStringHelper.asLongString("d")); assertEquals(table, unmarshal(marshal(table))); table.put("e", -126); assertEquals(table, unmarshal(marshal(table))); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/TestUtils.java000066400000000000000000000055311316117667700276410ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test; import com.rabbitmq.client.Connection; import com.rabbitmq.client.ConnectionFactory; import java.io.IOException; public class TestUtils { public static final boolean USE_NIO = System.getProperty("use.nio") == null ? false : true; public static ConnectionFactory connectionFactory() { ConnectionFactory connectionFactory = new ConnectionFactory(); if(USE_NIO) { connectionFactory.useNio(); } else { connectionFactory.useBlockingIo(); } return connectionFactory; } public static void close(Connection connection) { if(connection != null) { try { connection.close(); } catch (IOException e) { throw new RuntimeException(e); } } } public static boolean isVersion37orLater(Connection connection) { String currentVersion = connection.getServerProperties().get("version").toString(); if (currentVersion.contains("+")) { currentVersion = currentVersion.substring(0, currentVersion.indexOf("+")); } return "0.0.0".equals(currentVersion) ? true : versionCompare(currentVersion, "3.7.0") >= 0; } /** * http://stackoverflow.com/questions/6701948/efficient-way-to-compare-version-strings-in-java * */ static int versionCompare(String str1, String str2) { String[] vals1 = str1.split("\\."); String[] vals2 = str2.split("\\."); int i = 0; // set index to first non-equal ordinal or length of shortest version string while (i < vals1.length && i < vals2.length && vals1[i].equals(vals2[i])) { i++; } // compare first non-equal ordinal number if (i < vals1.length && i < vals2.length) { int diff = Integer.valueOf(vals1[i]).compareTo(Integer.valueOf(vals2[i])); return Integer.signum(diff); } // the strings are equal or one string is a substring of the other // e.g. "1.2.3" = "1.2.3" or "1.2.3" < "1.2.3.4" return Integer.signum(vals1.length - vals2.length); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/TruncatedInputStreamTest.java000066400000000000000000000070001316117667700326570ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test; import com.rabbitmq.client.impl.TruncatedInputStream; import org.junit.After; import org.junit.Before; import org.junit.Test; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import static org.junit.Assert.assertEquals; /** * Some basic (retroactive) tests for TruncatedInputStream. */ public class TruncatedInputStreamTest { /** a sample truncated stream to run tests on */ private TruncatedInputStream _truncStream; /** sample data to truncate */ private static final byte[] TEST_BYTES = new byte[] { 5, 4, 3, 2, 1 }; /** what length to truncate it to */ private static final int TRUNCATED_LENGTH = 3; @Before public void setUp() throws Exception { InputStream baseStream = new ByteArrayInputStream(TEST_BYTES); _truncStream = new TruncatedInputStream(baseStream, TRUNCATED_LENGTH); } @After public void tearDown() throws Exception { _truncStream = null; } /** * Check the amount of data initially available is as it should be * @throws IOException if there is an I/O problem */ @Test public void amountInitiallyAvailable() throws IOException { assertEquals(TRUNCATED_LENGTH, _truncStream.available()); } /** * Check the data read from the truncated stream is as it should be * @throws IOException if there is an I/O problem */ @Test public void readTruncatedBytes() throws IOException { byte[] readBytes = new byte[TEST_BYTES.length]; int numRead = _truncStream.read(readBytes); assertEquals(TRUNCATED_LENGTH, numRead); for (int i = 0; i < TRUNCATED_LENGTH; i++) { assertEquals(TEST_BYTES[i], readBytes[i]); } } /** * Check single-byte reads behave as they should * @throws IOException * */ @Test public void singleByteReads() throws IOException { for (int i = 0; i < TRUNCATED_LENGTH; i++) { assertEquals(TEST_BYTES[i], _truncStream.read()); } assertEquals(-1, _truncStream.read()); } private static final int TEST_OFFSET = 4; private static final int TEST_LENGTH = 2; /** * Check reading a specified number of bytes at an offset gives the right result */ @Test public void offsetMultipleByteReads() throws IOException { byte[] readBytes = new byte[TEST_OFFSET + TEST_LENGTH]; _truncStream.read(readBytes, TEST_OFFSET, TEST_LENGTH); for (int i = 0; i < TEST_OFFSET; i++) { // check the array's initially blank... assertEquals(0, readBytes[i]); } for (int i = 0; i < TEST_LENGTH; i++) { // ... and the rest of it a copy of the input assertEquals(TEST_BYTES[i], readBytes[TEST_OFFSET + i]); } } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/ValueOrExceptionTest.java000066400000000000000000000050031316117667700317670ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test; import com.rabbitmq.utility.SensibleClone; import com.rabbitmq.utility.ValueOrException; import org.junit.Test; import static org.junit.Assert.*; public class ValueOrExceptionTest { public static class InsufficientMagicException extends Exception implements SensibleClone { /** Default for no check. */ private static final long serialVersionUID = 1L; public InsufficientMagicException(String message) { super(message); } public InsufficientMagicException sensibleClone() { return new InsufficientMagicException(getMessage()); } } @Test public void storesValue() throws InsufficientMagicException { Integer value = Integer.valueOf(3); ValueOrException valueOrEx = ValueOrException.makeValue(value); Integer returnedValue = valueOrEx.getValue(); assertTrue(returnedValue == value); } @Test public void clonesException() { InsufficientMagicException exception = new InsufficientMagicException("dummy message"); ValueOrException valueOrEx = ValueOrException.makeException(exception); try { valueOrEx.getValue(); fail("Expected exception"); } catch(InsufficientMagicException returnedException) { assertTrue(returnedException != exception); assertEquals(returnedException.getMessage(), exception.getMessage()); boolean inGetValue = false; for(StackTraceElement elt : returnedException.getStackTrace()) inGetValue |= "getValue".equals(elt.getMethodName()); assertTrue(inGetValue); } } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/000077500000000000000000000000001316117667700271745ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/AbstractRejectTest.java000066400000000000000000000046631316117667700336100ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.io.IOException; import java.util.Arrays; import java.util.concurrent.TimeoutException; import com.rabbitmq.client.Channel; import com.rabbitmq.client.Envelope; import com.rabbitmq.client.GetResponse; import com.rabbitmq.client.QueueingConsumer; import com.rabbitmq.client.test.BrokerTestCase; abstract class AbstractRejectTest extends BrokerTestCase { protected Channel secondaryChannel; @Override public void setUp() throws IOException, TimeoutException { super.setUp(); secondaryChannel = connection.createChannel(); } @Override public void tearDown() throws IOException, TimeoutException { if (secondaryChannel != null) { secondaryChannel.abort(); secondaryChannel = null; } super.tearDown(); } protected long checkDelivery(QueueingConsumer.Delivery d, byte[] msg, boolean redelivered) { assertNotNull(d); return checkDelivery(d.getEnvelope(), d.getBody(), msg, redelivered); } protected long checkDelivery(GetResponse r, byte[] msg, boolean redelivered) { assertNotNull(r); return checkDelivery(r.getEnvelope(), r.getBody(), msg, redelivered); } protected long checkDelivery(Envelope e, byte[] m, byte[] msg, boolean redelivered) { assertNotNull(e); assertTrue(Arrays.equals(m, msg)); assertEquals(e.isRedeliver(), redelivered); return e.getDeliveryTag(); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/AlternateExchange.java000066400000000000000000000165321316117667700334300ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import static org.junit.Assert.assertEquals; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; import org.junit.Test; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.GetResponse; import com.rabbitmq.client.ReturnListener; import com.rabbitmq.client.test.BrokerTestCase; public class AlternateExchange extends BrokerTestCase { static private final String[] resources = new String[]{"x","u","v"}; static private final String[] keys = new String[]{"x","u","v","z"}; static private final boolean[] unrouted = new boolean[] {false, false, false}; private final AtomicBoolean gotReturn = new AtomicBoolean(); /** * Determine which of the queues in our test configuration we * expect a message with routing key key to get * delivered to: the queue (if any) named key. * * @param key the routing key of the message * @return an array of booleans that when zipped with {@link * #resources} indicates whether the messages is expected to be * routed to the respective queue */ private static boolean[] expected(String key) { boolean[] expected = new boolean[resources.length]; for (int i = 0; i < resources.length; i++) { expected[i] = resources[i].equals(key); } return expected; } @Override public void setUp() throws IOException, TimeoutException { super.setUp(); channel.addReturnListener(new ReturnListener() { public void handleReturn(int replyCode, String replyText, String exchange, String routingKey, AMQP.BasicProperties properties, byte[] body) throws IOException { gotReturn.set(true); } }); } @Override protected void createResources() throws IOException { for (String q : resources) { channel.queueDeclare(q, false, false, false, null); } } @Override protected void releaseResources() throws IOException { for (String r : resources) { channel.queueDelete(r); // declared by setupRouting channel.exchangeDelete(r); } } /** * Declare an direct exchange name with an * alternate-exchange ae and bind the queue * name to it with a binding key of * name. * * @param name the name of the exchange to be created, and queue * to be bound * @param ae the name of the alternate-exchage */ protected void setupRouting(String name, String ae) throws IOException { Map args = new HashMap(); if (ae != null) args.put("alternate-exchange", ae); channel.exchangeDelete(name); channel.exchangeDeclare(name, "direct", false, false, args); channel.queueBind(name, name, name); } protected void setupRouting() throws IOException { setupRouting("x", "u"); setupRouting("u", "v"); setupRouting("v", "x"); } protected void cleanup() throws IOException { for (String e : resources) { channel.exchangeDelete(e); } } /** * Perform an auto-acking 'basic.get' on each of the queues named * in {@link #resources} and check whether a message can be * retrieved when expected. * * @param expected an array of booleans that is zipped with {@link * #resources} and indicates whether a messages is expected * to be retrievable from the respective queue */ protected void checkGet(boolean[] expected) throws IOException { for (int i = 0; i < resources.length; i++) { String q = resources[i]; GetResponse r = channel.basicGet(q, true); assertEquals("check " + q , expected[i], r != null); } } /** * Test whether a message is routed as expected. * * We publish a message to exchange 'x' with a routing key of * key, check whether the message (actually, any * message) can be retrieved from the queues named in {@link * #resources} when expected, and whether a 'basic.return' is * received when expected. * * @param key the routing key of the message to be sent * @param mandatory whether the message should be marked as 'mandatory' * @param expected indicates which queues we expect the message to * get routed to * @param ret whether a 'basic.return' is expected * * @see #checkGet(boolean[]) */ protected void check(String key, boolean mandatory, boolean[] expected, boolean ret) throws IOException { gotReturn.set(false); channel.basicPublish("x", key, mandatory, false, null, "ae-test".getBytes()); checkGet(expected); assertEquals(ret, gotReturn.get()); } protected void check(String key, boolean[] expected, boolean ret) throws IOException { check(key, false, expected, ret); } protected void check(String key, boolean mandatory, boolean ret) throws IOException { check(key, mandatory, expected(key), ret); } protected void check(String key, boolean ret) throws IOException { check(key, false, ret); } /** * check various cases of missing AEs - we expect to see some * warnings in the server logs */ @Test public void missing() throws IOException { setupRouting("x", "u"); check("x", false); //no warning check("u", unrouted, false); //warning setupRouting("u", "v"); check("u", false); //no warning check("v", unrouted, false); //warning setupRouting("v", null); check("v", false); //no warning check("z", unrouted, false); //no warning cleanup(); } @Test public void ae() throws IOException { setupRouting(); for (String k : keys) { //ordinary check(k, false); //mandatory check(k, true, k.equals("z")); } cleanup(); } @Test public void cycleBreaking() throws IOException { setupRouting(); check("z", false); cleanup(); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/BasicConsume.java000066400000000000000000000030051316117667700324100ustar00rootroot00000000000000package com.rabbitmq.client.test.functional; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.Channel; import com.rabbitmq.client.DefaultConsumer; import com.rabbitmq.client.Envelope; import com.rabbitmq.client.test.BrokerTestCase; import org.junit.Test; import java.io.IOException; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import static org.junit.Assert.assertTrue; /** * */ public class BasicConsume extends BrokerTestCase { @Test public void basicConsumeOk() throws IOException, InterruptedException { String q = channel.queueDeclare().getQueue(); basicPublishPersistent("msg".getBytes("UTF-8"), q); basicPublishPersistent("msg".getBytes("UTF-8"), q); CountDownLatch latch = new CountDownLatch(2); channel.basicConsume(q, new CountDownLatchConsumer(channel, latch)); boolean nbOfExpectedMessagesHasBeenConsumed = latch.await(1, TimeUnit.SECONDS); assertTrue("Not all the messages have been received", nbOfExpectedMessagesHasBeenConsumed); } static class CountDownLatchConsumer extends DefaultConsumer { private final CountDownLatch latch; public CountDownLatchConsumer(Channel channel, CountDownLatch latch) { super(channel); this.latch = latch; } @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { latch.countDown(); } } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/BasicGet.java000066400000000000000000000046431316117667700315270ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.IOException; import java.util.concurrent.TimeoutException; import org.junit.Test; import com.rabbitmq.client.AlreadyClosedException; import com.rabbitmq.client.Channel; import com.rabbitmq.client.test.BrokerTestCase; public class BasicGet extends BrokerTestCase { @Test public void basicGetWithEnqueuedMessages() throws IOException, InterruptedException { assertTrue(channel.isOpen()); String q = channel.queueDeclare().getQueue(); basicPublishPersistent("msg".getBytes("UTF-8"), q); Thread.sleep(250); assertNotNull(channel.basicGet(q, true)); channel.queuePurge(q); assertNull(channel.basicGet(q, true)); channel.queueDelete(q); } @Test public void basicGetWithEmptyQueue() throws IOException, InterruptedException { assertTrue(channel.isOpen()); String q = channel.queueDeclare().getQueue(); assertNull(channel.basicGet(q, true)); channel.queueDelete(q); } @Test public void basicGetWithClosedChannel() throws IOException, InterruptedException, TimeoutException { assertTrue(channel.isOpen()); String q = channel.queueDeclare().getQueue(); channel.close(); assertFalse(channel.isOpen()); try { channel.basicGet(q, true); fail("expected basic.get on a closed channel to fail"); } catch (AlreadyClosedException e) { // passed } finally { Channel tch = connection.createChannel(); tch.queueDelete(q); tch.close(); } } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/BindingLifecycle.java000066400000000000000000000171511316117667700332360ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.IOException; import java.util.concurrent.TimeoutException; import org.junit.Test; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.GetResponse; /** * This tests whether bindings are created and nuked properly. * * The tests attempt to declare durable queues on a secondary node, if * present, and that node is restarted as part of the tests while the * primary node is still running. That way we exercise any node-down * handler code in the server. * */ public class BindingLifecycle extends BindingLifecycleBase { /** * This tests that when you purge a queue, all of its messages go. */ @Test public void queuePurge() throws IOException { Binding binding = setupExchangeBindings(false); channel.basicPublish(binding.x, binding.k, null, payload); // Purge the queue, and test that we don't recieve a message channel.queuePurge(binding.q); GetResponse response = channel.basicGet(binding.q, true); assertNull("The response SHOULD BE null", response); deleteExchangeAndQueue(binding); } /** * See bug 21854: * "When Queue.Purge is called, sent-but-unacknowledged messages are no * longer purged, even if the channel they were sent down is not * (Tx-)transacted." */ @SuppressWarnings("deprecation") @Test public void unackedPurge() throws IOException { Binding binding = setupExchangeBindings(false); channel.basicPublish(binding.x, binding.k, null, payload); GetResponse response = channel.basicGet(binding.q, false); assertFalse(response.getEnvelope().isRedeliver()); assertNotNull("The response SHOULD NOT BE null", response); // If we purge the queue the unacked message should still be there on // recover. channel.queuePurge(binding.q); response = channel.basicGet(binding.q, true); assertNull("The response SHOULD BE null", response); channel.basicRecover(); response = channel.basicGet(binding.q, false); channel.basicRecover(); assertTrue(response.getEnvelope().isRedeliver()); assertNotNull("The response SHOULD NOT BE null", response); // If we recover then purge the message should go away channel.queuePurge(binding.q); response = channel.basicGet(binding.q, true); assertNull("The response SHOULD BE null", response); deleteExchangeAndQueue(binding); } /** * This tests whether when you delete an exchange, that any * bindings attached to it are deleted as well. */ @Test public void exchangeDelete() throws IOException { boolean durable = true; Binding binding = setupExchangeAndRouteMessage(true); // Nuke the exchange and repeat this test, this time you // expect nothing to get routed channel.exchangeDelete(binding.x); channel.exchangeDeclare(binding.x, "direct"); sendUnroutable(binding); channel.queueDelete(binding.q); } /** * This tests whether the server checks that an exchange is * actually being used when you try to delete it with the ifunused * flag. * * To test this, you try to delete an exchange with a queue still * bound to it and expect the delete operation to fail. */ @Test public void exchangeIfUnused() throws IOException { boolean durable = true; Binding binding = setupExchangeBindings(true); try { channel.exchangeDelete(binding.x, true); } catch (IOException e) { checkShutdownSignal(AMQP.PRECONDITION_FAILED, e); openChannel(); deleteExchangeAndQueue(binding); return; } fail("Exchange delete should have failed"); } /** * This tests whether the server checks that an auto_delete * exchange actually deletes the bindings attached to it when it * is deleted. * * To test this, you declare and auto_delete exchange and bind an * auto_delete queue to it. * * Start a consumer on this queue, send a message, let it get * consumed and then cancel the consumer * * The unsubscribe should cause the queue to auto_delete, which in * turn should cause the exchange to auto_delete. * * Then re-declare the queue again and try to rebind it to the same exhange. * * Because the exchange has been auto-deleted, the bind operation * should fail. */ @Test public void exchangeAutoDelete() throws IOException, TimeoutException { doAutoDelete(false, 1); } /** * Runs something similar to testExchangeAutoDelete, but adds * different queues with the same binding to the same exchange. * * The difference should be that the original exchange should not * get auto-deleted */ @Test public void exchangeAutoDeleteManyBindings() throws IOException, TimeoutException { doAutoDelete(false, 10); } /** * */ @Test public void exchangePassiveDeclare() throws IOException { channel.exchangeDeclare("testPassive", "direct"); channel.exchangeDeclarePassive("testPassive"); try { channel.exchangeDeclarePassive("unknown_exchange"); fail("Passive declare of an unknown exchange should fail"); } catch (IOException ioe) { checkShutdownSignal(AMQP.NOT_FOUND, ioe); } } /** * Test the behaviour of queue.unbind */ @Test public void unbind() throws Exception { for (String exchange: new String[]{"amq.fanout", "amq.direct", "amq.topic", "amq.headers"}) { testUnbind(exchange); } } public void testUnbind(String exchange) throws Exception { Binding b = new Binding(channel.queueDeclare().getQueue(), exchange, "quay"); // failure cases Binding[] tests = new Binding[] { new Binding("unknown_queue", b.x, b.k), new Binding(b.q, "unknown_exchange", b.k), new Binding("unknown_unknown", "exchange_queue", b.k), new Binding(b.q, b.x, "unknown_rk"), new Binding("unknown_queue", "unknown_exchange", "unknown_rk") }; for (int i = 0; i < tests.length; i++) { Binding test = tests[i]; // check we can unbind all sorts of things that don't exist channel.queueUnbind(test.q, test.x, test.k); } // success case channel.queueBind(b.q, b.x, b.k); sendRoutable(b); channel.queueUnbind(b.q, b.x, b.k); sendUnroutable(b); } } BindingLifecycleBase.java000066400000000000000000000144601316117667700337520ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.fail; import java.io.IOException; import java.util.concurrent.TimeoutException; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.GetResponse; import com.rabbitmq.client.QueueingConsumer; /** * This tests whether bindings are created and nuked properly. * * The tests attempt to declare durable queues on a secondary node, if * present, and that node is restarted as part of the tests while the * primary node is still running. That way we exercise any node-down * handler code in the server. * */ public class BindingLifecycleBase extends ClusteredTestBase { protected static final String K = "K-" + System.currentTimeMillis(); protected static final int N = 1; protected static final String Q = "Q-" + System.currentTimeMillis(); protected static final String X = "X-" + System.currentTimeMillis(); protected static final byte[] payload = ("" + System.currentTimeMillis()).getBytes(); protected static String randomString() { return "-" + System.nanoTime(); } protected void createQueueAndBindToExchange(Binding binding, boolean durable) throws IOException { channel.exchangeDeclare(binding.x, "direct", durable); channel.queueDeclare(binding.q, durable, false, false, null); channel.queueBind(binding.q, binding.x, binding.k); } protected void declareDurableQueue(String q) throws IOException { alternateChannel.queueDeclare(q, true, false, false, null); } protected void deleteExchangeAndQueue(Binding binding) throws IOException { channel.queueDelete(binding.q); channel.exchangeDelete(binding.x); } protected void doAutoDelete(boolean durable, int queues) throws IOException, TimeoutException { String[] queueNames = null; Binding binding = Binding.randomBinding(); channel.exchangeDeclare(binding.x, "direct", durable, true, null); channel.queueDeclare(binding.q, durable, false, true, null); channel.queueBind(binding.q, binding.x, binding.k); if (queues > 1) { int j = queues - 1; queueNames = new String[j]; for (int i = 0; i < j; i++) { queueNames[i] = randomString(); channel.queueDeclare(queueNames[i], durable, false, false, null); channel.queueBind(queueNames[i], binding.x, binding.k); channel.basicConsume(queueNames[i], true, new QueueingConsumer(channel)); } } subscribeSendUnsubscribe(binding); if (durable) { restart(); } if (queues > 1 && queueNames != null) { for (String s : queueNames) { channel.basicConsume(s, true, new QueueingConsumer(channel)); Binding tmp = new Binding(s, binding.x, binding.k); sendUnroutable(tmp); } } channel.queueDeclare(binding.q, durable, true, true, null); // if (queues == 1): Because the exchange does not exist, this // bind should fail try { channel.queueBind(binding.q, binding.x, binding.k); sendRoutable(binding); } catch (IOException e) { checkShutdownSignal(AMQP.NOT_FOUND, e); channel = null; return; } if (queues == 1) { deleteExchangeAndQueue(binding); fail("Queue bind should have failed"); } // Do some cleanup if (queues > 1 && queueNames != null) { for (String q : queueNames) { channel.queueDelete(q); } } } @Override protected void restart() throws IOException, TimeoutException { } protected void sendRoutable(Binding binding) throws IOException { channel.basicPublish(binding.x, binding.k, null, payload); GetResponse response = channel.basicGet(binding.q, true); assertNotNull("The response should not be null", response); } protected void sendUnroutable(Binding binding) throws IOException { channel.basicPublish(binding.x, binding.k, null, payload); GetResponse response = channel.basicGet(binding.q, true); assertNull("The response SHOULD BE null", response); } protected Binding setupExchangeAndRouteMessage(boolean durable) throws IOException { Binding binding = setupExchangeBindings(durable); sendRoutable(binding); return binding; } protected Binding setupExchangeBindings(boolean durable) throws IOException { Binding binding = Binding.randomBinding(); createQueueAndBindToExchange(binding, durable); return binding; } protected void subscribeSendUnsubscribe(Binding binding) throws IOException { String tag = channel.basicConsume(binding.q, new QueueingConsumer(channel)); sendUnroutable(binding); channel.basicCancel(tag); } protected static class Binding { final String q; final String x; final String k; static Binding randomBinding() { return new Binding(randomString(), randomString(), randomString()); } protected Binding(String q, String x, String k) { this.q = q; this.x = x; this.k = k; } } // A couple of tests that are common to the subclasses (which differ on // whether the broker is restarted) /** * * The same thing as testExchangeAutoDelete, but with durable * queues. * * Main difference is restarting the broker to make sure that the * durable queues are blasted away. */ public void testExchangeAutoDeleteDurable() throws IOException, TimeoutException { doAutoDelete(true, 1); } /** * The same thing as testExchangeAutoDeleteManyBindings, but with * durable queues. */ public void testExchangeAutoDeleteDurableManyBindings() throws IOException, TimeoutException { doAutoDelete(true, 10); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/CcRoutes.java000066400000000000000000000131741316117667700315740ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.fail; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.TimeoutException; import org.junit.Test; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.AMQP.BasicProperties; import com.rabbitmq.client.GetResponse; import com.rabbitmq.client.test.BrokerTestCase; public class CcRoutes extends BrokerTestCase { static private final String[] queues = new String[]{"queue1", "queue2", "queue3"}; protected final String exDirect = "direct_cc_exchange"; protected final String exTopic = "topic_cc_exchange"; protected BasicProperties.Builder propsBuilder; protected Map headers; protected List ccList; protected List bccList; @Override public void setUp() throws IOException, TimeoutException { super.setUp(); propsBuilder = new BasicProperties.Builder(); headers = new HashMap(); ccList = new ArrayList(); bccList = new ArrayList(); } @Override protected void createResources() throws IOException, TimeoutException { super.createResources(); for (String q : queues) { channel.queueDeclare(q, false, true, true, null); } channel.exchangeDeclare(exDirect, "direct", false, true, null); channel.exchangeDeclare(exTopic, "topic", false, true, null); } @Test public void ccList() throws IOException { ccList.add("queue2"); ccList.add("queue3"); headerPublish("", "queue1", ccList, null); expect(new String []{"queue1", "queue2", "queue3"}, true); } @Test public void ccIgnoreEmptyAndInvalidRoutes() throws IOException { bccList.add("frob"); headerPublish("", "queue1", ccList, bccList); expect(new String []{"queue1"}, true); } @Test public void bcc() throws IOException { bccList.add("queue2"); headerPublish("", "queue1", null, bccList); expect(new String []{"queue1", "queue2"}, false); } @Test public void noDuplicates() throws IOException { ccList.add("queue1"); ccList.add("queue1"); bccList.add("queue1"); headerPublish("", "queue1", ccList, bccList); expect(new String[] {"queue1"}, true); } @Test public void directExchangeWithoutBindings() throws IOException { ccList.add("queue1"); headerPublish(exDirect, "queue2", ccList, null); expect(new String[] {}, true); } @Test public void topicExchange() throws IOException { ccList.add("routing_key"); channel.queueBind("queue2", exTopic, "routing_key"); headerPublish(exTopic, "", ccList, null); expect(new String[] {"queue2"}, true); } @Test public void boundExchanges() throws IOException { ccList.add("routing_key1"); bccList.add("routing_key2"); channel.exchangeBind(exTopic, exDirect, "routing_key1"); channel.queueBind("queue2", exTopic, "routing_key2"); headerPublish(exDirect, "", ccList, bccList); expect(new String[] {"queue2"}, true); } @Test public void nonArray() throws IOException { headers.put("CC", 0); propsBuilder.headers(headers); channel.basicPublish("", "queue1", propsBuilder.build(), new byte[0]); try { expect(new String[] {}, false); fail(); } catch (IOException e) { checkShutdownSignal(AMQP.PRECONDITION_FAILED, e); } } private void headerPublish(String ex, String to, List cc, List bcc) throws IOException { if (cc != null) { headers.put("CC", ccList); } if (bcc != null) { headers.put("BCC", bccList); } propsBuilder.headers(headers); channel.basicPublish(ex, to, propsBuilder.build(), new byte[0]); } private void expect(String[] expectedQueues, boolean usedCc) throws IOException { GetResponse getResponse; List expectedList = Arrays.asList(expectedQueues); for (String q : queues) { getResponse = basicGet(q); if (expectedList.contains(q)) { assertNotNull(getResponse); assertEquals(0, getResponse.getMessageCount()); Map headers = getResponse.getProps().getHeaders(); if (headers != null){ assertEquals(usedCc, headers.containsKey("CC")); assertFalse(headers.containsKey("BCC")); } } else { assertNull(getResponse); } } } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/ClusteredTestBase.java000066400000000000000000000110001316117667700334140ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; import com.rabbitmq.client.ConnectionFactory; import com.rabbitmq.client.test.BrokerTestCase; import com.rabbitmq.tools.Host; import java.io.IOException; import java.util.concurrent.TimeoutException; /** * Base class for tests which would like a second, clustered node. */ public class ClusteredTestBase extends BrokerTestCase { // If these are non-null then the secondary node is up and clustered public Channel clusteredChannel; public Connection clusteredConnection; // These will always be non-null - if there is clustering they will point // to the secondary node, otherwise the primary public Channel alternateChannel; public Connection alternateConnection; @Override public void openChannel() throws IOException { super.openChannel(); if (clusteredConnection != null) { clusteredChannel = clusteredConnection.createChannel(); } alternateChannel = clusteredChannel == null ? channel : clusteredChannel; } private static boolean nonClusteredWarningPrinted; @Override public void openConnection() throws IOException, TimeoutException { super.openConnection(); if (clusteredConnection == null) { try { ConnectionFactory cf2 = connectionFactory.clone(); cf2.setHost("localhost"); cf2.setPort(5673); clusteredConnection = cf2.newConnection(); } catch (IOException e) { // Must be no secondary node } } if (clusteredConnection != null && !clustered(connection, clusteredConnection)) { clusteredConnection.close(); clusteredConnection = null; if (!nonClusteredWarningPrinted) { System.out.println("NOTE: Only one clustered node was detected - certain tests that"); System.out.println("could test clustering will not do so."); nonClusteredWarningPrinted = true; } } alternateConnection = clusteredConnection == null ? connection : clusteredConnection; } private boolean clustered(Connection c1, Connection c2) throws IOException { Channel ch1 = c1.createChannel(); Channel ch2 = c2.createChannel(); // autodelete but not exclusive String q = ch1.queueDeclare("", false, false, true, null).getQueue(); try { ch2.queueDeclarePassive(q); } catch (IOException e) { checkShutdownSignal(AMQP.NOT_FOUND, e); // If we can't see the queue, secondary node must be up but not // clustered, hence not interesting to us return false; } ch1.queueDelete(q); ch1.abort(); ch2.abort(); return true; } @Override public void closeChannel() throws IOException { if (clusteredChannel != null) { clusteredChannel.abort(); clusteredChannel = null; alternateChannel = null; } super.closeChannel(); } @Override public void closeConnection() throws IOException { if (clusteredConnection != null) { clusteredConnection.abort(); clusteredConnection = null; alternateConnection = null; } super.closeConnection(); } protected void stopSecondary() throws IOException { Host.invokeMakeTarget("stop-rabbit-on-node RABBITMQ_NODENAME=\'" + Host.nodenameB() + "\'"); } protected void startSecondary() throws IOException { Host.invokeMakeTarget("start-rabbit-on-node RABBITMQ_NODENAME=\'" + Host.nodenameB() + "\'"); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/Confirm.java000066400000000000000000000256721316117667700314500ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import static org.junit.Assert.*; import org.junit.Test; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.Channel; import com.rabbitmq.client.ConfirmListener; import com.rabbitmq.client.DefaultConsumer; import com.rabbitmq.client.GetResponse; import com.rabbitmq.client.MessageProperties; import com.rabbitmq.client.ShutdownSignalException; import com.rabbitmq.client.test.BrokerTestCase; import java.io.IOException; import java.util.Collections; import java.util.Map; import java.util.SortedSet; import java.util.TreeSet; import java.util.concurrent.TimeoutException; public class Confirm extends BrokerTestCase { private final static int NUM_MESSAGES = 1000; private static final String TTL_ARG = "x-message-ttl"; @Override public void setUp() throws IOException, TimeoutException { super.setUp(); channel.confirmSelect(); channel.queueDeclare("confirm-test", true, true, false, null); channel.queueDeclare("confirm-durable-nonexclusive", true, false, false, null); channel.basicConsume("confirm-test", true, new DefaultConsumer(channel)); channel.queueDeclare("confirm-test-nondurable", false, true, false, null); channel.basicConsume("confirm-test-nondurable", true, new DefaultConsumer(channel)); channel.queueDeclare("confirm-test-noconsumer", true, true, false, null); channel.queueDeclare("confirm-test-2", true, true, false, null); channel.basicConsume("confirm-test-2", true, new DefaultConsumer(channel)); channel.queueBind("confirm-test", "amq.direct", "confirm-multiple-queues"); channel.queueBind("confirm-test-2", "amq.direct", "confirm-multiple-queues"); } @Test public void persistentMandatoryCombinations() throws IOException, InterruptedException, TimeoutException { boolean b[] = { false, true }; for (boolean persistent : b) { for (boolean mandatory : b) { confirmTest("", "confirm-test", persistent, mandatory); } } } @Test public void nonDurable() throws IOException, InterruptedException, TimeoutException { confirmTest("", "confirm-test-nondurable", true, false); } @Test public void mandatoryNoRoute() throws IOException, InterruptedException, TimeoutException { confirmTest("", "confirm-test-doesnotexist", false, true); confirmTest("", "confirm-test-doesnotexist", true, true); } @Test public void multipleQueues() throws IOException, InterruptedException, TimeoutException { confirmTest("amq.direct", "confirm-multiple-queues", true, false); } /* For testQueueDelete and testQueuePurge to be * relevant, the msg_store must not write the messages to disk * (thus causing a confirm). I'd manually comment out the line in * internal_sync that notifies the clients. */ @Test public void queueDelete() throws IOException, InterruptedException, TimeoutException { publishN("","confirm-test-noconsumer", true, false); channel.queueDelete("confirm-test-noconsumer"); channel.waitForConfirmsOrDie(60000); } @Test public void queuePurge() throws IOException, InterruptedException, TimeoutException { publishN("", "confirm-test-noconsumer", true, false); channel.queuePurge("confirm-test-noconsumer"); channel.waitForConfirmsOrDie(60000); } /* Tests rabbitmq-server #854 */ @Test public void confirmQueuePurge() throws IOException, InterruptedException, TimeoutException { channel.basicQos(1); for (int i = 0; i < 20000; i++) { publish("", "confirm-durable-nonexclusive", true, false); if (i % 100 == 0) { channel.queuePurge("confirm-durable-nonexclusive"); } } channel.waitForConfirmsOrDie(90000); } @Test public void basicReject() throws IOException, InterruptedException, TimeoutException { basicRejectCommon(false); channel.waitForConfirmsOrDie(60000); } @Test public void queueTTL() throws IOException, InterruptedException, TimeoutException { for (int ttl : new int[]{ 1, 0 }) { Map argMap = Collections.singletonMap(TTL_ARG, (Object)ttl); channel.queueDeclare("confirm-ttl", true, true, false, argMap); publishN("", "confirm-ttl", true, false); channel.waitForConfirmsOrDie(60000); channel.queueDelete("confirm-ttl"); } } @Test public void basicRejectRequeue() throws IOException, InterruptedException, TimeoutException { basicRejectCommon(true); /* wait confirms to go through the broker */ Thread.sleep(1000); channel.basicConsume("confirm-test-noconsumer", true, new DefaultConsumer(channel)); channel.waitForConfirmsOrDie(60000); } @Test public void basicRecover() throws IOException, InterruptedException, TimeoutException { publishN("", "confirm-test-noconsumer", true, false); for (long i = 0; i < NUM_MESSAGES; i++) { GetResponse resp = channel.basicGet("confirm-test-noconsumer", false); resp.getEnvelope().getDeliveryTag(); // not acking } channel.basicRecover(true); Thread.sleep(1000); channel.basicConsume("confirm-test-noconsumer", true, new DefaultConsumer(channel)); channel.waitForConfirmsOrDie(60000); } @Test public void select() throws IOException { channel.confirmSelect(); try { Channel ch = connection.createChannel(); ch.confirmSelect(); ch.txSelect(); fail(); } catch (IOException ioe) { checkShutdownSignal(AMQP.PRECONDITION_FAILED, ioe); } try { Channel ch = connection.createChannel(); ch.txSelect(); ch.confirmSelect(); fail(); } catch (IOException ioe) { checkShutdownSignal(AMQP.PRECONDITION_FAILED, ioe); } } @Test public void waitForConfirms() throws IOException, InterruptedException, TimeoutException { final SortedSet unconfirmedSet = Collections.synchronizedSortedSet(new TreeSet()); channel.addConfirmListener(new ConfirmListener() { public void handleAck(long seqNo, boolean multiple) { if (!unconfirmedSet.contains(seqNo)) { fail("got duplicate ack: " + seqNo); } if (multiple) { unconfirmedSet.headSet(seqNo + 1).clear(); } else { unconfirmedSet.remove(seqNo); } } public void handleNack(long seqNo, boolean multiple) { fail("got a nack"); } }); for (long i = 0; i < NUM_MESSAGES; i++) { unconfirmedSet.add(channel.getNextPublishSeqNo()); publish("", "confirm-test", true, false); } channel.waitForConfirmsOrDie(60000); if (!unconfirmedSet.isEmpty()) { fail("waitForConfirms returned with unconfirmed messages"); } } @Test public void waitForConfirmsWithoutConfirmSelected() throws IOException, InterruptedException { channel = connection.createChannel(); // Don't enable Confirm mode publish("", "confirm-test", true, false); try { channel.waitForConfirms(60000); fail("waitForConfirms without confirms selected succeeded"); } catch (IllegalStateException _e) {} catch (TimeoutException e) { e.printStackTrace(); } } @Test public void waitForConfirmsException() throws IOException, InterruptedException, TimeoutException { publishN("", "confirm-test", true, false); channel.close(); try { channel.waitForConfirmsOrDie(60000); fail("waitAcks worked on a closed channel"); } catch (ShutdownSignalException sse) { if (!(sse.getReason() instanceof AMQP.Channel.Close)) fail("Shutdown reason not Channel.Close"); //whoosh; everything ok } catch (InterruptedException e) { // whoosh; we should probably re-run, though } } /* Publish NUM_MESSAGES messages and wait for confirmations. */ public void confirmTest(String exchange, String queueName, boolean persistent, boolean mandatory) throws IOException, InterruptedException, TimeoutException { publishN(exchange, queueName, persistent, mandatory); channel.waitForConfirmsOrDie(60000); } private void publishN(String exchangeName, String queueName, boolean persistent, boolean mandatory) throws IOException { for (long i = 0; i < NUM_MESSAGES; i++) { publish(exchangeName, queueName, persistent, mandatory); } } private void basicRejectCommon(boolean requeue) throws IOException { publishN("", "confirm-test-noconsumer", true, false); for (long i = 0; i < NUM_MESSAGES; i++) { GetResponse resp = channel.basicGet("confirm-test-noconsumer", false); long dtag = resp.getEnvelope().getDeliveryTag(); channel.basicReject(dtag, requeue); } } protected void publish(String exchangeName, String queueName, boolean persistent, boolean mandatory) throws IOException { channel.basicPublish(exchangeName, queueName, mandatory, false, persistent ? MessageProperties.PERSISTENT_BASIC : MessageProperties.BASIC, "nop".getBytes()); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/ConnectionOpen.java000066400000000000000000000104651316117667700327660ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.DataInputStream; import java.io.IOException; import java.net.Socket; import java.util.concurrent.TimeoutException; import com.rabbitmq.client.test.TestUtils; import org.junit.Test; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.ConnectionFactory; import com.rabbitmq.client.MalformedFrameException; import com.rabbitmq.client.Method; import com.rabbitmq.client.impl.AMQCommand; import com.rabbitmq.client.impl.SocketFrameHandler; import javax.net.SocketFactory; /** * Check that protocol negotiation works */ public class ConnectionOpen { @Test public void correctProtocolHeader() throws IOException { ConnectionFactory factory = TestUtils.connectionFactory(); SocketFrameHandler fh = new SocketFrameHandler(SocketFactory.getDefault().createSocket("localhost", AMQP.PROTOCOL.PORT)); fh.sendHeader(); AMQCommand command = new AMQCommand(); while (!command.handleFrame(fh.readFrame())) { } Method m = command.getMethod(); // System.out.println(m.getClass()); assertTrue("First command must be Connection.start", m instanceof AMQP.Connection.Start); AMQP.Connection.Start start = (AMQP.Connection.Start) m; assertTrue("Version in Connection.start is <= what we sent", start.getVersionMajor() < AMQP.PROTOCOL.MAJOR || (start.getVersionMajor() == AMQP.PROTOCOL.MAJOR && start.getVersionMinor() <= AMQP.PROTOCOL.MINOR)); } @Test public void crazyProtocolHeader() throws IOException { ConnectionFactory factory = TestUtils.connectionFactory(); // keep the frame handler's socket Socket fhSocket = SocketFactory.getDefault().createSocket("localhost", AMQP.PROTOCOL.PORT); SocketFrameHandler fh = new SocketFrameHandler(fhSocket); fh.sendHeader(100, 3); // major, minor DataInputStream in = fh.getInputStream(); // we should get a valid protocol header back byte[] header = new byte[4]; in.read(header); // The protocol header is "AMQP" plus a version that the server // supports. We can really only test for the first bit. assertEquals("AMQP", new String(header)); in.read(header); assertEquals(in.available(), 0); // At this point the socket should have been closed. We can // directly test for this, but since Socket.isClosed is purported to be // unreliable, we can also test whether trying to read more bytes // gives an error. if (!fhSocket.isClosed()) { fh.setTimeout(500); // NB the frame handler will return null if the socket times out try { fh.readFrame(); fail("Expected socket read to fail due to socket being closed"); } catch (MalformedFrameException mfe) { fail("Expected nothing, rather than a badly-formed something"); } catch (IOException ioe) { } } } @Test public void frameMaxLessThanFrameMinSize() throws IOException, TimeoutException { ConnectionFactory factory = TestUtils.connectionFactory(); factory.setRequestedFrameMax(100); try { factory.newConnection(); } catch (IOException ioe) { return; } fail("Broker should have closed the connection since our frame max < frame_min_size"); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/ConnectionRecovery.java000066400000000000000000001103261316117667700336600ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import com.rabbitmq.client.*; import com.rabbitmq.client.impl.NetworkConnection; import com.rabbitmq.client.impl.recovery.*; import com.rabbitmq.client.test.BrokerTestCase; import com.rabbitmq.client.test.TestUtils; import com.rabbitmq.tools.Host; import org.junit.Test; import java.io.IOException; import java.lang.reflect.Field; import java.util.*; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import static org.junit.Assert.*; @SuppressWarnings("ThrowFromFinallyBlock") public class ConnectionRecovery extends BrokerTestCase { private static final long RECOVERY_INTERVAL = 2000; @Test public void connectionRecovery() throws IOException, InterruptedException { assertTrue(connection.isOpen()); closeAndWaitForRecovery(); assertTrue(connection.isOpen()); } @Test public void namedConnectionRecovery() throws IOException, InterruptedException, TimeoutException { String connectionName = "custom name"; RecoverableConnection c = newRecoveringConnection(connectionName); try { assertTrue(c.isOpen()); assertEquals(connectionName, c.getClientProvidedName()); closeAndWaitForRecovery(c); assertTrue(c.isOpen()); assertEquals(connectionName, c.getClientProvidedName()); } finally { c.abort(); } } @Test public void connectionRecoveryWithServerRestart() throws IOException, InterruptedException { assertTrue(connection.isOpen()); restartPrimaryAndWaitForRecovery(); assertTrue(connection.isOpen()); } @Test public void connectionRecoveryWithArrayOfAddresses() throws IOException, InterruptedException, TimeoutException { final Address[] addresses = {new Address("127.0.0.1"), new Address("127.0.0.1", 5672)}; RecoverableConnection c = newRecoveringConnection(addresses); try { assertTrue(c.isOpen()); closeAndWaitForRecovery(c); assertTrue(c.isOpen()); } finally { c.abort(); } } @Test public void connectionRecoveryWithListOfAddresses() throws IOException, InterruptedException, TimeoutException { final List
addresses = Arrays.asList(new Address("127.0.0.1"), new Address("127.0.0.1", 5672)); RecoverableConnection c = newRecoveringConnection(addresses); try { assertTrue(c.isOpen()); closeAndWaitForRecovery(c); assertTrue(c.isOpen()); } finally { c.abort(); } } @Test public void connectionRecoveryWithDisabledTopologyRecovery() throws IOException, InterruptedException, TimeoutException { RecoverableConnection c = newRecoveringConnection(true); Channel ch = c.createChannel(); String q = "java-client.test.recovery.q2"; ch.queueDeclare(q, false, true, false, null); ch.queueDeclarePassive(q); assertTrue(c.isOpen()); try { CountDownLatch shutdownLatch = prepareForShutdown(c); CountDownLatch recoveryLatch = prepareForRecovery(c); Host.closeConnection((NetworkConnection) c); wait(shutdownLatch); wait(recoveryLatch); assertTrue(c.isOpen()); ch.queueDeclarePassive(q); fail("expected passive declaration to throw"); } catch (java.io.IOException e) { // expected } finally { c.abort(); } } // see https://github.com/rabbitmq/rabbitmq-java-client/issues/135 @Test public void thatShutdownHooksOnConnectionFireBeforeRecoveryStarts() throws IOException, InterruptedException { final List events = new CopyOnWriteArrayList(); final CountDownLatch latch = new CountDownLatch(2); // one when started, another when complete connection.addShutdownListener(new ShutdownListener() { public void shutdownCompleted(ShutdownSignalException cause) { events.add("shutdown hook 1"); } }); connection.addShutdownListener(new ShutdownListener() { public void shutdownCompleted(ShutdownSignalException cause) { events.add("shutdown hook 2"); } }); // note: we do not want to expose RecoveryCanBeginListener so this // test does not use it final CountDownLatch recoveryCanBeginLatch = new CountDownLatch(1); ((AutorecoveringConnection)connection).getDelegate().addRecoveryCanBeginListener(new RecoveryCanBeginListener() { @Override public void recoveryCanBegin(ShutdownSignalException cause) { events.add("recovery start hook 1"); recoveryCanBeginLatch.countDown(); } }); ((RecoverableConnection)connection).addRecoveryListener(new RecoveryListener() { @Override public void handleRecovery(Recoverable recoverable) { latch.countDown(); } @Override public void handleRecoveryStarted(Recoverable recoverable) { latch.countDown(); } }); assertTrue(connection.isOpen()); closeAndWaitForRecovery(); assertTrue(connection.isOpen()); assertEquals("shutdown hook 1", events.get(0)); assertEquals("shutdown hook 2", events.get(1)); recoveryCanBeginLatch.await(5, TimeUnit.SECONDS); assertEquals("recovery start hook 1", events.get(2)); connection.close(); wait(latch); } @Test public void shutdownHooksRecoveryOnConnection() throws IOException, InterruptedException { final CountDownLatch latch = new CountDownLatch(2); connection.addShutdownListener(new ShutdownListener() { public void shutdownCompleted(ShutdownSignalException cause) { latch.countDown(); } }); assertTrue(connection.isOpen()); closeAndWaitForRecovery(); assertTrue(connection.isOpen()); connection.close(); wait(latch); } @Test public void shutdownHooksRecoveryOnChannel() throws IOException, InterruptedException { final CountDownLatch latch = new CountDownLatch(3); channel.addShutdownListener(new ShutdownListener() { public void shutdownCompleted(ShutdownSignalException cause) { latch.countDown(); } }); assertTrue(connection.isOpen()); closeAndWaitForRecovery(); assertTrue(connection.isOpen()); closeAndWaitForRecovery(); assertTrue(connection.isOpen()); connection.close(); wait(latch); } @Test public void blockedListenerRecovery() throws IOException, InterruptedException { final CountDownLatch latch = new CountDownLatch(2); connection.addBlockedListener(new BlockedListener() { public void handleBlocked(String reason) throws IOException { latch.countDown(); } public void handleUnblocked() throws IOException { latch.countDown(); } }); closeAndWaitForRecovery(); block(); channel.basicPublish("", "", null, "".getBytes()); unblock(); wait(latch); } @Test public void channelRecovery() throws IOException, InterruptedException { Channel ch1 = connection.createChannel(); Channel ch2 = connection.createChannel(); assertTrue(ch1.isOpen()); assertTrue(ch2.isOpen()); closeAndWaitForRecovery(); expectChannelRecovery(ch1); expectChannelRecovery(ch2); } @Test public void returnListenerRecovery() throws IOException, InterruptedException { final CountDownLatch latch = new CountDownLatch(1); channel.addReturnListener(new ReturnListener() { public void handleReturn(int replyCode, String replyText, String exchange, String routingKey, AMQP.BasicProperties properties, byte[] body) throws IOException { latch.countDown(); } }); closeAndWaitForRecovery(); expectChannelRecovery(channel); channel.basicPublish("", "unknown", true, false, null, "mandatory1".getBytes()); wait(latch); } @Test public void confirmListenerRecovery() throws IOException, InterruptedException, TimeoutException { final CountDownLatch latch = new CountDownLatch(1); channel.addConfirmListener(new ConfirmListener() { public void handleAck(long deliveryTag, boolean multiple) throws IOException { latch.countDown(); } public void handleNack(long deliveryTag, boolean multiple) throws IOException { latch.countDown(); } }); String q = channel.queueDeclare(UUID.randomUUID().toString(), false, false, false, null).getQueue(); closeAndWaitForRecovery(); expectChannelRecovery(channel); channel.confirmSelect(); basicPublishVolatile(q); waitForConfirms(channel); wait(latch); } @Test public void exchangeRecovery() throws IOException, InterruptedException, TimeoutException { Channel ch = connection.createChannel(); String x = "java-client.test.recovery.x1"; declareExchange(ch, x); closeAndWaitForRecovery(); expectChannelRecovery(ch); expectExchangeRecovery(ch, x); ch.exchangeDelete(x); } @Test public void exchangeRecoveryWithNoWait() throws IOException, InterruptedException, TimeoutException { Channel ch = connection.createChannel(); String x = "java-client.test.recovery.x1-nowait"; declareExchangeNoWait(ch, x); closeAndWaitForRecovery(); expectChannelRecovery(ch); expectExchangeRecovery(ch, x); ch.exchangeDelete(x); } @Test public void clientNamedQueueRecovery() throws IOException, InterruptedException, TimeoutException { testClientNamedQueueRecoveryWith("java-client.test.recovery.q1", false); } @Test public void clientNamedQueueRecoveryWithNoWait() throws IOException, InterruptedException, TimeoutException { testClientNamedQueueRecoveryWith("java-client.test.recovery.q1-nowait", true); } private void testClientNamedQueueRecoveryWith(String q, boolean noWait) throws IOException, InterruptedException, TimeoutException { Channel ch = connection.createChannel(); if(noWait) { declareClientNamedQueueNoWait(ch, q); } else { declareClientNamedQueue(ch, q); } closeAndWaitForRecovery(); expectChannelRecovery(ch); expectQueueRecovery(ch, q); ch.queueDelete(q); } @Test public void clientNamedQueueBindingRecovery() throws IOException, InterruptedException, TimeoutException { String q = "java-client.test.recovery.q2"; String x = "tmp-fanout"; Channel ch = connection.createChannel(); ch.queueDelete(q); ch.exchangeDelete(x); ch.exchangeDeclare(x, "fanout"); declareClientNamedAutoDeleteQueue(ch, q); ch.queueBind(q, x, ""); closeAndWaitForRecovery(); expectChannelRecovery(ch); expectAutoDeleteQueueAndBindingRecovery(ch, x, q); ch.queueDelete(q); ch.exchangeDelete(x); } // bug 26552 @Test public void clientNamedTransientAutoDeleteQueueAndBindingRecovery() throws IOException, InterruptedException, TimeoutException { String q = UUID.randomUUID().toString(); String x = "tmp-fanout"; Channel ch = connection.createChannel(); ch.queueDelete(q); ch.exchangeDelete(x); ch.exchangeDeclare(x, "fanout"); ch.queueDeclare(q, false, false, true, null); ch.queueBind(q, x, ""); restartPrimaryAndWaitForRecovery(); expectChannelRecovery(ch); ch.confirmSelect(); ch.queuePurge(q); ch.exchangeDeclare(x, "fanout"); ch.basicPublish(x, "", null, "msg".getBytes()); waitForConfirms(ch); AMQP.Queue.DeclareOk ok = ch.queueDeclare(q, false, false, true, null); assertEquals(1, ok.getMessageCount()); ch.queueDelete(q); ch.exchangeDelete(x); } // bug 26552 @Test public void serverNamedTransientAutoDeleteQueueAndBindingRecovery() throws IOException, InterruptedException, TimeoutException { String x = "tmp-fanout"; Channel ch = connection.createChannel(); ch.exchangeDelete(x); ch.exchangeDeclare(x, "fanout"); String q = ch.queueDeclare("", false, false, true, null).getQueue(); final AtomicReference nameBefore = new AtomicReference(q); final AtomicReference nameAfter = new AtomicReference(); final CountDownLatch listenerLatch = new CountDownLatch(1); ((AutorecoveringConnection)connection).addQueueRecoveryListener(new QueueRecoveryListener() { @Override public void queueRecovered(String oldName, String newName) { nameBefore.set(oldName); nameAfter.set(newName); listenerLatch.countDown(); } }); ch.queueBind(nameBefore.get(), x, ""); restartPrimaryAndWaitForRecovery(); expectChannelRecovery(ch); ch.confirmSelect(); ch.exchangeDeclare(x, "fanout"); ch.basicPublish(x, "", null, "msg".getBytes()); waitForConfirms(ch); AMQP.Queue.DeclareOk ok = ch.queueDeclarePassive(nameAfter.get()); assertEquals(1, ok.getMessageCount()); ch.queueDelete(nameAfter.get()); ch.exchangeDelete(x); } @Test public void declarationOfManyAutoDeleteQueuesWithTransientConsumer() throws IOException, TimeoutException { Channel ch = connection.createChannel(); assertRecordedQueues(connection, 0); for(int i = 0; i < 5000; i++) { String q = UUID.randomUUID().toString(); ch.queueDeclare(q, false, false, true, null); DefaultConsumer dummy = new DefaultConsumer(ch); String tag = ch.basicConsume(q, true, dummy); ch.basicCancel(tag); } assertRecordedQueues(connection, 0); ch.close(); } @Test public void declarationOfManyAutoDeleteExchangesWithTransientQueuesThatAreUnbound() throws IOException, TimeoutException { Channel ch = connection.createChannel(); assertRecordedExchanges(connection, 0); for(int i = 0; i < 5000; i++) { String x = UUID.randomUUID().toString(); ch.exchangeDeclare(x, "fanout", false, true, null); String q = ch.queueDeclare().getQueue(); final String rk = "doesn't matter"; ch.queueBind(q, x, rk); ch.queueUnbind(q, x, rk); ch.queueDelete(q); } assertRecordedExchanges(connection, 0); ch.close(); } @Test public void declarationOfManyAutoDeleteExchangesWithTransientQueuesThatAreDeleted() throws IOException, TimeoutException { Channel ch = connection.createChannel(); assertRecordedExchanges(connection, 0); for(int i = 0; i < 5000; i++) { String x = UUID.randomUUID().toString(); ch.exchangeDeclare(x, "fanout", false, true, null); String q = ch.queueDeclare().getQueue(); ch.queueBind(q, x, "doesn't matter"); ch.queueDelete(q); } assertRecordedExchanges(connection, 0); ch.close(); } @Test public void declarationOfManyAutoDeleteExchangesWithTransientExchangesThatAreUnbound() throws IOException, TimeoutException { Channel ch = connection.createChannel(); assertRecordedExchanges(connection, 0); for(int i = 0; i < 5000; i++) { String src = "src-" + UUID.randomUUID().toString(); String dest = "dest-" + UUID.randomUUID().toString(); ch.exchangeDeclare(src, "fanout", false, true, null); ch.exchangeDeclare(dest, "fanout", false, true, null); final String rk = "doesn't matter"; ch.exchangeBind(dest, src, rk); ch.exchangeUnbind(dest, src, rk); ch.exchangeDelete(dest); } assertRecordedExchanges(connection, 0); ch.close(); } @Test public void declarationOfManyAutoDeleteExchangesWithTransientExchangesThatAreDeleted() throws IOException, TimeoutException { Channel ch = connection.createChannel(); assertRecordedExchanges(connection, 0); for(int i = 0; i < 5000; i++) { String src = "src-" + UUID.randomUUID().toString(); String dest = "dest-" + UUID.randomUUID().toString(); ch.exchangeDeclare(src, "fanout", false, true, null); ch.exchangeDeclare(dest, "fanout", false, true, null); ch.exchangeBind(dest, src, "doesn't matter"); ch.exchangeDelete(dest); } assertRecordedExchanges(connection, 0); ch.close(); } @Test public void serverNamedQueueRecovery() throws IOException, InterruptedException { String q = channel.queueDeclare("", false, false, false, null).getQueue(); String x = "amq.fanout"; channel.queueBind(q, x, ""); final AtomicReference nameBefore = new AtomicReference(); final AtomicReference nameAfter = new AtomicReference(); final CountDownLatch listenerLatch = new CountDownLatch(1); ((AutorecoveringConnection)connection).addQueueRecoveryListener(new QueueRecoveryListener() { @Override public void queueRecovered(String oldName, String newName) { nameBefore.set(oldName); nameAfter.set(newName); listenerLatch.countDown(); } }); closeAndWaitForRecovery(); wait(listenerLatch); expectChannelRecovery(channel); channel.basicPublish(x, "", null, "msg".getBytes()); assertDelivered(q, 1); assertFalse(nameBefore.get().equals(nameAfter.get())); channel.queueDelete(q); } @Test public void exchangeToExchangeBindingRecovery() throws IOException, InterruptedException { String q = channel.queueDeclare("", false, false, false, null).getQueue(); String x1 = "amq.fanout"; String x2 = generateExchangeName(); channel.exchangeDeclare(x2, "fanout"); channel.exchangeBind(x1, x2, ""); channel.queueBind(q, x1, ""); try { closeAndWaitForRecovery(); expectChannelRecovery(channel); channel.basicPublish(x2, "", null, "msg".getBytes()); assertDelivered(q, 1); } finally { channel.exchangeDelete(x2); channel.queueDelete(q); } } @Test public void thatDeletedQueueBindingsDontReappearOnRecovery() throws IOException, InterruptedException { String q = channel.queueDeclare("", false, false, false, null).getQueue(); String x1 = "amq.fanout"; String x2 = generateExchangeName(); channel.exchangeDeclare(x2, "fanout"); channel.exchangeBind(x1, x2, ""); channel.queueBind(q, x1, ""); channel.queueUnbind(q, x1, ""); try { closeAndWaitForRecovery(); expectChannelRecovery(channel); channel.basicPublish(x2, "", null, "msg".getBytes()); assertDelivered(q, 0); } finally { channel.exchangeDelete(x2); channel.queueDelete(q); } } @Test public void thatDeletedExchangeBindingsDontReappearOnRecovery() throws IOException, InterruptedException { String q = channel.queueDeclare("", false, false, false, null).getQueue(); String x1 = "amq.fanout"; String x2 = generateExchangeName(); channel.exchangeDeclare(x2, "fanout"); channel.exchangeBind(x1, x2, ""); channel.queueBind(q, x1, ""); channel.exchangeUnbind(x1, x2, ""); try { closeAndWaitForRecovery(); expectChannelRecovery(channel); channel.basicPublish(x2, "", null, "msg".getBytes()); assertDelivered(q, 0); } finally { channel.exchangeDelete(x2); channel.queueDelete(q); } } @Test public void thatDeletedExchangeDoesNotReappearOnRecover() throws IOException, InterruptedException { String x = generateExchangeName(); channel.exchangeDeclare(x, "fanout"); channel.exchangeDelete(x); try { closeAndWaitForRecovery(); expectChannelRecovery(channel); channel.exchangeDeclarePassive(x); fail("Expected passive declare to fail"); } catch (IOException ioe) { // expected } } @Test public void thatDeletedQueueDoesNotReappearOnRecover() throws IOException, InterruptedException { String q = channel.queueDeclare().getQueue(); channel.queueDelete(q); try { closeAndWaitForRecovery(); expectChannelRecovery(channel); channel.queueDeclarePassive(q); fail("Expected passive declare to fail"); } catch (IOException ioe) { // expected } } @Test public void thatCancelledConsumerDoesNotReappearOnRecover() throws IOException, InterruptedException { String q = UUID.randomUUID().toString(); channel.queueDeclare(q, false, false, false, null); String tag = channel.basicConsume(q, new DefaultConsumer(channel)); assertConsumerCount(1, q); channel.basicCancel(tag); closeAndWaitForRecovery(); expectChannelRecovery(channel); assertConsumerCount(0, q); } @Test public void consumerRecoveryWithManyConsumers() throws IOException, InterruptedException { String q = channel.queueDeclare(UUID.randomUUID().toString(), false, false, false, null).getQueue(); final int n = 1024; for (int i = 0; i < n; i++) { channel.basicConsume(q, new DefaultConsumer(channel)); } final AtomicReference tagA = new AtomicReference(); final AtomicReference tagB = new AtomicReference(); final CountDownLatch listenerLatch = new CountDownLatch(n); ((AutorecoveringConnection)connection).addConsumerRecoveryListener(new ConsumerRecoveryListener() { @Override public void consumerRecovered(String oldConsumerTag, String newConsumerTag) { tagA.set(oldConsumerTag); tagB.set(newConsumerTag); listenerLatch.countDown(); } }); assertConsumerCount(n, q); closeAndWaitForRecovery(); wait(listenerLatch); assertTrue(tagA.get().equals(tagB.get())); expectChannelRecovery(channel); assertConsumerCount(n, q); } @Test public void subsequentRecoveriesWithClientNamedQueue() throws IOException, InterruptedException { String q = channel.queueDeclare(UUID.randomUUID().toString(), false, false, false, null).getQueue(); assertConsumerCount(0, q); channel.basicConsume(q, new DefaultConsumer(channel)); for(int i = 0; i < 10; i++) { assertConsumerCount(1, q); closeAndWaitForRecovery(); } channel.queueDelete(q); } @Test public void queueRecoveryWithManyQueues() throws IOException, InterruptedException, TimeoutException { List qs = new ArrayList(); final int n = 1024; for (int i = 0; i < n; i++) { qs.add(channel.queueDeclare(UUID.randomUUID().toString(), true, false, false, null).getQueue()); } closeAndWaitForRecovery(); expectChannelRecovery(channel); for(String q : qs) { expectQueueRecovery(channel, q); channel.queueDelete(q); } } @Test public void channelRecoveryCallback() throws IOException, InterruptedException { final CountDownLatch latch = new CountDownLatch(2); final CountDownLatch startLatch = new CountDownLatch(2); final RecoveryListener listener = new RecoveryListener() { public void handleRecovery(Recoverable recoverable) { latch.countDown(); } public void handleRecoveryStarted(Recoverable recoverable) { startLatch.countDown(); } }; RecoverableChannel ch1 = (RecoverableChannel) connection.createChannel(); ch1.addRecoveryListener(listener); RecoverableChannel ch2 = (RecoverableChannel) connection.createChannel(); ch2.addRecoveryListener(listener); assertTrue(ch1.isOpen()); assertTrue(ch2.isOpen()); closeAndWaitForRecovery(); expectChannelRecovery(ch1); expectChannelRecovery(ch2); wait(latch); wait(startLatch); } @Test public void basicAckAfterChannelRecovery() throws IOException, InterruptedException, TimeoutException { final AtomicInteger consumed = new AtomicInteger(0); int n = 5; final CountDownLatch latch = new CountDownLatch(n); Consumer consumer = new DefaultConsumer(channel) { @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { try { if (consumed.intValue() > 0 && consumed.intValue() % 4 == 0) { CountDownLatch recoveryLatch = prepareForRecovery(connection); Host.closeConnection((AutorecoveringConnection)connection); ConnectionRecovery.wait(recoveryLatch); } channel.basicAck(envelope.getDeliveryTag(), false); } catch (InterruptedException e) { // ignore } finally { consumed.incrementAndGet(); latch.countDown(); } } }; String q = channel.queueDeclare().getQueue(); channel.basicConsume(q, consumer); RecoverableConnection publishingConnection = newRecoveringConnection(false); Channel publishingChannel = publishingConnection.createChannel(); for (int i = 0; i < n; i++) { publishingChannel.basicPublish("", q, null, "msg".getBytes()); } wait(latch); publishingConnection.abort(); } @Test public void consumersAreRemovedFromConnectionWhenChannelIsClosed() throws Exception { RecoverableConnection connection = newRecoveringConnection(true); try { Field consumersField = AutorecoveringConnection.class.getDeclaredField("consumers"); consumersField.setAccessible(true); Map connectionConsumers = (Map) consumersField.get(connection); Channel channel1 = connection.createChannel(); Channel channel2 = connection.createChannel(); assertEquals(0, connectionConsumers.size()); String queue = channel1.queueDeclare().getQueue(); channel1.basicConsume(queue, true, new HashMap(), new DefaultConsumer(channel1)); assertEquals(1, connectionConsumers.size()); channel1.basicConsume(queue, true, new HashMap(), new DefaultConsumer(channel1)); assertEquals(2, connectionConsumers.size()); channel2.basicConsume(queue, true, new HashMap(), new DefaultConsumer(channel2)); assertEquals(3, connectionConsumers.size()); channel1.close(); assertEquals(3 - 2, connectionConsumers.size()); channel2.close(); assertEquals(0, connectionConsumers.size()); } finally { connection.abort(); } } private void assertConsumerCount(int exp, String q) throws IOException { assertEquals(exp, channel.queueDeclarePassive(q).getConsumerCount()); } private AMQP.Queue.DeclareOk declareClientNamedQueue(Channel ch, String q) throws IOException { return ch.queueDeclare(q, true, false, false, null); } private AMQP.Queue.DeclareOk declareClientNamedAutoDeleteQueue(Channel ch, String q) throws IOException { return ch.queueDeclare(q, true, false, true, null); } private void declareClientNamedQueueNoWait(Channel ch, String q) throws IOException { ch.queueDeclareNoWait(q, true, false, false, null); } private AMQP.Exchange.DeclareOk declareExchange(Channel ch, String x) throws IOException { return ch.exchangeDeclare(x, "fanout", false); } private void declareExchangeNoWait(Channel ch, String x) throws IOException { ch.exchangeDeclareNoWait(x, "fanout", false, false, false, null); } private void expectQueueRecovery(Channel ch, String q) throws IOException, InterruptedException, TimeoutException { ch.confirmSelect(); ch.queuePurge(q); AMQP.Queue.DeclareOk ok1 = declareClientNamedQueue(ch, q); assertEquals(0, ok1.getMessageCount()); ch.basicPublish("", q, null, "msg".getBytes()); waitForConfirms(ch); AMQP.Queue.DeclareOk ok2 = declareClientNamedQueue(ch, q); assertEquals(1, ok2.getMessageCount()); } private void expectAutoDeleteQueueAndBindingRecovery(Channel ch, String x, String q) throws IOException, InterruptedException, TimeoutException { ch.confirmSelect(); ch.queuePurge(q); AMQP.Queue.DeclareOk ok1 = declareClientNamedAutoDeleteQueue(ch, q); assertEquals(0, ok1.getMessageCount()); ch.exchangeDeclare(x, "fanout"); ch.basicPublish(x, "", null, "msg".getBytes()); waitForConfirms(ch); AMQP.Queue.DeclareOk ok2 = declareClientNamedAutoDeleteQueue(ch, q); assertEquals(1, ok2.getMessageCount()); } private void expectExchangeRecovery(Channel ch, String x) throws IOException, InterruptedException, TimeoutException { ch.confirmSelect(); String q = ch.queueDeclare().getQueue(); final String rk = "routing-key"; ch.queueBind(q, x, rk); ch.basicPublish(x, rk, null, "msg".getBytes()); waitForConfirms(ch); ch.exchangeDeclarePassive(x); } private CountDownLatch prepareForRecovery(Connection conn) { final CountDownLatch latch = new CountDownLatch(1); ((AutorecoveringConnection)conn).addRecoveryListener(new RecoveryListener() { public void handleRecovery(Recoverable recoverable) { latch.countDown(); } public void handleRecoveryStarted(Recoverable recoverable) { // No-op } }); return latch; } private CountDownLatch prepareForShutdown(Connection conn) throws InterruptedException { final CountDownLatch latch = new CountDownLatch(1); conn.addShutdownListener(new ShutdownListener() { public void shutdownCompleted(ShutdownSignalException cause) { latch.countDown(); } }); return latch; } private void closeAndWaitForRecovery() throws IOException, InterruptedException { closeAndWaitForRecovery((AutorecoveringConnection)this.connection); } private void closeAndWaitForRecovery(RecoverableConnection connection) throws IOException, InterruptedException { CountDownLatch latch = prepareForRecovery(connection); Host.closeConnection((NetworkConnection) connection); wait(latch); } private void restartPrimaryAndWaitForRecovery() throws IOException, InterruptedException { restartPrimaryAndWaitForRecovery(this.connection); } private void restartPrimaryAndWaitForRecovery(Connection connection) throws IOException, InterruptedException { CountDownLatch latch = prepareForRecovery(connection); // restart without tearing down and setting up // new connection and channel bareRestart(); wait(latch); } private void expectChannelRecovery(Channel ch) throws InterruptedException { assertTrue(ch.isOpen()); } @Override protected ConnectionFactory newConnectionFactory() { return buildConnectionFactoryWithRecoveryEnabled(false); } private RecoverableConnection newRecoveringConnection(boolean disableTopologyRecovery) throws IOException, TimeoutException { ConnectionFactory cf = buildConnectionFactoryWithRecoveryEnabled(disableTopologyRecovery); return (AutorecoveringConnection) cf.newConnection(); } private RecoverableConnection newRecoveringConnection(Address[] addresses) throws IOException, TimeoutException { ConnectionFactory cf = buildConnectionFactoryWithRecoveryEnabled(false); // specifically use the Address[] overload return (AutorecoveringConnection) cf.newConnection(addresses); } private RecoverableConnection newRecoveringConnection(boolean disableTopologyRecovery, List
addresses) throws IOException, TimeoutException { ConnectionFactory cf = buildConnectionFactoryWithRecoveryEnabled(disableTopologyRecovery); return (AutorecoveringConnection) cf.newConnection(addresses); } private RecoverableConnection newRecoveringConnection(List
addresses) throws IOException, TimeoutException { return newRecoveringConnection(false, addresses); } private RecoverableConnection newRecoveringConnection(boolean disableTopologyRecovery, String connectionName) throws IOException, TimeoutException { ConnectionFactory cf = buildConnectionFactoryWithRecoveryEnabled(disableTopologyRecovery); return (RecoverableConnection) cf.newConnection(connectionName); } private RecoverableConnection newRecoveringConnection(String connectionName) throws IOException, TimeoutException { return newRecoveringConnection(false, connectionName); } private ConnectionFactory buildConnectionFactoryWithRecoveryEnabled(boolean disableTopologyRecovery) { ConnectionFactory cf = TestUtils.connectionFactory(); cf.setNetworkRecoveryInterval(RECOVERY_INTERVAL); cf.setAutomaticRecoveryEnabled(true); if (disableTopologyRecovery) { cf.setTopologyRecoveryEnabled(false); } return cf; } private static void wait(CountDownLatch latch) throws InterruptedException { // we want to wait for recovery to complete for a reasonable amount of time // but still make recovery failures easy to notice in development environments assertTrue(latch.await(90, TimeUnit.SECONDS)); } private void waitForConfirms(Channel ch) throws InterruptedException, TimeoutException { ch.waitForConfirms(30 * 60 * 1000); } private void assertRecordedQueues(Connection conn, int size) { assertEquals(size, ((AutorecoveringConnection)conn).getRecordedQueues().size()); } private void assertRecordedExchanges(Connection conn, int size) { assertEquals(size, ((AutorecoveringConnection)conn).getRecordedExchanges().size()); } } ConsumerCancelNotification.java000066400000000000000000000067111316117667700352350ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import com.rabbitmq.client.Channel; import com.rabbitmq.client.Consumer; import com.rabbitmq.client.DefaultConsumer; import com.rabbitmq.client.ShutdownSignalException; import com.rabbitmq.client.test.BrokerTestCase; import org.junit.Test; import java.io.IOException; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; public class ConsumerCancelNotification extends BrokerTestCase { private final String queue = "cancel_notification_queue"; @Test public void consumerCancellationNotification() throws IOException, InterruptedException { final BlockingQueue result = new ArrayBlockingQueue(1); channel.queueDeclare(queue, false, true, false, null); Consumer consumer = new DefaultConsumer(channel) { @Override public void handleCancel(String consumerTag) throws IOException { try { result.put(true); } catch (InterruptedException e) { fail(); } } }; channel.basicConsume(queue, consumer); channel.queueDelete(queue); assertTrue(result.take()); } class AlteringConsumer extends DefaultConsumer { private final String altQueue; private final CountDownLatch latch; public AlteringConsumer(Channel channel, String altQueue, CountDownLatch latch) { super(channel); this.altQueue = altQueue; this.latch = latch; } @Override public void handleShutdownSignal(String consumerTag, ShutdownSignalException sig) { // no-op } @Override public void handleCancel(String consumerTag) { try { this.getChannel().queueDeclare(this.altQueue, false, true, false, null); latch.countDown(); } catch (IOException e) { // e.printStackTrace(); } } } @Test public void consumerCancellationHandlerUsesBlockingOperations() throws IOException, InterruptedException { final String altQueue = "basic.cancel.fallback"; channel.queueDeclare(queue, false, true, false, null); CountDownLatch latch = new CountDownLatch(1); final AlteringConsumer consumer = new AlteringConsumer(channel, altQueue, latch); channel.basicConsume(queue, consumer); channel.queueDelete(queue); latch.await(2, TimeUnit.SECONDS); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/ConsumerCount.java000066400000000000000000000026571316117667700326550ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import static org.junit.Assert.assertEquals; import java.io.IOException; import org.junit.Test; import com.rabbitmq.client.DefaultConsumer; import com.rabbitmq.client.test.BrokerTestCase; public class ConsumerCount extends BrokerTestCase { @Test public void consumerCount() throws IOException { String q = generateQueueName(); channel.queueDeclare(q, false, true, false, null); assertEquals(0, channel.consumerCount(q)); String tag = channel.basicConsume(q, new DefaultConsumer(channel)); assertEquals(1, channel.consumerCount(q)); channel.basicCancel(tag); assertEquals(0, channel.consumerCount(q)); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/ConsumerPriorities.java000066400000000000000000000103601316117667700337040ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import com.rabbitmq.client.*; import com.rabbitmq.client.test.BrokerTestCase; import org.junit.Test; import java.io.IOException; import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; public class ConsumerPriorities extends BrokerTestCase { @Test public void validation() throws IOException { assertFailValidation(args("banana")); assertFailValidation(args(new HashMap())); assertFailValidation(args(null)); assertFailValidation(args(Arrays.asList(1, 2, 3))); } private void assertFailValidation(Map args) throws IOException { Channel ch = connection.createChannel(); String queue = ch.queueDeclare().getQueue(); try { ch.basicConsume(queue, true, args, new DefaultConsumer(ch)); fail("Validation should fail for " + args); } catch (IOException ioe) { checkShutdownSignal(AMQP.PRECONDITION_FAILED, ioe); } } private static final int COUNT = 10; @Test public void consumerPriorities() throws Exception { String queue = channel.queueDeclare().getQueue(); QueueMessageConsumer highConsumer = new QueueMessageConsumer(channel); QueueMessageConsumer medConsumer = new QueueMessageConsumer(channel); QueueMessageConsumer lowConsumer = new QueueMessageConsumer(channel); String high = channel.basicConsume(queue, true, args(1), highConsumer); String med = channel.basicConsume(queue, true, medConsumer); channel.basicConsume(queue, true, args(-1), lowConsumer); publish(queue, COUNT, "high"); channel.basicCancel(high); publish(queue, COUNT, "med"); channel.basicCancel(med); publish(queue, COUNT, "low"); assertContents(highConsumer, COUNT, "high"); assertContents(medConsumer, COUNT, "med"); assertContents(lowConsumer, COUNT, "low"); } private Map args(Object o) { Map map = new HashMap(); map.put("x-priority", o); return map; } private void assertContents(QueueMessageConsumer c, int count, String msg) throws InterruptedException { for (int i = 0; i < count; i++) { byte[] body = c.nextDelivery(100); assertEquals(msg, new String(body)); } assertEquals(null, c.nextDelivery()); } private void publish(String queue, int count, String msg) throws IOException { for (int i = 0; i < count; i++) { channel.basicPublish("", queue, MessageProperties.MINIMAL_BASIC, msg.getBytes()); } } class QueueMessageConsumer extends DefaultConsumer { BlockingQueue messages = new LinkedBlockingQueue(); public QueueMessageConsumer(Channel channel) { super(channel); } @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { messages.add(body); } byte[] nextDelivery() { return messages.poll(); } byte[] nextDelivery(long timeoutInMs) throws InterruptedException { return messages.poll(timeoutInMs, TimeUnit.MILLISECONDS); } } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/DeadLetterExchange.java000066400000000000000000000662021316117667700335250ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import com.rabbitmq.client.*; import com.rabbitmq.client.AMQP.BasicProperties; import com.rabbitmq.client.test.BrokerTestCase; import com.rabbitmq.client.test.TestUtils; import org.junit.Test; import java.io.IOException; import java.util.*; import java.util.concurrent.*; import static org.junit.Assert.*; public class DeadLetterExchange extends BrokerTestCase { public static final String DLX = "dead.letter.exchange"; public static final String DLX_ARG = "x-dead-letter-exchange"; public static final String DLX_RK_ARG = "x-dead-letter-routing-key"; public static final String TEST_QUEUE_NAME = "test.queue.dead.letter"; public static final String DLQ = "queue.dlq"; public static final String DLQ2 = "queue.dlq2"; public static final int MSG_COUNT = 10; public static final int TTL = 1000; @Override protected void createResources() throws IOException { channel.exchangeDelete(DLX); channel.queueDelete(DLQ); channel.exchangeDeclare(DLX, "direct"); channel.queueDeclare(DLQ, false, true, false, null); } @Override protected void releaseResources() throws IOException { channel.exchangeDelete(DLX); } @Test public void declareQueueWithExistingDeadLetterExchange() throws IOException { declareQueue(DLX); } @Test public void declareQueueWithNonExistingDeadLetterExchange() throws IOException { declareQueue("some.random.exchange.name"); } @Test public void declareQueueWithEquivalentDeadLetterExchange() throws IOException { declareQueue(DLX); declareQueue(DLX); } @Test public void declareQueueWithEquivalentDeadLetterRoutingKey() throws IOException { declareQueue(TEST_QUEUE_NAME, DLX, "routing_key", null); declareQueue(TEST_QUEUE_NAME, DLX, "routing_key", null); } @Test public void declareQueueWithInvalidDeadLetterExchangeArg() throws IOException { try { declareQueue(133); fail("x-dead-letter-exchange must be a valid exchange name"); } catch (IOException ex) { checkShutdownSignal(AMQP.PRECONDITION_FAILED, ex); } } @Test public void redeclareQueueWithInvalidDeadLetterExchangeArg() throws IOException { declareQueue("inequivalent_dlx_name", "dlx_foo", null, null); try { declareQueue("inequivalent_dlx_name", "dlx_bar", null, null); fail("x-dead-letter-exchange must be a valid exchange name " + "and must not change in subsequent declarations"); } catch (IOException ex) { checkShutdownSignal(AMQP.PRECONDITION_FAILED, ex); } } @Test public void declareQueueWithInvalidDeadLetterRoutingKeyArg() throws IOException { try { declareQueue("foo", "amq.direct", 144, null); fail("x-dead-letter-routing-key must be a string"); } catch (IOException ex) { checkShutdownSignal(AMQP.PRECONDITION_FAILED, ex); } } @Test public void redeclareQueueWithInvalidDeadLetterRoutingKeyArg() throws IOException { declareQueue("inequivalent_dlx_rk", "amq.direct", "dlx_rk", null); try { declareQueue("inequivalent_dlx_rk", "amq.direct", "dlx_rk2", null); fail("x-dead-letter-routing-key must be a string and must not " + "change in subsequent declarations"); } catch (IOException ex) { checkShutdownSignal(AMQP.PRECONDITION_FAILED, ex); } } @Test public void declareQueueWithRoutingKeyButNoDeadLetterExchange() throws IOException { try { Map args = new HashMap(); args.put(DLX_RK_ARG, "foo"); channel.queueDeclare(randomQueueName(), false, true, false, args); fail("dlx must be defined if dl-rk is set"); } catch (IOException ex) { checkShutdownSignal(AMQP.PRECONDITION_FAILED, ex); } } @Test public void redeclareQueueWithRoutingKeyButNoDeadLetterExchange() throws IOException, InterruptedException { try { String queueName = randomQueueName(); Map args = new HashMap(); channel.queueDeclare(queueName, false, true, false, args); args.put(DLX_RK_ARG, "foo"); channel.queueDeclare(queueName, false, true, false, args); fail("x-dead-letter-exchange must be specified if " + "x-dead-letter-routing-key is set"); } catch (IOException ex) { checkShutdownSignal(AMQP.PRECONDITION_FAILED, ex); } } @Test public void deadLetterQueueTTLExpiredMessages() throws Exception { ttlTest(TTL); } @Test public void deadLetterQueueZeroTTLExpiredMessages() throws Exception { ttlTest(0); } @Test public void deadLetterQueueTTLPromptExpiry() throws Exception { Map args = new HashMap(); args.put("x-message-ttl", TTL); declareQueue(TEST_QUEUE_NAME, DLX, null, args); channel.queueBind(TEST_QUEUE_NAME, "amq.direct", "test"); channel.queueBind(DLQ, DLX, "test"); //measure round-trip latency AccumulatingMessageConsumer c = new AccumulatingMessageConsumer(channel); String cTag = channel.basicConsume(TEST_QUEUE_NAME, true, c); long start = System.currentTimeMillis(); publish(null, "test"); byte[] body = c.nextDelivery(TTL); long stop = System.currentTimeMillis(); assertNotNull(body); channel.basicCancel(cTag); long latency = stop-start; channel.basicConsume(DLQ, true, c); // publish messages at regular intervals until currentTime + // 3/4th of TTL int count = 0; start = System.currentTimeMillis(); stop = start + TTL * 3 / 4; long now = start; while (now < stop) { publish(null, Long.toString(now)); count++; Thread.sleep(TTL / 100); now = System.currentTimeMillis(); } checkPromptArrival(c, count, latency); start = System.currentTimeMillis(); // publish message - which kicks off the queue's ttl timer - // and immediately fetch it in noack mode publishAt(start); basicGet(TEST_QUEUE_NAME); // publish a 2nd message and immediately fetch it in ack mode publishAt(start + TTL * 1 / 2); GetResponse r = channel.basicGet(TEST_QUEUE_NAME, false); // publish a 3rd message publishAt(start + TTL * 3 / 4); // reject 2nd message after the initial timer has fired but // before the message is due to expire waitUntil(start + TTL * 5 / 4); channel.basicReject(r.getEnvelope().getDeliveryTag(), true); checkPromptArrival(c, 2, latency); } @Test public void deadLetterDeletedDLX() throws Exception { declareQueue(TEST_QUEUE_NAME, DLX, null, null, 1); channel.queueBind(TEST_QUEUE_NAME, "amq.direct", "test"); channel.queueBind(DLQ, DLX, "test"); channel.exchangeDelete(DLX); publishN(MSG_COUNT); sleep(100); consumeN(DLQ, 0, WithResponse.NULL); channel.exchangeDeclare(DLX, "direct"); channel.queueBind(DLQ, DLX, "test"); publishN(MSG_COUNT); sleep(100); consumeN(DLQ, MSG_COUNT, WithResponse.NULL); } @Test public void deadLetterPerMessageTTLRemoved() throws Exception { declareQueue(TEST_QUEUE_NAME, DLX, null, null, 1); channel.queueBind(TEST_QUEUE_NAME, "amq.direct", "test"); channel.queueBind(DLQ, DLX, "test"); final BasicProperties props = MessageProperties.BASIC.builder().expiration("100").build(); publish(props, "test message"); // The message's expiration property should have been removed, thus // after 100ms of hitting the queue, the message should get routed to // the DLQ *AND* should remain there, not getting removed after a subsequent // wait time > 100ms sleep(500); consumeN(DLQ, 1, new WithResponse() { @SuppressWarnings("unchecked") public void process(GetResponse getResponse) { assertNull(getResponse.getProps().getExpiration()); Map headers = getResponse.getProps().getHeaders(); assertNotNull(headers); ArrayList death = (ArrayList)headers.get("x-death"); assertNotNull(death); assertDeathReason(death, 0, TEST_QUEUE_NAME, "expired"); final Map deathHeader = (Map)death.get(0); assertEquals("100", deathHeader.get("original-expiration").toString()); } }); } @Test public void deadLetterOnReject() throws Exception { rejectionTest(false); } @Test public void deadLetterOnNack() throws Exception { rejectionTest(true); } @Test public void deadLetterNoDeadLetterQueue() throws IOException { channel.queueDelete(DLQ); declareQueue(TEST_QUEUE_NAME, DLX, null, null, 1); channel.queueBind(TEST_QUEUE_NAME, "amq.direct", "test"); publishN(MSG_COUNT); } @Test public void deadLetterMultipleDeadLetterQueues() throws IOException { declareQueue(TEST_QUEUE_NAME, DLX, null, null, 1); channel.queueDeclare(DLQ2, false, true, false, null); channel.queueBind(TEST_QUEUE_NAME, "amq.direct", "test"); channel.queueBind(DLQ, DLX, "test"); channel.queueBind(DLQ2, DLX, "test"); publishN(MSG_COUNT); } @Test public void deadLetterTwice() throws Exception { declareQueue(TEST_QUEUE_NAME, DLX, null, null, 1); channel.queueDelete(DLQ); declareQueue(DLQ, DLX, null, null, 1); channel.queueDeclare(DLQ2, false, true, false, null); channel.queueBind(TEST_QUEUE_NAME, "amq.direct", "test"); channel.queueBind(DLQ, DLX, "test"); channel.queueBind(DLQ2, DLX, "test"); publishN(MSG_COUNT); sleep(100); // There should now be two copies of each message on DLQ2: one // with one set of death headers, and another with two sets. consumeN(DLQ2, MSG_COUNT*2, new WithResponse() { @SuppressWarnings("unchecked") public void process(GetResponse getResponse) { Map headers = getResponse.getProps().getHeaders(); assertNotNull(headers); ArrayList death = (ArrayList)headers.get("x-death"); assertNotNull(death); if (death.size() == 1) { assertDeathReason(death, 0, TEST_QUEUE_NAME, "expired"); } else if (death.size() == 2) { assertDeathReason(death, 0, DLQ, "expired"); assertDeathReason(death, 1, TEST_QUEUE_NAME, "expired"); } else { fail("message was dead-lettered more times than expected"); } } }); } @Test public void deadLetterSelf() throws Exception { declareQueue(TEST_QUEUE_NAME, "amq.direct", "test", null, 1); channel.queueBind(TEST_QUEUE_NAME, "amq.direct", "test"); publishN(MSG_COUNT); // This test hangs if the queue doesn't process ALL the // messages before being deleted, so make sure the next // sleep is long enough. sleep(200); // The messages will NOT be dead-lettered to self. consumeN(TEST_QUEUE_NAME, 0, WithResponse.NULL); } @Test public void deadLetterCycle() throws Exception { // testDeadLetterTwice and testDeadLetterSelf both test that we drop // messages in pure-expiry cycles. So we just need to test that // non-pure-expiry cycles do not drop messages. declareQueue("queue1", "", "queue2", null, 1); declareQueue("queue2", "", "queue1", null, 0); channel.basicPublish("", "queue1", MessageProperties.BASIC, "".getBytes()); final CountDownLatch latch = new CountDownLatch(10); channel.basicConsume("queue2", false, new DefaultConsumer(channel) { @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { channel.basicReject(envelope.getDeliveryTag(), false); latch.countDown(); } }); assertTrue(latch.await(10, TimeUnit.SECONDS)); } @Test public void deadLetterNewRK() throws Exception { declareQueue(TEST_QUEUE_NAME, DLX, "test-other", null, 1); channel.queueDeclare(DLQ2, false, true, false, null); channel.queueBind(TEST_QUEUE_NAME, "amq.direct", "test"); channel.queueBind(DLQ, DLX, "test"); channel.queueBind(DLQ2, DLX, "test-other"); Map headers = new HashMap(); headers.put("CC", Arrays.asList("foo")); headers.put("BCC", Arrays.asList("bar")); publishN(MSG_COUNT, (new AMQP.BasicProperties.Builder()) .headers(headers) .build()); sleep(100); consumeN(DLQ, 0, WithResponse.NULL); consumeN(DLQ2, MSG_COUNT, new WithResponse() { @SuppressWarnings("unchecked") public void process(GetResponse getResponse) { Map headers = getResponse.getProps().getHeaders(); assertNotNull(headers); assertNull(headers.get("CC")); assertNull(headers.get("BCC")); ArrayList death = (ArrayList)headers.get("x-death"); assertNotNull(death); assertEquals(1, death.size()); assertDeathReason(death, 0, TEST_QUEUE_NAME, "expired", "amq.direct", Arrays.asList("test", "foo")); } }); } @SuppressWarnings("unchecked") @Test public void republish() throws Exception { Map args = new HashMap(); args.put("x-message-ttl", 100); declareQueue(TEST_QUEUE_NAME, DLX, null, args); channel.queueBind(TEST_QUEUE_NAME, "amq.direct", "test"); channel.queueBind(DLQ, DLX, "test"); publishN(1); sleep(200); GetResponse getResponse = channel.basicGet(DLQ, true); assertNotNull("Message not dead-lettered", getResponse); assertEquals("test message", new String(getResponse.getBody())); BasicProperties props = getResponse.getProps(); Map headers = props.getHeaders(); assertNotNull(headers); ArrayList death = (ArrayList) headers.get("x-death"); assertNotNull(death); assertEquals(1, death.size()); assertDeathReason(death, 0, TEST_QUEUE_NAME, "expired", "amq.direct", Arrays.asList("test")); // Make queue zero length args = new HashMap(); args.put("x-max-length", 0); channel.queueDelete(TEST_QUEUE_NAME); declareQueue(TEST_QUEUE_NAME, DLX, null, args); channel.queueBind(TEST_QUEUE_NAME, "amq.direct", "test"); sleep(100); //Queueing second time with same props channel.basicPublish("amq.direct", "test", new AMQP.BasicProperties.Builder() .headers(headers) .build(), "test message".getBytes()); sleep(100); getResponse = channel.basicGet(DLQ, true); assertNotNull("Message not dead-lettered", getResponse); assertEquals("test message", new String(getResponse.getBody())); headers = getResponse.getProps().getHeaders(); assertNotNull(headers); death = (ArrayList) headers.get("x-death"); assertNotNull(death); assertEquals(2, death.size()); assertDeathReason(death, 0, TEST_QUEUE_NAME, "maxlen", "amq.direct", Arrays.asList("test")); assertDeathReason(death, 1, TEST_QUEUE_NAME, "expired", "amq.direct", Arrays.asList("test")); //Set invalid headers headers.put("x-death", "[I, am, not, array]"); channel.basicPublish("amq.direct", "test", new AMQP.BasicProperties.Builder() .headers(headers) .build(), "test message".getBytes()); sleep(100); getResponse = channel.basicGet(DLQ, true); assertNotNull("Message not dead-lettered", getResponse); assertEquals("test message", new String(getResponse.getBody())); headers = getResponse.getProps().getHeaders(); assertNotNull(headers); death = (ArrayList) headers.get("x-death"); assertNotNull(death); assertEquals(1, death.size()); assertDeathReason(death, 0, TEST_QUEUE_NAME, "maxlen", "amq.direct", Arrays.asList("test")); } public void rejectionTest(final boolean useNack) throws Exception { deadLetterTest(new Callable() { public Void call() throws Exception { for (int x = 0; x < MSG_COUNT; x++) { GetResponse getResponse = channel.basicGet(TEST_QUEUE_NAME, false); long tag = getResponse.getEnvelope().getDeliveryTag(); if (useNack) { channel.basicNack(tag, false, false); } else { channel.basicReject(tag, false); } } return null; } }, null, "rejected"); } private void deadLetterTest(final Runnable deathTrigger, Map queueDeclareArgs, String reason) throws Exception { deadLetterTest(new Callable() { public Object call() throws Exception { deathTrigger.run(); return null; } }, queueDeclareArgs, reason); } private void deadLetterTest(Callable deathTrigger, Map queueDeclareArgs, final String reason) throws Exception { declareQueue(TEST_QUEUE_NAME, DLX, null, queueDeclareArgs); channel.queueBind(TEST_QUEUE_NAME, "amq.direct", "test"); channel.queueBind(DLQ, DLX, "test"); publishN(MSG_COUNT); deathTrigger.call(); consume(channel, reason); } public static void consume(final Channel channel, final String reason) throws IOException { consumeN(channel, DLQ, MSG_COUNT, new WithResponse() { @SuppressWarnings("unchecked") public void process(GetResponse getResponse) { Map headers = getResponse.getProps().getHeaders(); assertNotNull(headers); ArrayList death = (ArrayList) headers.get("x-death"); assertNotNull(death); // the following assertions shouldn't be checked on version lower than 3.7 // as the headers are new in 3.7 // see https://github.com/rabbitmq/rabbitmq-server/issues/1332 if(TestUtils.isVersion37orLater(channel.getConnection())) { assertNotNull(headers.get("x-first-death-queue")); assertNotNull(headers.get("x-first-death-reason")); assertNotNull(headers.get("x-first-death-exchange")); } assertEquals(1, death.size()); assertDeathReason(death, 0, TEST_QUEUE_NAME, reason, "amq.direct", Arrays.asList("test")); } }); } private void ttlTest(final long ttl) throws Exception { Map args = new HashMap(); args.put("x-message-ttl", ttl); deadLetterTest(new Runnable() { public void run() { sleep(ttl + 1500); } }, args, "expired"); } private void sleep(long millis) { try { Thread.sleep(millis); } catch (InterruptedException ex) { // whoosh } } /* check that each message arrives within epsilon of the publication time + TTL + latency */ private void checkPromptArrival(AccumulatingMessageConsumer c, int count, long latency) throws Exception { long epsilon = TTL / 10; for (int i = 0; i < count; i++) { byte[] body = c.nextDelivery(TTL + TTL + latency + epsilon); assertNotNull("message #" + i + " did not expire", body); long now = System.currentTimeMillis(); long publishTime = Long.valueOf(new String(body)); long targetTime = publishTime + TTL + latency; assertTrue("expiry outside bounds (+/- " + epsilon + "): " + (now - targetTime), (now >= targetTime - epsilon) && (now <= targetTime + epsilon)); } } private void declareQueue(Object deadLetterExchange) throws IOException { declareQueue(TEST_QUEUE_NAME, deadLetterExchange, null, null); } private void declareQueue(String queue, Object deadLetterExchange, Object deadLetterRoutingKey, Map args) throws IOException { declareQueue(queue, deadLetterExchange, deadLetterRoutingKey, args, 0); } private void declareQueue(String queue, Object deadLetterExchange, Object deadLetterRoutingKey, Map args, int ttl) throws IOException { if (args == null) { args = new HashMap(); } if (ttl > 0){ args.put("x-message-ttl", ttl); } args.put(DLX_ARG, deadLetterExchange); if (deadLetterRoutingKey != null) { args.put(DLX_RK_ARG, deadLetterRoutingKey); } channel.queueDeclare(queue, false, true, false, args); } private void publishN(int n) throws IOException { publishN(n, null); } private void publishN(int n, AMQP.BasicProperties props) throws IOException { for(int x = 0; x < n; x++) { publish(props, "test message"); } } private void publish(AMQP.BasicProperties props, String body) throws IOException { channel.basicPublish("amq.direct", "test", props, body.getBytes()); } private void publishAt(long when) throws Exception { waitUntil(when); publish(null, Long.toString(System.currentTimeMillis())); } private void waitUntil(long when) throws Exception { long delay = when - System.currentTimeMillis(); Thread.sleep(delay > 0 ? delay : 0); } private void consumeN(String queue, int n, WithResponse withResponse) throws IOException { consumeN(channel, queue, n, withResponse); } private static void consumeN(Channel channel, String queue, int n, WithResponse withResponse) throws IOException { for(int x = 0; x < n; x++) { GetResponse getResponse = channel.basicGet(queue, true); assertNotNull("Messages not dead-lettered (" + (n-x) + " left)", getResponse); assertEquals("test message", new String(getResponse.getBody())); withResponse.process(getResponse); } GetResponse getResponse = channel.basicGet(queue, true); assertNull("expected empty queue", getResponse); } @SuppressWarnings("unchecked") private static void assertDeathReason(List death, int num, String queue, String reason, String exchange, List routingKeys) { Map deathHeader = (Map)death.get(num); assertEquals(exchange, deathHeader.get("exchange").toString()); List deathRKs = new ArrayList(); for (Object rk : (ArrayList)deathHeader.get("routing-keys")) { deathRKs.add(rk.toString()); } Collections.sort(deathRKs); Collections.sort(routingKeys); assertEquals(routingKeys, deathRKs); assertDeathReason(death, num, queue, reason); } @SuppressWarnings("unchecked") private static void assertDeathReason(List death, int num, String queue, String reason) { Map deathHeader = (Map)death.get(num); assertEquals(queue, deathHeader.get("queue").toString()); assertEquals(reason, deathHeader.get("reason").toString()); } private static interface WithResponse { static final WithResponse NULL = new WithResponse() { public void process(GetResponse getResponse) { } }; public void process(GetResponse response); } private static String randomQueueName() { return DeadLetterExchange.class.getSimpleName() + "-" + UUID.randomUUID().toString(); } class AccumulatingMessageConsumer extends DefaultConsumer { BlockingQueue messages = new LinkedBlockingQueue(); public AccumulatingMessageConsumer(Channel channel) { super(channel); } @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { messages.add(body); } byte[] nextDelivery() { return messages.poll(); } byte[] nextDelivery(long timeoutInMs) throws InterruptedException { return messages.poll(timeoutInMs, TimeUnit.MILLISECONDS); } } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/DefaultExchange.java000066400000000000000000000047311316117667700330730ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import static org.junit.Assert.fail; import java.io.IOException; import org.junit.Test; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.test.BrokerTestCase; public class DefaultExchange extends BrokerTestCase { String queueName; @Override protected void createResources() throws IOException { queueName = channel.queueDeclare().getQueue(); } // See bug 22101: publish and declare are the only operations // permitted on the default exchange @Test public void defaultExchangePublish() throws IOException { basicPublishVolatile("", queueName); // Implicit binding assertDelivered(queueName, 1); } @Test public void bindToDefaultExchange() throws IOException { try { channel.queueBind(queueName, "", "foobar"); fail(); } catch (IOException ioe) { checkShutdownSignal(AMQP.ACCESS_REFUSED, ioe); } } @Test public void unbindFromDefaultExchange() throws IOException { try { channel.queueUnbind(queueName, "", queueName); fail(); } catch (IOException ioe) { checkShutdownSignal(AMQP.ACCESS_REFUSED, ioe); } } @Test public void declareDefaultExchange() throws IOException { try { channel.exchangeDeclare("", "direct", true); fail(); } catch (IOException ioe) { checkShutdownSignal(AMQP.ACCESS_REFUSED, ioe); } } @Test public void deleteDefaultExchange() throws IOException { try { channel.exchangeDelete(""); fail(); } catch (IOException ioe) { checkShutdownSignal(AMQP.ACCESS_REFUSED, ioe); } } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/DirectReplyTo.java000066400000000000000000000120571316117667700325750ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.io.IOException; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import com.rabbitmq.client.*; import org.junit.Test; import com.rabbitmq.client.test.BrokerTestCase; public class DirectReplyTo extends BrokerTestCase { private static final String QUEUE = "amq.rabbitmq.reply-to"; @Test public void roundTrip() throws IOException, InterruptedException { QueueMessageConsumer c = new QueueMessageConsumer(channel); String replyTo = rpcFirstHalf(c); declare(connection, replyTo, true); channel.confirmSelect(); basicPublishVolatile("response".getBytes(), "", replyTo, MessageProperties.BASIC); channel.waitForConfirms(); byte[] body = c.nextDelivery(10000); assertEquals("response", new String(body)); } @Test public void hack() throws IOException, InterruptedException { QueueMessageConsumer c = new QueueMessageConsumer(channel); String replyTo = rpcFirstHalf(c); // 5 chars should overwrite part of the key but not the pid; aiming to prove // we can't publish using just the pid replyTo = replyTo.substring(0, replyTo.length() - 5) + "xxxxx"; declare(connection, replyTo, false); basicPublishVolatile("response".getBytes(), "", replyTo, MessageProperties.BASIC); byte[] body = c.nextDelivery(500); assertNull(body); } private void declare(Connection connection, String q, boolean expectedExists) throws IOException { Channel ch = connection.createChannel(); try { ch.queueDeclarePassive(q); assertTrue(expectedExists); } catch (IOException e) { assertFalse(expectedExists); checkShutdownSignal(AMQP.NOT_FOUND, e); // Hmmm... channel = connection.createChannel(); } } @Test public void consumeFail() throws IOException, InterruptedException { DefaultConsumer c = new DefaultConsumer(channel); Channel ch = connection.createChannel(); try { ch.basicConsume(QUEUE, false, c); } catch (IOException e) { // Can't have ack mode checkShutdownSignal(AMQP.PRECONDITION_FAILED, e); } ch = connection.createChannel(); ch.basicConsume(QUEUE, true, c); try { ch.basicConsume(QUEUE, true, c); } catch (IOException e) { // Can't have multiple consumers checkShutdownSignal(AMQP.PRECONDITION_FAILED, e); } } @Test public void consumeSuccess() throws IOException, InterruptedException { DefaultConsumer c = new DefaultConsumer(channel); String ctag = channel.basicConsume(QUEUE, true, c); channel.basicCancel(ctag); String ctag2 = channel.basicConsume(QUEUE, true, c); channel.basicCancel(ctag2); assertNotSame(ctag, ctag2); } private String rpcFirstHalf(Consumer c) throws IOException { channel.basicConsume(QUEUE, true, c); String serverQueue = channel.queueDeclare().getQueue(); basicPublishVolatile("request".getBytes(), "", serverQueue, props()); GetResponse req = channel.basicGet(serverQueue, true); return req.getProps().getReplyTo(); } private AMQP.BasicProperties props() { return MessageProperties.BASIC.builder().replyTo(QUEUE).build(); } class QueueMessageConsumer extends DefaultConsumer { BlockingQueue messages = new LinkedBlockingQueue(); public QueueMessageConsumer(Channel channel) { super(channel); } @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { messages.add(body); } byte[] nextDelivery() { return messages.poll(); } byte[] nextDelivery(long timeoutInMs) throws InterruptedException { return messages.poll(timeoutInMs, TimeUnit.MILLISECONDS); } } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/DoubleDeletion.java000066400000000000000000000030021316117667700327300ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import java.io.IOException; import org.junit.Test; import com.rabbitmq.client.test.BrokerTestCase; public class DoubleDeletion extends BrokerTestCase { protected static final String Q = "DoubleDeletionQueue"; protected static final String X = "DoubleDeletionExchange"; @Test public void doubleDeletionQueue() throws IOException { channel.queueDelete(Q); channel.queueDeclare(Q, false, false, false, null); channel.queueDelete(Q); channel.queueDelete(Q); } @Test public void doubleDeletionExchange() throws IOException { channel.exchangeDelete(X); channel.exchangeDeclare(X, "direct"); channel.exchangeDelete(X); channel.exchangeDelete(X); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/DurableOnTransient.java000066400000000000000000000054121316117667700336040ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import static org.junit.Assert.assertNotNull; import java.io.IOException; import org.junit.Test; import com.rabbitmq.client.GetResponse; import com.rabbitmq.client.MessageProperties; public class DurableOnTransient extends ClusteredTestBase { protected static final String Q = "SemiDurableBindings.DurableQueue"; protected static final String X = "SemiDurableBindings.TransientExchange"; private GetResponse basicGet() throws IOException { return channel.basicGet(Q, true); } private void basicPublish() throws IOException { channel.basicPublish(X, "", MessageProperties.PERSISTENT_TEXT_PLAIN, "persistent message".getBytes()); } protected void createResources() throws IOException { channel.exchangeDelete(X); // transient exchange channel.exchangeDeclare(X, "direct", false); channel.queueDelete(Q); // durable queue channel.queueDeclare(Q, true, false, false, null); } protected void releaseResources() throws IOException { channel.queueDelete(Q); channel.exchangeDelete(X); } @Test public void bindDurableToTransient() throws IOException { channel.queueBind(Q, X, ""); basicPublish(); assertNotNull(basicGet()); } @Test public void semiDurableBindingRemoval() throws IOException { if (clusteredConnection != null) { deleteExchange("x"); declareTransientTopicExchange("x"); clusteredChannel.queueDelete("q"); clusteredChannel.queueDeclare("q", true, false, false, null); channel.queueBind("q", "x", "k"); stopSecondary(); deleteExchange("x"); startSecondary(); declareTransientTopicExchange("x"); basicPublishVolatile("x", "k"); assertDelivered("q", 0); deleteQueue("q"); deleteExchange("x"); } } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/ExceptionHandling.java000066400000000000000000000106151316117667700334450ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import java.io.IOException; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import com.rabbitmq.client.test.TestUtils; import org.junit.Test; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; import com.rabbitmq.client.ConnectionFactory; import com.rabbitmq.client.Consumer; import com.rabbitmq.client.DefaultConsumer; import com.rabbitmq.client.Envelope; import com.rabbitmq.client.ExceptionHandler; import com.rabbitmq.client.impl.DefaultExceptionHandler; import com.rabbitmq.client.impl.ForgivingExceptionHandler; public class ExceptionHandling { private ConnectionFactory newConnectionFactory(ExceptionHandler eh) { ConnectionFactory cf = TestUtils.connectionFactory(); cf.setExceptionHandler(eh); return cf; } @Test public void defaultConsumerHandleConsumerException() throws IOException, InterruptedException, TimeoutException { final CountDownLatch latch = new CountDownLatch(1); final ExceptionHandler eh = new DefaultExceptionHandler() { @Override public void handleConsumerException(Channel channel, Throwable exception, Consumer consumer, String consumerTag, String methodName) { super.handleConsumerException(channel, exception, consumer, consumerTag, methodName); latch.countDown(); } }; testConsumerHandleConsumerException(eh, latch, true); } @Test public void forgivingConsumerHandleConsumerException() throws IOException, InterruptedException, TimeoutException { final CountDownLatch latch = new CountDownLatch(1); final ExceptionHandler eh = new ForgivingExceptionHandler() { @Override public void handleConsumerException(Channel channel, Throwable exception, Consumer consumer, String consumerTag, String methodName) { super.handleConsumerException(channel, exception, consumer, consumerTag, methodName); latch.countDown(); } }; testConsumerHandleConsumerException(eh, latch, false); } protected void testConsumerHandleConsumerException(ExceptionHandler eh, CountDownLatch latch, boolean expectChannelClose) throws InterruptedException, TimeoutException, IOException { ConnectionFactory cf = newConnectionFactory(eh); assertEquals(cf.getExceptionHandler(), eh); Connection conn = cf.newConnection(); assertEquals(conn.getExceptionHandler(), eh); Channel ch = conn.createChannel(); String q = ch.queueDeclare().getQueue(); ch.basicConsume(q, new DefaultConsumer(ch) { @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { throw new RuntimeException("exception expected here, don't freak out"); } }); ch.basicPublish("", q, null, "".getBytes()); wait(latch); assertEquals(!expectChannelClose, ch.isOpen()); } @Test public void nullExceptionHandler() { ConnectionFactory cf = TestUtils.connectionFactory(); try { cf.setExceptionHandler(null); fail("expected setExceptionHandler to throw"); } catch (IllegalArgumentException iae) { // expected } } private void wait(CountDownLatch latch) throws InterruptedException { latch.await(1800, TimeUnit.SECONDS); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/ExceptionMessages.java000066400000000000000000000041341316117667700334670ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.IOException; import java.util.UUID; import org.junit.Test; import com.rabbitmq.client.AlreadyClosedException; import com.rabbitmq.client.test.BrokerTestCase; public class ExceptionMessages extends BrokerTestCase { @Test public void alreadyClosedExceptionMessageWithChannelError() throws IOException { String uuid = UUID.randomUUID().toString(); try { channel.queueDeclarePassive(uuid); fail("expected queueDeclarePassive to throw"); } catch (IOException e) { // ignored } try { channel.queueDeclarePassive(uuid); fail("expected queueDeclarePassive to throw"); } catch (AlreadyClosedException ace) { assertTrue(ace.getMessage().startsWith("channel is already closed due to channel error")); } } @Test public void alreadyClosedExceptionMessageWithCleanClose() throws IOException { String uuid = UUID.randomUUID().toString(); try { channel.abort(); channel.queueDeclare(uuid, false, false, false, null); } catch (AlreadyClosedException ace) { assertTrue(ace.getMessage().startsWith("channel is already closed due to clean channel shutdown")); } } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/ExchangeDeclare.java000066400000000000000000000124101316117667700330370ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import static org.junit.Assert.assertEquals; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeoutException; import com.rabbitmq.client.test.TestUtils; import org.junit.Test; import com.rabbitmq.client.BuiltinExchangeType; import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; import com.rabbitmq.client.ConnectionFactory; public class ExchangeDeclare extends ExchangeEquivalenceBase { static final String TYPE = "direct"; static final String NAME = "exchange_test"; public void releaseResources() throws IOException { channel.exchangeDelete(NAME); } @Test public void exchangeNoArgsEquivalence() throws IOException { channel.exchangeDeclare(NAME, TYPE, false, false, null); verifyEquivalent(NAME, TYPE, false, false, null); } @Test public void singleLineFeedStrippedFromExchangeName() throws IOException { channel.exchangeDeclare("exchange_test\n", TYPE, false, false, null); verifyEquivalent(NAME, TYPE, false, false, null); } @Test public void multipleLineFeedsStrippedFromExchangeName() throws IOException { channel.exchangeDeclare("exchange\n_test\n", TYPE, false, false, null); verifyEquivalent(NAME, TYPE, false, false, null); } @Test public void multipleLineFeedAndCarriageReturnsStrippedFromExchangeName() throws IOException { channel.exchangeDeclare("e\nxc\rhange\n\r_test\n\r", TYPE, false, false, null); verifyEquivalent(NAME, TYPE, false, false, null); } @Test public void exchangeNonsenseArgsEquivalent() throws IOException { channel.exchangeDeclare(NAME, TYPE, false, false, null); Map args = new HashMap(); args.put("nonsensical-argument-surely-not-in-use", "foo"); verifyEquivalent(NAME, TYPE, false, false, args); } @Test public void exchangeDurableNotEquivalent() throws IOException { channel.exchangeDeclare(NAME, TYPE, false, false, null); verifyNotEquivalent(NAME, TYPE, true, false, null); } @Test public void exchangeTypeNotEquivalent() throws IOException { channel.exchangeDeclare(NAME, "direct", false, false, null); verifyNotEquivalent(NAME, "fanout", false, false, null); } @Test public void exchangeAutoDeleteNotEquivalent() throws IOException { channel.exchangeDeclare(NAME, "direct", false, false, null); verifyNotEquivalent(NAME, "direct", false, true, null); } @Test public void exchangeDeclaredWithEnumerationEquivalentOnNonRecoverableConnection() throws IOException, InterruptedException { doTestExchangeDeclaredWithEnumerationEquivalent(channel); } @Test public void exchangeDeclaredWithEnumerationEquivalentOnRecoverableConnection() throws IOException, TimeoutException, InterruptedException { ConnectionFactory connectionFactory = TestUtils.connectionFactory(); connectionFactory.setAutomaticRecoveryEnabled(true); connectionFactory.setTopologyRecoveryEnabled(false); Connection c = connectionFactory.newConnection(); try { doTestExchangeDeclaredWithEnumerationEquivalent(c.createChannel()); } finally { c.abort(); } } private void doTestExchangeDeclaredWithEnumerationEquivalent(Channel channel) throws IOException, InterruptedException { assertEquals("There are 4 standard exchange types", 4, BuiltinExchangeType.values().length); for (BuiltinExchangeType exchangeType : BuiltinExchangeType.values()) { channel.exchangeDeclare(NAME, exchangeType); verifyEquivalent(NAME, exchangeType.getType(), false, false, null); channel.exchangeDelete(NAME); channel.exchangeDeclare(NAME, exchangeType, false); verifyEquivalent(NAME, exchangeType.getType(), false, false, null); channel.exchangeDelete(NAME); channel.exchangeDeclare(NAME, exchangeType, false, false, null); verifyEquivalent(NAME, exchangeType.getType(), false, false, null); channel.exchangeDelete(NAME); channel.exchangeDeclare(NAME, exchangeType, false, false, false, null); verifyEquivalent(NAME, exchangeType.getType(), false, false, null); channel.exchangeDelete(NAME); channel.exchangeDeclareNoWait(NAME, exchangeType, false, false, false, null); // no check, this one is asynchronous channel.exchangeDelete(NAME); } } } ExchangeDeleteIfUnused.java000066400000000000000000000041761316117667700343000ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import static org.junit.Assert.fail; import java.io.IOException; import java.util.concurrent.TimeoutException; import org.junit.Test; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.test.BrokerTestCase; /* Declare an exchange, bind a queue to it, then try to delete it, * setting if-unused to true. This should throw an exception. */ public class ExchangeDeleteIfUnused extends BrokerTestCase { private final static String EXCHANGE_NAME = "xchg1"; private final static String ROUTING_KEY = "something"; protected void createResources() throws IOException, TimeoutException { super.createResources(); channel.exchangeDeclare(EXCHANGE_NAME, "direct"); String queueName = channel.queueDeclare().getQueue(); channel.queueBind(queueName, EXCHANGE_NAME, ROUTING_KEY); } protected void releaseResources() throws IOException { channel.exchangeDelete(EXCHANGE_NAME); super.releaseResources(); } /* Attempt to Exchange.Delete(ifUnused = true) a used exchange. * Should throw an exception. */ @Test public void exchangeDelete() { try { channel.exchangeDelete(EXCHANGE_NAME, true); fail("Exception expected if exchange in use"); } catch (IOException e) { checkShutdownSignal(AMQP.PRECONDITION_FAILED, e); } } } ExchangeDeletePredeclared.java000066400000000000000000000026661316117667700347720ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.test.BrokerTestCase; import java.io.IOException; public class ExchangeDeletePredeclared extends BrokerTestCase { public void testDeletingPredeclaredAmqExchange() throws IOException { try { channel.exchangeDelete("amq.fanout"); } catch (IOException e) { checkShutdownSignal(AMQP.ACCESS_REFUSED, e); } } public void testDeletingPredeclaredAmqRabbitMQExchange() throws IOException { try { channel.exchangeDelete("amq.rabbitmq.log"); } catch (IOException e) { checkShutdownSignal(AMQP.ACCESS_REFUSED, e); } } } ExchangeEquivalenceBase.java000066400000000000000000000034631316117667700344650ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import static org.junit.Assert.fail; import java.io.IOException; import java.util.Map; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.test.BrokerTestCase; public abstract class ExchangeEquivalenceBase extends BrokerTestCase { public void verifyEquivalent(String name, String type, boolean durable, boolean autoDelete, Map args) throws IOException { channel.exchangeDeclarePassive(name); channel.exchangeDeclare(name, type, durable, autoDelete, args); } // Note: this will close the channel public void verifyNotEquivalent(String name, String type, boolean durable, boolean autoDelete, Map args) throws IOException { channel.exchangeDeclarePassive(name); try { channel.exchangeDeclare(name, type, durable, autoDelete, args); fail("Exchange was supposed to be not equivalent"); } catch (IOException ioe) { checkShutdownSignal(AMQP.PRECONDITION_FAILED, ioe); } } } ExchangeExchangeBindings.java000066400000000000000000000164331316117667700346320ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import java.io.IOException; import org.junit.Test; import com.rabbitmq.client.QueueingConsumer; import com.rabbitmq.client.QueueingConsumer.Delivery; import com.rabbitmq.client.ShutdownSignalException; import com.rabbitmq.client.test.BrokerTestCase; public class ExchangeExchangeBindings extends BrokerTestCase { private static final int TIMEOUT = 5000; private static final byte[] MARKER = "MARK".getBytes(); private final String[] queues = new String[] { "q0", "q1", "q2" }; private final String[] exchanges = new String[] { "e0", "e1", "e2" }; private final String[][] bindings = new String[][] { { "q0", "e0" }, { "q1", "e1" }, { "q2", "e2" } }; private final QueueingConsumer[] consumers = new QueueingConsumer[] { null, null, null }; protected void publishWithMarker(String x, String rk) throws IOException { basicPublishVolatile(x, rk); basicPublishVolatile(MARKER, x, rk); } @Override protected void createResources() throws IOException { for (String q : queues) { channel.queueDeclare(q, false, false, false, null); } for (String e : exchanges) { channel.exchangeDeclare(e, "fanout"); } for (String[] binding : bindings) { channel.queueBind(binding[0], binding[1], ""); } for (int idx = 0; idx < consumers.length; ++idx) { QueueingConsumer consumer = new QueueingConsumer(channel); channel.basicConsume(queues[idx], true, consumer); consumers[idx] = consumer; } } @Override protected void releaseResources() throws IOException { for (String q : queues) { channel.queueDelete(q); } for (String e : exchanges) { channel.exchangeDelete(e); } } protected void consumeNoDuplicates(QueueingConsumer consumer) throws ShutdownSignalException, InterruptedException { assertNotNull(consumer.nextDelivery(TIMEOUT)); Delivery markerDelivery = consumer.nextDelivery(TIMEOUT); assertEquals(new String(MARKER), new String(markerDelivery.getBody())); } @Test public void bindingCreationDeletion() throws IOException { channel.exchangeUnbind("e2", "e1", ""); channel.exchangeBind("e2", "e1", ""); channel.exchangeBind("e2", "e1", ""); channel.exchangeUnbind("e2", "e1", ""); channel.exchangeUnbind("e2", "e1", ""); } /* pre (eN --> qN) for N in [0..2] * test (e0 --> q0) * add binding (e1 --> e0) * test (e1 --> {q1, q0}) * add binding (e2 --> e1) * test (e2 --> {q2, q1, q0}) */ @Test public void simpleChains() throws IOException, ShutdownSignalException, InterruptedException { publishWithMarker("e0", ""); consumeNoDuplicates(consumers[0]); channel.exchangeBind("e0", "e1", ""); publishWithMarker("e1", ""); consumeNoDuplicates(consumers[0]); consumeNoDuplicates(consumers[1]); channel.exchangeBind("e1", "e2", ""); publishWithMarker("e2", ""); consumeNoDuplicates(consumers[0]); consumeNoDuplicates(consumers[1]); consumeNoDuplicates(consumers[2]); channel.exchangeUnbind("e0", "e1", ""); channel.exchangeUnbind("e1", "e2", ""); } /* pre (eN --> qN) for N in [0..2] * add binding (e0 --> q1) * test (e0 --> {q0, q1}) * add binding (e1 --> e0) * resulting in: (e1 --> {q1, e0 --> {q0, q1}}) * test (e1 --> {q0, q1}) */ @Test public void duplicateQueueDestinations() throws IOException, ShutdownSignalException, InterruptedException { channel.queueBind("q1", "e0", ""); publishWithMarker("e0", ""); consumeNoDuplicates(consumers[0]); consumeNoDuplicates(consumers[1]); channel.exchangeBind("e0", "e1", ""); publishWithMarker("e1", ""); consumeNoDuplicates(consumers[0]); consumeNoDuplicates(consumers[1]); channel.exchangeUnbind("e0", "e1", ""); } /* pre (eN --> qN) for N in [0..2] * add binding (e1 --> e0) * add binding (e2 --> e1) * add binding (e0 --> e2) * test (eN --> {q0, q1, q2}) for N in [0..2] */ @Test public void exchangeRoutingLoop() throws IOException, ShutdownSignalException, InterruptedException { channel.exchangeBind("e0", "e1", ""); channel.exchangeBind("e1", "e2", ""); channel.exchangeBind("e2", "e0", ""); for (String e : exchanges) { publishWithMarker(e, ""); for (QueueingConsumer c : consumers) { consumeNoDuplicates(c); } } channel.exchangeUnbind("e0", "e1", ""); channel.exchangeUnbind("e1", "e2", ""); channel.exchangeUnbind("e2", "e0", ""); } /* pre (eN --> qN) for N in [0..2] * create topic e and bind e --> eN with rk eN for N in [0..2] * test publish with rk to e * create direct ef and bind e --> ef with rk # * bind ef --> eN with rk eN for N in [0..2] * test publish with rk to e * ( end up with: e -(#)-> ef -(eN)-> eN --> qN; * e -(eN)-> eN for N in [0..2] ) * Then remove the first set of bindings from e --> eN for N in [0..2] * test publish with rk to e */ @Test public void topicExchange() throws IOException, ShutdownSignalException, InterruptedException { channel.exchangeDeclare("e", "topic"); for (String e : exchanges) { channel.exchangeBind(e, "e", e); } publishAndConsumeAll("e"); channel.exchangeDeclare("ef", "direct"); channel.exchangeBind("ef", "e", "#"); for (String e : exchanges) { channel.exchangeBind(e, "ef", e); } publishAndConsumeAll("e"); for (String e : exchanges) { channel.exchangeUnbind(e, "e", e); } publishAndConsumeAll("e"); channel.exchangeDelete("ef"); channel.exchangeDelete("e"); } protected void publishAndConsumeAll(String exchange) throws IOException, ShutdownSignalException, InterruptedException { for (String e : exchanges) { publishWithMarker(exchange, e); } for (QueueingConsumer c : consumers) { consumeNoDuplicates(c); } } } ExchangeExchangeBindingsAutoDelete.java000066400000000000000000000101021316117667700365710ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import static org.junit.Assert.fail; import java.io.IOException; import org.junit.Test; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.test.BrokerTestCase; public class ExchangeExchangeBindingsAutoDelete extends BrokerTestCase { protected void declareExchanges(String[] names) throws IOException { for (String e : names) { channel.exchangeDeclare(e, "fanout", false, true, null); } } protected void assertExchangesNotExist(String[] names) throws IOException { for (String e : names) { assertExchangeNotExists(e); } } protected void assertExchangeNotExists(String name) throws IOException { try { connection.createChannel().exchangeDeclarePassive(name); fail("Exchange " + name + " still exists."); } catch (IOException e) { checkShutdownSignal(AMQP.NOT_FOUND, e); } } /* * build (A -> B) and (B -> A) and then delete one binding and both * exchanges should autodelete */ @Test public void autoDeleteExchangesSimpleLoop() throws IOException { String[] exchanges = new String[] {"A", "B"}; declareExchanges(exchanges); channel.exchangeBind("A", "B", ""); channel.exchangeBind("B", "A", ""); channel.exchangeUnbind("A", "B", ""); assertExchangesNotExist(exchanges); } /* * build (A -> B) (B -> C) (C -> D) and then delete D. All should autodelete */ @Test public void transientAutoDelete() throws IOException { String[] exchanges = new String[] {"A", "B", "C", "D"}; declareExchanges(exchanges); channel.exchangeBind("B", "A", ""); channel.exchangeBind("C", "B", ""); channel.exchangeBind("D", "C", ""); channel.exchangeDelete("D"); assertExchangesNotExist(exchanges); } /* * build (A -> B) (B -> C) (C -> D) (Source -> A) (Source -> B) (Source -> * C) (Source -> D) On removal of D, all should autodelete */ @Test public void repeatedTargetAutoDelete() throws IOException { String[] exchanges = new String[] {"A", "B", "C", "D"}; declareExchanges(exchanges); channel.exchangeDeclare("Source", "fanout", false, true, null); channel.exchangeBind("B", "A", ""); channel.exchangeBind("C", "B", ""); channel.exchangeBind("D", "C", ""); for (String e : exchanges) { channel.exchangeBind(e, "Source", ""); } channel.exchangeDelete("A"); // Source should still be there. We'll verify this by redeclaring // it here and verifying it goes away later channel.exchangeDeclare("Source", "fanout", false, true, null); channel.exchangeDelete("D"); assertExchangesNotExist(exchanges); assertExchangeNotExists("Source"); } /* * build (A -> B) (B -> C) (A -> C). Delete C and they should all vanish */ @Test public void autoDeleteBindingToVanishedExchange() throws IOException { String[] exchanges = new String[] {"A", "B", "C"}; declareExchanges(exchanges); channel.exchangeBind("C", "B", ""); channel.exchangeBind("B", "A", ""); channel.exchangeBind("C", "A", ""); channel.exchangeDelete("C"); assertExchangesNotExist(exchanges); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/FrameMax.java000066400000000000000000000155351316117667700315500ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import java.io.IOException; import java.net.Socket; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.TimeoutException; import com.rabbitmq.client.test.TestUtils; import org.junit.Test; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.Address; import com.rabbitmq.client.Connection; import com.rabbitmq.client.ConnectionFactory; import com.rabbitmq.client.GetResponse; import com.rabbitmq.client.impl.AMQCommand; import com.rabbitmq.client.impl.AMQConnection; import com.rabbitmq.client.impl.Frame; import com.rabbitmq.client.impl.FrameHandler; import com.rabbitmq.client.impl.LongStringHelper; import com.rabbitmq.client.impl.SocketFrameHandler; import com.rabbitmq.client.test.BrokerTestCase; public class FrameMax extends BrokerTestCase { /* This value for FrameMax is larger than the minimum and less * than what Rabbit suggests. */ final static int FRAME_MAX = 70000; final static int REAL_FRAME_MAX = FRAME_MAX - 8; public FrameMax() { connectionFactory = new MyConnectionFactory(); connectionFactory.setRequestedFrameMax(FRAME_MAX); } @Test public void negotiationOk() { assertEquals(FRAME_MAX, connection.getFrameMax()); } /* Publish a message of size FRAME_MAX. The broker should split * this into two frames before sending back. Frame content should * be less or equal to frame-max - 8. */ @Test public void frameSizes() throws IOException, InterruptedException { String queueName = channel.queueDeclare().getQueue(); /* This should result in at least 3 frames. */ int howMuch = 2*FRAME_MAX; basicPublishVolatile(new byte[howMuch], queueName); /* Receive everything that was sent out. */ while (howMuch > 0) { try { GetResponse response = channel.basicGet(queueName, false); howMuch -= response.getBody().length; } catch (Exception e) { e.printStackTrace(); fail("Exception in basicGet loop: " + e); } } } /* server should reject frames larger than AMQP.FRAME_MIN_SIZE * during connection negotiation */ @Test public void rejectLargeFramesDuringConnectionNegotiation() throws IOException, TimeoutException { ConnectionFactory cf = TestUtils.connectionFactory(); cf.getClientProperties().put("too_long", LongStringHelper.asLongString(new byte[AMQP.FRAME_MIN_SIZE])); try { cf.newConnection(); fail("Expected exception during connection negotiation"); } catch (IOException e) { } } /* server should reject frames larger than the negotiated frame * size */ @Test public void rejectExceedingFrameMax() throws IOException, TimeoutException { closeChannel(); closeConnection(); ConnectionFactory cf = new GenerousConnectionFactory(); connection = cf.newConnection(); openChannel(); basicPublishVolatile(new byte[connection.getFrameMax()], "void"); expectError(AMQP.FRAME_ERROR); } /* ConnectionFactory that uses MyFrameHandler rather than * SocketFrameHandler. */ private static class MyConnectionFactory extends ConnectionFactory { public MyConnectionFactory() { super(); if(TestUtils.USE_NIO) { useNio(); } else { useBlockingIo(); } } protected FrameHandler createFrameHandler(Socket sock) throws IOException { return new MyFrameHandler(sock); } } /* FrameHandler with added frame-max error checking. */ private static class MyFrameHandler extends SocketFrameHandler { public MyFrameHandler(Socket socket) throws IOException { super(socket); } public Frame readFrame() throws IOException { Frame f = super.readFrame(); int size = f.getPayload().length; if (size > REAL_FRAME_MAX) fail("Received frame of size " + size + ", which exceeds " + REAL_FRAME_MAX + "."); //System.out.printf("Received a frame of size %d.\n", f.getPayload().length); return f; } } /* AMQConnection with a frame_max that is one higher than what it tells the server. */ private static class GenerousAMQConnection extends AMQConnection { public GenerousAMQConnection(ConnectionFactory factory, FrameHandler handler, ExecutorService executor) { super(factory.params(executor), handler); } @Override public int getFrameMax() { // the RabbitMQ broker permits frames that are oversize by // up to EMPTY_FRAME_SIZE octets return super.getFrameMax() + AMQCommand.EMPTY_FRAME_SIZE + 1; } } private static class GenerousConnectionFactory extends ConnectionFactory { public GenerousConnectionFactory() { super(); if(TestUtils.USE_NIO) { useNio(); } else { useBlockingIo(); } } @Override public Connection newConnection(ExecutorService executor, List
addrs) throws IOException, TimeoutException { IOException lastException = null; for (Address addr : addrs) { try { FrameHandler frameHandler = createFrameHandlerFactory().create(addr, null); AMQConnection conn = new GenerousAMQConnection(this, frameHandler, executor); conn.start(); return conn; } catch (IOException e) { lastException = e; } } throw (lastException != null) ? lastException : new IOException("failed to connect"); } } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/FunctionalTests.java000066400000000000000000000050301316117667700331620ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import com.rabbitmq.client.impl.WorkPoolTests; import com.rabbitmq.client.test.AbstractRMQTestSuite; import com.rabbitmq.client.test.Bug20004Test; import com.rabbitmq.client.test.RequiredPropertiesSuite; import org.junit.runner.RunWith; import org.junit.runners.Suite; @RunWith(RequiredPropertiesSuite.class) @Suite.SuiteClasses({ ConnectionOpen.class, Heartbeat.class, Tables.class, DoubleDeletion.class, Routing.class, BindingLifecycle.class, Recover.class, Reject.class, Transactions.class, RequeueOnConnectionClose.class, RequeueOnChannelClose.class, DurableOnTransient.class, NoRequeueOnCancel.class, Bug20004Test.class, ExchangeDeleteIfUnused.class, QosTests.class, AlternateExchange.class, ExchangeExchangeBindings.class, ExchangeExchangeBindingsAutoDelete.class, ExchangeDeclare.class, FrameMax.class, QueueLifecycle.class, QueueLease.class, QueueExclusivity.class, QueueSizeLimit.class, InvalidAcks.class, InvalidAcksTx.class, DefaultExchange.class, UnbindAutoDeleteExchange.class, Confirm.class, ConsumerCancelNotification.class, UnexpectedFrames.class, PerQueueTTL.class, PerMessageTTL.class, PerQueueVsPerMessageTTL.class, DeadLetterExchange.class, SaslMechanisms.class, UserIDHeader.class, InternalExchange.class, CcRoutes.class, WorkPoolTests.class, HeadersExchangeValidation.class, ConsumerPriorities.class, Policies.class, ConnectionRecovery.class, ExceptionHandling.class, PerConsumerPrefetch.class, DirectReplyTo.class, ConsumerCount.class, BasicGet.class, Nack.class, ExceptionMessages.class, Metrics.class }) public class FunctionalTests { // initialize system properties static{ new AbstractRMQTestSuite(){}; } } HeadersExchangeValidation.java000066400000000000000000000043621316117667700350160ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import static org.junit.Assert.fail; import java.io.IOException; import java.util.HashMap; import org.junit.Test; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.Channel; import com.rabbitmq.client.test.BrokerTestCase; public class HeadersExchangeValidation extends BrokerTestCase { @Test public void headersValidation() throws IOException { AMQP.Queue.DeclareOk ok = channel.queueDeclare(); String queue = ok.getQueue(); HashMap arguments = new HashMap(); succeedBind(queue, arguments); arguments.put("x-match", 23); failBind(queue, arguments); arguments.put("x-match", "all or any I don't mind"); failBind(queue, arguments); arguments.put("x-match", "all"); succeedBind(queue, arguments); arguments.put("x-match", "any"); succeedBind(queue, arguments); } private void failBind(String queue, HashMap arguments) { try { Channel ch = connection.createChannel(); ch.queueBind(queue, "amq.headers", "", arguments); fail("Expected failure"); } catch (IOException e) { checkShutdownSignal(AMQP.PRECONDITION_FAILED, e); } } private void succeedBind(String queue, HashMap arguments) throws IOException { Channel ch = connection.createChannel(); ch.queueBind(queue, "amq.headers", "", arguments); ch.abort(); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/Heartbeat.java000066400000000000000000000030261316117667700317370ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import com.rabbitmq.client.impl.recovery.AutorecoveringConnection; import com.rabbitmq.client.test.BrokerTestCase; import org.junit.Test; import java.io.IOException; import static org.junit.Assert.*; public class Heartbeat extends BrokerTestCase { public Heartbeat() { super(); connectionFactory.setRequestedHeartbeat(1); } @Test public void heartbeat() throws IOException, InterruptedException { assertEquals(1, connection.getHeartbeat()); Thread.sleep(3100); assertTrue(connection.isOpen()); ((AutorecoveringConnection)connection).getDelegate().setHeartbeat(0); assertEquals(0, connection.getHeartbeat()); Thread.sleep(3100); assertFalse(connection.isOpen()); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/InternalExchange.java000066400000000000000000000064601316117667700332640ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import static org.junit.Assert.assertTrue; import java.io.IOException; import java.util.Arrays; import org.junit.Test; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.GetResponse; import com.rabbitmq.client.test.BrokerTestCase; // // Functional test demonstrating use of an internal exchange in an exchange to // exchange routing scenario. The routing topology is: // // ------- ------- // -/ \- -/ \- // / \ / \ +-------------+ // | e0 +------| e1 +-----------+ q1 | // \ / \ / +-------------+ // -\ /- -\ /- // ------- ------- // (internal) // // Where a non-internal exchange is bound to an internal exchange, which in // turn is bound to a queue. A client should be able to publish to e0, but // not to e1, and publications to e0 should be delivered into q1. // public class InternalExchange extends BrokerTestCase { private final String[] queues = new String[] { "q1" }; private final String[] exchanges = new String[] { "e0", "e1" }; protected void createResources() throws IOException { // The queues and exchange we create here are all auto-delete, so we // don't need to override releaseResources() with their deletions... for (String q : queues) { channel.queueDeclare(q, false, true, true, null); } // The second exchange, "e1", will be an 'internal' one. for ( String e : exchanges ) { channel.exchangeDeclare(e, "direct", false, true, !e.equals("e0"), null); } channel.exchangeBind("e1", "e0", ""); channel.queueBind("q1", "e1", ""); } @Test public void tryPublishingToInternalExchange() throws IOException { byte[] testDataBody = "test-data".getBytes(); // We should be able to publish to the non-internal exchange as usual // and see our message land in the queue... channel.basicPublish("e0", "", null, testDataBody); GetResponse r = channel.basicGet("q1", true); assertTrue(Arrays.equals(r.getBody(), testDataBody)); // Publishing to the internal exchange will not be allowed... channel.basicPublish("e1", "", null, testDataBody); expectError(AMQP.ACCESS_REFUSED); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/InvalidAcks.java000066400000000000000000000017031316117667700322300ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import java.io.IOException; public class InvalidAcks extends InvalidAcksBase { protected void select() throws IOException {} protected void commit() throws IOException {} } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/InvalidAcksBase.java000066400000000000000000000036131316117667700330250ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.test.BrokerTestCase; import java.io.IOException; import org.junit.Test; /** * See bug 21846: * Basic.Ack is now required to signal a channel error immediately upon * detecting an invalid deliveryTag, even if the channel is (Tx-)transacted. * * Specifically, a client MUST not acknowledge the same message more than once. */ public abstract class InvalidAcksBase extends BrokerTestCase { protected abstract void select() throws IOException; protected abstract void commit() throws IOException; @Test public void doubleAck() throws IOException { select(); String q = channel.queueDeclare().getQueue(); basicPublishVolatile(q); commit(); long tag = channel.basicGet(q, false).getEnvelope().getDeliveryTag(); channel.basicAck(tag, false); channel.basicAck(tag, false); expectError(AMQP.PRECONDITION_FAILED); } @Test public void crazyAck() throws IOException { select(); channel.basicAck(123456, false); expectError(AMQP.PRECONDITION_FAILED); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/InvalidAcksTx.java000066400000000000000000000020071316117667700325420ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import java.io.IOException; public class InvalidAcksTx extends InvalidAcksBase { protected void select() throws IOException { channel.txSelect(); } protected void commit() throws IOException { channel.txCommit(); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/MessageCount.java000066400000000000000000000026431316117667700324410ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import static org.junit.Assert.assertEquals; import java.io.IOException; import org.junit.Test; import com.rabbitmq.client.test.BrokerTestCase; public class MessageCount extends BrokerTestCase { @Test public void messageCount() throws IOException { String q = generateQueueName(); channel.queueDeclare(q, false, true, false, null); assertEquals(0, channel.messageCount(q)); basicPublishVolatile(q); assertEquals(1, channel.messageCount(q)); basicPublishVolatile(q); assertEquals(2, channel.messageCount(q)); channel.queuePurge(q); assertEquals(0, channel.messageCount(q)); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/Metrics.java000066400000000000000000000543751316117667700314630ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; import com.rabbitmq.client.ConnectionFactory; import com.rabbitmq.client.DefaultConsumer; import com.rabbitmq.client.Envelope; import com.rabbitmq.client.GetResponse; import com.rabbitmq.client.Recoverable; import com.rabbitmq.client.RecoveryListener; import com.rabbitmq.client.impl.StandardMetricsCollector; import com.rabbitmq.client.impl.recovery.AutorecoveringConnection; import com.rabbitmq.client.test.BrokerTestCase; import com.rabbitmq.client.test.TestUtils; import com.rabbitmq.tools.Host; import org.awaitility.Duration; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import java.io.IOException; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Random; import java.util.concurrent.Callable; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import static org.awaitility.Awaitility.waitAtMost; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; /** * */ @RunWith(Parameterized.class) public class Metrics extends BrokerTestCase { @Parameterized.Parameters public static Object[] data() { return new Object[] { createConnectionFactory(), createAutoRecoveryConnectionFactory() }; } @Parameterized.Parameter public ConnectionFactory connectionFactory; static final String QUEUE = "metrics.queue"; @Override protected void createResources() throws IOException, TimeoutException { channel.queueDeclare(QUEUE, true, false, false, null); } @Override protected void releaseResources() throws IOException { channel.queueDelete(QUEUE); } @Test public void metrics() throws IOException, TimeoutException { StandardMetricsCollector metrics = new StandardMetricsCollector(); connectionFactory.setMetricsCollector(metrics); Connection connection1 = null; Connection connection2 = null; try { connection1 = connectionFactory.newConnection(); assertThat(metrics.getConnections().getCount(), is(1L)); connection1.createChannel(); connection1.createChannel(); Channel channel = connection1.createChannel(); assertThat(metrics.getChannels().getCount(), is(3L)); sendMessage(channel); assertThat(metrics.getPublishedMessages().getCount(), is(1L)); sendMessage(channel); assertThat(metrics.getPublishedMessages().getCount(), is(2L)); channel.basicGet(QUEUE, true); assertThat(metrics.getConsumedMessages().getCount(), is(1L)); channel.basicGet(QUEUE, true); assertThat(metrics.getConsumedMessages().getCount(), is(2L)); channel.basicGet(QUEUE, true); assertThat(metrics.getConsumedMessages().getCount(), is(2L)); connection2 = connectionFactory.newConnection(); assertThat(metrics.getConnections().getCount(), is(2L)); connection2.createChannel(); channel = connection2.createChannel(); assertThat(metrics.getChannels().getCount(), is(3L+2L)); sendMessage(channel); sendMessage(channel); assertThat(metrics.getPublishedMessages().getCount(), is(2L+2L)); channel.basicGet(QUEUE, true); assertThat(metrics.getConsumedMessages().getCount(), is(2L+1L)); channel.basicConsume(QUEUE, true, new DefaultConsumer(channel)); waitAtMost(timeout()).until(() -> metrics.getConsumedMessages().getCount(), equalTo(2L+1L+1L)); safeClose(connection1); waitAtMost(timeout()).until(() -> metrics.getConnections().getCount(), equalTo(1L)); waitAtMost(timeout()).until(() -> metrics.getChannels().getCount(), equalTo(2L)); safeClose(connection2); waitAtMost(timeout()).until(() -> metrics.getConnections().getCount(), equalTo(0L)); waitAtMost(timeout()).until(() -> metrics.getChannels().getCount(), equalTo(0L)); assertThat(metrics.getAcknowledgedMessages().getCount(), is(0L)); assertThat(metrics.getRejectedMessages().getCount(), is(0L)); } finally { safeClose(connection1); safeClose(connection2); } } @Test public void metricsAck() throws IOException, TimeoutException { StandardMetricsCollector metrics = new StandardMetricsCollector(); connectionFactory.setMetricsCollector(metrics); Connection connection = null; try { connection = connectionFactory.newConnection(); Channel channel1 = connection.createChannel(); Channel channel2 = connection.createChannel(); sendMessage(channel1); GetResponse getResponse = channel1.basicGet(QUEUE, false); channel1.basicAck(getResponse.getEnvelope().getDeliveryTag(), false); assertThat(metrics.getConsumedMessages().getCount(), is(1L)); assertThat(metrics.getAcknowledgedMessages().getCount(), is(1L)); // basicGet / basicAck sendMessage(channel1); sendMessage(channel2); sendMessage(channel1); sendMessage(channel2); sendMessage(channel1); sendMessage(channel2); GetResponse response1 = channel1.basicGet(QUEUE, false); GetResponse response2 = channel2.basicGet(QUEUE, false); GetResponse response3 = channel1.basicGet(QUEUE, false); GetResponse response4 = channel2.basicGet(QUEUE, false); GetResponse response5 = channel1.basicGet(QUEUE, false); GetResponse response6 = channel2.basicGet(QUEUE, false); assertThat(metrics.getConsumedMessages().getCount(), is(1L+6L)); assertThat(metrics.getAcknowledgedMessages().getCount(), is(1L)); channel1.basicAck(response5.getEnvelope().getDeliveryTag(), false); assertThat(metrics.getAcknowledgedMessages().getCount(), is(1L+1L)); channel1.basicAck(response3.getEnvelope().getDeliveryTag(), true); assertThat(metrics.getAcknowledgedMessages().getCount(), is(1L+1L+2L)); channel2.basicAck(response2.getEnvelope().getDeliveryTag(), true); assertThat(metrics.getAcknowledgedMessages().getCount(), is(1L+(1L+2L)+1L)); channel2.basicAck(response6.getEnvelope().getDeliveryTag(), true); assertThat(metrics.getAcknowledgedMessages().getCount(), is(1L+(1L+2L)+1L+2L)); long alreadySentMessages = 1+(1+2)+1+2; // basicConsume / basicAck channel1.basicConsume(QUEUE, false, new MultipleAckConsumer(channel1, false)); channel1.basicConsume(QUEUE, false, new MultipleAckConsumer(channel1, true)); channel2.basicConsume(QUEUE, false, new MultipleAckConsumer(channel2, false)); channel2.basicConsume(QUEUE, false, new MultipleAckConsumer(channel2, true)); int nbMessages = 10; for(int i = 0; i < nbMessages; i++) { sendMessage(i%2 == 0 ? channel1 : channel2); } waitAtMost(timeout()).until( () -> metrics.getConsumedMessages().getCount(), equalTo(alreadySentMessages+nbMessages) ); waitAtMost(timeout()).until( () -> metrics.getAcknowledgedMessages().getCount(), equalTo(alreadySentMessages+nbMessages) ); } finally { safeClose(connection); } } @Test public void metricsReject() throws IOException, TimeoutException { StandardMetricsCollector metrics = new StandardMetricsCollector(); connectionFactory.setMetricsCollector(metrics); Connection connection = null; try { connection = connectionFactory.newConnection(); Channel channel = connection.createChannel(); sendMessage(channel); sendMessage(channel); sendMessage(channel); GetResponse response1 = channel.basicGet(QUEUE, false); GetResponse response2 = channel.basicGet(QUEUE, false); GetResponse response3 = channel.basicGet(QUEUE, false); channel.basicReject(response2.getEnvelope().getDeliveryTag(), false); assertThat(metrics.getRejectedMessages().getCount(), is(1L)); channel.basicNack(response3.getEnvelope().getDeliveryTag(), true, false); assertThat(metrics.getRejectedMessages().getCount(), is(1L+2L)); } finally { safeClose(connection); } } @Test public void multiThreadedMetricsStandardConnection() throws InterruptedException, TimeoutException, IOException { StandardMetricsCollector metrics = new StandardMetricsCollector(); connectionFactory.setMetricsCollector(metrics); int nbConnections = 3; int nbChannelsPerConnection = 5; int nbChannels = nbConnections * nbChannelsPerConnection; long nbOfMessages = 100; int nbTasks = nbChannels; // channel are not thread-safe Random random = new Random(); // create connections Connection [] connections = new Connection[nbConnections]; ExecutorService executorService = Executors.newFixedThreadPool(nbTasks); try { Channel [] channels = new Channel[nbChannels]; for(int i = 0; i < nbConnections; i++) { connections[i] = connectionFactory.newConnection(); for(int j = 0; j < nbChannelsPerConnection; j++) { Channel channel = connections[i].createChannel(); channel.basicQos(1); channels[i * nbChannelsPerConnection + j] = channel; } } // consume messages without ack for(int i = 0; i < nbOfMessages; i++) { sendMessage(channels[random.nextInt(nbChannels)]); } List> tasks = new ArrayList>(); for(int i = 0; i < nbTasks; i++) { Channel channelForConsuming = channels[random.nextInt(nbChannels)]; tasks.add(random.nextInt(10)%2 == 0 ? new BasicGetTask(channelForConsuming, true) : new BasicConsumeTask(channelForConsuming, true)); } executorService.invokeAll(tasks); assertThat(metrics.getPublishedMessages().getCount(), is(nbOfMessages)); waitAtMost(timeout()).until(() -> metrics.getConsumedMessages().getCount(), equalTo(nbOfMessages)); assertThat(metrics.getAcknowledgedMessages().getCount(), is(0L)); // to remove the listeners for(int i = 0; i < nbChannels; i++) { channels[i].close(); Channel channel = connections[random.nextInt(nbConnections)].createChannel(); channel.basicQos(1); channels[i] = channel; } // consume messages with ack for(int i = 0; i < nbOfMessages; i++) { sendMessage(channels[random.nextInt(nbChannels)]); } executorService.shutdownNow(); executorService = Executors.newFixedThreadPool(nbTasks); tasks = new ArrayList>(); for(int i = 0; i < nbTasks; i++) { Channel channelForConsuming = channels[i]; tasks.add(random.nextBoolean() ? new BasicGetTask(channelForConsuming, false) : new BasicConsumeTask(channelForConsuming, false)); } executorService.invokeAll(tasks); assertThat(metrics.getPublishedMessages().getCount(), is(2*nbOfMessages)); waitAtMost(timeout()).until(() -> metrics.getConsumedMessages().getCount(), equalTo(2*nbOfMessages)); waitAtMost(timeout()).until(() -> metrics.getAcknowledgedMessages().getCount(), equalTo(nbOfMessages)); // to remove the listeners for(int i = 0; i < nbChannels; i++) { channels[i].close(); Channel channel = connections[random.nextInt(nbConnections)].createChannel(); channel.basicQos(1); channels[i] = channel; } // consume messages and reject them for(int i = 0; i < nbOfMessages; i++) { sendMessage(channels[random.nextInt(nbChannels)]); } executorService.shutdownNow(); executorService = Executors.newFixedThreadPool(nbTasks); tasks = new ArrayList>(); for(int i = 0; i < nbTasks; i++) { Channel channelForConsuming = channels[i]; tasks.add(random.nextBoolean() ? new BasicGetRejectTask(channelForConsuming) : new BasicConsumeRejectTask(channelForConsuming)); } executorService.invokeAll(tasks); assertThat(metrics.getPublishedMessages().getCount(), is(3*nbOfMessages)); waitAtMost(timeout()).until(() -> metrics.getConsumedMessages().getCount(), equalTo(3*nbOfMessages)); waitAtMost(timeout()).until(() -> metrics.getAcknowledgedMessages().getCount(), equalTo(nbOfMessages)); waitAtMost(timeout()).until(() -> metrics.getRejectedMessages().getCount(), equalTo(nbOfMessages)); } finally { for (Connection connection : connections) { safeClose(connection); } executorService.shutdownNow(); } } @Test public void errorInChannel() throws IOException, TimeoutException { StandardMetricsCollector metrics = new StandardMetricsCollector(); connectionFactory.setMetricsCollector(metrics); Connection connection = null; try { connection = connectionFactory.newConnection(); Channel channel = connection.createChannel(); assertThat(metrics.getConnections().getCount(), is(1L)); assertThat(metrics.getChannels().getCount(), is(1L)); channel.basicPublish("unlikelynameforanexchange", "", null, "msg".getBytes("UTF-8")); waitAtMost(timeout()).until(() -> metrics.getChannels().getCount(), is(0L)); assertThat(metrics.getConnections().getCount(), is(1L)); } finally { safeClose(connection); } } @Test public void checkListenersWithAutoRecoveryConnection() throws Exception { ConnectionFactory connectionFactory = createConnectionFactory(); connectionFactory.setNetworkRecoveryInterval(2000); connectionFactory.setAutomaticRecoveryEnabled(true); StandardMetricsCollector metrics = new StandardMetricsCollector(); connectionFactory.setMetricsCollector(metrics); Connection connection = null; try { connection = connectionFactory.newConnection(); Collection shutdownHooks = getShutdownHooks(connection); assertThat(shutdownHooks.size(), is(0)); connection.createChannel(); assertThat(metrics.getConnections().getCount(), is(1L)); assertThat(metrics.getChannels().getCount(), is(1L)); closeAndWaitForRecovery((AutorecoveringConnection) connection); assertThat(metrics.getConnections().getCount(), is(1L)); assertThat(metrics.getChannels().getCount(), is(1L)); assertThat(shutdownHooks.size(), is(0)); } finally { safeClose(connection); } } private static ConnectionFactory createConnectionFactory() { ConnectionFactory connectionFactory = TestUtils.connectionFactory(); connectionFactory.setAutomaticRecoveryEnabled(false); return connectionFactory; } private static ConnectionFactory createAutoRecoveryConnectionFactory() { ConnectionFactory connectionFactory = TestUtils.connectionFactory(); connectionFactory.setAutomaticRecoveryEnabled(true); return connectionFactory; } private void closeAndWaitForRecovery(AutorecoveringConnection connection) throws IOException, InterruptedException { final CountDownLatch latch = new CountDownLatch(1); connection.addRecoveryListener(new RecoveryListener() { public void handleRecovery(Recoverable recoverable) { latch.countDown(); } @Override public void handleRecoveryStarted(Recoverable recoverable) { // no-op } }); Host.closeConnection(connection); assertTrue(latch.await(5, TimeUnit.SECONDS)); } private Collection getShutdownHooks(Connection connection) throws NoSuchFieldException, IllegalAccessException { Field shutdownHooksField = connection.getClass().getDeclaredField("shutdownHooks"); shutdownHooksField.setAccessible(true); return (Collection) shutdownHooksField.get(connection); } private static class BasicGetTask implements Callable { final Channel channel; final boolean autoAck; final Random random = new Random(); private BasicGetTask(Channel channel, boolean autoAck) { this.channel = channel; this.autoAck = autoAck; } @Override public Void call() throws Exception { GetResponse getResponse = this.channel.basicGet(QUEUE, autoAck); if(!autoAck) { channel.basicAck(getResponse.getEnvelope().getDeliveryTag(), random.nextBoolean()); } return null; } } private static class BasicConsumeTask implements Callable { final Channel channel; final boolean autoAck; final Random random = new Random(); private BasicConsumeTask(Channel channel, boolean autoAck) { this.channel = channel; this.autoAck = autoAck; } @Override public Void call() throws Exception { this.channel.basicConsume(QUEUE, autoAck, new DefaultConsumer(channel) { @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { if(!autoAck) { getChannel().basicAck(envelope.getDeliveryTag(), random.nextBoolean()); } } }); return null; } } private static class BasicGetRejectTask implements Callable { final Channel channel; final Random random = new Random(); private BasicGetRejectTask(Channel channel) { this.channel = channel; } @Override public Void call() throws Exception { GetResponse response = channel.basicGet(QUEUE, false); if(response != null) { if(random.nextBoolean()) { channel.basicNack(response.getEnvelope().getDeliveryTag(), random.nextBoolean(), false); } else { channel.basicReject(response.getEnvelope().getDeliveryTag(), false); } } return null; } } private static class BasicConsumeRejectTask implements Callable { final Channel channel; final Random random = new Random(); private BasicConsumeRejectTask(Channel channel) { this.channel = channel; } @Override public Void call() throws Exception { this.channel.basicConsume(QUEUE, false, new DefaultConsumer(channel) { @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { if(random.nextBoolean()) { channel.basicNack(envelope.getDeliveryTag(), random.nextBoolean(), false); } else { channel.basicReject(envelope.getDeliveryTag(), false); } } }); return null; } } private void safeClose(Connection connection) { if(connection != null) { try { connection.abort(); } catch (Exception e) { // OK } } } private void sendMessage(Channel channel) throws IOException { channel.basicPublish("", QUEUE, null, "msg".getBytes("UTF-8")); } private Duration timeout() { return new Duration(10, TimeUnit.SECONDS); } private static class MultipleAckConsumer extends DefaultConsumer { final boolean multiple; public MultipleAckConsumer(Channel channel, boolean multiple) { super(channel); this.multiple = multiple; } @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { try { Thread.sleep(new Random().nextInt(10)); } catch (InterruptedException e) { throw new RuntimeException("Error during randomized wait",e); } getChannel().basicAck(envelope.getDeliveryTag(), multiple); } } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/Nack.java000066400000000000000000000114531316117667700307170ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.util.HashSet; import java.util.Set; import org.junit.Test; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.QueueingConsumer; public class Nack extends AbstractRejectTest { @Test public void singleNack() throws Exception { String q = channel.queueDeclare("", false, true, false, null).getQueue(); byte[] m1 = "1".getBytes(); byte[] m2 = "2".getBytes(); basicPublishVolatile(m1, q); basicPublishVolatile(m2, q); long tag1 = checkDelivery(channel.basicGet(q, false), m1, false); long tag2 = checkDelivery(channel.basicGet(q, false), m2, false); QueueingConsumer c = new QueueingConsumer(secondaryChannel); String consumerTag = secondaryChannel.basicConsume(q, false, c); // requeue channel.basicNack(tag2, false, true); long tag3 = checkDelivery(c.nextDelivery(), m2, true); secondaryChannel.basicCancel(consumerTag); // no requeue secondaryChannel.basicNack(tag3, false, false); assertNull(channel.basicGet(q, false)); channel.basicAck(tag1, false); channel.basicNack(tag3, false, true); expectError(AMQP.PRECONDITION_FAILED); } @Test public void multiNack() throws Exception { String q = channel.queueDeclare("", false, true, false, null).getQueue(); byte[] m1 = "1".getBytes(); byte[] m2 = "2".getBytes(); byte[] m3 = "3".getBytes(); byte[] m4 = "4".getBytes(); basicPublishVolatile(m1, q); basicPublishVolatile(m2, q); basicPublishVolatile(m3, q); basicPublishVolatile(m4, q); checkDelivery(channel.basicGet(q, false), m1, false); long tag1 = checkDelivery(channel.basicGet(q, false), m2, false); checkDelivery(channel.basicGet(q, false), m3, false); long tag2 = checkDelivery(channel.basicGet(q, false), m4, false); // ack, leaving a gap in un-acked sequence channel.basicAck(tag1, false); QueueingConsumer c = new QueueingConsumer(secondaryChannel); String consumerTag = secondaryChannel.basicConsume(q, false, c); // requeue multi channel.basicNack(tag2, true, true); long tag3 = checkDeliveries(c, m1, m3, m4); secondaryChannel.basicCancel(consumerTag); // no requeue secondaryChannel.basicNack(tag3, true, false); assertNull(channel.basicGet(q, false)); channel.basicNack(tag3, true, true); expectError(AMQP.PRECONDITION_FAILED); } @Test public void nackAll() throws Exception { String q = channel.queueDeclare("", false, true, false, null).getQueue(); byte[] m1 = "1".getBytes(); byte[] m2 = "2".getBytes(); basicPublishVolatile(m1, q); basicPublishVolatile(m2, q); checkDelivery(channel.basicGet(q, false), m1, false); checkDelivery(channel.basicGet(q, false), m2, false); // nack all channel.basicNack(0, true, true); QueueingConsumer c = new QueueingConsumer(secondaryChannel); String consumerTag = secondaryChannel.basicConsume(q, true, c); checkDeliveries(c, m1, m2); secondaryChannel.basicCancel(consumerTag); } private long checkDeliveries(QueueingConsumer c, byte[]... messages) throws InterruptedException { Set msgSet = new HashSet(); for (byte[] message : messages) { msgSet.add(new String(message)); } long lastTag = -1; for(int x = 0; x < messages.length; x++) { QueueingConsumer.Delivery delivery = c.nextDelivery(); String m = new String(delivery.getBody()); assertTrue("Unexpected message", msgSet.remove(m)); checkDelivery(delivery, m.getBytes(), true); lastTag = delivery.getEnvelope().getDeliveryTag(); } assertTrue(msgSet.isEmpty()); return lastTag; } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/NoRequeueOnCancel.java000066400000000000000000000043361316117667700333600ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.io.IOException; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import com.rabbitmq.client.*; import org.junit.Test; import com.rabbitmq.client.test.BrokerTestCase; public class NoRequeueOnCancel extends BrokerTestCase { protected final String Q = "NoRequeueOnCancel"; protected void createResources() throws IOException { channel.queueDeclare(Q, false, false, false, null); } protected void releaseResources() throws IOException { channel.queueDelete(Q); } @Test public void noRequeueOnCancel() throws IOException, InterruptedException { channel.basicPublish("", Q, null, "1".getBytes()); final CountDownLatch latch = new CountDownLatch(1); Consumer c = new DefaultConsumer(channel) { @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { latch.countDown(); } }; String consumerTag = channel.basicConsume(Q, false, c); assertTrue(latch.await(5, TimeUnit.SECONDS)); channel.basicCancel(consumerTag); assertNull(channel.basicGet(Q, true)); closeChannel(); openChannel(); assertNotNull(channel.basicGet(Q, true)); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/Nowait.java000066400000000000000000000055451316117667700313110ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import com.rabbitmq.client.test.BrokerTestCase; import java.io.IOException; public class Nowait extends BrokerTestCase { public void testQueueDeclareWithNowait() throws IOException { String q = generateQueueName(); channel.queueDeclareNoWait(q, false, true, true, null); channel.queueDeclarePassive(q); } public void testQueueBindWithNowait() throws IOException { String q = generateQueueName(); channel.queueDeclareNoWait(q, false, true, true, null); channel.queueBindNoWait(q, "amq.fanout", "", null); } public void testExchangeDeclareWithNowait() throws IOException { String x = generateExchangeName(); try { channel.exchangeDeclareNoWait(x, "fanout", false, false, false, null); channel.exchangeDeclarePassive(x); } finally { channel.exchangeDelete(x); } } public void testExchangeBindWithNowait() throws IOException { String x = generateExchangeName(); try { channel.exchangeDeclareNoWait(x, "fanout", false, false, false, null); channel.exchangeBindNoWait(x, "amq.fanout", "", null); } finally { channel.exchangeDelete(x); } } public void testExchangeUnbindWithNowait() throws IOException { String x = generateExchangeName(); try { channel.exchangeDeclare(x, "fanout", false, false, false, null); channel.exchangeBind(x, "amq.fanout", "", null); channel.exchangeUnbindNoWait(x, "amq.fanout", "", null); } finally { channel.exchangeDelete(x); } } public void testQueueDeleteWithNowait() throws IOException { String q = generateQueueName(); channel.queueDeclareNoWait(q, false, true, true, null); channel.queueDeleteNoWait(q, false, false); } public void testExchangeDeleteWithNowait() throws IOException { String x = generateExchangeName(); channel.exchangeDeclareNoWait(x, "fanout", false, false, false, null); channel.exchangeDeleteNoWait(x, false); } } PerConsumerPrefetch.java000066400000000000000000000115461316117667700337120ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import static com.rabbitmq.client.test.functional.QosTests.drain; import java.io.IOException; import java.util.Arrays; import java.util.List; import org.junit.Test; import com.rabbitmq.client.GetResponse; import com.rabbitmq.client.QueueingConsumer; import com.rabbitmq.client.QueueingConsumer.Delivery; import com.rabbitmq.client.test.BrokerTestCase; public class PerConsumerPrefetch extends BrokerTestCase { private String q; @Override protected void createResources() throws IOException { q = channel.queueDeclare().getQueue(); } private interface Closure { public void makeMore(List deliveries) throws IOException; } @Test public void singleAck() throws IOException { testPrefetch(new Closure() { public void makeMore(List deliveries) throws IOException { for (Delivery del : deliveries) { ack(del, false); } } }); } @Test public void multiAck() throws IOException { testPrefetch(new Closure() { public void makeMore(List deliveries) throws IOException { ack(deliveries.get(deliveries.size() - 1), true); } }); } @Test public void singleNack() throws IOException { for (final boolean requeue: Arrays.asList(false, true)) { testPrefetch(new Closure() { public void makeMore(List deliveries) throws IOException { for (Delivery del : deliveries) { nack(del, false, requeue); } } }); } } @Test public void multiNack() throws IOException { for (final boolean requeue: Arrays.asList(false, true)) { testPrefetch(new Closure() { public void makeMore(List deliveries) throws IOException { nack(deliveries.get(deliveries.size() - 1), true, requeue); } }); } } @Test public void recover() throws IOException { testPrefetch(new Closure() { public void makeMore(List deliveries) throws IOException { channel.basicRecover(); } }); } private void testPrefetch(Closure closure) throws IOException { QueueingConsumer c = new QueueingConsumer(channel); publish(q, 15); consume(c, 5, false); List deliveries = drain(c, 5); ack(channel.basicGet(q, false), false); drain(c, 0); closure.makeMore(deliveries); drain(c, 5); } @Test public void prefetchOnEmpty() throws IOException { QueueingConsumer c = new QueueingConsumer(channel); publish(q, 5); consume(c, 10, false); drain(c, 5); publish(q, 10); drain(c, 5); } @Test public void autoAckIgnoresPrefetch() throws IOException { QueueingConsumer c = new QueueingConsumer(channel); publish(q, 10); consume(c, 1, true); drain(c, 10); } @Test public void prefetchZeroMeansInfinity() throws IOException { QueueingConsumer c = new QueueingConsumer(channel); publish(q, 10); consume(c, 0, false); drain(c, 10); } private void publish(String q, int n) throws IOException { for (int i = 0; i < n; i++) { channel.basicPublish("", q, null, "".getBytes()); } } private void consume(QueueingConsumer c, int prefetch, boolean autoAck) throws IOException { channel.basicQos(prefetch); channel.basicConsume(q, autoAck, c); } private void ack(Delivery del, boolean multi) throws IOException { channel.basicAck(del.getEnvelope().getDeliveryTag(), multi); } private void ack(GetResponse get, boolean multi) throws IOException { channel.basicAck(get.getEnvelope().getDeliveryTag(), multi); } private void nack(Delivery del, boolean multi, boolean requeue) throws IOException { channel.basicNack(del.getEnvelope().getDeliveryTag(), multi, requeue); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/PerMessageTTL.java000066400000000000000000000055511316117667700324640ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import java.io.IOException; import org.junit.Test; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.MessageProperties; import com.rabbitmq.client.QueueingConsumer; public class PerMessageTTL extends TTLHandling { protected Object sessionTTL; @Override protected void publish(String msg) throws IOException { basicPublishVolatile(msg.getBytes(), TTL_EXCHANGE, TTL_QUEUE_NAME, MessageProperties.TEXT_PLAIN .builder() .expiration(String.valueOf(sessionTTL)) .build()); } @Override protected AMQP.Queue.DeclareOk declareQueue(String name, Object ttlValue) throws IOException { this.sessionTTL = ttlValue; return this.channel.queueDeclare(name, false, true, false, null); } @Test public void expiryWhenConsumerIsLateToTheParty() throws Exception { declareAndBindQueue(500); publish(MSG[0]); this.sessionTTL = 100; publish(MSG[1]); Thread.sleep(200); QueueingConsumer c = new QueueingConsumer(channel); channel.basicConsume(TTL_QUEUE_NAME, c); assertNotNull("Message unexpectedly expired", c.nextDelivery(100)); assertNull("Message should have been expired!!", c.nextDelivery(100)); } @Test public void restartingExpiry() throws Exception { final String expiryDelay = "2000"; declareDurableQueue(TTL_QUEUE_NAME); bindQueue(); channel.basicPublish(TTL_EXCHANGE, TTL_QUEUE_NAME, MessageProperties.MINIMAL_PERSISTENT_BASIC .builder() .expiration(expiryDelay) .build(), new byte[]{}); long expiryStartTime = System.currentTimeMillis(); restart(); Thread.sleep(Integer.parseInt(expiryDelay)); try { assertNull("Message should have expired after broker restart", get()); } finally { deleteQueue(TTL_QUEUE_NAME); } } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/PerQueueTTL.java000066400000000000000000000051311316117667700321560ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import static org.junit.Assert.fail; import java.io.IOException; import java.util.Collections; import java.util.Map; import org.junit.Test; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.MessageProperties; public class PerQueueTTL extends TTLHandling { protected static final String TTL_ARG = "x-message-ttl"; @Override protected AMQP.Queue.DeclareOk declareQueue(String name, Object ttlValue) throws IOException { Map argMap = Collections.singletonMap(TTL_ARG, ttlValue); return this.channel.queueDeclare(name, false, true, false, argMap); } @Test public void queueReDeclareEquivalence() throws Exception { declareQueue(10); try { declareQueue(20); fail("Should not be able to redeclare with different x-message-ttl"); } catch(IOException ex) { checkShutdownSignal(AMQP.PRECONDITION_FAILED, ex); } } @Test public void queueReDeclareSemanticEquivalence() throws Exception { declareQueue((byte)10); declareQueue(10); declareQueue((short)10); declareQueue(10L); } @Test public void queueReDeclareSemanticNonEquivalence() throws Exception { declareQueue(10); try { declareQueue(10.0); fail("Should not be able to redeclare with x-message-ttl argument of different type"); } catch(IOException ex) { checkShutdownSignal(AMQP.PRECONDITION_FAILED, ex); } } protected void publishWithExpiration(String msg, Object sessionTTL) throws IOException { basicPublishVolatile(msg.getBytes(), TTL_EXCHANGE, TTL_QUEUE_NAME, MessageProperties.TEXT_PLAIN .builder() .expiration(String.valueOf(sessionTTL)) .build()); } } PerQueueVsPerMessageTTL.java000066400000000000000000000043471316117667700343740ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import static org.junit.Assert.assertNull; import java.io.IOException; import java.util.Collections; import java.util.Map; import org.junit.Test; import com.rabbitmq.client.AMQP; public class PerQueueVsPerMessageTTL extends PerMessageTTL { @Test public void smallerPerQueueExpiryWins() throws IOException, InterruptedException { declareAndBindQueue(10); this.sessionTTL = 1000; publish("message1"); Thread.sleep(100); assertNull("per-queue ttl should have removed message after 10ms!", get()); } @Override protected AMQP.Queue.DeclareOk declareQueue(String name, Object ttlValue) throws IOException { final Object mappedTTL = (ttlValue instanceof String && ((String) ttlValue).contains("foobar")) ? ttlValue : longValue(ttlValue) * 2; this.sessionTTL = ttlValue; Map argMap = Collections.singletonMap(PerQueueTTL.TTL_ARG, mappedTTL); return this.channel.queueDeclare(name, false, true, false, argMap); } private Long longValue(final Object ttl) { if (ttl instanceof Short) { return ((Short)ttl).longValue(); } else if (ttl instanceof Integer) { return ((Integer)ttl).longValue(); } else if (ttl instanceof Long) { return (Long) ttl; } else { throw new IllegalArgumentException("ttl not of expected type"); } } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/Policies.java000066400000000000000000000207271316117667700316160ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import java.io.IOException; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.junit.Test; import com.rabbitmq.client.Channel; import com.rabbitmq.client.GetResponse; import com.rabbitmq.client.test.BrokerTestCase; import com.rabbitmq.client.test.server.HATests; import com.rabbitmq.tools.Host; public class Policies extends BrokerTestCase { private static final int DELAY = 100; // MILLIS @Override protected void createResources() throws IOException { setPolicy("AE", "^has-ae", "\"alternate-exchange\":\"ae\""); setPolicy("DLX", "^has-dlx", "\"dead-letter-exchange\":\"dlx\",\"dead-letter-routing-key\":\"rk\""); setPolicy("TTL", "^has-ttl", "\"message-ttl\":" + DELAY); setPolicy("Expires", "^has-expires", "\"expires\":" + DELAY); setPolicy("MaxLength", "^has-max-length", "\"max-length\":1"); channel.exchangeDeclare("has-ae", "fanout"); Map args = new HashMap(); args.put("alternate-exchange", "ae2"); channel.exchangeDeclare("has-ae-args", "fanout", false, false, args); } @Test public void alternateExchange() throws IOException, InterruptedException { String q = declareQueue(); channel.exchangeDeclare("ae", "fanout", false, true, null); channel.queueBind(q, "ae", ""); basicPublishVolatile("has-ae", ""); assertDelivered(q, 1); clearPolicies(); basicPublishVolatile("has-ae", ""); assertDelivered(q, 0); } // i.e. the argument takes priority over the policy @Test public void alternateExchangeArgs() throws IOException { String q = declareQueue(); channel.exchangeDeclare("ae2", "fanout", false, true, null); channel.queueBind(q, "ae2", ""); basicPublishVolatile("has-ae-args", ""); assertDelivered(q, 1); } @Test public void deadLetterExchange() throws IOException, InterruptedException { Map args = ttlArgs(0); String src = declareQueue("has-dlx", args); String dest = declareQueue(); channel.exchangeDeclare("dlx", "fanout", false, true, null); channel.queueBind(dest, "dlx", ""); basicPublishVolatile(src); Thread.sleep(DELAY); GetResponse resp = channel.basicGet(dest, true); assertEquals("rk", resp.getEnvelope().getRoutingKey()); clearPolicies(); basicPublishVolatile(src); Thread.sleep(DELAY); assertDelivered(dest, 0); } // again the argument takes priority over the policy @Test public void deadLetterExchangeArgs() throws IOException, InterruptedException { Map args = ttlArgs(0); args.put("x-dead-letter-exchange", "dlx2"); args.put("x-dead-letter-routing-key", "rk2"); String src = declareQueue("has-dlx-args", args); String dest = declareQueue(); channel.exchangeDeclare("dlx2", "fanout", false, true, null); channel.queueBind(dest, "dlx2", ""); basicPublishVolatile(src); Thread.sleep(DELAY); GetResponse resp = channel.basicGet(dest, true); assertEquals("rk2", resp.getEnvelope().getRoutingKey()); } @Test public void tTL() throws IOException, InterruptedException { String q = declareQueue("has-ttl", null); basicPublishVolatile(q); Thread.sleep(2 * DELAY); assertDelivered(q, 0); clearPolicies(); basicPublishVolatile(q); Thread.sleep(2 * DELAY); assertDelivered(q, 1); } // Test that we get lower of args and policy @Test public void tTLArgs() throws IOException, InterruptedException { String q = declareQueue("has-ttl", ttlArgs(3 * DELAY)); basicPublishVolatile(q); Thread.sleep(2 * DELAY); assertDelivered(q, 0); clearPolicies(); basicPublishVolatile(q); Thread.sleep(2 * DELAY); assertDelivered(q, 1); basicPublishVolatile(q); Thread.sleep(4 * DELAY); assertDelivered(q, 0); } @Test public void expires() throws IOException, InterruptedException { String q = declareQueue("has-expires", null); Thread.sleep(2 * DELAY); assertFalse(queueExists(q)); clearPolicies(); q = declareQueue("has-expires", null); Thread.sleep(2 * DELAY); assertTrue(queueExists(q)); } // Test that we get lower of args and policy @Test public void expiresArgs() throws IOException, InterruptedException { String q = declareQueue("has-expires", args("x-expires", 3 * DELAY)); Thread.sleep(2 * DELAY); assertFalse(queueExists(q)); clearPolicies(); q = declareQueue("has-expires", args("x-expires", 3 * DELAY)); Thread.sleep(2 * DELAY); assertTrue(queueExists(q)); } @Test public void maxLength() throws IOException, InterruptedException { String q = declareQueue("has-max-length", null); basicPublishVolatileN(q, 3); assertDelivered(q, 1); clearPolicies(); basicPublishVolatileN(q, 3); assertDelivered(q, 3); } @Test public void maxLengthArgs() throws IOException, InterruptedException { String q = declareQueue("has-max-length", args("x-max-length", 2)); basicPublishVolatileN(q, 3); assertDelivered(q, 1); clearPolicies(); basicPublishVolatileN(q, 3); assertDelivered(q, 2); } @Override protected void releaseResources() throws IOException { clearPolicies(); channel.exchangeDelete("has-ae"); channel.exchangeDelete("has-ae-args"); } private final Set policies = new HashSet(); private void setPolicy(String name, String pattern, String definition) throws IOException { // We need to override the HA policy that we use in HATests, so // priority 1. But we still want a valid test of HA, so add the // ha-mode definition. if (HATests.HA_TESTS_RUNNING) { definition += ",\"ha-mode\":\"all\""; } Host.rabbitmqctl("set_policy --priority 1 " + name + " " + pattern + " {" + escapeDefinition(definition) + "}"); policies.add(name); } private String escapeDefinition(String definition) { return definition.replaceAll(",", "\\\\,").replaceAll("\"", "\\\\\\\""); } private void clearPolicies() throws IOException { for (String policy : policies) { Host.rabbitmqctl("clear_policy " + policy); } policies.clear(); } private Map ttlArgs(int ttl) { return args("x-message-ttl", ttl); } private Map args(String name, Object value) { Map args = new HashMap(); args.put(name, value); return args; } private String declareQueue() throws IOException { return channel.queueDeclare().getQueue(); } private String declareQueue(String name, Map args) throws IOException { return channel.queueDeclare(name, false, true, false, args).getQueue(); } private boolean queueExists(String name) throws IOException { Channel ch2 = connection.createChannel(); try { ch2.queueDeclarePassive(name); return true; } catch (IOException ioe) { return false; } } private void basicPublishVolatileN(String q, int count) throws IOException { for (int i = 0; i < count; i++) { basicPublishVolatile(q); } } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/QosTests.java000066400000000000000000000353431316117667700316340ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.concurrent.TimeoutException; import org.junit.Test; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.Channel; import com.rabbitmq.client.Envelope; import com.rabbitmq.client.GetResponse; import com.rabbitmq.client.QueueingConsumer; import com.rabbitmq.client.QueueingConsumer.Delivery; import com.rabbitmq.client.test.BrokerTestCase; public class QosTests extends BrokerTestCase { public void setUp() throws IOException, TimeoutException { openConnection(); openChannel(); } public void tearDown() throws IOException { closeChannel(); closeConnection(); } public void fill(int n) throws IOException { for (int i = 0; i < n; i++) { channel.basicPublish("amq.fanout", "", null, Integer.toString(i).getBytes()); } } /** * receive n messages - check that we receive no fewer and cannot * receive more **/ public static List drain(QueueingConsumer c, int n) throws IOException { List res = new LinkedList(); try { long start = System.currentTimeMillis(); for (int i = 0; i < n; i++) { Delivery d = c.nextDelivery(1000); assertNotNull(d); res.add(d); } long finish = System.currentTimeMillis(); Thread.sleep( (n == 0 ? 0 : (finish - start) / n) + 10 ); assertNull(c.nextDelivery(0)); } catch (InterruptedException ie) { fail("interrupted"); } return res; } @Test public void messageLimitPrefetchSizeFails() throws IOException { try { channel.basicQos(1000, 0, false); fail("basic.qos{pretfetch_size=NonZero} should not be supported"); } catch (IOException ioe) { checkShutdownSignal(AMQP.NOT_IMPLEMENTED, ioe); } } @Test public void messageLimitUnlimited() throws IOException { QueueingConsumer c = new QueueingConsumer(channel); configure(c, 0, 1, 2); drain(c, 2); } @Test public void noAckNoAlterLimit() throws IOException { QueueingConsumer c = new QueueingConsumer(channel); declareBindConsume(channel, c, true); channel.basicQos(1, true); fill(2); drain(c, 2); } @Test public void noAckObeysLimit() throws IOException { channel.basicQos(1, true); QueueingConsumer c1 = new QueueingConsumer(channel); declareBindConsume(channel, c1, false); fill(1); QueueingConsumer c2 = new QueueingConsumer(channel); declareBindConsume(channel, c2, true); fill(1); try { Delivery d = c2.nextDelivery(1000); assertNull(d); } catch (InterruptedException ie) { fail("interrupted"); } List d = drain(c1, 1); ack(d, false); // must ack before the next one appears d = drain(c1, 1); ack(d, false); drain(c2, 1); } @Test public void permutations() throws IOException { closeChannel(); for (int limit : Arrays.asList(1, 2)) { for (boolean multiAck : Arrays.asList(false, true)) { for (boolean txMode : Arrays.asList(true, false)) { for (int queueCount : Arrays.asList(1, 2)) { openChannel(); runLimitTests(limit, multiAck, txMode, queueCount); closeChannel(); } } } } } @Test public void fairness() throws IOException { QueueingConsumer c = new QueueingConsumer(channel); final int queueCount = 3; final int messageCount = 100; List queues = configure(c, 1, queueCount, messageCount); for (int i = 0; i < messageCount - 1; i++) { List d = drain(c, 1); ack(d, false); } //Perfect fairness would result in every queue having //messageCount * (1 - 1 / queueCount) messages left. Perfect //unfairness would result in one queue having no messages //left and the other queues having messageCount messages left. // //We simply check that every queue has had *some* message(s) //consumed from it. That ensures that no queue is "left //behind" - a notion of fairness somewhat short of perfect but //probably good enough. for (String q : queues) { AMQP.Queue.DeclareOk ok = channel.queueDeclarePassive(q); assertTrue(ok.getMessageCount() < messageCount); } } @Test public void singleChannelAndQueueFairness() throws IOException { //check that when we have multiple consumers on the same //channel & queue, and a prefetch limit set, that all //consumers get a fair share of the messages. channel.basicQos(1, true); String q = channel.queueDeclare().getQueue(); channel.queueBind(q, "amq.fanout", ""); final Map counts = Collections.synchronizedMap(new HashMap()); QueueingConsumer c = new QueueingConsumer(channel) { @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { counts.put(consumerTag, counts.get(consumerTag) + 1); super.handleDelivery(consumerTag, envelope, properties, body); } }; channel.basicConsume(q, false, "c1", c); channel.basicConsume(q, false, "c2", c); int count = 10; counts.put("c1", 0); counts.put("c2", 0); fill(count); try { for (int i = 0; i < count; i++) { Delivery d = c.nextDelivery(); channel.basicAck(d.getEnvelope().getDeliveryTag(), false); } } catch (InterruptedException ie) { fail("interrupted"); } //we only check that the server isn't grossly unfair; perfect //fairness is too much to ask for (even though RabbitMQ atm //does actually provide it in this case) assertTrue(counts.get("c1").intValue() > 0); assertTrue(counts.get("c2").intValue() > 0); } @Test public void consumerLifecycle() throws IOException { channel.basicQos(1, true); QueueingConsumer c = new QueueingConsumer(channel); String queue = "qosTest"; channel.queueDeclare(queue, false, false, false, null); channel.queueBind(queue, "amq.fanout", ""); fill(3); String tag; for (int i = 0; i < 2; i++) { tag = channel.basicConsume(queue, false, c); List d = drain(c, 1); channel.basicCancel(tag); drain(c, 0); ack(d, true); drain(c, 0); } channel.queueDelete(queue); } @Test public void setLimitAfterConsume() throws IOException { QueueingConsumer c = new QueueingConsumer(channel); declareBindConsume(c); channel.basicQos(1, true); fill(3); //We actually only guarantee that the limit takes effect //*eventually*, so this can in fact fail. It's pretty unlikely //though. List d = drain(c, 1); ack(d, true); drain(c, 1); } @Test public void limitIncrease() throws IOException { QueueingConsumer c = new QueueingConsumer(channel); configure(c, 1, 3); channel.basicQos(2, true); drain(c, 1); } @Test public void limitDecrease() throws IOException { QueueingConsumer c = new QueueingConsumer(channel); List d = configure(c, 2, 4); channel.basicQos(1, true); drain(c, 0); ack(d, true); drain(c, 1); } @Test public void limitedToUnlimited() throws IOException { QueueingConsumer c = new QueueingConsumer(channel); configure(c, 1, 3); channel.basicQos(0, true); drain(c, 2); } @Test public void limitingMultipleChannels() throws IOException { Channel ch1 = connection.createChannel(); Channel ch2 = connection.createChannel(); QueueingConsumer c1 = new QueueingConsumer(ch1); QueueingConsumer c2 = new QueueingConsumer(ch2); String q1 = declareBindConsume(ch1, c1, false); String q2 = declareBindConsume(ch2, c2, false); ch1.basicConsume(q2, false, c1); ch2.basicConsume(q1, false, c2); ch1.basicQos(1, true); ch2.basicQos(1, true); fill(5); List d1 = drain(c1, 1); List d2 = drain(c2, 1); ackDelivery(ch1, d1.remove(0), true); ackDelivery(ch2, d2.remove(0), true); drain(c1, 1); drain(c2, 1); ch1.abort(); ch2.abort(); } @Test public void limitInheritsUnackedCount() throws IOException { QueueingConsumer c = new QueueingConsumer(channel); declareBindConsume(c); fill(1); drain(c, 1); channel.basicQos(2, true); fill(2); drain(c, 1); } @Test public void recoverReducesLimit() throws Exception { channel.basicQos(2, true); QueueingConsumer c = new QueueingConsumer(channel); declareBindConsume(c); fill(3); drain(c, 2); channel.basicRecover(true); drain(c, 2); } protected void runLimitTests(int limit, boolean multiAck, boolean txMode, int queueCount) throws IOException { QueueingConsumer c = new QueueingConsumer(channel); // We attempt to drain 'limit' messages twice, do one // basic.get per queue, and need one message to spare //-> 2*limit + 1*queueCount + 1 List queues = configure(c, limit, queueCount, 2*limit + 1*queueCount + 1); if (txMode) { channel.txSelect(); } //is limit enforced? List d = drain(c, limit); //is basic.get not limited? List tags = new ArrayList(); for (String q : queues) { GetResponse r = channel.basicGet(q, false); assertNotNull(r); tags.add(r.getEnvelope().getDeliveryTag()); } //are acks handled correctly? //and does the basic.get above have no effect on limiting? Delivery last = ack(d, multiAck); if (txMode) { drain(c, 0); channel.txRollback(); drain(c, 0); ackDelivery(last, true); channel.txCommit(); } drain(c, limit); //do acks for basic.gets have no effect on limiting? for (long t : tags) { channel.basicAck(t, false); } if (txMode) { channel.txCommit(); } drain(c, 0); } protected Delivery ack(List d, boolean multiAck) throws IOException { Delivery last = null; for (Delivery tmp : d) { if (!multiAck) ackDelivery(tmp, false); last = tmp; } if (multiAck) ackDelivery(last, true); return last; } protected List configure(QueueingConsumer c, int limit, int queueCount, int messages) throws IOException { channel.basicQos(limit, true); //declare/bind/consume-from queues List queues = new ArrayList(); for (int i = 0; i < queueCount; i++) { queues.add(declareBindConsume(c)); } //publish fill(messages); return queues; } protected List configure(QueueingConsumer c, int limit, int messages) throws IOException { channel.basicQos(limit, true); declareBindConsume(c); fill(messages); return drain(c, limit); } protected String declareBindConsume(QueueingConsumer c) throws IOException { return declareBindConsume(channel, c, false); } protected String declareBindConsume(Channel ch, QueueingConsumer c, boolean noAck) throws IOException { String queue = declareBind(ch); ch.basicConsume(queue, noAck, c); return queue; } protected String declareBind(Channel ch) throws IOException { AMQP.Queue.DeclareOk ok = ch.queueDeclare(); String queue = ok.getQueue(); ch.queueBind(queue, "amq.fanout", ""); return queue; } protected void ackDelivery(Delivery d, boolean multiple) throws IOException { ackDelivery(channel, d, multiple); } protected void ackDelivery(Channel ch, Delivery d, boolean multiple) throws IOException { ch.basicAck(d.getEnvelope().getDeliveryTag(), multiple); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/QueueExclusivity.java000066400000000000000000000122631316117667700334000ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import static org.junit.Assert.fail; import java.io.IOException; import java.util.HashMap; import java.util.concurrent.TimeoutException; import org.junit.Test; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; import com.rabbitmq.client.QueueingConsumer; import com.rabbitmq.client.test.BrokerTestCase; // Test queue auto-delete and exclusive semantics. public class QueueExclusivity extends BrokerTestCase { final HashMap noArgs = new HashMap(); public Connection altConnection; public Channel altChannel; final String q = "exclusiveQ"; protected void createResources() throws IOException, TimeoutException { altConnection = connectionFactory.newConnection(); altChannel = altConnection.createChannel(); altChannel.queueDeclare(q, // not durable, exclusive, not auto-delete false, true, false, noArgs); } protected void releaseResources() throws IOException { if (altConnection != null && altConnection.isOpen()) { altConnection.close(); } } @Test public void queueExclusiveForPassiveDeclare() throws Exception { try { channel.queueDeclarePassive(q); } catch (IOException ioe) { checkShutdownSignal(AMQP.RESOURCE_LOCKED, ioe); return; } fail("Passive queue declaration of an exclusive queue from another connection should fail"); } // This is a different scenario because active declare takes notice of // the all the arguments @Test public void queueExclusiveForDeclare() throws Exception { try { channel.queueDeclare(q, false, true, false, noArgs); } catch (IOException ioe) { checkShutdownSignal(AMQP.RESOURCE_LOCKED, ioe); return; } fail("Active queue declaration of an exclusive queue from another connection should fail"); } @Test public void queueExclusiveForConsume() throws Exception { QueueingConsumer c = new QueueingConsumer(channel); try { channel.basicConsume(q, c); } catch (IOException ioe) { checkShutdownSignal(AMQP.RESOURCE_LOCKED, ioe); return; } fail("Exclusive queue should be locked for basic consume from another connection"); } @Test public void queueExclusiveForPurge() throws Exception { try { channel.queuePurge(q); } catch (IOException ioe) { checkShutdownSignal(AMQP.RESOURCE_LOCKED, ioe); return; } fail("Exclusive queue should be locked for queue purge from another connection"); } @Test public void queueExclusiveForDelete() throws Exception { try { channel.queueDelete(q); } catch (IOException ioe) { checkShutdownSignal(AMQP.RESOURCE_LOCKED, ioe); return; } fail("Exclusive queue should be locked for queue delete from another connection"); } @Test public void queueExclusiveForBind() throws Exception { try { channel.queueBind(q, "amq.direct", ""); } catch (IOException ioe) { checkShutdownSignal(AMQP.RESOURCE_LOCKED, ioe); return; } fail("Exclusive queue should be locked for queue bind from another connection"); } // NB The spec XML doesn't mention queue.unbind, basic.cancel, or // basic.get in the exclusive rule. It seems the most sensible // interpretation to include queue.unbind and basic.get in the // prohibition. // basic.cancel is inherently local to a channel, so it // *doesn't* make sense to include it. @Test public void queueExclusiveForUnbind() throws Exception { altChannel.queueBind(q, "amq.direct", ""); try { channel.queueUnbind(q, "amq.direct", ""); } catch (IOException ioe) { checkShutdownSignal(AMQP.RESOURCE_LOCKED, ioe); return; } fail("Exclusive queue should be locked for queue unbind from another connection"); } @Test public void queueExclusiveForGet() throws Exception { try { channel.basicGet(q, true); } catch (IOException ioe) { checkShutdownSignal(AMQP.RESOURCE_LOCKED, ioe); return; } fail("Exclusive queue should be locked for basic get from another connection"); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/QueueLease.java000066400000000000000000000217741316117667700321100ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import static org.junit.Assert.fail; import java.io.IOException; import java.util.HashMap; import java.util.Map; import org.junit.Test; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.Consumer; import com.rabbitmq.client.DefaultConsumer; import com.rabbitmq.client.test.BrokerTestCase; public class QueueLease extends BrokerTestCase { private final static String TEST_EXPIRE_QUEUE = "leaseq"; private final static String TEST_NORMAL_QUEUE = "noleaseq"; private final static String TEST_EXPIRE_REDECLARE_QUEUE = "equivexpire"; // Currently the expiration timer is very responsive but this may // very well change in the future, so tweak accordingly. private final static int QUEUE_EXPIRES = 1000; // msecs private final static int SHOULD_EXPIRE_WITHIN = 2000; /** * Verify that a queue with the 'x-expires` flag is actually deleted within * a sensible period of time after expiry. */ @Test public void queueExpires() throws IOException, InterruptedException { verifyQueueExpires(TEST_EXPIRE_QUEUE, true); } /** * Verify that the server does not delete normal queues... ;) */ @Test public void doesNotExpireOthers() throws IOException, InterruptedException { verifyQueueExpires(TEST_NORMAL_QUEUE, false); } @Test public void expireMayBeByte() throws IOException { Map args = new HashMap(); args.put("x-expires", (byte)100); try { channel.queueDeclare("expiresMayBeByte", false, true, false, args); } catch (IOException e) { fail("server did not accept x-expires of type byte"); } } @Test public void expireMayBeShort() throws IOException { Map args = new HashMap(); args.put("x-expires", (short)100); try { channel.queueDeclare("expiresMayBeShort", false, true, false, args); } catch (IOException e) { fail("server did not accept x-expires of type short"); } } @Test public void expireMayBeLong() throws IOException { Map args = new HashMap(); args.put("x-expires", 100L); try { channel.queueDeclare("expiresMayBeLong", false, true, false, args); } catch (IOException e) { fail("server did not accept x-expires of type long"); } } @Test public void expireMustBeGtZero() throws IOException { Map args = new HashMap(); args.put("x-expires", 0); try { channel.queueDeclare("expiresMustBeGtZero", false, false, false, args); fail("server accepted x-expires of zero ms."); } catch (IOException e) { checkShutdownSignal(AMQP.PRECONDITION_FAILED, e); } } @Test public void expireMustBePositive() throws IOException { Map args = new HashMap(); args.put("x-expires", -10); try { channel.queueDeclare("expiresMustBePositive", false, false, false, args); fail("server accepted negative x-expires."); } catch (IOException e) { checkShutdownSignal(AMQP.PRECONDITION_FAILED, e); } } /** * Verify that the server throws an error if the client redeclares a queue * with mismatching 'x-expires' values. */ @Test public void queueRedeclareEquivalence() throws IOException { Map args1 = new HashMap(); args1.put("x-expires", 10000); Map args2 = new HashMap(); args2.put("x-expires", 20000); channel.queueDeclare(TEST_EXPIRE_REDECLARE_QUEUE, false, false, false, args1); try { channel.queueDeclare(TEST_EXPIRE_REDECLARE_QUEUE, false, false, false, args2); fail("Able to redeclare queue with mismatching expire flags."); } catch (IOException e) { checkShutdownSignal(AMQP.PRECONDITION_FAILED, e); } } @Test public void activeQueueDeclareExtendsLease() throws InterruptedException, IOException { Map args = new HashMap(); args.put("x-expires", QUEUE_EXPIRES); channel.queueDeclare(TEST_EXPIRE_QUEUE, false, false, false, args); Thread.sleep(QUEUE_EXPIRES * 3 / 4); try { channel.queueDeclare(TEST_EXPIRE_QUEUE, false, false, false, args); } catch (IOException e) { checkShutdownSignal(AMQP.NOT_FOUND, e); fail("Queue expired before active re-declaration."); } Thread.sleep(QUEUE_EXPIRES * 3 / 4); try { channel.queueDeclarePassive(TEST_EXPIRE_QUEUE); } catch (IOException e) { checkShutdownSignal(AMQP.NOT_FOUND, e); fail("Queue expired: active re-declaration did not extend lease."); } } @Test public void passiveQueueDeclareExtendsLease() throws InterruptedException, IOException { Map args = new HashMap(); args.put("x-expires", QUEUE_EXPIRES); channel.queueDeclare(TEST_EXPIRE_QUEUE, false, false, false, args); Thread.sleep(QUEUE_EXPIRES * 3 / 4); try { channel.queueDeclarePassive(TEST_EXPIRE_QUEUE); } catch (IOException e) { checkShutdownSignal(AMQP.NOT_FOUND, e); fail("Queue expired before before passive re-declaration."); } Thread.sleep(QUEUE_EXPIRES * 3 / 4); try { channel.queueDeclarePassive(TEST_EXPIRE_QUEUE); } catch (IOException e) { checkShutdownSignal(AMQP.NOT_FOUND, e); fail("Queue expired: passive redeclaration did not extend lease."); } } @Test public void expiresWithConsumers() throws InterruptedException, IOException { Map args = new HashMap(); args.put("x-expires", QUEUE_EXPIRES); channel.queueDeclare(TEST_EXPIRE_QUEUE, false, false, false, args); Consumer consumer = new DefaultConsumer(channel); String consumerTag = channel.basicConsume(TEST_EXPIRE_QUEUE, consumer); Thread.sleep(SHOULD_EXPIRE_WITHIN); try { channel.queueDeclarePassive(TEST_EXPIRE_QUEUE); } catch (IOException e) { checkShutdownSignal(AMQP.NOT_FOUND, e); fail("Queue expired before before passive re-declaration."); } channel.basicCancel(consumerTag); Thread.sleep(SHOULD_EXPIRE_WITHIN); try { channel.queueDeclarePassive(TEST_EXPIRE_QUEUE); fail("Queue should have been expired by now."); } catch (IOException e) { checkShutdownSignal(AMQP.NOT_FOUND, e); } } void verifyQueueExpires(String name, boolean expire) throws IOException, InterruptedException { Map args = new HashMap(); if (expire) { args.put("x-expires", QUEUE_EXPIRES); } channel.queueDeclare(name, false, false, false, args); Thread.sleep(SHOULD_EXPIRE_WITHIN / 4); try { channel.queueDeclarePassive(name); } catch (IOException e) { checkShutdownSignal(AMQP.NOT_FOUND, e); fail("Queue expired before deadline."); } Thread.sleep(SHOULD_EXPIRE_WITHIN); // be on the safe side try { channel.queueDeclarePassive(name); if (expire) { fail("Queue should have been expired by now."); } } catch (IOException e) { if (expire) { checkShutdownSignal(AMQP.NOT_FOUND, e); } else { fail("Queue without expire flag deleted."); } } } protected void releaseResources() throws IOException { try { channel.queueDelete(TEST_NORMAL_QUEUE); channel.queueDelete(TEST_EXPIRE_QUEUE); channel.queueDelete(TEST_EXPIRE_REDECLARE_QUEUE); } catch (IOException e) { } super.releaseResources(); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/QueueLifecycle.java000066400000000000000000000175111316117667700327500ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.Consumer; import com.rabbitmq.client.DefaultConsumer; import com.rabbitmq.client.test.BrokerTestCase; import org.junit.Test; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeoutException; import static org.junit.Assert.fail; /** * Test queue auto-delete and exclusive semantics. */ public class QueueLifecycle extends BrokerTestCase { void verifyQueueExists(String name) throws IOException { channel.queueDeclarePassive(name); } void verifyQueueMissing(String name) throws IOException { // we can't in general check with a passive declare, since that // may return an IOException because of exclusivity. But we can // check that we can happily declare another with the same name: // the only circumstance in which this won't result in an error is // if it doesn't exist. try { channel.queueDeclare(name, false, false, false, null); } catch (IOException ioe) { fail("Queue.Declare threw an exception, probably meaning that the queue already exists"); } // clean up channel.queueDelete(name); } /** * Verify that a queue both exists and has the properties as given * * @throws IOException * if one of these conditions is not true */ void verifyQueue(String name, boolean durable, boolean exclusive, boolean autoDelete, Map args) throws IOException { verifyQueueExists(name); // use passive/equivalent rule to check that it has the same properties channel.queueDeclare(name, durable, exclusive, autoDelete, args); } // NB the exception will close the connection void verifyNotEquivalent(boolean durable, boolean exclusive, boolean autoDelete) throws IOException { String q = "queue"; channel.queueDeclare(q, false, false, false, null); try { verifyQueue(q, durable, exclusive, autoDelete, null); } catch (IOException ioe) { if (exclusive) checkShutdownSignal(AMQP.RESOURCE_LOCKED, ioe); else checkShutdownSignal(AMQP.PRECONDITION_FAILED, ioe); return; } fail("Queue.declare should have been rejected as not equivalent"); } /** From amqp-0-9-1.xml, for "passive" property, "equivalent" rule: * "If not set and the queue exists, the server MUST check that the * existing queue has the same values for durable, exclusive, * auto-delete, and arguments fields. The server MUST respond with * Declare-Ok if the requested queue matches these fields, and MUST * raise a channel exception if not." */ @Test public void queueEquivalence() throws IOException { String q = "queue"; channel.queueDeclare(q, false, false, false, null); // equivalent verifyQueue(q, false, false, false, null); // the spec says that the arguments table is matched on // being semantically equivalent. HashMap args = new HashMap(); args.put("assumed-to-be-semantically-void", "bar"); verifyQueue(q, false, false, false, args); } // not equivalent in various ways @Test public void queueNonEquivalenceDurable() throws IOException { verifyNotEquivalent(true, false, false); } @Test public void queueNonEquivalenceExclusive() throws IOException { verifyNotEquivalent(false, true, false); } @Test public void queueNonEquivalenceAutoDelete() throws IOException { verifyNotEquivalent(false, false, true); } // Note that this assumes that auto-deletion is synchronous with // basic.cancel, // which is not actually in the spec. (If it isn't, there's a race here). @Test public void queueAutoDelete() throws IOException { String name = "tempqueue"; channel.queueDeclare(name, false, false, true, null); // now it's there verifyQueue(name, false, false, true, null); Consumer consumer = new DefaultConsumer(channel); String consumerTag = channel.basicConsume(name, consumer); channel.basicCancel(consumerTag); // now it's not .. we hope try { verifyQueueExists(name); } catch (IOException ioe) { checkShutdownSignal(AMQP.NOT_FOUND, ioe); return; } fail("Queue should have been auto-deleted after we removed its only consumer"); } @Test public void exclusiveNotAutoDelete() throws IOException { String name = "exclusivequeue"; channel.queueDeclare(name, false, true, false, null); // now it's there verifyQueue(name, false, true, false, null); Consumer consumer = new DefaultConsumer(channel); String consumerTag = channel.basicConsume(name, consumer); channel.basicCancel(consumerTag); // and still there, because exclusive no longer implies autodelete verifyQueueExists(name); } @Test public void exclusiveGoesWithConnection() throws IOException, TimeoutException { String name = "exclusivequeue2"; channel.queueDeclare(name, false, true, false, null); // now it's there verifyQueue(name, false, true, false, null); closeConnection(); openConnection(); openChannel(); verifyQueueMissing(name); } @Test public void argumentArrays() throws IOException { Map args = new HashMap(); String[] arr = new String[]{"foo", "bar", "baz"}; args.put("my-key", arr); String queueName = "argumentArraysQueue"; channel.queueDeclare(queueName, true, true, false, args); verifyQueue(queueName, true, true, false, args); } @Test public void queueNamesLongerThan255Characters() throws IOException { String q = new String(new byte[300]).replace('\u0000', 'x'); try { channel.queueDeclare(q, false, false, false, null); fail("queueDeclare should have failed"); } catch (IllegalArgumentException ignored) { // expected } } @Test public void singleLineFeedStrippedFromQueueName() throws IOException { channel.queueDeclare("que\nue_test", false, false, true, null); verifyQueue(NAME_STRIPPED, false, false, true, null); } @Test public void multipleLineFeedsStrippedFromQueueName() throws IOException { channel.queueDeclare("que\nue_\ntest\n", false, false, true, null); verifyQueue(NAME_STRIPPED, false, false, true, null); } @Test public void multipleLineFeedAndCarriageReturnsStrippedFromQueueName() throws IOException { channel.queueDeclare("q\ru\ne\r\nue_\ntest\n\r", false, false, true, null); verifyQueue(NAME_STRIPPED, false, false, true, null); } static final String NAME_STRIPPED = "queue_test"; @Override protected void releaseResources() throws IOException { channel.queueDelete(NAME_STRIPPED); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/QueueSizeLimit.java000066400000000000000000000131441316117667700327600ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.junit.Test; import com.rabbitmq.client.GetResponse; import com.rabbitmq.client.test.BrokerTestCase; /** * Test queue max length limit. */ public class QueueSizeLimit extends BrokerTestCase { private final int MAXMAXLENGTH = 3; private final String q = "queue-maxlength"; @Test public void queueSize() throws IOException, InterruptedException { for (int maxLen = 0; maxLen <= MAXMAXLENGTH; maxLen ++){ setupNonDlxTest(maxLen, false); assertHead(maxLen, "msg2", q); deleteQueue(q); } } @Test public void queueSizeUnacked() throws IOException, InterruptedException { for (int maxLen = 0; maxLen <= MAXMAXLENGTH; maxLen ++){ setupNonDlxTest(maxLen, true); assertHead(maxLen > 0 ? 1 : 0, "msg" + (maxLen + 1), q); deleteQueue(q); } } @Test public void queueSizeDlx() throws IOException, InterruptedException { for (int maxLen = 0; maxLen <= MAXMAXLENGTH; maxLen ++){ setupDlxTest(maxLen, false); assertHead(1, "msg1", "DLQ"); deleteQueue(q); deleteQueue("DLQ"); } } @Test public void queueSizeUnackedDlx() throws IOException, InterruptedException { for (int maxLen = 0; maxLen <= MAXMAXLENGTH; maxLen ++){ setupDlxTest(maxLen, true); assertHead(maxLen > 0 ? 0 : 1, "msg1", "DLQ"); deleteQueue(q); deleteQueue("DLQ"); } } @Test public void requeue() throws IOException, InterruptedException { for (int maxLen = 1; maxLen <= MAXMAXLENGTH; maxLen ++) { declareQueue(maxLen, false); setupRequeueTest(maxLen); assertHead(maxLen, "msg1", q); deleteQueue(q); } } @Test public void requeueWithDlx() throws IOException, InterruptedException { for (int maxLen = 1; maxLen <= MAXMAXLENGTH; maxLen ++) { declareQueue(maxLen, true); setupRequeueTest(maxLen); assertHead(maxLen, "msg1", q); assertHead(maxLen, "msg1", "DLQ"); deleteQueue(q); deleteQueue("DLQ"); } } private void setupNonDlxTest(int maxLen, boolean unAcked) throws IOException, InterruptedException { declareQueue(maxLen, false); fill(maxLen); if (unAcked) getUnacked(maxLen); publish("msg" + (maxLen + 1)); } private void setupDlxTest(int maxLen, boolean unAcked) throws IOException, InterruptedException { declareQueue(maxLen, true); fill(maxLen); if (unAcked) getUnacked(maxLen); publish("msg" + (maxLen + 1)); try { Thread.sleep(100); } catch (InterruptedException _e) { } } private void setupRequeueTest(int maxLen) throws IOException, InterruptedException { fill(maxLen); List tags = getUnacked(maxLen); fill(maxLen); channel.basicNack(tags.get(0), false, true); if (maxLen > 1) channel.basicNack(tags.get(maxLen - 1), true, true); } private void declareQueue(int maxLen, boolean dlx) throws IOException { Map args = new HashMap(); args.put("x-max-length", maxLen); if (dlx) { args.put("x-dead-letter-exchange", "amq.fanout"); channel.queueDeclare("DLQ", false, true, false, null); channel.queueBind("DLQ", "amq.fanout", ""); } channel.queueDeclare(q, false, true, true, args); } private void fill(int count) throws IOException, InterruptedException { for (int i=1; i <= count; i++){ publish("msg" + i); } } private void publish(String payload) throws IOException, InterruptedException { basicPublishVolatile(payload.getBytes(), q); } private void assertHead(int expectedLength, String expectedHeadPayload, String queueName) throws IOException { GetResponse head = channel.basicGet(queueName, true); if (expectedLength > 0) { assertNotNull(head); assertEquals(expectedHeadPayload, new String(head.getBody())); assertEquals(expectedLength, head.getMessageCount() + 1); } else { assertNull(head); } } private List getUnacked(int howMany) throws IOException { List tags = new ArrayList(howMany); for (;howMany > 0; howMany --) { GetResponse response = channel.basicGet(q, false); tags.add(response.getEnvelope().getDeliveryTag()); } return tags; } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/Recover.java000066400000000000000000000114611316117667700314470ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.IOException; import java.util.Arrays; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; import com.rabbitmq.client.*; import org.junit.Test; import com.rabbitmq.client.test.BrokerTestCase; public class Recover extends BrokerTestCase { String queue; final byte[] body = "message".getBytes(); public void createResources() throws IOException { AMQP.Queue.DeclareOk ok = channel.queueDeclare(); queue = ok.getQueue(); } static interface RecoverCallback { void recover(Channel channel) throws IOException; } // The AMQP specification under-specifies the behaviour when // requeue=false. So we can't really test any scenarios for // requeue=false. void verifyRedeliverOnRecover(RecoverCallback call) throws IOException, InterruptedException { QueueingConsumer consumer = new QueueingConsumer(channel); channel.basicConsume(queue, false, consumer); // require acks. channel.basicPublish("", queue, new AMQP.BasicProperties.Builder().build(), body); QueueingConsumer.Delivery delivery = consumer.nextDelivery(); assertTrue("consumed message body not as sent", Arrays.equals(body, delivery.getBody())); // Don't ack it, and get it redelivered to the same consumer call.recover(channel); QueueingConsumer.Delivery secondDelivery = consumer.nextDelivery(5000); assertNotNull("timed out waiting for redelivered message", secondDelivery); assertTrue("consumed (redelivered) message body not as sent", Arrays.equals(body, delivery.getBody())); } void verifyNoRedeliveryWithAutoAck(RecoverCallback call) throws IOException, InterruptedException { final CountDownLatch latch = new CountDownLatch(1); final AtomicReference bodyReference = new AtomicReference(); Consumer consumer = new DefaultConsumer(channel) { @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { bodyReference.set(body); latch.countDown(); } }; channel.basicConsume(queue, true, consumer); // auto ack. channel.basicPublish("", queue, new AMQP.BasicProperties.Builder().build(), body); assertTrue(latch.await(5, TimeUnit.SECONDS)); assertTrue("consumed message body not as sent", Arrays.equals(body, bodyReference.get())); call.recover(channel); assertNull("should be no message available", channel.basicGet(queue, true)); } final RecoverCallback recoverSync = new RecoverCallback() { public void recover(Channel channel) throws IOException { channel.basicRecover(true); } }; final RecoverCallback recoverSyncConvenience = new RecoverCallback() { public void recover(Channel channel) throws IOException { channel.basicRecover(); } }; @Test public void redeliveryOnRecover() throws IOException, InterruptedException { verifyRedeliverOnRecover(recoverSync); } @Test public void redeliverOnRecoverConvenience() throws IOException, InterruptedException { verifyRedeliverOnRecover(recoverSyncConvenience); } @Test public void noRedeliveryWithAutoAck() throws IOException, InterruptedException { verifyNoRedeliveryWithAutoAck(recoverSync); } @Test public void requeueFalseNotSupported() throws Exception { try { channel.basicRecover(false); fail("basicRecover(false) should not be supported"); } catch(IOException ioe) { checkShutdownSignal(AMQP.NOT_IMPLEMENTED, ioe); } } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/Reject.java000066400000000000000000000037231316117667700312600ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import static org.junit.Assert.assertNull; import java.io.IOException; import org.junit.Test; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.QueueingConsumer; public class Reject extends AbstractRejectTest { @Test public void reject() throws IOException, InterruptedException { String q = channel.queueDeclare("", false, true, false, null).getQueue(); byte[] m1 = "1".getBytes(); byte[] m2 = "2".getBytes(); basicPublishVolatile(m1, q); basicPublishVolatile(m2, q); long tag1 = checkDelivery(channel.basicGet(q, false), m1, false); long tag2 = checkDelivery(channel.basicGet(q, false), m2, false); QueueingConsumer c = new QueueingConsumer(secondaryChannel); String consumerTag = secondaryChannel.basicConsume(q, false, c); channel.basicReject(tag2, true); long tag3 = checkDelivery(c.nextDelivery(), m2, true); secondaryChannel.basicCancel(consumerTag); secondaryChannel.basicReject(tag3, false); assertNull(channel.basicGet(q, false)); channel.basicAck(tag1, false); channel.basicReject(tag3, false); expectError(AMQP.PRECONDITION_FAILED); } } RequeueOnChannelClose.java000066400000000000000000000020211316117667700341420ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import java.io.IOException; public class RequeueOnChannelClose extends RequeueOnClose { protected void open() throws IOException { openChannel(); } protected void close() throws IOException { closeChannel(); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/RequeueOnClose.java000066400000000000000000000225141316117667700327410ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import static org.junit.Assert.*; import org.junit.Test; import com.rabbitmq.client.test.BrokerTestCase; import java.io.IOException; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeoutException; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.Channel; import com.rabbitmq.client.DefaultConsumer; import com.rabbitmq.client.Envelope; import com.rabbitmq.client.GetResponse; import com.rabbitmq.client.QueueingConsumer; import com.rabbitmq.client.ShutdownSignalException; /** * Test Requeue of messages on different types of close. * Methods {@link #open} and {@link #close} must be implemented by a concrete subclass. */ public abstract class RequeueOnClose extends BrokerTestCase { private static final String Q = "RequeueOnClose"; private static final int MESSAGE_COUNT = 2000; protected abstract void open() throws IOException, TimeoutException; protected abstract void close() throws IOException; public void setUp() throws IOException { // Override to disable the default behaviour from BrokerTestCase. } public void tearDown() throws IOException { // Override to disable the default behaviour from BrokerTestCase. } private void injectMessage() throws IOException { channel.queueDeclare(Q, false, false, false, null); channel.queueDelete(Q); channel.queueDeclare(Q, false, false, false, null); channel.basicPublish("", Q, null, "RequeueOnClose message".getBytes()); } private GetResponse getMessage() throws IOException { return channel.basicGet(Q, false); } private void publishAndGet(int count, boolean doAck) throws IOException, InterruptedException, TimeoutException { openConnection(); for (int repeat = 0; repeat < count; repeat++) { open(); injectMessage(); GetResponse r1 = getMessage(); if (doAck) channel.basicAck(r1.getEnvelope().getDeliveryTag(), false); close(); open(); if (doAck) { assertNull("Expected missing second basicGet (repeat="+repeat+")", getMessage()); } else { assertNotNull("Expected present second basicGet (repeat="+repeat+")", getMessage()); } close(); } closeConnection(); } /** * Test we don't requeue acknowledged messages (using get) * @throws Exception untested */ @Test public void normal() throws Exception { publishAndGet(3, true); } /** * Test we requeue unacknowledged messages (using get) * @throws Exception untested */ @Test public void requeueing() throws Exception { publishAndGet(3, false); } /** * Test we requeue unacknowledged message (using consumer) * @throws Exception untested */ @Test public void requeueingConsumer() throws Exception { openConnection(); open(); injectMessage(); QueueingConsumer c = new QueueingConsumer(channel); channel.basicConsume(Q, c); c.nextDelivery(); close(); open(); assertNotNull(getMessage()); close(); closeConnection(); } private void publishLotsAndGet() throws IOException, InterruptedException, ShutdownSignalException, TimeoutException { openConnection(); open(); channel.queueDeclare(Q, false, false, false, null); channel.queueDelete(Q); channel.queueDeclare(Q, false, false, false, null); for (int i = 0; i < MESSAGE_COUNT; i++) { channel.basicPublish("", Q, null, "in flight message".getBytes()); } QueueingConsumer c = new QueueingConsumer(channel); channel.basicConsume(Q, c); c.nextDelivery(); close(); open(); for (int i = 0; i < MESSAGE_COUNT; i++) { assertNotNull("only got " + i + " out of " + MESSAGE_COUNT + " messages", channel.basicGet(Q, true)); } assertNull("got more messages than " + MESSAGE_COUNT + " expected", channel.basicGet(Q, true)); channel.queueDelete(Q); close(); closeConnection(); } /** * Test close while consuming many messages successfully requeues unacknowledged messages * @throws Exception untested */ @Test public void requeueInFlight() throws Exception { for (int i = 0; i < 5; i++) { publishLotsAndGet(); } } /** * Test close while consuming partially not acked with cancel successfully requeues unacknowledged messages * @throws Exception untested */ @Test public void requeueInFlightConsumerNoAck() throws Exception { for (int i = 0; i < 5; i++) { publishLotsAndConsumeSome(false, true); } } /** * Test close while consuming partially acked with cancel successfully requeues unacknowledged messages * @throws Exception untested */ @Test public void requeueInFlightConsumerAck() throws Exception { for (int i = 0; i < 5; i++) { publishLotsAndConsumeSome(true, true); } } /** * Test close while consuming partially not acked without cancel successfully requeues unacknowledged messages * @throws Exception untested */ @Test public void requeueInFlightConsumerNoAckNoCancel() throws Exception { for (int i = 0; i < 5; i++) { publishLotsAndConsumeSome(false, false); } } /** * Test close while consuming partially acked without cancel successfully requeues unacknowledged messages * @throws Exception untested */ @Test public void requeueInFlightConsumerAckNoCancel() throws Exception { for (int i = 0; i < 5; i++) { publishLotsAndConsumeSome(true, false); } } private static final int MESSAGES_TO_CONSUME = 20; private void publishLotsAndConsumeSome(boolean ack, boolean cancelBeforeFinish) throws IOException, InterruptedException, ShutdownSignalException, TimeoutException { openConnection(); open(); channel.queueDeclare(Q, false, false, false, null); channel.queueDelete(Q); channel.queueDeclare(Q, false, false, false, null); for (int i = 0; i < MESSAGE_COUNT; i++) { channel.basicPublish("", Q, null, "in flight message".getBytes()); } CountDownLatch latch = new CountDownLatch(1); PartialConsumer c = new PartialConsumer(channel, MESSAGES_TO_CONSUME, ack, latch, cancelBeforeFinish); channel.basicConsume(Q, c); latch.await(); // wait for consumer close(); open(); int requeuedMsgCount = (ack) ? MESSAGE_COUNT - MESSAGES_TO_CONSUME : MESSAGE_COUNT; for (int i = 0; i < requeuedMsgCount; i++) { assertNotNull("only got " + i + " out of " + requeuedMsgCount + " messages", channel.basicGet(Q, true)); } int countMoreMsgs = 0; while (null != channel.basicGet(Q, true)) { countMoreMsgs++; } assertTrue("got " + countMoreMsgs + " more messages than " + requeuedMsgCount + " expected", 0==countMoreMsgs); channel.queueDelete(Q); close(); closeConnection(); } private class PartialConsumer extends DefaultConsumer { private volatile int count; private final Channel channel; private final CountDownLatch latch; private volatile boolean acknowledge; private final boolean cancelBeforeFinish; public PartialConsumer(Channel channel, int count, boolean acknowledge, CountDownLatch latch, boolean cancelBeforeFinish) { super(channel); this.count = count; this.channel = channel; this.latch = latch; this.acknowledge = acknowledge; this.cancelBeforeFinish = cancelBeforeFinish; } @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { if (this.acknowledge) this.channel.basicAck(envelope.getDeliveryTag(), false); if (--this.count == 0) { if (this.cancelBeforeFinish) this.channel.basicCancel(this.getConsumerTag()); this.acknowledge = false; // don't acknowledge any more this.latch.countDown(); } } } } RequeueOnConnectionClose.java000066400000000000000000000021511316117667700346750ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import java.io.IOException; import java.util.concurrent.TimeoutException; public class RequeueOnConnectionClose extends RequeueOnClose { protected void open() throws IOException, TimeoutException { openConnection(); openChannel(); } protected void close() throws IOException { closeConnection(); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/Routing.java000066400000000000000000000244411316117667700314730ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.fail; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.TimeoutException; import org.junit.Test; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.AlreadyClosedException; import com.rabbitmq.client.GetResponse; import com.rabbitmq.client.ReturnListener; import com.rabbitmq.client.test.BrokerTestCase; import com.rabbitmq.utility.BlockingCell; public class Routing extends BrokerTestCase { protected final String E = "MRDQ"; protected final String Q1 = "foo"; protected final String Q2 = "bar"; private volatile BlockingCell returnCell; protected void createResources() throws IOException { channel.exchangeDeclare(E, "direct"); channel.queueDeclare(Q1, false, false, false, null); channel.queueDeclare(Q2, false, false, false, null); } protected void releaseResources() throws IOException { channel.queueDelete(Q1); channel.queueDelete(Q2); channel.exchangeDelete(E); } private void bind(String queue, String routingKey) throws IOException { channel.queueBind(queue, E, routingKey); } private void check(String routingKey, boolean expectQ1, boolean expectQ2) throws IOException { channel.basicPublish(E, routingKey, null, "mrdq".getBytes()); checkGet(Q1, expectQ1); checkGet(Q2, expectQ2); } private void checkGet(String queue, boolean messageExpected) throws IOException { GetResponse r = channel.basicGet(queue, true); if (messageExpected) { assertNotNull(r); } else { assertNull(r); } } /** * Tests the "default queue name" and "default routing key" pieces * of the spec. See the doc for the "queue" and "routing key" * fields of queue.bind. */ @Test public void mRDQRouting() throws IOException { bind(Q1, "baz"); //Q1, "baz" bind(Q1, ""); //Q1, "" bind("", "baz"); //Q2, "baz" bind("", ""); //Q2, Q2 check("", true, false); check(Q1, false, false); check(Q2, false, true); check("baz", true, true); } /** * If a queue has more than one binding to an exchange, it should * NOT receive duplicate copies of a message that matches both * bindings. */ @Test public void doubleBinding() throws IOException { channel.queueBind(Q1, "amq.topic", "x.#"); channel.queueBind(Q1, "amq.topic", "#.x"); channel.basicPublish("amq.topic", "x.y", null, "x.y".getBytes()); checkGet(Q1, true); checkGet(Q1, false); channel.basicPublish("amq.topic", "y.x", null, "y.x".getBytes()); checkGet(Q1, true); checkGet(Q1, false); channel.basicPublish("amq.topic", "x.x", null, "x.x".getBytes()); checkGet(Q1, true); checkGet(Q1, false); } @Test public void fanoutRouting() throws Exception { List queues = new ArrayList(); for (int i = 0; i < 2; i++) { String q = "Q-" + System.nanoTime(); channel.queueDeclare(q, false, true, true, null); channel.queueBind(q, "amq.fanout", ""); queues.add(q); } channel.basicPublish("amq.fanout", System.nanoTime() + "", null, "fanout".getBytes()); for (String q : queues) { checkGet(q, true); } for (String q : queues) { channel.queueDelete(q); } } @Test public void topicRouting() throws Exception { List queues = new ArrayList(); //100+ queues is the trigger point for bug20046 for (int i = 0; i < 100; i++) { channel.queueDeclare(); AMQP.Queue.DeclareOk ok = channel.queueDeclare(); String q = ok.getQueue(); channel.queueBind(q, "amq.topic", "#"); queues.add(q); } channel.basicPublish("amq.topic", "", null, "topic".getBytes()); for (String q : queues) { checkGet(q, true); } } @Test public void headersRouting() throws Exception { Map spec = new HashMap(); spec.put("h1", "12345"); spec.put("h2", "bar"); spec.put("h3", null); spec.put("x-match", "all"); channel.queueBind(Q1, "amq.match", "", spec); spec.put("x-match", "any"); channel.queueBind(Q2, "amq.match", "", spec); AMQP.BasicProperties.Builder props = new AMQP.BasicProperties.Builder(); channel.basicPublish("amq.match", "", null, "0".getBytes()); channel.basicPublish("amq.match", "", props.build(), "0b".getBytes()); Map map = new HashMap(); props.headers(map); map.clear(); map.put("h1", "12345"); channel.basicPublish("amq.match", "", props.build(), "1".getBytes()); map.clear(); map.put("h1", "12345"); channel.basicPublish("amq.match", "", props.build(), "1b".getBytes()); map.clear(); map.put("h2", "bar"); channel.basicPublish("amq.match", "", props.build(), "2".getBytes()); map.clear(); map.put("h1", "12345"); map.put("h2", "bar"); channel.basicPublish("amq.match", "", props.build(), "3".getBytes()); map.clear(); map.put("h1", "12345"); map.put("h2", "bar"); map.put("h3", null); channel.basicPublish("amq.match", "", props.build(), "4".getBytes()); map.clear(); map.put("h1", "12345"); map.put("h2", "quux"); channel.basicPublish("amq.match", "", props.build(), "5".getBytes()); map.clear(); map.put("h1", "zot"); map.put("h2", "quux"); map.put("h3", null); channel.basicPublish("amq.match", "", props.build(), "6".getBytes()); map.clear(); map.put("h3", null); channel.basicPublish("amq.match", "", props.build(), "7".getBytes()); map.clear(); map.put("h1", "zot"); map.put("h2", "quux"); channel.basicPublish("amq.match", "", props.build(), "8".getBytes()); checkGet(Q1, true); // 4 checkGet(Q1, false); checkGet(Q2, true); // 1 checkGet(Q2, true); // 2 checkGet(Q2, true); // 3 checkGet(Q2, true); // 4 checkGet(Q2, true); // 5 checkGet(Q2, true); // 6 checkGet(Q2, true); // 7 checkGet(Q2, true); // 8 checkGet(Q2, false); } @Test public void basicReturn() throws IOException { channel.addReturnListener(makeReturnListener()); returnCell = new BlockingCell(); //returned 'mandatory' publish channel.basicPublish("", "unknown", true, false, null, "mandatory1".getBytes()); checkReturn(AMQP.NO_ROUTE); //routed 'mandatory' publish channel.basicPublish("", Q1, true, false, null, "mandatory2".getBytes()); assertNotNull(channel.basicGet(Q1, true)); //'immediate' publish channel.basicPublish("", Q1, false, true, null, "immediate".getBytes()); try { channel.basicQos(0); //flush fail("basic.publish{immediate=true} should not be supported"); } catch (IOException ioe) { checkShutdownSignal(AMQP.NOT_IMPLEMENTED, ioe); } catch (AlreadyClosedException ioe) { checkShutdownSignal(AMQP.NOT_IMPLEMENTED, ioe); } } @Test public void basicReturnTransactional() throws IOException { channel.txSelect(); channel.addReturnListener(makeReturnListener()); returnCell = new BlockingCell(); //returned 'mandatory' publish channel.basicPublish("", "unknown", true, false, null, "mandatory1".getBytes()); try { returnCell.uninterruptibleGet(200); fail("basic.return issued prior to tx.commit"); } catch (TimeoutException toe) {} channel.txCommit(); checkReturn(AMQP.NO_ROUTE); //routed 'mandatory' publish channel.basicPublish("", Q1, true, false, null, "mandatory2".getBytes()); channel.txCommit(); assertNotNull(channel.basicGet(Q1, true)); //returned 'mandatory' publish when message is routable on //publish but not on commit channel.basicPublish("", Q1, true, false, null, "mandatory2".getBytes()); channel.queueDelete(Q1); channel.txCommit(); checkReturn(AMQP.NO_ROUTE); channel.queueDeclare(Q1, false, false, false, null); } protected ReturnListener makeReturnListener() { return new ReturnListener() { public void handleReturn(int replyCode, String replyText, String exchange, String routingKey, AMQP.BasicProperties properties, byte[] body) throws IOException { Routing.this.returnCell.set(replyCode); } }; } protected void checkReturn(int replyCode) { assertEquals((int)returnCell.uninterruptibleGet(), AMQP.NO_ROUTE); returnCell = new BlockingCell(); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/SaslMechanisms.java000066400000000000000000000137651316117667700327650ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import static org.junit.Assert.fail; import java.io.IOException; import java.util.Arrays; import java.util.Map; import java.util.concurrent.TimeoutException; import com.rabbitmq.client.test.TestUtils; import org.junit.Test; import com.rabbitmq.client.AuthenticationFailureException; import com.rabbitmq.client.Connection; import com.rabbitmq.client.ConnectionFactory; import com.rabbitmq.client.LongString; import com.rabbitmq.client.PossibleAuthenticationFailureException; import com.rabbitmq.client.SaslConfig; import com.rabbitmq.client.SaslMechanism; import com.rabbitmq.client.impl.AMQConnection; import com.rabbitmq.client.impl.LongStringHelper; import com.rabbitmq.client.test.BrokerTestCase; public class SaslMechanisms extends BrokerTestCase { private String[] mechanisms; public class Mechanism implements SaslMechanism { private final String name; private final byte[][] responses; private int counter; public Mechanism(String name, byte[][] responses) { this.name = name; this.responses = responses; } public String getName() { return name; } public LongString handleChallenge(LongString challenge, String username, String password) { counter++; return LongStringHelper.asLongString(responses[counter-1]); } } public class Config implements SaslConfig { private final String name; private final byte[][] responses; public Config(String name, byte[][] responses) { this.name = name; this.responses = responses; } public SaslMechanism getSaslMechanism(String[] mechanisms) { SaslMechanisms.this.mechanisms = mechanisms; return new Mechanism(name, responses); } } @Test public void plainLogin() throws IOException, TimeoutException { loginOk("PLAIN", new byte[][] {"\0guest\0guest".getBytes()} ); loginBad("PLAIN", new byte[][] {"\0guest\0wrong".getBytes()} ); } @Test public void aMQPlainLogin() throws IOException, TimeoutException { // guest / guest loginOk("AMQPLAIN", new byte[][] {{5,76,79,71,73,78,83,0,0,0,5,103,117,101,115,116,8,80,65,83,83,87,79,82,68,83,0,0,0,5,103,117,101,115,116}} ); // guest / wrong loginBad("AMQPLAIN", new byte[][] {{5,76,79,71,73,78,83,0,0,0,5,103,117,101,115,116,8,80,65,83,83,87,79,82,68,83,0,0,0,5,119,114,111,110,103}} ); } @Test public void cRLogin() throws IOException, TimeoutException { // Make sure mechanisms is populated loginOk("PLAIN", new byte[][] {"\0guest\0guest".getBytes()} ); // We might be running this standalone if (Arrays.asList(mechanisms).contains("RABBIT-CR-DEMO")) { loginOk("RABBIT-CR-DEMO", new byte[][] {"guest".getBytes(), "My password is guest".getBytes()} ); loginBad("RABBIT-CR-DEMO", new byte[][] {"guest".getBytes(), "My password is wrong".getBytes()} ); } } @Test public void connectionCloseAuthFailureUsername() throws IOException, TimeoutException { connectionCloseAuthFailure("incorrect-username", "incorrect-password"); } @Test public void connectionCloseAuthFailurePassword() throws IOException, TimeoutException { connectionCloseAuthFailure(connectionFactory.getUsername(), "incorrect-password"); } public void connectionCloseAuthFailure(String username, String password) throws IOException, TimeoutException { String failDetail = "for username " + username + " and password " + password; try { Connection conn = connectionWithoutCapabilities(username, password); fail("Expected PossibleAuthenticationFailureException " + failDetail); conn.abort(); } catch (PossibleAuthenticationFailureException paf) { if (paf instanceof AuthenticationFailureException) { fail("Not expecting AuthenticationFailureException " + failDetail); } } } // start a connection without capabilities, causing authentication failures // to be reported by the broker by closing the connection private Connection connectionWithoutCapabilities(String username, String password) throws IOException, TimeoutException { ConnectionFactory customFactory = connectionFactory.clone(); customFactory.setUsername(username); customFactory.setPassword(password); Map customProperties = AMQConnection.defaultClientProperties(); customProperties.remove("capabilities"); customFactory.setClientProperties(customProperties); return customFactory.newConnection(); } private void loginOk(String name, byte[][] responses) throws IOException, TimeoutException { ConnectionFactory factory = TestUtils.connectionFactory(); factory.setSaslConfig(new Config(name, responses)); Connection connection = factory.newConnection(); connection.close(); } private void loginBad(String name, byte[][] responses) throws IOException, TimeoutException { try { loginOk(name, responses); fail("Login succeeded!"); } catch (AuthenticationFailureException e) { // Ok } } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/TTLHandling.java000066400000000000000000000165431316117667700321600ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.fail; import java.io.IOException; import org.junit.Test; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.GetResponse; import com.rabbitmq.client.QueueingConsumer; import com.rabbitmq.client.test.BrokerTestCase; public abstract class TTLHandling extends BrokerTestCase { protected static final String TTL_EXCHANGE = "ttl.exchange"; protected static final String TTL_QUEUE_NAME = "queue.ttl"; protected static final String TTL_INVALID_QUEUE_NAME = "invalid.queue.ttl"; protected static final String[] MSG = {"one", "two", "three"}; @Override protected void createResources() throws IOException { this.channel.exchangeDeclare(TTL_EXCHANGE, "direct"); } @Override protected void releaseResources() throws IOException { this.channel.exchangeDelete(TTL_EXCHANGE); } @Test public void multipleTTLTypes() throws IOException { final Object[] args = { (((byte)200) & (0xff)), (short)200, 200, 200L }; for (Object ttl : args) { try { declareAndBindQueue(ttl); publishAndSync(MSG[0]); } catch(IOException ex) { fail("Should be able to use " + ttl.getClass().getName() + " when setting TTL"); } } } @Test public void invalidTypeUsedInTTL() throws Exception { try { declareAndBindQueue("foobar"); publishAndSync(MSG[0]); fail("Should not be able to set TTL using non-numeric values"); } catch (IOException e) { checkShutdownSignal(AMQP.PRECONDITION_FAILED, e); } } @Test public void trailingCharsUsedInTTL() throws Exception { try { declareAndBindQueue("10000foobar"); publishAndSync(MSG[0]); fail("Should not be able to set TTL using non-numeric values"); } catch (IOException e) { checkShutdownSignal(AMQP.PRECONDITION_FAILED, e); } } @Test public void tTLMustBePositive() throws Exception { try { declareAndBindQueue(-10); publishAndSync(MSG[0]); fail("Should not be able to set TTL using negative values"); } catch (IOException e) { checkShutdownSignal(AMQP.PRECONDITION_FAILED, e); } } @Test public void tTLAllowZero() throws Exception { try { declareQueue(0); publishAndSync(MSG[0]); } catch (IOException e) { fail("Should be able to set ttl to zero"); } } @Test public void messagesExpireWhenUsingBasicGet() throws Exception { declareAndBindQueue(200); publish(MSG[0]); Thread.sleep(1000); String what = get(); assertNull("expected message " + what + " to have been removed", what); } @Test public void publishAndGetWithExpiry() throws Exception { declareAndBindQueue(200); publish(MSG[0]); Thread.sleep(150); publish(MSG[1]); Thread.sleep(100); publish(MSG[2]); assertEquals(MSG[1], get()); assertEquals(MSG[2], get()); assertNull(get()); } @Test public void transactionalPublishWithGet() throws Exception { declareAndBindQueue(100); this.channel.txSelect(); publish(MSG[0]); Thread.sleep(150); publish(MSG[1]); this.channel.txCommit(); Thread.sleep(50); assertEquals(MSG[0], get()); Thread.sleep(80); assertNull(get()); } @Test public void expiryWithRequeue() throws Exception { declareAndBindQueue(200); publish(MSG[0]); Thread.sleep(100); publish(MSG[1]); publish(MSG[2]); expectBodyAndRemainingMessages(MSG[0], 2); expectBodyAndRemainingMessages(MSG[1], 1); closeChannel(); openChannel(); Thread.sleep(110); expectBodyAndRemainingMessages(MSG[1], 1); expectBodyAndRemainingMessages(MSG[2], 0); } /* * Test expiry of re-queued messages after being consumed instantly */ @Test public void expiryWithReQueueAfterConsume() throws Exception { declareAndBindQueue(100); QueueingConsumer c = new QueueingConsumer(channel); channel.basicConsume(TTL_QUEUE_NAME, c); publish(MSG[0]); assertNotNull(c.nextDelivery(100)); closeChannel(); Thread.sleep(150); openChannel(); assertNull("Re-queued message not expired", get()); } @Test public void zeroTTLDelivery() throws Exception { declareAndBindQueue(0); // when there is no consumer, message should expire publish(MSG[0]); assertNull(get()); // when there is a consumer, message should be delivered QueueingConsumer c = new QueueingConsumer(channel); channel.basicConsume(TTL_QUEUE_NAME, c); publish(MSG[0]); QueueingConsumer.Delivery d = c.nextDelivery(100); assertNotNull(d); // requeued messages should expire channel.basicReject(d.getEnvelope().getDeliveryTag(), true); assertNull(c.nextDelivery(100)); } protected void expectBodyAndRemainingMessages(String body, int messagesLeft) throws IOException { GetResponse response = channel.basicGet(TTL_QUEUE_NAME, false); assertNotNull(response); assertEquals(body, new String(response.getBody())); assertEquals(messagesLeft, response.getMessageCount()); } protected void declareAndBindQueue(Object ttlValue) throws IOException { declareQueue(ttlValue); bindQueue(); } protected void bindQueue() throws IOException { this.channel.queueBind(TTL_QUEUE_NAME, TTL_EXCHANGE, TTL_QUEUE_NAME); } protected AMQP.Queue.DeclareOk declareQueue(Object ttlValue) throws IOException { return declareQueue(TTL_QUEUE_NAME, ttlValue); } protected abstract AMQP.Queue.DeclareOk declareQueue(String name, Object ttlValue) throws IOException; protected String get() throws IOException { GetResponse response = basicGet(TTL_QUEUE_NAME); return response == null ? null : new String(response.getBody()); } protected void publish(final String msg) throws IOException { basicPublishVolatile(msg.getBytes(), TTL_EXCHANGE, TTL_QUEUE_NAME); } protected void publishAndSync(String msg) throws IOException { publish(msg); this.channel.basicQos(0); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/Tables.java000066400000000000000000000077771316117667700312730ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.io.IOException; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import org.junit.Test; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.AMQP.BasicProperties; import com.rabbitmq.client.impl.LongStringHelper; import com.rabbitmq.client.test.BrokerTestCase; public class Tables extends BrokerTestCase { @Test public void types() throws IOException { Map table = new HashMap(); Map subTable = new HashMap(); subTable.put("key", 1); table.put("S", LongStringHelper.asLongString("string")); table.put("I", Integer.valueOf(1)); table.put("D", new BigDecimal("1.1")); table.put("T", new java.util.Date(1000000)); table.put("F", subTable); table.put("b", (byte)1); table.put("d", 1.1d); table.put("f", 1.1f); table.put("l", 1L); table.put("s", (short)1); table.put("t", true); table.put("x", "byte".getBytes()); table.put("V", null); List fieldArray = new ArrayList(); fieldArray.add(LongStringHelper.asLongString("foo")); fieldArray.add(123); table.put("A", fieldArray); //roundtrip of content headers AMQP.Queue.DeclareOk ok = channel.queueDeclare(); String q = ok.getQueue(); BasicProperties props = new BasicProperties(null, null, table, null, null, null, null, null, null, null, null, null, null, null); channel.basicPublish("", q, props, "".getBytes()); BasicProperties rProps = channel.basicGet(q, true).getProps(); assertMapsEqual(props.getHeaders(), rProps.getHeaders()); //sending as part of method arguments - we are relying on //exchange.declare ignoring the arguments table. channel.exchangeDeclare("x", "direct", false, false, table); channel.exchangeDelete("x"); } private static void assertMapsEqual(Map a, Map b) { assertEquals(a.keySet(), b.keySet()); Set keys = a.keySet(); for (String k : keys) { Object va = a.get(k); Object vb = b.get(k); if (va instanceof byte[] && vb instanceof byte[]) { assertTrue("unequal entry for key " + k, Arrays.equals((byte[])va, (byte[])vb)); } else if (va instanceof List && vb instanceof List) { Iterator vbi = ((List)vb).iterator(); for (Object vaEntry : (List)va) { Object vbEntry = vbi.next(); assertEquals("arrays unequal at key " + k, vaEntry, vbEntry); } } else { assertEquals("unequal entry for key " + k, va, vb); } } } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/Transactions.java000066400000000000000000000263641316117667700325220ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.fail; import java.io.IOException; import java.util.concurrent.TimeoutException; import org.junit.Test; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.GetResponse; import com.rabbitmq.client.test.BrokerTestCase; public class Transactions extends BrokerTestCase { protected static final String Q = "Transactions"; protected long latestTag = 0L; protected void createResources() throws IOException { channel.queueDeclare(Q, false, false, false, null); } protected void releaseResources() throws IOException { channel.queueDelete(Q); } private void txSelect() throws IOException { channel.txSelect(); } private void txCommit() throws IOException { channel.txCommit(); } private void txRollback() throws IOException { channel.txRollback(); } private void basicPublish() throws IOException { channel.basicPublish("", Q, null, "Tx message".getBytes()); } private GetResponse basicGet(boolean noAck) throws IOException { GetResponse r = channel.basicGet(Q, noAck); latestTag = (r == null) ? 0L : r.getEnvelope().getDeliveryTag(); return r; } private GetResponse basicGet() throws IOException { return basicGet(false); } private void basicAck(long tag, boolean multiple) throws IOException { channel.basicAck(tag, multiple); } private void basicAck() throws IOException { basicAck(latestTag, false); } private long[] publishSelectAndGet(int n) throws IOException { for (int i = 0; i < n; i++) { basicPublish(); } txSelect(); long tags[] = new long[n]; for (int i = 0; i < n; i++) { tags[i] = basicGet().getEnvelope().getDeliveryTag(); } return tags; } /* publishes are embargoed until commit */ @Test public void commitPublish() throws IOException { txSelect(); basicPublish(); assertNull(basicGet()); txCommit(); assertNotNull(basicGet()); txCommit(); } /* rollback rolls back publishes */ @Test public void rollbackPublish() throws IOException { txSelect(); basicPublish(); txRollback(); assertNull(basicGet()); } /* closing a channel rolls back publishes */ @Test public void rollbackPublishOnClose() throws IOException { txSelect(); basicPublish(); closeChannel(); openChannel(); assertNull(basicGet()); } /* closing a channel requeues both ack'ed and un-ack'ed messages */ @Test public void requeueOnClose() throws IOException { basicPublish(); basicPublish(); txSelect(); basicGet(); basicAck(); basicGet(); closeChannel(); openChannel(); assertNotNull(basicGet()); basicAck(); assertNotNull(basicGet()); basicAck(); } /* messages with committed acks are not requeued on channel close, messages that weren't ack'ed are requeued on close, but not before then. */ @Test public void commitAcks() throws IOException { basicPublish(); basicPublish(); txSelect(); basicGet(); basicAck(); basicGet(); txCommit(); assertNull(basicGet()); closeChannel(); openChannel(); assertNotNull(basicGet()); basicAck(); assertNull(basicGet()); } /* */ @Test public void commitAcksOutOfOrder() throws IOException { long tags[] = publishSelectAndGet(4); channel.basicNack(tags[3], false, false); channel.basicNack(tags[2], false, false); channel.basicAck(tags[1], false); channel.basicAck(tags[0], false); txCommit(); } /* rollback rolls back acks and a rolled back ack can be re-issued */ @Test public void rollbackAcksAndReAck() throws IOException { basicPublish(); txSelect(); basicGet(); basicAck(); txRollback(); basicAck(); txRollback(); closeChannel(); openChannel(); assertNotNull(basicGet()); basicAck(); } /* it is illegal to ack with an unknown delivery tag */ @Test public void unknownTagAck() throws IOException { basicPublish(); txSelect(); basicGet(); basicAck(); basicAck(latestTag+1, true); // "On a transacted channel, this check MUST be done immediately and // not delayed until a Tx.Commit." expectError(AMQP.PRECONDITION_FAILED); } /* rollback does not requeue delivered ack'ed or un-ack'ed messages */ @Test public void noRequeueOnRollback() throws IOException { basicPublish(); basicPublish(); txSelect(); basicGet(); basicAck(); basicGet(); txRollback(); assertNull(basicGet()); } /* auto-acks are not part of tx */ @Test public void autoAck() throws IOException { basicPublish(); txSelect(); basicGet(true); closeChannel(); openChannel(); assertNull(basicGet()); } /* "ack all", once committed, acks all delivered messages */ @Test public void ackAll() throws IOException { basicPublish(); basicPublish(); txSelect(); basicGet(); basicGet(); basicAck(0L, true); txCommit(); closeChannel(); openChannel(); assertNull(basicGet()); } @Test public void nonTransactedCommit() throws IOException { try { txCommit(); fail("Expected channel error"); } catch (IOException e) { checkShutdownSignal(AMQP.PRECONDITION_FAILED, e); } } @Test public void nonTransactedRollback() throws IOException { try { txRollback(); fail("Expected channel error"); } catch (IOException e) { checkShutdownSignal(AMQP.PRECONDITION_FAILED, e); } } @Test public void redeliverAckedUncommitted() throws IOException { txSelect(); basicPublish(); txCommit(); basicGet(); // Ack the message but do not commit the channel. The message // should not get redelivered (see // https://bugzilla.rabbitmq.com/show_bug.cgi?id=21845#c3) basicAck(); channel.basicRecover(true); assertNull("Acked uncommitted message redelivered", basicGet(true)); } @Test public void commitWithDeletedQueue() throws IOException, TimeoutException { txSelect(); basicPublish(); releaseResources(); try { txCommit(); } catch (IOException e) { closeConnection(); openConnection(); openChannel(); fail("commit failed"); } finally { createResources(); // To allow teardown to function cleanly } } @Test public void shuffleAcksBeforeRollback() throws IOException { long tags[] = publishSelectAndGet(3); basicAck(tags[2], false); basicAck(tags[1], false); txRollback(); basicAck(tags[0], true); basicAck(tags[1], false); basicAck(tags[2], false); txCommit(); } private abstract class NackMethod { abstract public void nack(long tag, boolean requeue) throws IOException; public void nack(boolean requeue) throws IOException { nack(latestTag, requeue); } public void nack() throws IOException { nack(latestTag, true); } } private final NackMethod basicNack = new NackMethod() { public void nack(long tag, boolean requeue) throws IOException { channel.basicNack(tag, false, requeue); } }; private final NackMethod basicReject = new NackMethod() { public void nack(long tag, boolean requeue) throws IOException { channel.basicReject(tag, requeue); } }; /* messages with nacks get requeued after the transaction commit. messages with nacks with requeue = false are not requeued. */ public void commitNacks(NackMethod method) throws IOException { basicPublish(); basicPublish(); txSelect(); basicGet(); method.nack(); basicGet(); method.nack(false); assertNull(basicGet()); txCommit(); assertNotNull(basicGet()); assertNull(basicGet()); } public void rollbackNacks(NackMethod method) throws IOException { basicPublish(); txSelect(); basicGet(); method.nack(true); txRollback(); assertNull(basicGet()); } public void commitAcksAndNacks(NackMethod method) throws IOException { long tags[] = publishSelectAndGet(3); basicAck(tags[1], false); basicAck(tags[0], false); method.nack(tags[2], false); txRollback(); basicAck(tags[2], false); method.nack(tags[0], true); method.nack(tags[1], false); txCommit(); assertNotNull(basicGet()); assertNull(basicGet()); } @Test public void commitNacks() throws IOException { commitNacks(basicNack); } @Test public void rollbackNacks() throws IOException { rollbackNacks(basicNack); } @Test public void commitAcksAndNacks() throws IOException { commitAcksAndNacks(basicNack); } @Test public void commitRejects() throws IOException { commitNacks(basicReject); } @Test public void rollbackRejects() throws IOException { rollbackNacks(basicReject); } @Test public void commitAcksAndRejects() throws IOException { commitAcksAndNacks(basicReject); } } UnbindAutoDeleteExchange.java000066400000000000000000000032311316117667700346150ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import static org.junit.Assert.fail; import java.io.IOException; import org.junit.Test; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.test.BrokerTestCase; /** * Test that unbinding from an auto-delete exchange causes the exchange to go * away */ public class UnbindAutoDeleteExchange extends BrokerTestCase { @Test public void unbind() throws IOException, InterruptedException { String exchange = "myexchange"; channel.exchangeDeclare(exchange, "fanout", false, true, null); String queue = channel.queueDeclare().getQueue(); channel.queueBind(queue, exchange, ""); channel.queueUnbind(queue, exchange, ""); try { channel.exchangeDeclarePassive(exchange); fail("exchange should no longer be there"); } catch (IOException e) { checkShutdownSignal(AMQP.NOT_FOUND, e); } } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/UnexpectedFrames.java000066400000000000000000000151121316117667700333010ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.ConnectionFactory; import com.rabbitmq.client.DefaultSocketConfigurator; import com.rabbitmq.client.impl.*; import com.rabbitmq.client.impl.recovery.AutorecoveringConnection; import com.rabbitmq.client.test.BrokerTestCase; import com.rabbitmq.client.test.TestUtils; import org.junit.Test; import javax.net.SocketFactory; import java.io.IOException; import java.net.Socket; /** * Test that the server correctly handles us when we send it bad frames */ public class UnexpectedFrames extends BrokerTestCase { private interface Confuser { public Frame confuse(Frame frame) throws IOException; } private static class ConfusedFrameHandler extends SocketFrameHandler { private boolean confusedOnce = false; public ConfusedFrameHandler(Socket socket) throws IOException { super(socket); } @Override public void writeFrame(Frame frame) throws IOException { if (confusedOnce) { super.writeFrame(frame); } else { Frame confusedFrame = confuser.confuse(frame); if (confusedFrame != frame) confusedOnce = true; if (confusedFrame != null) { super.writeFrame(confusedFrame); } } } public Confuser confuser = new Confuser() { public Frame confuse(Frame frame) { // Do nothing to start with, we need to negotiate before the // server will send us unexpected_frame errors return frame; } }; } private static class ConfusedConnectionFactory extends ConnectionFactory { public ConfusedConnectionFactory() { super(); if(TestUtils.USE_NIO) { useNio(); } else { useBlockingIo(); } } @Override protected FrameHandlerFactory createFrameHandlerFactory() { return new ConfusedFrameHandlerFactory(); } } private static class ConfusedFrameHandlerFactory extends SocketFrameHandlerFactory { private ConfusedFrameHandlerFactory() { super(1000, SocketFactory.getDefault(), new DefaultSocketConfigurator(), false); } @Override public FrameHandler create(Socket sock) throws IOException { return new ConfusedFrameHandler(sock); } } public UnexpectedFrames() { super(); connectionFactory = new ConfusedConnectionFactory(); } @Test public void missingHeader() throws IOException { expectUnexpectedFrameError(new Confuser() { public Frame confuse(Frame frame) { if (frame.type == AMQP.FRAME_HEADER) { return null; } return frame; } }); } @Test public void missingMethod() throws IOException { expectUnexpectedFrameError(new Confuser() { public Frame confuse(Frame frame) { if (frame.type == AMQP.FRAME_METHOD) { // We can't just skip the method as that will lead us to // send 0 bytes and hang waiting for a response. return new Frame(AMQP.FRAME_HEADER, frame.channel, frame.getPayload()); } return frame; } }); } @Test public void missingBody() throws IOException { expectUnexpectedFrameError(new Confuser() { public Frame confuse(Frame frame) { if (frame.type == AMQP.FRAME_BODY) { return null; } return frame; } }); } @Test public void wrongClassInHeader() throws IOException { expectUnexpectedFrameError(new Confuser() { public Frame confuse(Frame frame) { if (frame.type == AMQP.FRAME_HEADER) { byte[] payload = frame.getPayload(); Frame confusedFrame = new Frame(AMQP.FRAME_HEADER, frame.channel, payload); // First two bytes = class ID, must match class ID from // method. payload[0] = 12; payload[1] = 34; return confusedFrame; } return frame; } }); } @Test public void heartbeatOnChannel() throws IOException { expectUnexpectedFrameError(new Confuser() { public Frame confuse(Frame frame) { if (frame.type == AMQP.FRAME_METHOD) { return new Frame(AMQP.FRAME_HEARTBEAT, frame.channel); } return frame; } }); } @Test public void unknownFrameType() throws IOException { expectError(AMQP.FRAME_ERROR, new Confuser() { public Frame confuse(Frame frame) { if (frame.type == AMQP.FRAME_METHOD) { return new Frame(0, frame.channel, "1234567890\0001234567890".getBytes()); } return frame; } }); } private void expectError(int error, Confuser confuser) throws IOException { ((ConfusedFrameHandler)((AutorecoveringConnection)connection).getDelegate().getFrameHandler()). confuser = confuser; //NB: the frame confuser relies on the encoding of the //method field to be at least 8 bytes long channel.basicPublish("", "routing key", null, "Hello".getBytes()); expectError(error); } private void expectUnexpectedFrameError(Confuser confuser) throws IOException { expectError(AMQP.UNEXPECTED_FRAME, confuser); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/functional/UserIDHeader.java000066400000000000000000000045531316117667700323120ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.functional; import static org.junit.Assert.fail; import java.io.IOException; import java.util.concurrent.TimeoutException; import org.junit.Test; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.AlreadyClosedException; import com.rabbitmq.client.test.BrokerTestCase; import com.rabbitmq.tools.Host; public class UserIDHeader extends BrokerTestCase { private static final AMQP.BasicProperties GOOD = new AMQP.BasicProperties.Builder().userId("guest").build(); private static final AMQP.BasicProperties BAD = new AMQP.BasicProperties.Builder().userId("not the guest, honest").build(); @Test public void validUserId() throws IOException { publish(GOOD); } @Test public void invalidUserId() { try { publish(BAD); fail("Accepted publish with incorrect user ID"); } catch (IOException e) { checkShutdownSignal(AMQP.PRECONDITION_FAILED, e); } catch (AlreadyClosedException e) { checkShutdownSignal(AMQP.PRECONDITION_FAILED, e); } } @Test public void impersonatedUserId() throws IOException, TimeoutException { Host.rabbitmqctl("set_user_tags guest administrator impersonator"); connection = null; channel = null; setUp(); try { publish(BAD); } finally { Host.rabbitmqctl("set_user_tags guest administrator"); } } private void publish(AMQP.BasicProperties properties) throws IOException { channel.basicPublish("amq.fanout", "", properties, "".getBytes()); channel.queueDeclare(); // To flush the channel } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/performance/000077500000000000000000000000001316117667700273335ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/performance/CLIHelper.java000066400000000000000000000052321316117667700317470ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.performance; import java.util.Iterator; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.GnuParser; import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.Option; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; /** * Super class for handling repetative CLI stuff */ public class CLIHelper { private final Options options = new Options(); public static CLIHelper defaultHelper() { Options opts = new Options(); opts.addOption(new Option( "help", "print this message")); opts.addOption(new Option("h", "host", true, "broker host")); opts.addOption(new Option("p", "port", true, "broker port")); return new CLIHelper(opts); } public CLIHelper(Options opts) { Iterator it = opts.getOptions().iterator(); while (it.hasNext()) { options.addOption((Option) it.next()); } } public void addOption(Option option) { options.addOption(option); } public CommandLine parseCommandLine(String [] args) { CommandLineParser parser = new GnuParser(); CommandLine commandLine = null; try { commandLine = parser.parse(options, args); } catch (ParseException e) { printHelp(options); throw new RuntimeException("Parsing failed. Reason: " + e.getMessage()); } if (commandLine.hasOption("help")) { printHelp(options); return null; } return commandLine; } public void printHelp(Options options) { HelpFormatter formatter = new HelpFormatter(); formatter.printHelp(getClass().getSimpleName(), options); } public static int getOptionValue(CommandLine cmd, String s, int i) { return Integer.parseInt(cmd.getOptionValue(s, i + "")); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/performance/QosScaling.java000066400000000000000000000126041316117667700322440ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.performance; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; import com.rabbitmq.client.ConnectionFactory; import com.rabbitmq.client.QueueingConsumer; import com.rabbitmq.client.test.TestUtils; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.Option; import java.io.IOException; import java.util.List; import java.util.ArrayList; import java.util.concurrent.TimeoutException; public class QosScaling { protected static class Parameters { final String host; final int port; final int messageCount; final int queueCount; final int emptyCount; public static CommandLine parseCommandLine(String[] args) { CLIHelper helper = CLIHelper.defaultHelper(); helper.addOption(new Option("n", "messages", true, "number of messages to send")); helper.addOption(new Option("q", "queues", true, "number of queues to route messages to")); helper.addOption(new Option("e", "empty", true, "number of queues to leave empty")); return helper.parseCommandLine(args); } public Parameters(CommandLine cmd) { host = cmd.getOptionValue("h", "localhost"); port = CLIHelper.getOptionValue(cmd, "p", AMQP.PROTOCOL.PORT); messageCount = CLIHelper.getOptionValue(cmd, "n", 2000); queueCount = CLIHelper.getOptionValue(cmd, "q", 100); emptyCount = CLIHelper.getOptionValue(cmd, "e", 0); } public String toString() { StringBuilder b = new StringBuilder(); b.append("host=" + host); b.append(",port=" + port); b.append(",messages=" + messageCount); b.append(",queues=" + queueCount); b.append(",empty=" + emptyCount); return b.toString(); } } protected final Parameters params; protected final ConnectionFactory connectionFactory = TestUtils.connectionFactory(); protected Connection connection; protected Channel channel; public QosScaling(Parameters p) { params = p; } protected List consume(QueueingConsumer c) throws IOException { for (int i = 0; i < params.emptyCount; i++) { String queue = channel.queueDeclare().getQueue(); channel.basicConsume(queue, false, c); } List queues = new ArrayList(); for (int i = 0; i < params.queueCount; i++) { String queue = channel.queueDeclare().getQueue(); channel.basicConsume(queue, false, c); queues.add(queue); } return queues; } protected void publish(List queues) throws IOException { byte[] body = "".getBytes(); int messagesPerQueue = params.messageCount / queues.size(); for (String queue : queues) { for (int i = 0; i < messagesPerQueue; i++) { channel.basicPublish("", queue, null, body); } } //ensure that all the messages have reached the queues for (String queue : queues) { channel.queueDeclarePassive(queue); } } protected long drain(QueueingConsumer c) throws IOException { long start = System.nanoTime(); try { for (int i = 0; i < params.messageCount; i++) { long tag = c.nextDelivery().getEnvelope().getDeliveryTag(); channel.basicAck(tag, false); } } catch (InterruptedException e) { IOException ioe = new IOException(); ioe.initCause(e); throw ioe; } long finish = System.nanoTime(); return finish - start; } public long run() throws IOException, TimeoutException { connectionFactory.setHost(params.host); connectionFactory.setPort(params.port); connection = connectionFactory.newConnection(); channel = connection.createChannel(); channel.basicQos(1); QueueingConsumer consumer = new QueueingConsumer(channel); try { publish(consume(consumer)); return drain(consumer); } finally { connection.abort(); } } public static void main(String[] args) throws Exception { CommandLine cmd = Parameters.parseCommandLine(args); if (cmd == null) return; Parameters params = new Parameters(cmd); System.out.print(params.toString()); QosScaling test = new QosScaling(params); long result = test.run(); System.out.println(" -> " + result / 1000000 + "ms"); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/performance/ScalabilityTest.java000066400000000000000000000306121316117667700333000ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.performance; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintStream; import java.text.DecimalFormat; import java.text.NumberFormat; import java.util.Random; import java.util.Stack; import java.util.UUID; import java.util.Vector; import java.util.concurrent.CountDownLatch; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.Option; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; import com.rabbitmq.client.ConnectionFactory; import com.rabbitmq.client.MessageProperties; import com.rabbitmq.client.ReturnListener; /** * This tests the scalability of the routing tables in two aspects: * * 1. The rate of creation and deletion for a fixed level of bindings * per queue accross varying amounts of queues; * * 2. The rate of publishing n messages to an exchange with a fixed * amount of bindings per queue accross varying amounts of queues. */ public class ScalabilityTest { private static class Parameters { String host; int port; int messageCount; int base, maxQueueExp, maxBindingExp, maxExp; String filePrefix; } private abstract static class Measurements { protected final long[] times; private final long start; public Measurements(final int count) { times = new long[count]; start = System.nanoTime(); } public void addDataPoint(final int i) { times[i] = System.nanoTime() - start; } abstract public float[] analyse(final int base); protected static float[] calcOpTimes(final int base, final long[] t) { float[] r = new float[t.length]; for (int i = 0; i < t.length; i ++) { final int amount = pow(base, i); r[i] = t[i] / (float) amount / 1000; } return r; } } private static class CreationMeasurements extends Measurements { public CreationMeasurements(final int count) { super(count); } public float[] analyse(final int base) { return calcOpTimes(base, times); } } private static class DeletionMeasurements extends Measurements { public DeletionMeasurements(final int count) { super(count); } public float[] analyse(final int base) { final long tmp[] = new long[times.length]; final long totalTime = times[0]; int i; for (i = 0; i < times.length - 1; i++) { tmp[i] = totalTime - times[i + 1]; } tmp[i] = totalTime; return calcOpTimes(base, tmp); } } private static class Results { final float[][] creationTimes; final float[][] deletionTimes; final float[][] routingTimes; public Results(final int y) { creationTimes = new float[y][]; deletionTimes = new float[y][]; routingTimes = new float[y][]; } public void print(final int base, final String prefix) throws IOException { PrintStream s; s = open(prefix, "creation"); print(s, base, creationTimes); s.close(); s = open(prefix, "deletion"); print(s, base, deletionTimes); s.close(); s = open(prefix, "routing"); print(s, base, transpose(routingTimes)); s.close(); } private static PrintStream open(final String prefix, final String suffix) throws IOException { return new PrintStream(new FileOutputStream(prefix + suffix + ".dat")); } private static void print(final PrintStream s, final int base, final float[][] times) { for (int y = 0; y < times.length; y++) { s.println("# level " + pow(base, y)); for (int x = 0; x < times[y].length; x++) { s.println(pow(base, x) + " " + format.format(times[y][x])); } s.println(); s.println(); } } private float[][] transpose(float[][] m) { Vector> tmp = new Vector>(); for (int i = 0; i < m[0].length; i++) { tmp.addElement(new Vector()); } for (int i = 0; i < m.length; i++) { for (int j = 0; j < m[i].length; j++) { Vector v = tmp.get(j); v.addElement(m[i][j]); } } float[][] r = new float[tmp.size()][]; for (int i = 0; i < tmp.size(); i++) { Vector v = tmp.get(i); float[] vr = new float[v.size()]; for (int j = 0; j < v.size(); j++) { vr[j] = v.get(j); } r[i] = vr; } return r; } } private static final NumberFormat format = new DecimalFormat("0.00"); private final Parameters params; public ScalabilityTest(Parameters p) { params = p; } public static void main(String[] args) throws Exception { Parameters params = parseArgs(args); if (params == null) return; ScalabilityTest test = new ScalabilityTest(params); Results r = test.run(); if (params.filePrefix != null) r.print(params.base, params.filePrefix); } public Results run() throws Exception{ Connection con = new ConnectionFactory(){{setHost(params.host); setPort(params.port);}}.newConnection(); Channel channel = con.createChannel(); Results r = new Results(params.maxBindingExp); for (int y = 0; y < params.maxBindingExp; y++) { final int maxBindings = pow(params.base, y); String[] routingKeys = new String[maxBindings]; for (int b = 0; b < maxBindings; b++) { routingKeys[b] = UUID.randomUUID().toString(); } Stack queues = new Stack(); int maxQueueExp = Math.min(params.maxQueueExp, params.maxExp - y); System.out.println("---------------------------------"); System.out.println("| bindings = " + maxBindings + ", messages = " + params.messageCount); System.out.println("| Routing"); int q = 0; // create queues & bindings, time routing Measurements creation = new CreationMeasurements(maxQueueExp); float routingTimes[] = new float[maxQueueExp]; for (int x = 0; x < maxQueueExp; x++) { final int maxQueues = pow(params.base, x); for (; q < maxQueues; q++) { AMQP.Queue.DeclareOk ok = channel.queueDeclare(); queues.push(ok.getQueue()); for (int b = 0; b < maxBindings; b++) { channel.queueBind(ok.getQueue(), "amq.direct", routingKeys[b]); } } creation.addDataPoint(x); float routingTime = timeRouting(channel, routingKeys); routingTimes[x] = routingTime; printTime(params.base, x, routingTime); } r.routingTimes[y] = routingTimes; float[] creationTimes = creation.analyse(params.base); r.creationTimes[y] = creationTimes; System.out.println("| Creating"); printTimes(params.base, creationTimes); // delete queues & bindings Measurements deletion = new DeletionMeasurements(maxQueueExp); for (int x = maxQueueExp - 1; x >= 0; x--) { final int maxQueues = (x == 0) ? 0 : pow(params.base, x - 1); for (; q > maxQueues; q--) { channel.queueDelete(queues.pop()); } deletion.addDataPoint(x); } float[] deletionTimes = deletion.analyse(params.base); r.deletionTimes[y] = deletionTimes; System.out.println("| Deleting"); printTimes(params.base, deletionTimes); } channel.close(); con.close(); return r; } private float timeRouting(Channel channel, String[] routingKeys) throws IOException, InterruptedException { boolean mandatory = true; boolean immdediate = true; final CountDownLatch latch = new CountDownLatch(params.messageCount); channel.addReturnListener(new ReturnListener() { public void handleReturn(int replyCode, String replyText, String exchange, String routingKey, AMQP.BasicProperties properties, byte[] body) throws IOException { latch.countDown(); } }); final long start = System.nanoTime(); // route some messages Random r = new Random(); int size = routingKeys.length; for (int n = 0; n < params.messageCount; n ++) { String key = routingKeys[r.nextInt(size)]; channel.basicPublish("amq.direct", key, true, false, MessageProperties.MINIMAL_BASIC, null); } // wait for the returns to come back latch.await(); // Compute the roundtrip time final long finish = System.nanoTime(); final long wallclock = finish - start; return (params.messageCount == 0) ? (float)0.0 : wallclock / (float) params.messageCount / 1000; } private static Parameters parseArgs(String [] args) { CLIHelper helper = CLIHelper.defaultHelper(); helper.addOption(new Option("n", "messages", true, "number of messages to send")); helper.addOption(new Option("b", "base", true, "base for exponential scaling")); helper.addOption(new Option("x", "q-max-exp", true, "maximum queue count exponent")); helper.addOption(new Option("y", "b-max-exp", true, "maximum per-queue binding count exponent")); helper.addOption(new Option("c", "c-max-exp", true, "combined maximum exponent")); helper.addOption(new Option("f", "file", true, "result files prefix; defaults to no file output")); CommandLine cmd = helper.parseCommandLine(args); if (null == cmd) return null; Parameters params = new Parameters(); params.host = cmd.getOptionValue("h", "0.0.0.0"); params.port = CLIHelper.getOptionValue(cmd, "p", AMQP.PROTOCOL.PORT); params.messageCount = CLIHelper.getOptionValue(cmd, "n", 100); params.base = CLIHelper.getOptionValue(cmd, "b", 10); params.maxQueueExp = CLIHelper.getOptionValue(cmd, "x", 4); params.maxBindingExp = CLIHelper.getOptionValue(cmd, "y", 4); params.maxExp = CLIHelper.getOptionValue(cmd, "c", Math.max(params.maxQueueExp, params.maxBindingExp)); params.filePrefix = cmd.getOptionValue("f", null); return params; } private static int pow(int x, int y) { int r = 1; for( int i = 0; i < y; i++ ) r *= x; return r; } private static void printTimes(int base, float[] times) { for (int i = 0; i < times.length; i ++) { printTime(base, i, times[i]); } } private static void printTime(int base, int exp, float v) { System.out.println("| " + pow(base, exp) + " -> " + format.format(v) + " us/op"); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/performance/StressManagement.java000066400000000000000000000104441316117667700334610ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.performance; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; import com.rabbitmq.client.ConnectionFactory; import com.rabbitmq.client.MessageProperties; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.Option; import java.io.IOException; import java.util.concurrent.TimeoutException; public class StressManagement { protected static class Parameters { final String host; final int port; final int queueCount; final int channelCount; public static CommandLine parseCommandLine(String[] args) { CLIHelper helper = CLIHelper.defaultHelper(); helper.addOption(new Option("q", "queues", true, "number of queues")); helper.addOption(new Option("c", "channels", true, "number of channels")); return helper.parseCommandLine(args); } public Parameters(CommandLine cmd) { host = cmd.getOptionValue("h", "localhost"); port = CLIHelper.getOptionValue(cmd, "p", AMQP.PROTOCOL.PORT); queueCount = CLIHelper.getOptionValue(cmd, "q", 5000); channelCount = CLIHelper.getOptionValue(cmd, "c", 100); } public String toString() { StringBuilder b = new StringBuilder(); b.append("host=" + host); b.append(",port=" + port); b.append(",queues=" + queueCount); b.append(",channels=" + channelCount); return b.toString(); } } protected final Parameters params; protected final ConnectionFactory connectionFactory = new ConnectionFactory(); protected Connection connection; protected Channel publishChannel; protected Channel[] channels; public StressManagement(Parameters p) { params = p; } public long run() throws IOException, TimeoutException { connectionFactory.setHost(params.host); connectionFactory.setPort(params.port); connection = connectionFactory.newConnection(); publishChannel = connection.createChannel(); System.out.println("Declaring..."); channels = new Channel[params.channelCount]; for (int i = 0; i < params.channelCount; i++) { channels[i] = connection.createChannel(); } for (int i = 0; i < params.queueCount; i++) { publishChannel.queueDeclare("queue-" + i, false, true, false, null); publishChannel.queueBind("queue-" + i, "amq.fanout", ""); } System.out.println("Declaration complete, running..."); while (true) { for (int i = 0; i < params.channelCount; i++) { publishChannel.basicPublish("amq.fanout", "", MessageProperties.BASIC, "".getBytes()); for (int j = 0; j < params.queueCount; j++) { while (channels[i].basicGet("queue-" + j, true) == null) { try { Thread.sleep(10); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } } } } } public static void main(String[] args) throws Exception { CommandLine cmd = Parameters.parseCommandLine(args); if (cmd == null) return; Parameters params = new Parameters(cmd); System.out.println(params.toString()); StressManagement test = new StressManagement(params); test.run(); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/server/000077500000000000000000000000001316117667700263405ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/server/AbsentQueue.java000066400000000000000000000066651316117667700314410ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.server; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.Channel; import com.rabbitmq.client.test.functional.ClusteredTestBase; import org.junit.Test; import java.io.IOException; import java.util.concurrent.Callable; import java.util.concurrent.TimeoutException; import static org.junit.Assert.assertFalse; import static org.junit.Assert.fail; /** * This tests whether 'absent' queues - durable queues whose home node * is down - are handled properly. */ public class AbsentQueue extends ClusteredTestBase { private static final String Q = "absent-queue"; @Override public void setUp() throws IOException, TimeoutException { super.setUp(); if (clusteredConnection != null) stopSecondary(); } @Override public void tearDown() throws IOException, TimeoutException { if (clusteredConnection != null) startSecondary(); super.tearDown(); } @Override protected void createResources() throws IOException { alternateChannel.queueDeclare(Q, true, false, false, null); } @Override protected void releaseResources() throws IOException { alternateChannel.queueDelete(Q); } @Test public void notFound() throws Exception { if (!HATests.HA_TESTS_RUNNING) { // we don't care about this test in normal mode return; } waitPropagationInHa(); assertNotFound(() -> channel.queueDeclare(Q, true, false, false, null)); assertNotFound(() -> channel.queueDeclarePassive(Q)); assertNotFound(() -> channel.queuePurge(Q)); assertNotFound(() -> channel.basicGet(Q, true)); assertNotFound(() -> channel.queueBind(Q, "amq.fanout", "", null)); } protected void assertNotFound(Callable t) throws Exception { if (clusteredChannel == null) return; try { t.call(); if (!HATests.HA_TESTS_RUNNING) fail("expected not_found"); } catch (IOException ioe) { assertFalse(HATests.HA_TESTS_RUNNING); checkShutdownSignal(AMQP.NOT_FOUND, ioe); channel = connection.createChannel(); } } private void waitPropagationInHa() throws IOException, InterruptedException { // can be necessary to wait a bit in HA mode if (HATests.HA_TESTS_RUNNING) { long waited = 0; while(waited < 5000) { Channel tempChannel = connection.createChannel(); try { tempChannel.queueDeclarePassive(Q); break; } catch (IOException e) { } Thread.sleep(10); waited += 10; } } } } AlternateExchangeEquivalence.java000066400000000000000000000033211316117667700346670ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/server// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.server; import java.io.IOException; import java.util.HashMap; import java.util.Map; import org.junit.Test; import com.rabbitmq.client.test.functional.ExchangeEquivalenceBase; public class AlternateExchangeEquivalence extends ExchangeEquivalenceBase { static final Map args = new HashMap(); { args.put("alternate-exchange", "UME"); } @Test public void alternateExchangeEquivalence() throws IOException { channel.exchangeDeclare("alternate", "direct", false, false, args); verifyEquivalent("alternate", "direct", false, false, args); } @Test public void alternateExchangeNonEquivalence() throws IOException { channel.exchangeDeclare("alternate", "direct", false, false, args); Map altargs = new HashMap(); altargs.put("alternate-exchange", "somewhere"); verifyNotEquivalent("alternate", "direct", false, false, altargs); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/server/BlockedConnection.java000066400000000000000000000061221316117667700325670ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.server; import static org.junit.Assert.assertTrue; import java.io.IOException; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import com.rabbitmq.client.test.TestUtils; import org.junit.Test; import com.rabbitmq.client.BlockedListener; import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; import com.rabbitmq.client.ConnectionFactory; import com.rabbitmq.client.MessageProperties; import com.rabbitmq.client.test.BrokerTestCase; public class BlockedConnection extends BrokerTestCase { protected void releaseResources() throws IOException { try { unblock(); } catch (InterruptedException e) { e.printStackTrace(); } } // this test first opens a connection, then triggers // and alarm and blocks @Test public void testBlock() throws Exception { final CountDownLatch latch = new CountDownLatch(1); Connection connection = connection(latch); block(); publish(connection); assertTrue(latch.await(10, TimeUnit.SECONDS)); } // this test first triggers an alarm, then opens a // connection @Test public void initialBlock() throws Exception { final CountDownLatch latch = new CountDownLatch(1); block(); Connection connection = connection(latch); publish(connection); assertTrue(latch.await(10, TimeUnit.SECONDS)); } private Connection connection(final CountDownLatch latch) throws IOException, TimeoutException { ConnectionFactory factory = TestUtils.connectionFactory(); Connection connection = factory.newConnection(); connection.addBlockedListener(new BlockedListener() { public void handleBlocked(String reason) throws IOException { try { unblock(); } catch (InterruptedException e) { e.printStackTrace(); } } public void handleUnblocked() throws IOException { latch.countDown(); } }); return connection; } private void publish(Connection connection) throws IOException { Channel ch = connection.createChannel(); ch.basicPublish("", "", MessageProperties.BASIC, "".getBytes()); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/server/Bug19219Test.java000066400000000000000000000121701316117667700311670ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.server; import static org.junit.Assert.assertTrue; import java.io.IOException; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeoutException; import org.junit.Test; import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; import com.rabbitmq.client.Consumer; import com.rabbitmq.client.DefaultConsumer; import com.rabbitmq.client.MessageProperties; import com.rabbitmq.client.ShutdownSignalException; import com.rabbitmq.client.test.BrokerTestCase; /** * Test for bug 19219 - timeouts due to task parallelism in channel * closure code. */ public class Bug19219Test extends BrokerTestCase { /* These settings require careful tuning. Depending on them we get one of three outcomes: 1) this program terminates normally 2) the broker runs out of memory and eventually dies, and the this program barfs and/or dies 3) there are lots of timeout errors in the broker log It's the last case we are interested in. The settings below work on tanto against default. */ private static final int Q_COUNT = 1500; private static final int PUB_THREAD_COUNT = 100; private static final int CLOSE_DELAY = 2000; private static final Semaphore init = new Semaphore(0); private static final CountDownLatch resume = new CountDownLatch(1); private static void publish(final Channel ch) throws IOException { ch.basicPublish("amq.fanout", "", MessageProperties.PERSISTENT_TEXT_PLAIN, new byte[0]); } @Test public void it() throws IOException, InterruptedException { final Consumer c = new DefaultConsumer(channel); //1. create lots of auto-delete queues, bind them to the //amq.fanout exchange, and set up a non-auto-ack consumer for //each. for (int i = 0; i < Q_COUNT; i++) { String qName = channel.queueDeclare().getQueue(); channel.queueBind(qName, "amq.fanout", ""); channel.basicConsume(qName, false, c); } //2. send lots of messages in background, to keep the server, //and especially the queues, busy final Runnable r = new Runnable() { public void run() { try { startPublisher(); } catch (IOException e) { } catch (InterruptedException e) { } catch (TimeoutException e) { e.printStackTrace(); } } }; for (int i = 0; i < PUB_THREAD_COUNT; i++) { final Thread t = new Thread(r); t.start(); //wait for thread to finish initialisation init.acquire(); } //tell all threads to resume resume.countDown(); //wait for threads to get into full swing Thread.sleep(CLOSE_DELAY); //3. close channel. This will result in the server notifying //all the queues in parallel, which in turn will requeue all //the messages. The combined workload may result in some //notifications timing out. boolean success = false; try { channel.abort(); success = true; } catch (ShutdownSignalException e) { } finally { //We deliberately do not perform a clean shutdown of all //the connections. This test is pushing the server really //hard, so we chose the quickest way to end things. channel = null; connection = null; assertTrue(success); } } private void startPublisher() throws IOException, InterruptedException, TimeoutException { final Connection conn = connectionFactory.newConnection(); final Channel pubCh = conn.createChannel(); //This forces the initialisation of the guid generation, which //is an interaction with the persister and not something we //want to see delay things. publish(pubCh); //a synchronous request, to make sure the publish is done pubCh.queueDeclare(); //signal the main thread init.release(); //wait for main thread to let us resume resume.await(); //publish lots of messages while(true) { publish(pubCh); } } } ChannelLimitNegotiation.java000066400000000000000000000116001316117667700336720ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/server// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.server; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.fail; import java.io.IOException; import java.util.concurrent.Executors; import javax.net.SocketFactory; import com.rabbitmq.client.impl.recovery.AutorecoveringConnection; import com.rabbitmq.client.test.TestUtils; import org.junit.Test; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.Connection; import com.rabbitmq.client.ConnectionFactory; import com.rabbitmq.client.ShutdownListener; import com.rabbitmq.client.ShutdownSignalException; import com.rabbitmq.client.impl.AMQConnection; import com.rabbitmq.client.impl.ChannelN; import com.rabbitmq.client.impl.ConsumerWorkService; import com.rabbitmq.client.impl.SocketFrameHandler; import com.rabbitmq.client.test.BrokerTestCase; import com.rabbitmq.tools.Host; public class ChannelLimitNegotiation extends BrokerTestCase { class SpecialConnection extends AMQConnection { private final int channelMax; public SpecialConnection(int channelMax) throws Exception { this(TestUtils.connectionFactory(), channelMax); } private SpecialConnection(ConnectionFactory factory, int channelMax) throws Exception { super(factory.params(Executors.newFixedThreadPool(1)), new SocketFrameHandler(SocketFactory.getDefault().createSocket("localhost", AMQP.PROTOCOL.PORT))); this.channelMax = channelMax; } /** * Private API, allows for easier simulation of bogus clients. */ @Override protected int negotiateChannelMax(int requestedChannelMax, int serverMax) { return this.channelMax; } } @Test public void channelMaxLowerThanServerMinimum() throws Exception { int n = 64; ConnectionFactory cf = TestUtils.connectionFactory(); cf.setRequestedChannelMax(n); Connection conn = cf.newConnection(); assertEquals(n, conn.getChannelMax()); } @Test public void channelMaxGreaterThanServerValue() throws Exception { try { Host.rabbitmqctl("eval 'application:set_env(rabbit, channel_max, 2048).'"); SpecialConnection connection = new SpecialConnection(4096); try { connection.start(); fail("expected failure during connection negotiation"); } catch (IOException e) { // expected } } finally { Host.rabbitmqctl("eval 'application:set_env(rabbit, channel_max, 0).'"); } } @Test public void openingTooManyChannels() throws Exception { int n = 48; try { Host.rabbitmqctl("eval 'application:set_env(rabbit, channel_max, " + n + ").'"); ConnectionFactory cf = TestUtils.connectionFactory(); Connection conn = cf.newConnection(); assertEquals(n, conn.getChannelMax()); for (int i = 1; i <= n; i++) { assertNotNull(conn.createChannel(i)); } // ChannelManager guards against channel.open being sent assertNull(conn.createChannel(n + 1)); // Construct a channel directly final ChannelN ch = new ChannelN(((AutorecoveringConnection) conn).getDelegate(), n + 1, new ConsumerWorkService(Executors.newSingleThreadExecutor(), Executors.defaultThreadFactory(), ConnectionFactory.DEFAULT_SHUTDOWN_TIMEOUT)); conn.addShutdownListener(new ShutdownListener() { public void shutdownCompleted(ShutdownSignalException cause) { // make sure channel.open continuation is released ch.processShutdownSignal(cause, true, true); } }); ch.open(); fail("expected channel.open to cause a connection exception"); } catch (IOException e) { checkShutdownSignal(530, e); } finally { Host.rabbitmqctl("eval 'application:set_env(rabbit, channel_max, 0).'"); } } } DeadLetterExchangeDurable.java000066400000000000000000000060721316117667700341100ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/server// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.server; import static org.junit.Assert.assertNull; import java.io.IOException; import java.util.HashMap; import java.util.Map; import org.junit.Test; import com.rabbitmq.client.MessageProperties; import com.rabbitmq.client.test.BrokerTestCase; import com.rabbitmq.client.test.functional.DeadLetterExchange; import com.rabbitmq.tools.Host; public class DeadLetterExchangeDurable extends BrokerTestCase { @Override protected void createResources() throws IOException { Map args = new HashMap(); args.put("x-message-ttl", 5000); args.put("x-dead-letter-exchange", DeadLetterExchange.DLX); channel.exchangeDeclare(DeadLetterExchange.DLX, "direct", true); channel.queueDeclare(DeadLetterExchange.DLQ, true, false, false, null); channel.queueDeclare(DeadLetterExchange.TEST_QUEUE_NAME, true, false, false, args); channel.queueBind(DeadLetterExchange.TEST_QUEUE_NAME, "amq.direct", "test"); channel.queueBind(DeadLetterExchange.DLQ, DeadLetterExchange.DLX, "test"); } @Override protected void releaseResources() throws IOException { channel.exchangeDelete(DeadLetterExchange.DLX); channel.queueDelete(DeadLetterExchange.DLQ); channel.queueDelete(DeadLetterExchange.TEST_QUEUE_NAME); } @Test public void deadLetterQueueTTLExpiredWhileDown() throws Exception { // This test is nonsensical (and often breaks) in HA mode. if (HATests.HA_TESTS_RUNNING) return; for(int x = 0; x < DeadLetterExchange.MSG_COUNT; x++) { channel.basicPublish("amq.direct", "test", MessageProperties.MINIMAL_PERSISTENT_BASIC, "test message".getBytes()); } closeConnection(); Host.invokeMakeTarget("stop-rabbit-on-node"); Thread.sleep(5000); Host.invokeMakeTarget("start-rabbit-on-node"); openConnection(); openChannel(); //This has the effect of waiting for the queue to complete the //dead lettering. Some raciness remains though since the //dead-letter publication is async so the 'consume' below may //reach the dlq before all dead-lettered messages have arrived //there. assertNull(basicGet(DeadLetterExchange.TEST_QUEUE_NAME)); DeadLetterExchange.consume(channel, "expired"); } } DurableBindingLifecycle.java000066400000000000000000000126501316117667700336210ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/server// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.server; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import java.io.IOException; import java.util.concurrent.TimeoutException; import org.junit.Test; import com.rabbitmq.client.GetResponse; import com.rabbitmq.client.test.functional.BindingLifecycleBase; import com.rabbitmq.tools.Host; /** * This tests whether bindings are created and nuked properly. * * The tests attempt to declare durable queues on a secondary node, if * present, and that node is restarted as part of the tests while the * primary node is still running. That way we exercise any node-down * handler code in the server. * */ public class DurableBindingLifecycle extends BindingLifecycleBase { @Override protected void restart() throws IOException, TimeoutException { if (clusteredConnection != null) { clusteredConnection.abort(); clusteredConnection = null; clusteredChannel = null; alternateConnection = null; alternateChannel = null; Host.invokeMakeTarget( "stop-node" + " start-background-broker" + " RABBITMQ_NODENAME=\'" + Host.nodenameB() + "\'" + " RABBITMQ_NODE_PORT=" + Host.node_portB() + " RABBITMQ_CONFIG_FILE=\'" + Host.config_fileB() + "\'" ); } restartPrimary(); } private void restartPrimary() throws IOException, TimeoutException { tearDown(); bareRestart(); setUp(); } /** * Tests whether durable bindings are correctly recovered. */ @Test public void durableBindingRecovery() throws IOException, TimeoutException { declareDurableTopicExchange(X); declareAndBindDurableQueue(Q, X, K); restart(); for (int i = 0; i < N; i++) { basicPublishVolatile(X, K); } assertDelivered(Q, N); deleteQueue(Q); deleteExchange(X); } /** * This tests whether the bindings attached to a durable exchange * are correctly blown away when the exhange is nuked. * * This complements a unit test for testing non-durable exhanges. * In that case, an exchange is deleted and you expect any * bindings hanging to it to be deleted as well. To verify this, * the exchange is deleted and then recreated. * * After the recreation, the old bindings should no longer exist * and hence any messages published to that exchange get routed to * /dev/null * * This test exercises the durable variable of that test, so the * main difference is that the broker has to be restarted to * verify that the durable routes have been turfed. */ @Test public void durableBindingsDeletion() throws IOException, TimeoutException { declareDurableTopicExchange(X); declareAndBindDurableQueue(Q, X, K); deleteExchange(X); restart(); declareDurableTopicExchange(X); for (int i = 0; i < N; i++) { basicPublishVolatile(X, K); } GetResponse response = channel.basicGet(Q, true); assertNull("The initial response SHOULD BE null", response); deleteQueue(Q); deleteExchange(X); } /** * This tests whether the default bindings for durable queues * are recovered properly. * * The idea is to create a durable queue, nuke the server and then * publish a message to it using the queue name as a routing key */ @Test public void defaultBindingRecovery() throws IOException, TimeoutException { declareDurableQueue(Q); restart(); basicPublishVolatile("", Q); GetResponse response = channel.basicGet(Q, true); assertNotNull("The initial response SHOULD NOT be null", response); deleteQueue(Q); } /** * Test that when we have a transient exchange bound to a durable * queue and the durable queue is on a cluster node that restarts, * we do not lose the binding. See bug 24009. */ @Test public void transientExchangeDurableQueue() throws IOException, TimeoutException { // This test depends on the second node in the cluster to keep // the transient X alive if (clusteredConnection != null) { channel.exchangeDeclare("transientX", "fanout", false); channel.queueDeclare("durableQ", true, false, false, null); channel.queueBind("durableQ", "transientX", ""); restartPrimary(); basicPublishVolatile("transientX", ""); assertDelivered("durableQ", 1); deleteExchange("transientX"); deleteQueue("durableQ"); } } } EffectVisibilityCrossNodeTest.java000066400000000000000000000043721316117667700350560ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/server// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.server; import static org.junit.Assert.assertEquals; import java.io.IOException; import org.junit.Test; import com.rabbitmq.client.test.functional.ClusteredTestBase; /** * From bug 19844 - we want to be sure that publish vs everything else can't * happen out of order */ public class EffectVisibilityCrossNodeTest extends ClusteredTestBase { private final String[] queues = new String[QUEUES]; @Override protected void createResources() throws IOException { for (int i = 0; i < queues.length ; i++) { queues[i] = alternateChannel.queueDeclare("", false, false, true, null).getQueue(); alternateChannel.queueBind(queues[i], "amq.fanout", ""); } } @Override protected void releaseResources() throws IOException { for (int i = 0; i < queues.length ; i++) { alternateChannel.queueDelete(queues[i]); } } private static final int QUEUES = 5; private static final int BATCHES = 500; private static final int MESSAGES_PER_BATCH = 10; private static final byte[] msg = "".getBytes(); @Test public void effectVisibility() throws Exception { for (int i = 0; i < BATCHES; i++) { for (int j = 0; j < MESSAGES_PER_BATCH; j++) { channel.basicPublish("amq.fanout", "", null, msg); } for (int j = 0; j < queues.length ; j++) { assertEquals(MESSAGES_PER_BATCH, channel.queuePurge(queues[j]).getMessageCount()); } } } } ExclusiveQueueDurability.java000066400000000000000000000057621316117667700341430ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/server// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.server; import static org.junit.Assert.fail; import java.io.IOException; import java.util.concurrent.TimeoutException; import org.junit.Test; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.Channel; import com.rabbitmq.client.test.BrokerTestCase; /** * This tests whether exclusive, durable queues are deleted when appropriate * (following the scenarios given in bug 20578). */ public class ExclusiveQueueDurability extends BrokerTestCase { @Override protected boolean isAutomaticRecoveryEnabled() { // With automatic recovery enabled, queue can be re-created when launching the test suite // (because FunctionalTests are launched independently and as part of the HATests) // This then makes this test fail. return false; } void verifyQueueMissing(Channel channel, String queueName) throws IOException { try { channel.queueDeclare(queueName, false, false, false, null); } catch (IOException ioe) { checkShutdownSignal(AMQP.RESOURCE_LOCKED, ioe); fail("Declaring the queue resulted in a channel exception, probably meaning that it already exists"); } } // 1) connection and queue are on same node, node restarts -> queue // should no longer exist @Test public void connectionQueueSameNode() throws Exception { channel.queueDeclare("scenario1", true, true, false, null); restartPrimaryAbruptly(); verifyQueueMissing(channel, "scenario1"); } private void restartPrimaryAbruptly() throws IOException, TimeoutException { connection = null; channel = null; bareRestart(); setUp(); } /* * The other scenarios: * * 2) connection and queue are on different nodes, queue's node restarts, * connection is still alive -> queue should exist * * 3) connection and queue are on different nodes, queue's node restarts, * connection has been terminated in the meantime -> queue should no longer * exist * * There's no way to test these, as things stand; connections and queues are * tied to nodes, so one can't engineer a situation in which a connection * and its exclusive queue are on different nodes. */ } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/server/Firehose.java000066400000000000000000000061051316117667700307510ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.server; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import java.io.IOException; import java.util.List; import java.util.Map; import java.util.concurrent.TimeoutException; import org.junit.Test; import com.rabbitmq.client.GetResponse; import com.rabbitmq.client.test.BrokerTestCase; import com.rabbitmq.tools.Host; public class Firehose extends BrokerTestCase { private String q; private String firehose; @Override protected void createResources() throws IOException, TimeoutException { super.createResources(); channel.exchangeDeclare("test", "fanout", false, true, null); q = channel.queueDeclare().getQueue(); firehose = channel.queueDeclare().getQueue(); channel.queueBind(q, "test", ""); channel.queueBind(firehose, "amq.rabbitmq.trace", "#"); } @Test public void firehose() throws IOException { publishGet("not traced"); enable(); GetResponse msg = publishGet("traced"); disable(); publishGet("not traced"); GetResponse publish = basicGet(firehose); GetResponse deliver = basicGet(firehose); assertNotNull(publish); assertNotNull(deliver); assertDelivered(firehose, 0); // We don't test everything, that would be a bit OTT checkHeaders(publish.getProps().getHeaders()); Map delHeaders = deliver.getProps().getHeaders(); checkHeaders(delHeaders); assertNotNull(delHeaders.get("redelivered")); assertEquals(msg.getBody().length, publish.getBody().length); assertEquals(msg.getBody().length, deliver.getBody().length); } private GetResponse publishGet(String key) throws IOException { basicPublishVolatile("test", key); return basicGet(q); } private void checkHeaders(Map pubHeaders) { assertEquals("test", pubHeaders.get("exchange_name").toString()); @SuppressWarnings("unchecked") List routing_keys = (List) pubHeaders.get("routing_keys"); assertEquals("traced", routing_keys.get(0).toString()); } private void enable() throws IOException { Host.rabbitmqctl("trace_on"); } private void disable() throws IOException { Host.rabbitmqctl("trace_off"); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/server/HATests.java000066400000000000000000000041071316117667700305200ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.server; import com.rabbitmq.client.test.AbstractRMQTestSuite; import com.rabbitmq.client.test.RequiredPropertiesSuite; import com.rabbitmq.client.test.functional.FunctionalTests; import com.rabbitmq.tools.Host; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Suite; @RunWith(RequiredPropertiesSuite.class) @Suite.SuiteClasses({ HATests.SetUp.class, FunctionalTests.class, ServerTests.class, HATests.TearDown.class }) public class HATests { // initialize system properties static{ new AbstractRMQTestSuite(){}; } // this is horrific public static boolean HA_TESTS_RUNNING = false; // This is of course an abuse of the TestCase concept - but I don't want to // run this command on every test case. And there's no hook for "before / // after this test suite". public static class SetUp { @Test public void setUp() throws Exception { Host.rabbitmqctl("set_policy HA '.*' '{\"ha-mode\":\"all\"}'"); HA_TESTS_RUNNING = true; } @Test public void testNothing() {} } public static class TearDown { @Test public void tearDown() throws Exception { Host.rabbitmqctl("clear_policy HA"); HA_TESTS_RUNNING = false; } @Test public void testNothing() {} } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/server/LoopbackUsers.java000066400000000000000000000100731316117667700317600ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.server; import static org.junit.Assert.fail; import java.io.IOException; import java.net.Inet4Address; import java.net.InetAddress; import java.net.NetworkInterface; import java.net.SocketException; import java.util.Enumeration; import java.util.concurrent.TimeoutException; import com.rabbitmq.client.test.TestUtils; import org.junit.After; import org.junit.Before; import org.junit.Test; import com.rabbitmq.client.AuthenticationFailureException; import com.rabbitmq.client.ConnectionFactory; import com.rabbitmq.tools.Host; public class LoopbackUsers { @Before public void setUp() throws IOException { Host.rabbitmqctl("add_user test test"); Host.rabbitmqctl("set_permissions test '.*' '.*' '.*'"); } @After public void tearDown() throws IOException { Host.rabbitmqctl("delete_user test"); } @Test public void loopback() throws IOException, TimeoutException { String addr = findRealIPAddress().getHostAddress(); assertGuestFail(addr); Host.rabbitmqctl("eval 'application:set_env(rabbit, loopback_users, []).'"); assertGuestSucceed(addr); Host.rabbitmqctl("eval 'application:set_env(rabbit, loopback_users, [<<\"guest\">>]).'"); assertGuestFail(addr); } private void assertGuestSucceed(String addr) throws IOException, TimeoutException { succeedConnect("guest", addr); succeedConnect("guest", "localhost"); succeedConnect("test", addr); succeedConnect("test", "localhost"); } private void assertGuestFail(String addr) throws IOException, TimeoutException { failConnect("guest", addr); succeedConnect("guest", "localhost"); succeedConnect("test", addr); succeedConnect("test", "localhost"); } private void succeedConnect(String name, String addr) throws IOException, TimeoutException { getFactory(name, addr).newConnection().close(); } private void failConnect(String name, String addr) throws IOException, TimeoutException { try { getFactory(name, addr).newConnection(); fail(); } catch (AuthenticationFailureException e) { // success } } private ConnectionFactory getFactory(String name, String addr) { ConnectionFactory factory = TestUtils.connectionFactory(); factory.setUsername(name); factory.setPassword(name); factory.setHost(addr); return factory; } // Find the first IP address of a network interface that is up, not loopback, not point to point (e.g. VPN thing) private static InetAddress findRealIPAddress() throws SocketException { Enumeration ifs = NetworkInterface.getNetworkInterfaces(); while (ifs.hasMoreElements()) { NetworkInterface nif = ifs.nextElement(); if (nif.isUp() && !nif.isPointToPoint() && !nif.isLoopback() && !nif.isVirtual()) { Enumeration addrs = nif.getInetAddresses(); while (addrs.hasMoreElements()) { InetAddress addr = addrs.nextElement(); if (addr instanceof Inet4Address) { return addr; } } } } throw new RuntimeException("Could not determine real network address"); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/server/MemoryAlarms.java000066400000000000000000000077251316117667700316260ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.server; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import java.io.IOException; import java.util.concurrent.TimeoutException; import org.junit.Test; import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; import com.rabbitmq.client.QueueingConsumer; import com.rabbitmq.client.test.BrokerTestCase; public class MemoryAlarms extends BrokerTestCase { private static final String Q = "Restart"; private Connection connection2; private Channel channel2; @Override public void setUp() throws IOException, TimeoutException { connectionFactory.setRequestedHeartbeat(1); super.setUp(); if (connection2 == null) { connection2 = connectionFactory.newConnection(); } channel2 = connection2.createChannel(); } @Override public void tearDown() throws IOException, TimeoutException { if (channel2 != null) { channel2.abort(); channel2 = null; } if (connection2 != null) { connection2.abort(); connection2 = null; } super.tearDown(); connectionFactory.setRequestedHeartbeat(0); } @Override protected void createResources() throws IOException { channel.queueDeclare(Q, false, false, false, null); } @Override protected void releaseResources() throws IOException { try { clearAllResourceAlarms(); } catch (InterruptedException e) { e.printStackTrace(); } finally { channel.queueDelete(Q); } } @Test public void flowControl() throws IOException, InterruptedException { basicPublishVolatile(Q); setResourceAlarm("memory"); // non-publish actions only after an alarm should be fine assertNotNull(basicGet(Q)); QueueingConsumer c = new QueueingConsumer(channel); String consumerTag = channel.basicConsume(Q, true, c); // publishes after an alarm should not go through basicPublishVolatile(Q); // the publish is async, so this is racy. This also tests we don't die // by heartbeat (3x heartbeat interval + epsilon) assertNull(c.nextDelivery(3100)); // once the alarm has cleared the publishes should go through clearResourceAlarm("memory"); assertNotNull(c.nextDelivery(3100)); // everything should be back to normal channel.basicCancel(consumerTag); basicPublishVolatile(Q); assertNotNull(basicGet(Q)); } @Test public void overlappingAlarmsFlowControl() throws IOException, InterruptedException { QueueingConsumer c = new QueueingConsumer(channel); String consumerTag = channel.basicConsume(Q, true, c); setResourceAlarm("memory"); basicPublishVolatile(Q); assertNull(c.nextDelivery(100)); setResourceAlarm("disk"); assertNull(c.nextDelivery(100)); clearResourceAlarm("memory"); assertNull(c.nextDelivery(100)); clearResourceAlarm("disk"); assertNotNull(c.nextDelivery(3100)); channel.basicCancel(consumerTag); basicPublishVolatile(Q); assertNotNull(basicGet(Q)); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/server/MessageRecovery.java000066400000000000000000000052231316117667700323100ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.server; import java.io.IOException; import org.junit.Test; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.MessageProperties; import com.rabbitmq.client.test.ConfirmBase; import org.junit.Test; public class MessageRecovery extends ConfirmBase { private final static String Q = "recovery-test"; private final static String Q2 = "recovery-test-ha-check"; @Test public void messageRecovery() throws Exception { channel.queueDelete(Q); channel.queueDelete(Q2); channel.confirmSelect(); channel.queueDeclare(Q, true, false, false, null); channel.basicPublish("", Q, false, false, MessageProperties.PERSISTENT_BASIC, "nop".getBytes()); waitForConfirms(); channel.queueDeclare(Q2, false, false, false, null); restart(); // When testing in HA mode the message will be collected from // a promoted slave and will have its redelivered flag // set. But that only happens if there actually *is* a // slave. We test that by passively declaring, and // subsequently deleting, the secondary, non-durable queue, // which only succeeds if the queue survived the restart, // which in turn implies that it must have been a HA queue // with slave(s). // NB: this wont work when running against a single node broker // and running the test individually outside of the HA suite boolean expectDelivered = HATests.HA_TESTS_RUNNING; try { channel.queueDeclarePassive(Q2); channel.queueDelete(Q2); expectDelivered = true; } catch (IOException e) { checkShutdownSignal(AMQP.NOT_FOUND, e); openChannel(); } assertDelivered(Q, 1, expectDelivered); channel.queueDelete(Q); channel.queueDelete(Q2); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/server/Permissions.java000066400000000000000000000316511316117667700315240ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.server; import com.rabbitmq.client.*; import com.rabbitmq.client.impl.AMQChannel; import com.rabbitmq.client.impl.recovery.AutorecoveringChannel; import com.rabbitmq.client.test.BrokerTestCase; import com.rabbitmq.client.test.TestUtils; import com.rabbitmq.tools.Host; import org.junit.Test; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeoutException; import static org.junit.Assert.*; public class Permissions extends BrokerTestCase { private Channel adminCh; public Permissions() { ConnectionFactory factory = TestUtils.connectionFactory(); factory.setUsername("test"); factory.setPassword("test"); factory.setVirtualHost("/test"); connectionFactory = factory; } public void setUp() throws IOException, TimeoutException { deleteRestrictedAccount(); addRestrictedAccount(); super.setUp(); } public void tearDown() throws IOException, TimeoutException { super.tearDown(); deleteRestrictedAccount(); } protected void addRestrictedAccount() throws IOException { Host.rabbitmqctl("add_user test test"); Host.rabbitmqctl("add_user testadmin test"); Host.rabbitmqctl("add_vhost /test"); Host.rabbitmqctl("set_permissions -p /test test configure write read"); Host.rabbitmqctl("set_permissions -p /test testadmin \".*\" \".*\" \".*\""); } protected void deleteRestrictedAccount() throws IOException { Host.rabbitmqctlIgnoreErrors("clear_permissions -p /test testadmin"); Host.rabbitmqctlIgnoreErrors("clear_permissions -p /test test"); Host.rabbitmqctlIgnoreErrors("delete_vhost /test"); Host.rabbitmqctlIgnoreErrors("delete_user testadmin"); Host.rabbitmqctlIgnoreErrors("delete_user test"); } protected void createResources() throws IOException, TimeoutException { ConnectionFactory factory = TestUtils.connectionFactory(); factory.setUsername("testadmin"); factory.setPassword("test"); factory.setVirtualHost("/test"); Connection connection = factory.newConnection(); adminCh = connection.createChannel(); withNames(new WithName() { public void with(String name) throws IOException { adminCh.exchangeDeclare(name, "direct"); adminCh.queueDeclare(name, false, false, false, null); }}); } protected void releaseResources() throws IOException { withNames(new WithName() { public void with(String name) throws IOException { adminCh.queueDelete(name); adminCh.exchangeDelete(name); }}); adminCh.getConnection().abort(); } protected void withNames(WithName action) throws IOException { action.with("configure"); action.with("write"); action.with("read"); action.with("none"); } @Test public void auth() throws TimeoutException { ConnectionFactory unAuthFactory = TestUtils.connectionFactory(); unAuthFactory.setUsername("test"); unAuthFactory.setPassword("tset"); try { unAuthFactory.newConnection(); fail("Exception expected if password is wrong"); } catch (IOException e) { assertTrue(e instanceof AuthenticationFailureException); String msg = e.getMessage(); assertTrue("Exception message should contain 'auth'", msg.toLowerCase().contains("auth")); } } @Test public void exchangeConfiguration() throws IOException { runConfigureTest(new WithName() { public void with(String name) throws IOException { channel.exchangeDeclare(name, "direct"); }}); runConfigureTest(new WithName() { public void with(String name) throws IOException { channel.exchangeDelete(name); }}); } @Test public void queueConfiguration() throws IOException { runConfigureTest(new WithName() { public void with(String name) throws IOException { channel.queueDeclare(name, false, false, false, null); }}); runConfigureTest(new WithName() { public void with(String name) throws IOException { channel.queueDelete(name); }}); } @Test public void passiveDeclaration() throws IOException { runTest(true, true, true, true, new WithName() { public void with(String name) throws IOException { channel.exchangeDeclarePassive(name); }}); runTest(true, true, true, true, new WithName() { public void with(String name) throws IOException { channel.queueDeclarePassive(name); }}); } @Test public void binding() throws IOException { runTest(false, true, false, false, new WithName() { public void with(String name) throws IOException { channel.queueBind(name, "read", ""); }}); runTest(false, false, true, false, new WithName() { public void with(String name) throws IOException { channel.queueBind("write", name, ""); }}); } @Test public void publish() throws IOException { runTest(false, true, false, false, new WithName() { public void with(String name) throws IOException { channel.basicPublish(name, "", null, "foo".getBytes()); //followed by a dummy synchronous command in order //to catch any errors channel.basicQos(0); }}); } @Test public void get() throws IOException { runTest(false, false, true, false, new WithName() { public void with(String name) throws IOException { channel.basicGet(name, true); }}); } @Test public void consume() throws IOException { runTest(false, false, true, false, new WithName() { public void with(String name) throws IOException { channel.basicConsume(name, new QueueingConsumer(channel)); }}); } @Test public void purge() throws IOException { runTest(false, false, true, false, new WithName() { public void with(String name) throws IOException { AMQChannel channelDelegate = (AMQChannel) ((AutorecoveringChannel)channel).getDelegate(); channelDelegate.exnWrappingRpc(new AMQP.Queue.Purge.Builder() .queue(name) .build()); }}); } @Test public void altExchConfiguration() throws IOException { runTest(false, false, false, false, createAltExchConfigTest("configure-me")); runTest(false, false, false, false, createAltExchConfigTest("configure-and-write-me")); runTest(false, true, false, false, createAltExchConfigTest("configure-and-read-me")); } @Test public void dLXConfiguration() throws IOException { runTest(false, false, false, false, createDLXConfigTest("configure-me")); runTest(false, false, false, false, createDLXConfigTest("configure-and-write-me")); runTest(false, true, false, false, createDLXConfigTest("configure-and-read-me")); } @Test public void noAccess() throws IOException, InterruptedException { Host.rabbitmqctl("set_permissions -p /test test \"\" \"\" \"\""); Thread.sleep(2000); assertAccessRefused(new WithName() { public void with(String _e) throws IOException { channel.queueDeclare(); } } ); assertAccessRefused(new WithName() { public void with(String _e) throws IOException { channel.queueDeclare("justaqueue", false, false, true, null); } } ); assertAccessRefused(new WithName() { public void with(String _e) throws IOException { channel.queueDelete("configure"); } } ); assertAccessRefused(new WithName() { public void with(String _e) throws IOException { channel.queueBind("write", "write", "write"); } } ); assertAccessRefused(new WithName() { public void with(String _e) throws IOException { channel.queuePurge("read"); } } ); assertAccessRefused(new WithName() { public void with(String _e) throws IOException { channel.exchangeDeclare("justanexchange", "direct"); } } ); assertAccessRefused(new WithName() { public void with(String _e) throws IOException { channel.exchangeDeclare("configure", "direct"); } } ); assertAccessRefused(new WithName() { public void with(String _e) throws IOException { channel.basicPublish("write", "", null, "foo".getBytes()); channel.basicQos(0); } } ); assertAccessRefused(new WithName() { public void with(String _e) throws IOException { channel.basicGet("read", false); } } ); assertAccessRefused(new WithName() { public void with(String _e) throws IOException { channel.basicConsume("read", null); } } ); } protected WithName createAltExchConfigTest(final String exchange) throws IOException { return new WithName() { public void with(String ae) throws IOException { Map args = new HashMap(); args.put("alternate-exchange", ae); channel.exchangeDeclare(exchange, "direct", false, false, args); channel.exchangeDelete(exchange); }}; } protected WithName createDLXConfigTest(final String queue) throws IOException { return new WithName() { public void with(String dlx) throws IOException { Map args = new HashMap(); args.put("x-dead-letter-exchange", dlx); channel.queueDeclare(queue, false, false, false, args); channel.queueDelete(queue); }}; } protected void runConfigureTest(WithName test) throws IOException { runTest(true, "configure-me", test); runTest(false, "write-me", test); runTest(false, "read-me", test); runTest(false, "none", test); } protected void runTest(boolean expC, boolean expW, boolean expR, boolean expN, WithName test) throws IOException { runTest(expC, "configure", test); runTest(expW, "write", test); runTest(expR, "read", test); runTest(expN, "none", test); } protected void assertAccessRefused(WithName test) throws IOException { runTest(false, "", test); } protected void runTest(boolean exp, String name, WithName test) throws IOException { String msg = "'" + name + "' -> " + exp; try { test.with(name); assertTrue(msg, exp); } catch (IOException e) { assertFalse(msg, exp); checkShutdownSignal(AMQP.ACCESS_REFUSED, e); openChannel(); } catch (AlreadyClosedException e) { assertFalse(msg, exp); checkShutdownSignal(AMQP.ACCESS_REFUSED, e); openChannel(); } } private interface WithName { public void with(String name) throws IOException; } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/server/PersistenceGuarantees.java000066400000000000000000000046141316117667700335130ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.server; import static org.junit.Assert.assertEquals; import java.io.IOException; import com.rabbitmq.client.impl.nio.NioParams; import org.junit.Test; import com.rabbitmq.client.MessageProperties; import com.rabbitmq.client.test.BrokerTestCase; public class PersistenceGuarantees extends BrokerTestCase { private static final int COUNT = 10000; private String queue; @Override protected NioParams nioParams() { NioParams nioParams = super.nioParams(); // may need a higher enqueuing timeout on slow environments return nioParams .setWriteEnqueuingTimeoutInMs(nioParams.getWriteEnqueuingTimeoutInMs() * 3) .setWriteQueueCapacity(nioParams.getWriteQueueCapacity() * 2); } protected void declareQueue() throws IOException { queue = channel.queueDeclare("", true, false, false, null).getQueue(); } @Test public void txPersistence() throws Exception { declareQueue(); channel.txSelect(); publish(); channel.txCommit(); restart(); assertPersisted(); } @Test public void confirmPersistence() throws Exception { declareQueue(); channel.confirmSelect(); publish(); channel.waitForConfirms(); restart(); assertPersisted(); } private void assertPersisted() throws IOException { assertEquals(COUNT, channel.queueDelete(queue).getMessageCount()); } private void publish() throws IOException { for (int i = 0; i < COUNT; i++) { channel.basicPublish("", queue, false, false, MessageProperties.PERSISTENT_BASIC, "".getBytes()); } } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/server/PriorityQueues.java000066400000000000000000000062461316117667700322240ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.server; import static org.junit.Assert.assertEquals; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import org.junit.Test; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.DefaultConsumer; import com.rabbitmq.client.Envelope; import com.rabbitmq.client.test.BrokerTestCase; public class PriorityQueues extends BrokerTestCase { @Test public void prioritisingBasics() throws IOException, TimeoutException, InterruptedException { String q = "with-3-priorities"; int n = 3; channel.queueDeclare(q, true, false, false, argsWithPriorities(n)); publishWithPriorities(q, n); List xs = prioritiesOfEnqueuedMessages(q, n); assertEquals(Integer.valueOf(3), xs.get(0)); assertEquals(Integer.valueOf(2), xs.get(1)); assertEquals(Integer.valueOf(1), xs.get(2)); channel.queueDelete(q); } private List prioritiesOfEnqueuedMessages(String q, int n) throws InterruptedException, IOException { final List xs = new ArrayList(); final CountDownLatch latch = new CountDownLatch(n); channel.basicConsume(q, true, new DefaultConsumer(channel) { @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { xs.add(properties.getPriority()); latch.countDown(); } }); latch.await(5, TimeUnit.SECONDS); return xs; } private void publishWithPriorities(String q, int n) throws IOException, TimeoutException, InterruptedException { channel.confirmSelect(); for (int i = 1; i <= n; i++) { channel.basicPublish("", q, propsWithPriority(i), "msg".getBytes("UTF-8")); } channel.waitForConfirms(500); } private AMQP.BasicProperties propsWithPriority(int n) { return (new AMQP.BasicProperties.Builder()) .priority(n) .build(); } private Map argsWithPriorities(int n) { Map m = new HashMap(); m.put("x-max-priority", n); return m; } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/server/ServerTests.java000066400000000000000000000031561316117667700315010ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.server; import com.rabbitmq.client.test.AbstractRMQTestSuite; import com.rabbitmq.client.test.RequiredPropertiesSuite; import org.junit.runner.RunWith; import org.junit.runners.Suite; @RunWith(RequiredPropertiesSuite.class) @Suite.SuiteClasses({ Permissions.class, DurableBindingLifecycle.class, DeadLetterExchangeDurable.class, EffectVisibilityCrossNodeTest.class, ExclusiveQueueDurability.class, AbsentQueue.class, AlternateExchangeEquivalence.class, MemoryAlarms.class, MessageRecovery.class, Firehose.class, PersistenceGuarantees.class, Shutdown.class, BlockedConnection.class, ChannelLimitNegotiation.class, LoopbackUsers.class, XDeathHeaderGrowth.class, PriorityQueues.class, TopicPermissions.class }) public class ServerTests { // initialize system properties static{ new AbstractRMQTestSuite(){}; } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/server/Shutdown.java000066400000000000000000000020521316117667700310150ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.server; import org.junit.Test; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.test.BrokerTestCase; public class Shutdown extends BrokerTestCase { @Test public void errorOnShutdown() throws Exception { bareRestart(); expectError(AMQP.CONNECTION_FORCED); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/server/TopicPermissions.java000066400000000000000000000125341316117667700325220ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.server; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.AlreadyClosedException; import com.rabbitmq.client.BuiltinExchangeType; import com.rabbitmq.client.test.BrokerTestCase; import com.rabbitmq.tools.Host; import org.junit.Test; import java.io.IOException; import java.util.concurrent.Callable; import java.util.concurrent.TimeoutException; import static org.junit.Assert.fail; public class TopicPermissions extends BrokerTestCase { String protectedTopic = "protected.topic"; String notProtectedTopic = "not.protected.topic"; String noneTopicExchange = "not.a.topic"; @Override protected boolean shouldRun() throws IOException { return Host.isRabbitMqCtlCommandAvailable("set_topic_permissions"); } @Override protected void createResources() throws IOException, TimeoutException { channel.exchangeDeclare(protectedTopic, BuiltinExchangeType.TOPIC); channel.exchangeDeclare(notProtectedTopic, BuiltinExchangeType.TOPIC); channel.exchangeDeclare(noneTopicExchange, BuiltinExchangeType.DIRECT); Host.rabbitmqctl("set_topic_permissions -p / guest " + protectedTopic + " \"^{username}\" \"^{username}\""); Host.rabbitmqctl("set_topic_permissions -p / guest " + noneTopicExchange + " \"^{username}\" \"^{username}\""); } @Override protected void releaseResources() throws IOException { channel.exchangeDelete(protectedTopic); channel.exchangeDelete(notProtectedTopic); channel.exchangeDelete(noneTopicExchange); Host.rabbitmqctl("clear_topic_permissions -p / guest"); } @Test public void topicPermissions() throws IOException { assertAccessOk("Routing key matches on protected topic, should pass", () -> { channel.basicPublish(protectedTopic, "guest.b.c", null, "content".getBytes()); channel.basicQos(0); return null; }); assertAccessRefused("Routing key does not match on protected topic, should not pass", () -> { channel.basicPublish(protectedTopic, "b.c", null, "content".getBytes()); channel.basicQos(0); return null; }); assertAccessOk("Message sent on not-protected exchange, should pass", () -> { channel.basicPublish(notProtectedTopic, "guest.b.c", null, "content".getBytes()); channel.basicQos(0); return null; }); assertAccessOk("Routing key does not match on protected exchange, but not a topic, should pass", () -> { channel.basicPublish(noneTopicExchange, "b.c", null, "content".getBytes()); channel.basicQos(0); return null; }); assertAccessOk("Binding/unbinding on protected exchange with matching routing key, should pass", () -> { String queue = channel.queueDeclare().getQueue(); channel.queueBind(queue, protectedTopic, "guest.y.z"); channel.basicQos(0); channel.queueUnbind(queue, protectedTopic, "guest.y.z"); channel.basicQos(0); return null; }); assertAccessRefused("Binding/unbinding on protected exchange with none-matching routing key, should not pass", () -> { String queue = channel.queueDeclare().getQueue(); channel.queueBind(queue, protectedTopic, "y.z"); channel.basicQos(0); channel.queueUnbind(queue, protectedTopic, "y.z"); channel.basicQos(0); return null; }); assertAccessOk("Binding/unbinding on not-protected exchange with none-matching routing key, should pass", () -> { String queue = channel.queueDeclare().getQueue(); channel.queueBind(queue, notProtectedTopic, "y.z"); channel.basicQos(0); channel.queueUnbind(queue, notProtectedTopic, "y.z"); channel.basicQos(0); return null; }); } void assertAccessOk(String description, Callable action) { try { action.call(); } catch(Exception e) { fail(description + " (" + e.getMessage()+")"); } } void assertAccessRefused(String description, Callable action) throws IOException { try { action.call(); fail(description); } catch (IOException e) { checkShutdownSignal(AMQP.ACCESS_REFUSED, e); openChannel(); } catch (AlreadyClosedException e) { checkShutdownSignal(AMQP.ACCESS_REFUSED, e); openChannel(); } catch(Exception e) { fail("Unexpected exception: " + e.getMessage()); } } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/server/XDeathHeaderGrowth.java000066400000000000000000000227441316117667700326750ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.server; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; import org.junit.Test; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.Channel; import com.rabbitmq.client.DefaultConsumer; import com.rabbitmq.client.Envelope; import com.rabbitmq.client.test.BrokerTestCase; class RejectingConsumer extends DefaultConsumer { private CountDownLatch latch; private Map headers; private AtomicLong counter; public RejectingConsumer(Channel channel, CountDownLatch latch) { super(channel); this.latch = latch; this.counter = new AtomicLong(latch.getCount()); } @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { if(this.latch.getCount() > 0) { this.getChannel().basicReject(envelope.getDeliveryTag(), false); } else { if(this.getChannel().isOpen()) { this.getChannel().basicAck(envelope.getDeliveryTag(), false); } } if(this.counter.decrementAndGet() == 0) { // get headers only when the message has been redelivered // the expected number of times. // it looks like the message can be redelivered because // of the reject when handleDelivery isn't done yet or // before the latch releases the main thread. There's then // an additional delivery and the checks (transiently) fail. this.headers = properties.getHeaders(); } latch.countDown(); } public Map getHeaders() { return headers; } } public class XDeathHeaderGrowth extends BrokerTestCase { @SuppressWarnings("unchecked") @Test public void boundedXDeathHeaderGrowth() throws IOException, InterruptedException { final String x1 = "issues.rabbitmq-server-78.fanout1"; declareTransientFanoutExchange(x1); final String x2 = "issues.rabbitmq-server-78.fanout2"; declareTransientFanoutExchange(x2); final String x3 = "issues.rabbitmq-server-78.fanout3"; declareTransientFanoutExchange(x3); final String q1 = "issues.rabbitmq-server-78.queue1"; declareTransientQueue(q1, argumentsForDeadLetteringTo(x1)); final String q2 = "issues.rabbitmq-server-78.queue2"; declareTransientQueue(q2, argumentsForDeadLetteringTo(x2)); this.channel.queueBind(q2, x1, ""); final String q3 = "issues.rabbitmq-server-78.queue3"; declareTransientQueue(q3, argumentsForDeadLetteringTo(x3)); this.channel.queueBind(q3, x2, ""); final String qz = "issues.rabbitmq-server-78.destination"; declareTransientQueue(qz, argumentsForDeadLetteringWithoutTtlTo(x3)); this.channel.queueBind(qz, x3, ""); CountDownLatch latch = new CountDownLatch(10); RejectingConsumer cons = new RejectingConsumer(this.channel, latch); this.channel.basicConsume(qz, cons); this.channel.basicPublish("", q1, null, "msg".getBytes()); assertTrue(latch.await(5, TimeUnit.SECONDS)); List> events = (List>)cons.getHeaders().get("x-death"); assertEquals(4, events.size()); List qs = new ArrayList(); for (Map evt : events) { qs.add(evt.get("queue").toString()); } Collections.sort(qs); assertEquals(Arrays.asList(qz, q1, q2, q3), qs); List cs = new ArrayList(); for (Map evt : events) { cs.add((Long)evt.get("count")); } Collections.sort(cs); assertEquals(Arrays.asList(1L, 1L, 1L, 9L), cs); cleanUpExchanges(x1, x2, x3); cleanUpQueues(q1, q2, q3, qz); } private void cleanUpExchanges(String... xs) throws IOException { for(String x : xs) { this.channel.exchangeDelete(x); } } private void cleanUpQueues(String... qs) throws IOException { for(String q : qs) { this.channel.queueDelete(q); } } @SuppressWarnings("unchecked") @Test public void handlingOfXDeathHeadersFromEarlierVersions() throws IOException, InterruptedException { final String x1 = "issues.rabbitmq-server-152.fanout1"; declareTransientFanoutExchange(x1); final String x2 = "issues.rabbitmq-server-152.fanout2"; declareTransientFanoutExchange(x2); final String q1 = "issues.rabbitmq-server-152.queue1"; declareTransientQueue(q1, argumentsForDeadLetteringTo(x1)); final String q2 = "issues.rabbitmq-server-152.queue2"; declareTransientQueue(q2, argumentsForDeadLetteringTo(x2)); this.channel.queueBind(q2, x1, ""); final String qz = "issues.rabbitmq-server-152.destination"; declareTransientQueue(qz, argumentsForDeadLetteringWithoutTtlTo(x2)); this.channel.queueBind(qz, x2, ""); CountDownLatch latch = new CountDownLatch(10); RejectingConsumer cons = new RejectingConsumer(this.channel, latch); this.channel.basicConsume(qz, cons); final AMQP.BasicProperties.Builder bldr = new AMQP.BasicProperties.Builder(); AMQP.BasicProperties props = bldr.headers( propsWithLegacyXDeathsInHeaders("issues.rabbitmq-server-152.queue97", "issues.rabbitmq-server-152.queue97", "issues.rabbitmq-server-152.queue97", "issues.rabbitmq-server-152.queue98", "issues.rabbitmq-server-152.queue99")).build(); this.channel.basicPublish("", q1, props, "msg".getBytes()); assertTrue(latch.await(5, TimeUnit.SECONDS)); List> events = (List>)cons.getHeaders().get("x-death"); assertEquals(6, events.size()); List qs = new ArrayList(); for (Map evt : events) { qs.add(evt.get("queue").toString()); } Collections.sort(qs); assertEquals(Arrays.asList(qz, q1, q2, "issues.rabbitmq-server-152.queue97", "issues.rabbitmq-server-152.queue98", "issues.rabbitmq-server-152.queue99"), qs); List cs = new ArrayList(); for (Map evt : events) { cs.add((Long)evt.get("count")); } Collections.sort(cs); assertEquals(Arrays.asList(1L, 1L, 4L, 4L, 9L, 12L), cs); cleanUpExchanges(x1, x2); cleanUpQueues(q1, q2, qz, "issues.rabbitmq-server-152.queue97", "issues.rabbitmq-server-152.queue98", "issues.rabbitmq-server-152.queue99"); } private Map propsWithLegacyXDeathsInHeaders(String... qs) { Map m = new HashMap(); List> xDeaths = new ArrayList>(); for(String q : qs) { xDeaths.add(newXDeath(q)); xDeaths.add(newXDeath(q)); xDeaths.add(newXDeath(q)); xDeaths.add(newXDeath(q)); } m.put("x-death", xDeaths); return m; } private Map newXDeath(String q) { Map m = new HashMap(); m.put("reason", "expired"); m.put("queue", q); m.put("exchange", "issues.rabbitmq-server-152.fanout0"); m.put("routing-keys", Arrays.asList("routing-key-1", "routing-key-2")); m.put("random", UUID.randomUUID().toString()); return m; } private Map argumentsForDeadLetteringTo(String dlx) { return argumentsForDeadLetteringTo(dlx, 1); } private Map argumentsForDeadLetteringWithoutTtlTo(String dlx) { return argumentsForDeadLetteringTo(dlx, -1); } private Map argumentsForDeadLetteringTo(String dlx, int ttl) { Map m = new HashMap(); m.put("x-dead-letter-exchange", dlx); m.put("x-dead-letter-routing-key", "some-routing-key"); if(ttl > 0) { m.put("x-message-ttl", ttl); } return m; } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/ssl/000077500000000000000000000000001316117667700256335ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/ssl/BadVerifiedConnection.java000066400000000000000000000067731316117667700326770ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.ssl; import com.rabbitmq.client.test.TestUtils; import org.junit.Test; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLHandshakeException; import javax.net.ssl.TrustManagerFactory; import java.io.FileInputStream; import java.io.IOException; import java.security.*; import java.security.cert.CertificateException; import java.util.concurrent.TimeoutException; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.fail; /** * Test for bug 19356 - SSL Support in rabbitmq * */ public class BadVerifiedConnection extends UnverifiedConnection { public void openConnection() throws IOException, TimeoutException { try { String keystorePath = System.getProperty("test-keystore.empty"); assertNotNull(keystorePath); String keystorePasswd = System.getProperty("test-keystore.password"); assertNotNull(keystorePasswd); char [] keystorePassword = keystorePasswd.toCharArray(); KeyStore tks = KeyStore.getInstance("JKS"); tks.load(new FileInputStream(keystorePath), keystorePassword); TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); tmf.init(tks); String p12Path = System.getProperty("test-client-cert.path"); assertNotNull(p12Path); String p12Passwd = System.getProperty("test-client-cert.password"); assertNotNull(p12Passwd); KeyStore ks = KeyStore.getInstance("PKCS12"); char [] p12Password = p12Passwd.toCharArray(); ks.load(new FileInputStream(p12Path), p12Password); KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); kmf.init(ks, p12Password); SSLContext c = getSSLContext(); c.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); connectionFactory = TestUtils.connectionFactory(); connectionFactory.useSslProtocol(c); } catch (NoSuchAlgorithmException ex) { throw new IOException(ex.toString()); } catch (KeyManagementException ex) { throw new IOException(ex.toString()); } catch (KeyStoreException ex) { throw new IOException(ex.toString()); } catch (CertificateException ex) { throw new IOException(ex.toString()); } catch (UnrecoverableKeyException ex) { throw new IOException(ex.toString()); } try { connection = connectionFactory.newConnection(); fail(); } catch (SSLHandshakeException ignored) { } catch (IOException e) { fail(); } } public void openChannel() {} @Test public void sSL() {} } ConnectionFactoryDefaultTlsVersion.java000066400000000000000000000035231316117667700354070ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/ssl// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.ssl; import com.rabbitmq.client.ConnectionFactory; import junit.framework.TestCase; import org.junit.Assert; import org.junit.Test; public class ConnectionFactoryDefaultTlsVersion { @Test public void defaultTlsVersionJdk16ShouldTakeFallback() { String [] supportedProtocols = {"SSLv2Hello", "SSLv3", "TLSv1"}; String tlsProtocol = ConnectionFactory.computeDefaultTlsProcotol(supportedProtocols); Assert.assertEquals("TLSv1",tlsProtocol); } @Test public void defaultTlsVersionJdk17ShouldTakePrefered() { String [] supportedProtocols = {"SSLv2Hello", "SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2"}; String tlsProtocol = ConnectionFactory.computeDefaultTlsProcotol(supportedProtocols); Assert.assertEquals("TLSv1.2",tlsProtocol); } @Test public void defaultTlsVersionJdk18ShouldTakePrefered() { String [] supportedProtocols = {"SSLv2Hello", "SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2"}; String tlsProtocol = ConnectionFactory.computeDefaultTlsProcotol(supportedProtocols); Assert.assertEquals("TLSv1.2",tlsProtocol); } } NioTlsUnverifiedConnection.java000066400000000000000000000112551316117667700336740ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/ssl// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.ssl; import com.rabbitmq.client.*; import com.rabbitmq.client.impl.nio.NioParams; import com.rabbitmq.client.test.BrokerTestCase; import org.junit.Test; import org.slf4j.LoggerFactory; import javax.net.ssl.SSLEngine; import java.io.IOException; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; /** * */ public class NioTlsUnverifiedConnection extends BrokerTestCase { public void openConnection() throws IOException, TimeoutException { try { connectionFactory.useSslProtocol(); connectionFactory.useNio(); } catch (Exception ex) { throw new IOException(ex.toString()); } int attempt = 0; while(attempt < 3) { try { connection = connectionFactory.newConnection(); break; } catch(Exception e) { LoggerFactory.getLogger(getClass()).warn("Error when opening TLS connection"); attempt++; } } if(connection == null) { fail("Couldn't open TLS connection after 3 attempts"); } } @Test public void connectionGetConsume() throws Exception { CountDownLatch latch = new CountDownLatch(1); connection = basicGetBasicConsume(connection, "tls.nio.queue", latch, 100 * 1000); boolean messagesReceived = latch.await(5, TimeUnit.SECONDS); assertTrue("Message has not been received", messagesReceived); } @Test public void socketChannelConfigurator() throws Exception { ConnectionFactory connectionFactory = new ConnectionFactory(); connectionFactory.useNio(); connectionFactory.useSslProtocol(); NioParams nioParams = new NioParams(); final AtomicBoolean sslEngineHasBeenCalled = new AtomicBoolean(false); nioParams.setSslEngineConfigurator(new SslEngineConfigurator() { @Override public void configure(SSLEngine sslEngine) throws IOException { sslEngineHasBeenCalled.set(true); } }); connectionFactory.setNioParams(nioParams); Connection connection = null; try { connection = connectionFactory.newConnection(); assertTrue("The SSL engine configurator should have called", sslEngineHasBeenCalled.get()); } finally { if (connection != null) { connection.close(); } } } @Test public void messageSize() throws Exception { int [] sizes = new int [] {100, 1000, 10 * 1000, 1 * 1000 * 1000, 5 * 1000 * 1000}; for(int size : sizes) { CountDownLatch latch = new CountDownLatch(1); connection = basicGetBasicConsume(connection, "tls.nio.queue", latch, size); boolean messagesReceived = latch.await(5, TimeUnit.SECONDS); assertTrue("Message has not been received", messagesReceived); } } private Connection basicGetBasicConsume(Connection connection, String queue, final CountDownLatch latch, int msgSize) throws IOException, TimeoutException { Channel channel = connection.createChannel(); channel.queueDeclare(queue, false, false, false, null); channel.queuePurge(queue); channel.basicPublish("", queue, null, new byte[msgSize]); channel.basicConsume(queue, false, new DefaultConsumer(channel) { @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { getChannel().basicAck(envelope.getDeliveryTag(), false); latch.countDown(); getChannel().basicCancel(consumerTag); } }); return connection; } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/ssl/SSLTests.java000066400000000000000000000044371316117667700301720ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.ssl; import com.rabbitmq.client.test.AbstractRMQTestSuite; import org.junit.runner.RunWith; import org.junit.runner.Runner; import org.junit.runners.Suite; import org.junit.runners.model.InitializationError; import org.junit.runners.model.RunnerBuilder; import java.util.ArrayList; import java.util.List; @RunWith(SSLTests.SslSuite.class) @Suite.SuiteClasses({ UnverifiedConnection.class, VerifiedConnection.class, BadVerifiedConnection.class, ConnectionFactoryDefaultTlsVersion.class, NioTlsUnverifiedConnection.class }) public class SSLTests { // initialize system properties static{ new AbstractRMQTestSuite(){}; } public static class SslSuite extends Suite { public SslSuite(Class klass, RunnerBuilder builder) throws InitializationError { super(klass, builder); } public SslSuite(RunnerBuilder builder, Class[] classes) throws InitializationError { super(builder, classes); } protected SslSuite(Class klass, Class[] suiteClasses) throws InitializationError { super(klass, suiteClasses); } protected SslSuite(RunnerBuilder builder, Class klass, Class[] suiteClasses) throws InitializationError { super(builder, klass, suiteClasses); } protected SslSuite(Class klass, List runners) throws InitializationError { super(klass, runners); } @Override protected List getChildren() { if(!AbstractRMQTestSuite.requiredProperties() && !AbstractRMQTestSuite.isSSLAvailable()) { return new ArrayList(); } else { return super.getChildren(); } } } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/ssl/UnverifiedConnection.java000066400000000000000000000046321316117667700326230ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.ssl; import com.rabbitmq.client.GetResponse; import com.rabbitmq.client.test.BrokerTestCase; import org.junit.Test; import org.slf4j.LoggerFactory; import java.io.IOException; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.util.concurrent.TimeoutException; import static org.junit.Assert.*; /** * Test for bug 19356 - SSL Support in rabbitmq * */ public class UnverifiedConnection extends BrokerTestCase { public void openConnection() throws IOException, TimeoutException { try { connectionFactory.useSslProtocol(); } catch (NoSuchAlgorithmException ex) { throw new IOException(ex.toString()); } catch (KeyManagementException ex) { throw new IOException(ex.toString()); } int attempt = 0; while(attempt < 3) { try { connection = connectionFactory.newConnection(); break; } catch(Exception e) { LoggerFactory.getLogger(getClass()).warn("Error when opening TLS connection"); attempt++; } } if(connection == null) { fail("Couldn't open TLS connection after 3 attemps"); } } @Test public void sSL() throws IOException { channel.queueDeclare("Bug19356Test", false, true, true, null); channel.basicPublish("", "Bug19356Test", null, "SSL".getBytes()); GetResponse chResponse = channel.basicGet("Bug19356Test", false); assertNotNull(chResponse); byte[] body = chResponse.getBody(); assertEquals("SSL", new String(body)); } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/client/test/ssl/VerifiedConnection.java000066400000000000000000000075411316117667700322620ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.client.test.ssl; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.fail; import java.io.FileInputStream; import java.io.IOException; import java.security.KeyManagementException; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; import java.util.concurrent.TimeoutException; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManagerFactory; import com.rabbitmq.client.ConnectionFactory; import com.rabbitmq.client.test.TestUtils; import org.slf4j.LoggerFactory; /** * Test for bug 19356 - SSL Support in rabbitmq * */ public class VerifiedConnection extends UnverifiedConnection { public void openConnection() throws IOException, TimeoutException { try { String keystorePath = System.getProperty("test-keystore.ca"); assertNotNull(keystorePath); String keystorePasswd = System.getProperty("test-keystore.password"); assertNotNull(keystorePasswd); char [] keystorePassword = keystorePasswd.toCharArray(); KeyStore tks = KeyStore.getInstance("JKS"); tks.load(new FileInputStream(keystorePath), keystorePassword); TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); tmf.init(tks); String p12Path = System.getProperty("test-client-cert.path"); assertNotNull(p12Path); String p12Passwd = System.getProperty("test-client-cert.password"); assertNotNull(p12Passwd); KeyStore ks = KeyStore.getInstance("PKCS12"); char [] p12Password = p12Passwd.toCharArray(); ks.load(new FileInputStream(p12Path), p12Password); KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); kmf.init(ks, p12Password); SSLContext c = getSSLContext(); c.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); connectionFactory = TestUtils.connectionFactory(); connectionFactory.useSslProtocol(c); } catch (NoSuchAlgorithmException ex) { throw new IOException(ex.toString()); } catch (KeyManagementException ex) { throw new IOException(ex.toString()); } catch (KeyStoreException ex) { throw new IOException(ex.toString()); } catch (CertificateException ex) { throw new IOException(ex.toString()); } catch (UnrecoverableKeyException ex) { throw new IOException(ex.toString()); } int attempt = 0; while(attempt < 3) { try { connection = connectionFactory.newConnection(); break; } catch(Exception e) { LoggerFactory.getLogger(getClass()).warn("Error when opening TLS connection"); attempt++; } } if(connection == null) { fail("Couldn't open TLS connection after 3 attemps"); } } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/tools/000077500000000000000000000000001316117667700237355ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/tools/Host.java000066400000000000000000000161251316117667700255220ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.tools; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.List; import com.rabbitmq.client.impl.NetworkConnection; public class Host { public static String capture(InputStream is) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(is)); String line; StringBuilder buff = new StringBuilder(); while ((line = br.readLine()) != null) { buff.append(line).append("\n"); } return buff.toString(); } public static Process executeCommand(String command) throws IOException { Process pr = executeCommandProcess(command); int ev = waitForExitValue(pr); if (ev != 0) { String stdout = capture(pr.getInputStream()); String stderr = capture(pr.getErrorStream()); throw new IOException("unexpected command exit value: " + ev + "\ncommand: " + command + "\n" + "\nstdout:\n" + stdout + "\nstderr:\n" + stderr + "\n"); } return pr; } private static int waitForExitValue(Process pr) { while(true) { try { pr.waitFor(); break; } catch (InterruptedException ignored) {} } return pr.exitValue(); } public static Process executeCommandIgnoringErrors(String command) throws IOException { Process pr = executeCommandProcess(command); waitForExitValue(pr); return pr; } private static Process executeCommandProcess(String command) throws IOException { String[] finalCommand; if (System.getProperty("os.name").toLowerCase().contains("windows")) { finalCommand = new String[4]; finalCommand[0] = "C:\\winnt\\system32\\cmd.exe"; finalCommand[1] = "/y"; finalCommand[2] = "/c"; finalCommand[3] = command; } else { finalCommand = new String[3]; finalCommand[0] = "/bin/sh"; finalCommand[1] = "-c"; finalCommand[2] = command; } return Runtime.getRuntime().exec(finalCommand); } public static boolean isRabbitMqCtlCommandAvailable(String command) throws IOException { Process process = rabbitmqctlIgnoreErrors(""); String stderr = capture(process.getErrorStream()); return stderr.contains(command); } public static Process rabbitmqctl(String command) throws IOException { return executeCommand(rabbitmqctlCommand() + " -n \'" + nodenameA() + "\'" + " " + command); } public static Process rabbitmqctlIgnoreErrors(String command) throws IOException { return executeCommandIgnoringErrors(rabbitmqctlCommand() + " -n \'" + nodenameA() + "\'" + " " + command); } public static Process invokeMakeTarget(String command) throws IOException { File rabbitmqctl = new File(rabbitmqctlCommand()); return executeCommand(makeCommand() + " -C \'" + rabbitmqDir() + "\'" + " RABBITMQCTL=\'" + rabbitmqctl.getAbsolutePath() + "\'" + " RABBITMQ_NODENAME=\'" + nodenameA() + "\'" + " RABBITMQ_NODE_PORT=" + node_portA() + " RABBITMQ_CONFIG_FILE=\'" + config_fileA() + "\'" + " " + command); } public static String makeCommand() { return System.getProperty("make.bin", "make"); } public static String nodenameA() { return System.getProperty("test-broker.A.nodename"); } public static String node_portA() { return System.getProperty("test-broker.A.node_port"); } public static String config_fileA() { return System.getProperty("test-broker.A.config_file"); } public static String nodenameB() { return System.getProperty("test-broker.B.nodename"); } public static String node_portB() { return System.getProperty("test-broker.B.node_port"); } public static String config_fileB() { return System.getProperty("test-broker.B.config_file"); } public static String rabbitmqctlCommand() { return System.getProperty("rabbitmqctl.bin"); } public static String rabbitmqDir() { return System.getProperty("rabbitmq.dir"); } public static void closeConnection(String pid) throws IOException { rabbitmqctl("close_connection '" + pid + "' 'Closed via rabbitmqctl'"); } public static void closeConnection(NetworkConnection c) throws IOException { Host.ConnectionInfo ci = findConnectionInfoFor(Host.listConnections(), c); closeConnection(ci.getPid()); } public static class ConnectionInfo { private final String pid; private final int peerPort; public ConnectionInfo(String pid, int peerPort) { this.pid = pid; this.peerPort = peerPort; } public String getPid() { return pid; } public int getPeerPort() { return peerPort; } } public static List listConnections() throws IOException { String output = capture(rabbitmqctl("list_connections -q pid peer_port").getInputStream()); String[] allLines = output.split("\n"); ArrayList result = new ArrayList(); for (String line : allLines) { // line: 58713 String[] columns = line.split("\t"); result.add(new ConnectionInfo(columns[0], Integer.valueOf(columns[1]))); } return result; } private static Host.ConnectionInfo findConnectionInfoFor(List xs, NetworkConnection c) { Host.ConnectionInfo result = null; for (Host.ConnectionInfo ci : xs) { if(c.getLocalPort() == ci.getPeerPort()){ result = ci; break; } } return result; } } rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/utility/000077500000000000000000000000001316117667700243005ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/test/java/com/rabbitmq/utility/IntAllocatorTests.java000066400000000000000000000067601316117667700305720ustar00rootroot00000000000000// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.utility; import org.junit.Test; import java.util.HashSet; import java.util.Iterator; import java.util.Random; import java.util.Set; import static org.junit.Assert.*; public class IntAllocatorTests { private static final int TEST_ITERATIONS = 50000; private static final int HI_RANGE = 100000; private static final int LO_RANGE = 100; private final IntAllocator iAll = new IntAllocator(LO_RANGE, HI_RANGE); private final Random rand = new Random(70608L); @Test public void reserveAndFree() throws Exception { Set set = new HashSet(); for (int i = 0; i < TEST_ITERATIONS; ++i) { int trial = getTrial(rand); if (set.contains(trial)) { iAll.free(trial); set.remove(trial); } else { assertTrue("Did not reserve free integer " + trial, iAll.reserve(trial)); set.add(trial); } } for (int trial : set) { assertFalse("Integer " + trial + " not allocated!", iAll.reserve(trial)); } } @Test public void allocateAndFree() throws Exception { Set set = new HashSet(); for (int i=0; i < TEST_ITERATIONS; ++i) { if (getBool(rand)) { int trial = iAll.allocate(); assertFalse("Already allocated " + trial, set.contains(trial)); set.add(trial); } else { if (!set.isEmpty()) { int trial = extractOne(set); assertFalse("Allocator agreed to reserve " + trial, iAll.reserve(trial)); iAll.free(trial); } } } for (int trial : set) { assertFalse("Integer " + trial + " should be allocated!", iAll.reserve(trial)); } } @Test public void testToString() throws Exception { IntAllocator ibs = new IntAllocator(LO_RANGE, HI_RANGE); assertEquals("IntAllocator{allocated = []}", ibs.toString()); ibs.allocate(); assertEquals("IntAllocator{allocated = [100]}", ibs.toString()); for(int i = 200; i<211; i=i+4) { ibs.reserve(i); ibs.reserve(i+1); ibs.reserve(i+2); } assertEquals("IntAllocator{allocated = [100, 200..202, 204..206, 208..210]}" , ibs.toString()); } private static int extractOne(Set set) { Iterator iter = set.iterator(); int trial = iter.next(); iter.remove(); return trial; } private static int getTrial(Random rand) { return rand.nextInt(HI_RANGE-LO_RANGE+1) + LO_RANGE; } private static boolean getBool(Random rand) { return rand.nextBoolean(); } } rabbitmq-java-client-5.0.0/src/test/resources/000077500000000000000000000000001316117667700213075ustar00rootroot00000000000000rabbitmq-java-client-5.0.0/src/test/resources/config.properties000066400000000000000000000000771316117667700246760ustar00rootroot00000000000000broker.hostname=localhost broker.port=5672 broker.sslport=5671 rabbitmq-java-client-5.0.0/src/test/resources/hare@localhost.config000066400000000000000000000007431316117667700254320ustar00rootroot00000000000000% vim:ft=erlang: [ {rabbit, [ {ssl_listeners, [5670]}, {ssl_options, [ {cacertfile, "${test-tls-certs.dir}/testca/cacert.pem"}, {certfile, "${test-tls-certs.dir}/server/cert.pem"}, {keyfile, "${test-tls-certs.dir}/server/key.pem"}, {verify, verify_peer}, {fail_if_no_peer_cert, false}, {honor_cipher_order, true}]}, {auth_mechanisms, ['PLAIN', 'AMQPLAIN', 'EXTERNAL', 'RABBIT-CR-DEMO']} ]} ]. rabbitmq-java-client-5.0.0/src/test/resources/logback-test.xml000066400000000000000000000005011316117667700244040ustar00rootroot00000000000000 %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n rabbitmq-java-client-5.0.0/src/test/resources/rabbit@localhost.config000066400000000000000000000007431316117667700257560ustar00rootroot00000000000000% vim:ft=erlang: [ {rabbit, [ {ssl_listeners, [5671]}, {ssl_options, [ {cacertfile, "${test-tls-certs.dir}/testca/cacert.pem"}, {certfile, "${test-tls-certs.dir}/server/cert.pem"}, {keyfile, "${test-tls-certs.dir}/server/key.pem"}, {verify, verify_peer}, {fail_if_no_peer_cert, false}, {honor_cipher_order, true}]}, {auth_mechanisms, ['PLAIN', 'AMQPLAIN', 'EXTERNAL', 'RABBIT-CR-DEMO']} ]} ].