commit f92450a76d45a4e5e31f198ed71df7f49c898a07 Author: Ahab Date: Sun Apr 8 17:16:20 2018 +0200 Initial commit diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..dfe0770 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Auto detect text files and perform LF normalization +* text=auto diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bd505c9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,79 @@ +# To fix untracked files: +# git rm -r --cached . +# This removes any changed files from the index(staging area), then just run: +# git add . +# Commit it: +# git commit -m ".gitignore is now working" + +# git clean -n +# git clean -f -d +# git status + +# To delete entire commit history +# Checkout: +# git checkout --orphan latest_branch +# Commit the changes: +# git commit -am "commit message" +# Delete the branch: +# git branch -D master +# Rename the current branch to master: +# git branch -m master +# Finally, force update your repository: +# git push -f origin master + + + +# Ignored files: + +# NetBeans +nbproject/private/ +build/ +nbbuild/ +dist/ +nbdist/ +.nb-gradle/ + +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# OSX +.DS_Store +.AppleDouble +.LSOverride + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk +JavaUMC/nbproject/private/private.xml +/JavaUMC/nbproject/private/ +JavaUMC/nbproject/project.properties \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f288702 --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. 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 +them 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 prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. 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. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey 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; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If 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 convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU 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 that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + 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. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +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. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + 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 +state 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 3 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, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program 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, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU 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. But first, please read +. diff --git a/build.xml b/build.xml new file mode 100644 index 0000000..e49f63e --- /dev/null +++ b/build.xml @@ -0,0 +1,73 @@ + + + + + + + + + + + Builds, tests, and runs the project MiguelBridge. + + + diff --git a/manifest.mf b/manifest.mf new file mode 100644 index 0000000..328e8e5 --- /dev/null +++ b/manifest.mf @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +X-COMMENT: Main-Class will be added automatically by build + diff --git a/nbproject/build-impl.xml b/nbproject/build-impl.xml new file mode 100644 index 0000000..28f9abe --- /dev/null +++ b/nbproject/build-impl.xml @@ -0,0 +1,1413 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set src.dir + Must set test.src.dir + Must set build.dir + Must set dist.dir + Must set build.classes.dir + Must set dist.javadoc.dir + Must set build.test.classes.dir + Must set build.test.results.dir + Must set build.classes.excludes + Must set dist.jar + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + No tests executed. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set JVM to use for profiling in profiler.info.jvm + Must set profiler agent JVM arguments in profiler.info.jvmargs.agent + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + To run this application from the command line without Ant, try: + + java -jar "${dist.jar.resolved}" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set run.class + + + + Must select one file in the IDE or set run.class + + + + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set debug.class + + + + + Must select one file in the IDE or set debug.class + + + + + Must set fix.includes + + + + + + + + + + This target only works when run from inside the NetBeans IDE. + + + + + + + + + Must select one file in the IDE or set profile.class + This target only works when run from inside the NetBeans IDE. + + + + + + + + + This target only works when run from inside the NetBeans IDE. + + + + + + + + + + + + + This target only works when run from inside the NetBeans IDE. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set run.class + + + + + + Must select some files in the IDE or set test.includes + + + + + Must select one file in the IDE or set run.class + + + + + Must select one file in the IDE or set applet.url + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + Some tests failed; see details above. + + + + + + + + + Must select some files in the IDE or set test.includes + + + + Some tests failed; see details above. + + + + Must select some files in the IDE or set test.class + Must select some method in the IDE or set test.method + + + + Some tests failed; see details above. + + + + + Must select one file in the IDE or set test.class + + + + Must select one file in the IDE or set test.class + Must select some method in the IDE or set test.method + + + + + + + + + + + + + + Must select one file in the IDE or set applet.url + + + + + + + + + Must select one file in the IDE or set applet.url + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/nbproject/genfiles.properties b/nbproject/genfiles.properties new file mode 100644 index 0000000..64e3c61 --- /dev/null +++ b/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=84bad5c7 +build.xml.script.CRC32=cdd627cf +build.xml.stylesheet.CRC32=8064a381@1.75.2.48 +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. +nbproject/build-impl.xml.data.CRC32=84bad5c7 +nbproject/build-impl.xml.script.CRC32=06f300cf +nbproject/build-impl.xml.stylesheet.CRC32=876e7a8f@1.75.2.48 diff --git a/nbproject/project.properties b/nbproject/project.properties new file mode 100644 index 0000000..a5fbd20 --- /dev/null +++ b/nbproject/project.properties @@ -0,0 +1,73 @@ +annotation.processing.enabled=true +annotation.processing.enabled.in.editor=false +annotation.processing.processor.options= +annotation.processing.processors.list= +annotation.processing.run.all.processors=true +annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output +build.classes.dir=${build.dir}/classes +build.classes.excludes=**/*.java,**/*.form +# This directory is removed when the project is cleaned: +build.dir=build +build.generated.dir=${build.dir}/generated +build.generated.sources.dir=${build.dir}/generated-sources +# Only compile against the classpath explicitly listed here: +build.sysclasspath=ignore +build.test.classes.dir=${build.dir}/test/classes +build.test.results.dir=${build.dir}/test/results +# Uncomment to specify the preferred debugger connection transport: +#debug.transport=dt_socket +debug.classpath=\ + ${run.classpath} +debug.test.classpath=\ + ${run.test.classpath} +# Files in build.classes.dir which should be excluded from distribution jar +dist.archive.excludes= +# This directory is removed when the project is cleaned: +dist.dir=dist +dist.jar=${dist.dir}/MiguelBridge.jar +dist.javadoc.dir=${dist.dir}/javadoc +excludes= +includes=** +jar.compress=false +javac.classpath= +# Space-separated list of extra javac options +javac.compilerargs= +javac.deprecation=false +javac.processorpath=\ + ${javac.classpath} +javac.source=1.7 +javac.target=1.7 +javac.test.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir} +javac.test.processorpath=\ + ${javac.test.classpath} +javadoc.additionalparam= +javadoc.author=false +javadoc.encoding=${source.encoding} +javadoc.noindex=false +javadoc.nonavbar=false +javadoc.notree=false +javadoc.private=false +javadoc.splitindex=true +javadoc.use=true +javadoc.version=false +javadoc.windowtitle= +main.class= +manifest.file=manifest.mf +meta.inf.dir=${src.dir}/META-INF +mkdist.disabled=false +platform.active=default_platform +run.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir} +# Space-separated list of JVM arguments used when running the project. +# You may also define separate properties like run-sys-prop.name=value instead of -Dname=value. +# To set system properties for unit tests define test-sys-prop.name=value: +run.jvmargs= +run.test.classpath=\ + ${javac.test.classpath}:\ + ${build.test.classes.dir} +source.encoding=UTF-8 +src.dir=src +test.src.dir=test diff --git a/nbproject/project.xml b/nbproject/project.xml new file mode 100644 index 0000000..88d4a26 --- /dev/null +++ b/nbproject/project.xml @@ -0,0 +1,15 @@ + + + org.netbeans.modules.java.j2seproject + + + MiguelBridge + + + + + + + + + diff --git a/src/main/java/io/kamax/matrix/MalformedEventException.java b/src/main/java/io/kamax/matrix/MalformedEventException.java new file mode 100644 index 0000000..d24c1e3 --- /dev/null +++ b/src/main/java/io/kamax/matrix/MalformedEventException.java @@ -0,0 +1,33 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2018 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix; + +public class MalformedEventException extends MatrixException { + + public MalformedEventException(String s) { + super("M_NOT_JSON", s); + } + + public static MalformedEventException forId(String id) { + return new MalformedEventException("Event " + id + " is malformed"); + } + +} diff --git a/src/main/java/io/kamax/matrix/MatrixErrorInfo.java b/src/main/java/io/kamax/matrix/MatrixErrorInfo.java new file mode 100644 index 0000000..d5d70a5 --- /dev/null +++ b/src/main/java/io/kamax/matrix/MatrixErrorInfo.java @@ -0,0 +1,44 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix; + +public class MatrixErrorInfo { + + private String errcode; + private String error; + + public MatrixErrorInfo(String errcode) { + this.errcode = errcode; + } + + public MatrixErrorInfo(Throwable t) { + this.errcode = "AS_INTERNAL_SERVER_ERROR"; + } + + public String getErrcode() { + return errcode; + } + + public String getError() { + return error; + } + +} diff --git a/src/main/java/io/kamax/matrix/MatrixException.java b/src/main/java/io/kamax/matrix/MatrixException.java new file mode 100644 index 0000000..af86c20 --- /dev/null +++ b/src/main/java/io/kamax/matrix/MatrixException.java @@ -0,0 +1,48 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2018 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix; + +public class MatrixException extends RuntimeException { + + private String errorCode; + private String error; + + public MatrixException(String errorCode, String error) { + super(errorCode + ": " + error); + this.errorCode = errorCode; + this.error = error; + } + + public MatrixException(String errorCode, String error, Throwable t) { + super(errorCode + ": " + error, t); + this.errorCode = errorCode; + this.error = error; + } + + public String getErrorCode() { + return errorCode; + } + + public String getError() { + return error; + } + +} diff --git a/src/main/java/io/kamax/matrix/MatrixID.java b/src/main/java/io/kamax/matrix/MatrixID.java new file mode 100644 index 0000000..cf6138f --- /dev/null +++ b/src/main/java/io/kamax/matrix/MatrixID.java @@ -0,0 +1,169 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class MatrixID implements _MatrixID { + + public static class Builder { + + private MatrixID mxId; + + public Builder(String id) { + mxId = MatrixID.parse(id); + } + + public MatrixID valid() { + if (!mxId.isValid()) { + throw new IllegalArgumentException(mxId + " is not a valid Matrix ID"); + } + return mxId; + } + + public MatrixID acceptable() { + if (!mxId.isAcceptable()) { + throw new IllegalArgumentException(mxId + " is not an acceptable Matrix ID"); + } + return mxId; + } + + } + + private static final Pattern LAX_PATTERN = Pattern.compile("@(.*?):(.+)"); + private static final Pattern STRICT_PATTERN = Pattern.compile("@([0-9a-z-.=_]+):(.+)"); + + private String id; + + private String localpart; + private String domain; + + private static String buildRaw(String localpart, String domain) { + return "@" + localpart + ":" + domain; + } + + private static MatrixID parse(String id) { + Matcher m = LAX_PATTERN.matcher(id); + if (!m.matches()) { + throw new IllegalArgumentException(id + " is not a Matrix ID"); + } + + MatrixID mxId = new MatrixID(); + mxId.id = id; + mxId.localpart = m.group(1); + mxId.domain = m.group(2); + return mxId; + } + + public static Builder from(String id) { + return new Builder(id); + } + + public static Builder from(String local, String domain) { + return from(buildRaw(local, domain)); + } + + public static MatrixID asValid(String id) { + return new Builder(id).valid(); + } + + public static MatrixID asAcceptable(String local, String domain) { + return from(local, domain).acceptable(); + } + + public static MatrixID asAcceptable(String id) { + return from(id).acceptable(); + } + + private MatrixID() { + // not for public consumption + } + + private MatrixID(MatrixID mxId) { + this.id = mxId.id; + this.localpart = mxId.localpart; + this.domain = mxId.domain; + } + + @Deprecated + public MatrixID(String mxId) { + this(parse(mxId)); + } + + @Deprecated + public MatrixID(String localpart, String domain) { + this(parse(buildRaw(localpart, domain))); + } + + @Override + public String getId() { + return id; + } + + @Override + public String getLocalPart() { + return localpart; + } + + @Override + public String getDomain() { + return domain; + } + + @Override + public MatrixID canonicalize() { + return parse(getId().toLowerCase()); + } + + @Override + public boolean isValid() { + return isAcceptable() && STRICT_PATTERN.matcher(id).matches(); + } + + @Override + public boolean isAcceptable() { + // TODO properly implement + + return id.length() <= 255; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof MatrixID)) return false; + + MatrixID matrixID = (MatrixID) o; + + return id.equals(matrixID.id); + } + + @Override + public int hashCode() { + return id.hashCode(); + } + + @Override + public String toString() { + return getId(); + } + +} diff --git a/src/main/java/io/kamax/matrix/ThreePid.java b/src/main/java/io/kamax/matrix/ThreePid.java new file mode 100644 index 0000000..c1e2c72 --- /dev/null +++ b/src/main/java/io/kamax/matrix/ThreePid.java @@ -0,0 +1,61 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix; + +public class ThreePid implements _ThreePid { + + private String medium; + private String address; + + public ThreePid(String medium, String address) { + this.medium = medium; + this.address = address; + } + + @Override + public String getMedium() { + return medium; + } + + @Override + public String getAddress() { + return address; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + ThreePid threePid = (ThreePid) o; + + if (!medium.equals(threePid.medium)) return false; + return address.equals(threePid.address); + } + + @Override + public int hashCode() { + int result = medium.hashCode(); + result = 31 * result + address.hashCode(); + return result; + } + +} diff --git a/src/main/java/io/kamax/matrix/ThreePidMapping.java b/src/main/java/io/kamax/matrix/ThreePidMapping.java new file mode 100644 index 0000000..e8f6f18 --- /dev/null +++ b/src/main/java/io/kamax/matrix/ThreePidMapping.java @@ -0,0 +1,61 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix; + +public class ThreePidMapping implements _ThreePidMapping { + + private _ThreePid threePid; + private _MatrixID mxId; + + public ThreePidMapping(_ThreePid threePid, _MatrixID mxId) { + this.threePid = threePid; + this.mxId = mxId; + } + + @Override + public _ThreePid getThreePid() { + return threePid; + } + + @Override + public _MatrixID getMatrixId() { + return mxId; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + ThreePidMapping that = (ThreePidMapping) o; + + if (!threePid.equals(that.threePid)) return false; + return mxId.equals(that.mxId); + } + + @Override + public int hashCode() { + int result = threePid.hashCode(); + result = 31 * result + mxId.hashCode(); + return result; + } + +} diff --git a/src/main/java/io/kamax/matrix/ThreePidMedium.java b/src/main/java/io/kamax/matrix/ThreePidMedium.java new file mode 100644 index 0000000..7760aad --- /dev/null +++ b/src/main/java/io/kamax/matrix/ThreePidMedium.java @@ -0,0 +1,46 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix; + +public enum ThreePidMedium { + + Email("email"), + PhoneNumber("msisdn"); + + private String id; + + ThreePidMedium(String id) { + this.id = id; + } + + public String getId() { + return id; + } + + public String toString() { + return getId(); + } + + public boolean is(String s) { + return getId().contentEquals(s); + } + +} diff --git a/src/main/java/io/kamax/matrix/_MatrixContent.java b/src/main/java/io/kamax/matrix/_MatrixContent.java new file mode 100644 index 0000000..0fcb073 --- /dev/null +++ b/src/main/java/io/kamax/matrix/_MatrixContent.java @@ -0,0 +1,38 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix; + +import java.net.URI; +import java.util.Optional; + +public interface _MatrixContent { + + URI getAddress(); + + boolean isValid(); + + Optional getType(); + + byte[] getData(); + + Optional getFilename(); + +} diff --git a/src/main/java/io/kamax/matrix/_MatrixID.java b/src/main/java/io/kamax/matrix/_MatrixID.java new file mode 100644 index 0000000..9316dfb --- /dev/null +++ b/src/main/java/io/kamax/matrix/_MatrixID.java @@ -0,0 +1,55 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix; + +public interface _MatrixID { + + String getId(); + + String getLocalPart(); + + String getDomain(); + + /** + * Render this Matrix ID strictly valid. In technical term, transform this ID so + * isValid() returns true. + * + * @return A canonical Matrix ID + */ + _MatrixID canonicalize(); + + /** + * If the Matrix ID is strictly valid in the protocol as per + * http://matrix.org/docs/spec/intro.html#user-identifiers + * + * @return true if strictly valid, false if not + */ + boolean isValid(); + + /** + * If the Matrix ID is acceptable in the protocol as per + * http://matrix.org/docs/spec/intro.html#historical-user-ids + * + * @return + */ + boolean isAcceptable(); + +} diff --git a/src/main/java/io/kamax/matrix/_MatrixUser.java b/src/main/java/io/kamax/matrix/_MatrixUser.java new file mode 100644 index 0000000..fd7ada2 --- /dev/null +++ b/src/main/java/io/kamax/matrix/_MatrixUser.java @@ -0,0 +1,37 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix; + +import io.kamax.matrix.client._Presence; + +import java.util.Optional; + +public interface _MatrixUser { + + _MatrixID getId(); + + Optional getName(); + + Optional<_MatrixContent> getAvatar(); + + Optional<_Presence> getPresence(); + +} diff --git a/src/main/java/io/kamax/matrix/_ThreePid.java b/src/main/java/io/kamax/matrix/_ThreePid.java new file mode 100644 index 0000000..486a32e --- /dev/null +++ b/src/main/java/io/kamax/matrix/_ThreePid.java @@ -0,0 +1,29 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix; + +public interface _ThreePid { + + String getMedium(); + + String getAddress(); + +} diff --git a/src/main/java/io/kamax/matrix/_ThreePidMapping.java b/src/main/java/io/kamax/matrix/_ThreePidMapping.java new file mode 100644 index 0000000..fa9bcf1 --- /dev/null +++ b/src/main/java/io/kamax/matrix/_ThreePidMapping.java @@ -0,0 +1,29 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix; + +public interface _ThreePidMapping { + + _ThreePid getThreePid(); + + _MatrixID getMatrixId(); + +} diff --git a/src/main/java/io/kamax/matrix/client/AMatrixHttpClient.java b/src/main/java/io/kamax/matrix/client/AMatrixHttpClient.java new file mode 100644 index 0000000..15f9863 --- /dev/null +++ b/src/main/java/io/kamax/matrix/client/AMatrixHttpClient.java @@ -0,0 +1,401 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.client; + +import com.google.gson.Gson; +import com.google.gson.JsonParser; + +import io.kamax.matrix.MatrixErrorInfo; +import io.kamax.matrix._MatrixID; +import io.kamax.matrix.hs._MatrixHomeserver; +import io.kamax.matrix.json.GsonUtil; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.http.HttpEntity; +import org.apache.http.client.entity.EntityBuilder; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpRequestBase; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.entity.ContentType; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.charset.Charset; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public abstract class AMatrixHttpClient implements _MatrixClientRaw { + + private Logger log = LoggerFactory.getLogger(AMatrixHttpClient.class); + + protected MatrixClientContext context = new MatrixClientContext(); + + protected Gson gson = new Gson(); + protected JsonParser jsonParser = new JsonParser(); + private CloseableHttpClient client = HttpClients.createDefault(); + + private Pattern accessTokenUrlPattern = Pattern.compile("\\?access_token=(?[^&]*)"); + + public AMatrixHttpClient(String domain) { + context.setDomain(domain); + } + + public AMatrixHttpClient(URL hsBaseUrl) { + context.setHsBaseUrl(hsBaseUrl); + } + + protected AMatrixHttpClient(MatrixClientContext context) { + this.context = new MatrixClientContext(context); + } + + @Override + public Optional<_AutoDiscoverySettings> discoverSettings() { + if (StringUtils.isBlank(context.getDomain())) { + throw new IllegalStateException("A non-empty Matrix domain must be set to discover the client settings"); + } + + try { + String hostname = context.getDomain().split(":")[0]; + log.info("Performing .well-known auto-discovery for {}", hostname); + + URIBuilder builder = new URIBuilder(); + builder.setScheme("https"); + builder.setHost(hostname); + builder.setPath("/.well-known/matrix/client"); + HttpGet req = new HttpGet(builder.build()); + String body = execute(new MatrixHttpRequest(req).addIgnoredErrorCode(404)); + if (StringUtils.isBlank(body)) { + if (Objects.isNull(context.getHsBaseUrl())) { + throw new IllegalStateException("No valid Homeserver base URL was found"); + } + + // No .well-known data found + // FIXME improve SDK so we can differentiate between not found and empty. + // not found = skip + // empty = failure + return Optional.empty(); + } + + log.info("Found body: {}", body); + + WellKnownAutoDiscoverySettings settings = new WellKnownAutoDiscoverySettings(body); + log.info("Found .well-known data"); + + // TODO reconsider if and where we should check for an already present HS url in the context + if (settings.getHsBaseUrls().isEmpty()) { + throw new IllegalStateException("No valid Homeserver base URL was found"); + } + + for (URL baseUrlCandidate : settings.getHsBaseUrls()) { + context.setHsBaseUrl(baseUrlCandidate); + try { + if (!getHomeApiVersions().isEmpty()) { + log.info("Found a valid HS at {}", getContext().getHsBaseUrl().toString()); + break; + } + } catch (MatrixClientRequestException e) { + log.warn("Error when trying to fetch {}: {}", baseUrlCandidate, e.getMessage()); + } + } + + for (URL baseUrlCandidate : settings.getIsBaseUrls()) { + context.setIsBaseUrl(baseUrlCandidate); + try { + if (validateIsBaseUrl()) { + log.info("Found a valid IS at {}", getContext().getHsBaseUrl().toString()); + break; + } + } catch (MatrixClientRequestException e) { + log.warn("Error when trying to fetch {}: {}", baseUrlCandidate, e.getMessage()); + } + } + + return Optional.of(settings); + } catch (URISyntaxException e) { // The domain was invalid when used in a URL + throw new IllegalArgumentException(e); + } + } + + @Override + public MatrixClientContext getContext() { + return context; + } + + @Override + public _MatrixHomeserver getHomeserver() { + return context.getHomeserver(); + } + + @Override + public Optional getAccessToken() { + return Optional.ofNullable(context.getToken()); + } + + public String getAccessTokenOrThrow() { + return getAccessToken() + .orElseThrow(() -> new IllegalStateException("This method can only be used with a valid token.")); + } + + @Override + public List getHomeApiVersions() { + String body = execute(new HttpGet(getPath("client", "", "versions"))); + return GsonUtil.asList(GsonUtil.parseObj(body), "versions", String.class); + } + + @Override + public boolean validateIsBaseUrl() { + String body = execute(new HttpGet(getIdentityPath("identity", "api", "/v1"))); + return "{}".equals(body); + } + + @Override + public Optional<_MatrixID> getUser() { + return context.getUser(); + } + + protected String execute(HttpRequestBase request) { + return execute(new MatrixHttpRequest(request)); + } + + protected String execute(MatrixHttpRequest matrixRequest) { + log(matrixRequest.getHttpRequest()); + try (CloseableHttpResponse response = client.execute(matrixRequest.getHttpRequest())) { + + String body = getBody(response.getEntity()); + int responseStatus = response.getStatusLine().getStatusCode(); + + if (responseStatus == 200) { + log.debug("Request successfully executed."); + } else if (matrixRequest.getIgnoredErrorCodes().contains(responseStatus)) { + log.debug("Error code ignored: " + responseStatus); + return ""; + } else { + MatrixErrorInfo info = createErrorInfo(body, responseStatus); + + body = handleError(matrixRequest, responseStatus, info); + } + return body; + + } catch (IOException e) { + throw new MatrixClientRequestException(e); + } + } + + /** + * Default handling of errors. Can be overwritten by a custom implementation in inherited classes. + * + * @param matrixRequest + * @param responseStatus + * @param info + * @return body of the response of a repeated call of the request, else this methods throws a + * MatrixClientRequestException + */ + protected String handleError(MatrixHttpRequest matrixRequest, int responseStatus, MatrixErrorInfo info) { + String message = String.format("Request failed with status code: %s", responseStatus); + + if (responseStatus == 429) { + return handleRateLimited(matrixRequest, info); + } + + throw new MatrixClientRequestException(info, message); + } + + /** + * Default handling of rate limited calls. Can be overwritten by a custom implementation in inherited classes. + * + * @param matrixRequest + * @param info + * @return body of the response of a repeated call of the request, else this methods throws a + * MatrixClientRequestException + */ + protected String handleRateLimited(MatrixHttpRequest matrixRequest, MatrixErrorInfo info) { + throw new MatrixClientRequestException(info, "Request was rate limited."); + // TODO Add default handling of rate limited call, i.e. repeated call after given time interval. + // 1. Wait for timeout + // 2. return execute(request) + } + + protected MatrixHttpContentResult executeContentRequest(MatrixHttpRequest matrixRequest) { + log(matrixRequest.getHttpRequest()); + try (CloseableHttpResponse response = client.execute(matrixRequest.getHttpRequest())) { + + HttpEntity entity = response.getEntity(); + int responseStatus = response.getStatusLine().getStatusCode(); + + MatrixHttpContentResult result = new MatrixHttpContentResult(response); + + if (responseStatus == 200) { + log.debug("Request successfully executed."); + + if (entity == null) { + log.debug("No data received."); + } else if (entity.getContentType() == null) { + log.debug("No content type was given."); + } + + } else if (matrixRequest.getIgnoredErrorCodes().contains(responseStatus)) { + log.debug("Error code ignored: " + responseStatus); + } else { + String body = getBody(entity); + MatrixErrorInfo info = createErrorInfo(body, responseStatus); + + result = handleErrorContentRequest(matrixRequest, responseStatus, info); + } + return result; + + } catch (IOException e) { + throw new MatrixClientRequestException(e); + } + } + + protected MatrixHttpContentResult handleErrorContentRequest(MatrixHttpRequest matrixRequest, int responseStatus, + MatrixErrorInfo info) { + String message = String.format("Request failed with status code: %s", responseStatus); + + if (responseStatus == 429) { + return handleRateLimitedContentRequest(matrixRequest, info); + } + + throw new MatrixClientRequestException(info, message); + } + + protected MatrixHttpContentResult handleRateLimitedContentRequest(MatrixHttpRequest matrixRequest, + MatrixErrorInfo info) { + throw new MatrixClientRequestException(info, "Request was rate limited."); + // TODO Add default handling of rate limited call, i.e. repeated call after given time interval. + // 1. Wait for timeout + // 2. return execute(request) + } + + protected Optional extractAsStringFromBody(String body, String jsonObjectName) { + if (StringUtils.isNotEmpty(body)) { + return Optional.of(new JsonParser().parse(body).getAsJsonObject().get(jsonObjectName).getAsString()); + } + return Optional.empty(); + } + + private String getBody(HttpEntity entity) throws IOException { + Charset charset = ContentType.getOrDefault(entity).getCharset(); + return IOUtils.toString(entity.getContent(), charset); + } + + private MatrixErrorInfo createErrorInfo(String body, int responseStatus) { + MatrixErrorInfo info = gson.fromJson(body, MatrixErrorInfo.class); + log.debug("Request returned with an error. Status code: {}, errcode: {}, error: {}", responseStatus, + info.getErrcode(), info.getError()); + return info; + } + + private void log(HttpRequestBase req) { + String reqUrl = req.getURI().toASCIIString(); + Matcher m = accessTokenUrlPattern.matcher(reqUrl); + if (m.find()) { + StringBuilder b = new StringBuilder(); + b.append(reqUrl.substring(0, m.start("token"))); + b.append(""); + b.append(reqUrl.substring(m.end("token"), reqUrl.length())); + reqUrl = b.toString(); + } + + log.debug("Doing {} {}", req.getMethod(), reqUrl); + } + + protected URIBuilder getPathBuilder(URIBuilder base, String module, String version, String action) { + base.setPath(base.getPath() + "/_matrix/" + module + "/" + version + action); + if (context.isVirtual()) { + context.getUser().ifPresent(user -> base.setParameter("user_id", user.getId())); + } + + return base; + } + + protected URIBuilder getPathBuilder(String module, String version, String action) { + return getPathBuilder(context.getHomeserver().getBaseEndpointBuilder(), module, version, action); + } + + protected URIBuilder getIdentityPathBuilder(String module, String version, String action) { + return getPathBuilder(new URIBuilder(URI.create(context.getIsBaseUrl().toString())), module, version, action); + } + + protected URI getPath(String module, String version, String action) { + try { + return getPathBuilder(module, version, action).build(); + } catch (URISyntaxException e) { + throw new IllegalArgumentException(e); + } + } + + protected URI getIdentityPath(String module, String version, String action) { + try { + return getIdentityPathBuilder(module, version, action).build(); + } catch (URISyntaxException e) { + throw new IllegalArgumentException(e); + } + } + + protected URIBuilder getClientPathBuilder(String action) { + return getPathBuilder("client", "r0", action); + } + + protected URIBuilder getMediaPathBuilder(String action) { + return getPathBuilder("media", "v1", action); + } + + protected URI getWithAccessToken(URIBuilder builder) { + try { + builder.setParameter("access_token", getAccessTokenOrThrow()); + return builder.build(); + } catch (URISyntaxException e) { + throw new IllegalArgumentException(e); + } + } + + protected URI getClientPathWithAccessToken(String action) { + return getWithAccessToken(getClientPathBuilder(action)); + } + + protected URI getClientPath(String action) { + try { + return getClientPathBuilder(action).build(); + } catch (URISyntaxException e) { + throw new IllegalArgumentException(e); + } + } + + protected URI getMediaPath(String action) { + return getWithAccessToken(getMediaPathBuilder(action)); + } + + protected HttpEntity getJsonEntity(Object o) { + return EntityBuilder.create().setText(gson.toJson(o)).setContentType(ContentType.APPLICATION_JSON).build(); + } +} diff --git a/src/main/java/io/kamax/matrix/client/MatrixClientContext.java b/src/main/java/io/kamax/matrix/client/MatrixClientContext.java new file mode 100644 index 0000000..ca41eb2 --- /dev/null +++ b/src/main/java/io/kamax/matrix/client/MatrixClientContext.java @@ -0,0 +1,142 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.client; + +import io.kamax.matrix.MatrixID; +import io.kamax.matrix._MatrixID; +import io.kamax.matrix.hs.MatrixHomeserver; +import io.kamax.matrix.hs._MatrixHomeserver; + +import java.net.URL; +import java.util.Objects; +import java.util.Optional; + +public class MatrixClientContext { + + private String domain; + private URL hsBaseUrl; + private URL isBaseUrl; + private _MatrixID user; + private String token; + private boolean isVirtual; + private String deviceId; + + public MatrixClientContext() { + // stub + } + + public MatrixClientContext(MatrixClientContext other) { + this.domain = other.domain; + this.hsBaseUrl = other.hsBaseUrl; + this.isBaseUrl = other.isBaseUrl; + this.user = other.user; + this.token = other.token; + this.isVirtual = other.isVirtual; + this.deviceId = other.deviceId; + } + + public MatrixClientContext(_MatrixHomeserver hs) { + setDomain(hs.getDomain()); + setHsBaseUrl(hs.getBaseEndpoint()); + } + + public MatrixClientContext(_MatrixHomeserver hs, _MatrixID user, String token) { + this(hs); + setUser(user); + setToken(token); + } + + public _MatrixHomeserver getHomeserver() { + if (Objects.isNull(hsBaseUrl)) { + throw new IllegalStateException("Homeserver Base URL is not set"); + } + + return new MatrixHomeserver(domain, hsBaseUrl.toString()); + } + + public String getDomain() { + return domain; + } + + public MatrixClientContext setDomain(String domain) { + this.domain = domain; + return this; + } + + public URL getHsBaseUrl() { + return hsBaseUrl; + } + + public MatrixClientContext setHsBaseUrl(URL hsBaseUrl) { + this.hsBaseUrl = hsBaseUrl; + return this; + } + + public URL getIsBaseUrl() { + return isBaseUrl; + } + + public MatrixClientContext setIsBaseUrl(URL isBaseUrl) { + this.isBaseUrl = isBaseUrl; + return this; + } + + public Optional<_MatrixID> getUser() { + return Optional.ofNullable(user); + } + + public MatrixClientContext setUser(_MatrixID user) { + this.user = user; + return this; + } + + public MatrixClientContext setUserWithLocalpart(String localpart) { + setUser(MatrixID.asAcceptable(localpart, getDomain())); + return this; + } + + public String getToken() { + return token; + } + + public MatrixClientContext setToken(String token) { + this.token = token; + return this; + } + + public boolean isVirtual() { + return isVirtual; + } + + public MatrixClientContext setVirtual(boolean virtual) { + isVirtual = virtual; + return this; + } + + public String getDeviceId() { + return deviceId; + } + + public MatrixClientContext setDeviceId(String deviceId) { + this.deviceId = deviceId; + return this; + } +} diff --git a/src/main/java/io/kamax/matrix/client/MatrixClientRequestException.java b/src/main/java/io/kamax/matrix/client/MatrixClientRequestException.java new file mode 100644 index 0000000..08024a0 --- /dev/null +++ b/src/main/java/io/kamax/matrix/client/MatrixClientRequestException.java @@ -0,0 +1,46 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.client; + +import io.kamax.matrix.MatrixErrorInfo; + +import java.io.IOException; +import java.util.Optional; + +public class MatrixClientRequestException extends RuntimeException { + + private MatrixErrorInfo errorInfo; + + public MatrixClientRequestException(IOException e) { + super(e); + } + + public MatrixClientRequestException(MatrixErrorInfo errorInfo, String message) { + super(message); + + this.errorInfo = errorInfo; + } + + public Optional getError() { + return Optional.ofNullable(errorInfo); + } + +} diff --git a/src/main/java/io/kamax/matrix/client/MatrixHttpContent.java b/src/main/java/io/kamax/matrix/client/MatrixHttpContent.java new file mode 100644 index 0000000..df6dd02 --- /dev/null +++ b/src/main/java/io/kamax/matrix/client/MatrixHttpContent.java @@ -0,0 +1,126 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.client; + +import io.kamax.matrix._MatrixContent; + +import org.apache.commons.lang3.StringUtils; +import org.apache.http.Header; +import org.apache.http.client.methods.HttpGet; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.net.URI; +import java.util.Optional; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class MatrixHttpContent extends AMatrixHttpClient implements _MatrixContent { + + private Logger log = LoggerFactory.getLogger(MatrixHttpContent.class); + private final Pattern filenamePattern = Pattern.compile("filename=\"?(?[^\";]+)"); + private URI address; + + private MatrixHttpContentResult result; + + private boolean loaded = false; + private boolean valid = false; + + public MatrixHttpContent(MatrixClientContext context, URI address) { + super(context); + this.address = address; + } + + // TODO switch a HTTP HEAD to fetch initial data, instead of loading in memory directly + private synchronized void load() { + if (loaded) { + return; + } + + try { + if (!StringUtils.equalsIgnoreCase("mxc", address.getScheme())) { + log.debug("{} is not a supported protocol for avatars, ignoring", address.getScheme()); + } else { + URI path = getMediaPath("/download/" + address.getHost() + address.getPath()); + + MatrixHttpRequest request = new MatrixHttpRequest(new HttpGet(path)); + result = executeContentRequest(request); + valid = result.isValid(); + } + + } catch (MatrixClientRequestException e) { + valid = false; + } + loaded = true; + } + + @Override + public URI getAddress() { + return address; + } + + @Override + public boolean isValid() { + load(); + + return valid; + } + + @Override + public Optional getType() { + load(); + + if (!isValid()) { + throw new IllegalStateException("This method should only be called, if valid is true."); + } + return result.getContentType(); + } + + @Override + public byte[] getData() { + load(); + + if (!isValid()) { + throw new IllegalStateException("This method should only be called, if valid is true."); + } + return result.getData(); + } + + @Override + public Optional getFilename() { + load(); + + if (!isValid()) { + throw new IllegalStateException("This method should only be called, if valid is true."); + } + + Optional
contentDisposition = result.getHeader("Content-Disposition"); + if (contentDisposition.isPresent()) { + Matcher m = filenamePattern.matcher(contentDisposition.get().getValue()); + if (m.find()) { + return Optional.of(m.group("filename")); + } + } + + return Optional.empty(); + } + +} diff --git a/src/main/java/io/kamax/matrix/client/MatrixHttpContentResult.java b/src/main/java/io/kamax/matrix/client/MatrixHttpContentResult.java new file mode 100644 index 0000000..3055097 --- /dev/null +++ b/src/main/java/io/kamax/matrix/client/MatrixHttpContentResult.java @@ -0,0 +1,79 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Arne Augenstein + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.client; + +import org.apache.http.Header; +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.CloseableHttpResponse; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.*; + +public class MatrixHttpContentResult { + private final boolean valid; + private final List
headers; + private final Optional contentType; + private final byte[] data; + + public MatrixHttpContentResult(CloseableHttpResponse response) throws IOException { + HttpEntity entity = response.getEntity(); + valid = entity != null && response.getStatusLine().getStatusCode() == 200; + + if (entity != null) { + headers = Arrays.asList(response.getAllHeaders()); + Header contentTypeHeader = entity.getContentType(); + if (contentTypeHeader != null) { + contentType = Optional.of(contentTypeHeader.getValue()); + } else { + contentType = Optional.empty(); + } + ByteArrayOutputStream outStream = new ByteArrayOutputStream(); + entity.writeTo(outStream); + data = outStream.toByteArray(); + } else { + headers = new ArrayList<>(); + contentType = Optional.empty(); + data = new byte[0]; + } + } + + public boolean isValid() { + return valid; + } + + public Optional
getHeader(String name) { + for (Header header : headers) { + if (Objects.equals(header.getName(), name)) { + return Optional.of(header); + } + } + return Optional.empty(); + } + + public Optional getContentType() { + return contentType; + } + + public byte[] getData() { + return data; + } +} diff --git a/src/main/java/io/kamax/matrix/client/MatrixHttpRequest.java b/src/main/java/io/kamax/matrix/client/MatrixHttpRequest.java new file mode 100644 index 0000000..f8015f6 --- /dev/null +++ b/src/main/java/io/kamax/matrix/client/MatrixHttpRequest.java @@ -0,0 +1,49 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Arne Augenstein + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.client; + +import org.apache.http.client.methods.HttpRequestBase; + +import java.util.ArrayList; +import java.util.List; + +public class MatrixHttpRequest { + private final HttpRequestBase httpRequest; + private List ignoredErrorCodes = new ArrayList<>(); + + public MatrixHttpRequest(HttpRequestBase request) { + this.httpRequest = request; + } + + public MatrixHttpRequest addIgnoredErrorCode(int errcode) { + ignoredErrorCodes.add(errcode); + return this; + } + + public HttpRequestBase getHttpRequest() { + return httpRequest; + } + + public List getIgnoredErrorCodes() { + return ignoredErrorCodes; + } + +} diff --git a/src/main/java/io/kamax/matrix/client/MatrixHttpRoom.java b/src/main/java/io/kamax/matrix/client/MatrixHttpRoom.java new file mode 100644 index 0000000..b0ad9b1 --- /dev/null +++ b/src/main/java/io/kamax/matrix/client/MatrixHttpRoom.java @@ -0,0 +1,183 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.client; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +import io.kamax.matrix.MatrixID; +import io.kamax.matrix._MatrixID; +import io.kamax.matrix.hs._MatrixRoom; +import io.kamax.matrix.json.GsonUtil; +import io.kamax.matrix.json.RoomMessageChunkResponseJson; +import io.kamax.matrix.json.RoomMessageFormattedTextPutBody; +import io.kamax.matrix.json.RoomMessageTextPutBody; +import io.kamax.matrix.json.event.MatrixJsonEvent; +import io.kamax.matrix.room.MatrixRoomMessageChunk; +import io.kamax.matrix.room._MatrixRoomMessageChunk; +import io.kamax.matrix.room._MatrixRoomMessageChunkOptions; + +import org.apache.commons.lang3.StringUtils; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.client.utils.URIBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.net.URI; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; + +public class MatrixHttpRoom extends AMatrixHttpClient implements _MatrixRoom { + + private Logger log = LoggerFactory.getLogger(MatrixHttpRoom.class); + + private String roomId; + + public MatrixHttpRoom(MatrixClientContext context, String roomId) { + super(context); + this.roomId = roomId; + } + + @Override + protected URIBuilder getClientPathBuilder(String action) { + URIBuilder builder = super.getClientPathBuilder(action); + builder.setPath(builder.getPath().replace("{roomId}", roomId)); + + return builder; + } + + @Override + public String getAddress() { + return roomId; + } + + @Override + public Optional getName() { + URI path = getClientPathWithAccessToken("/rooms/{roomId}/state/m.room.name"); + + MatrixHttpRequest request = new MatrixHttpRequest(new HttpGet(path)); + request.addIgnoredErrorCode(404); + String body = execute(request); + return extractAsStringFromBody(body, "name"); + } + + @Override + public Optional getTopic() { + URI path = getClientPathWithAccessToken("/rooms/{roomId}/state/m.room.topic"); + MatrixHttpRequest matrixRequest = new MatrixHttpRequest(new HttpGet(path)); + matrixRequest.addIgnoredErrorCode(404); + String body = execute(matrixRequest); + return extractAsStringFromBody(body, "topic"); + } + + @Override + public void join() { + URI path = getClientPathWithAccessToken("/rooms/{roomId}/join"); + execute(new HttpPost(path)); + } + + @Override + public void leave() { + URI path = getClientPathWithAccessToken("/rooms/{roomId}/leave"); + MatrixHttpRequest request = new MatrixHttpRequest(new HttpPost(path)); + + // TODO Find a better way to handle room objects for unknown rooms + // Maybe throw exception? + // TODO implement method to check room existence - isValid() ? + // if (res.getStatusLine().getStatusCode() == 404) { + // log.warn("Room {} is not joined, ignoring call", roomId); + // return; + // } + request.addIgnoredErrorCode(404); + execute(request); + } + + private void sendMessage(RoomMessageTextPutBody content) { + URI path = getClientPathWithAccessToken("/rooms/{roomId}/send/m.room.message/" + System.currentTimeMillis()); + HttpPut httpPut = new HttpPut(path); + httpPut.setEntity(getJsonEntity(content)); + execute(httpPut); + } + + @Override + public void sendText(String message) { + sendMessage(new RoomMessageTextPutBody(message)); + } + + @Override + public void sendFormattedText(String formatted, String rawFallback) { + // TODO sanitize input + sendMessage(new RoomMessageFormattedTextPutBody(rawFallback, formatted)); + } + + @Override + public void sendNotice(String message) { + sendMessage(new RoomMessageTextPutBody("m.notice", message)); + } + + @Override + public void sendNotice(String formatted, String plain) { + // TODO sanitize input + sendMessage(new RoomMessageFormattedTextPutBody("m.notice", plain, formatted)); + } + + @Override + public void invite(_MatrixID mxId) { + URI path = getClientPathWithAccessToken("/rooms/{roomId}/invite"); + HttpPost req = new HttpPost(path); + req.setEntity(getJsonEntity(GsonUtil.makeObj("user_id", mxId.getId()))); + execute(req); + } + + @Override + public List<_MatrixID> getJoinedUsers() { + URI path = getClientPathWithAccessToken("/rooms/{roomId}/joined_members"); + String body = execute(new HttpGet(path)); + + List<_MatrixID> ids = new ArrayList<>(); + if (StringUtils.isNotEmpty(body)) { + JsonObject joinedUsers = jsonParser.parse(body).getAsJsonObject().get("joined").getAsJsonObject(); + for (Map.Entry entry : joinedUsers.entrySet()) { + ids.add(new MatrixID(entry.getKey())); + } + } + return ids; + } + + @Override + public _MatrixRoomMessageChunk getMessages(_MatrixRoomMessageChunkOptions options) { + URIBuilder builder = getClientPathBuilder("/rooms/{roomId}/messages"); + builder.setParameter("from", options.getFromToken()); + builder.setParameter("dir", options.getDirection()); + options.getToToken().ifPresent(token -> builder.setParameter("to", token)); + options.getLimit().ifPresent(limit -> builder.setParameter("limit", limit.toString())); + + String bodyRaw = execute(new HttpGet(getWithAccessToken(builder))); + RoomMessageChunkResponseJson body = GsonUtil.get().fromJson(bodyRaw, RoomMessageChunkResponseJson.class); + return new MatrixRoomMessageChunk(body.getStart(), body.getEnd(), + body.getChunk().stream().map(MatrixJsonEvent::new).collect(Collectors.toList())); + } +} diff --git a/src/main/java/io/kamax/matrix/client/MatrixHttpUser.java b/src/main/java/io/kamax/matrix/client/MatrixHttpUser.java new file mode 100644 index 0000000..b9850c3 --- /dev/null +++ b/src/main/java/io/kamax/matrix/client/MatrixHttpUser.java @@ -0,0 +1,95 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.client; + +import io.kamax.matrix._MatrixContent; +import io.kamax.matrix._MatrixID; +import io.kamax.matrix._MatrixUser; +import io.kamax.matrix.client.regular.Presence; +import io.kamax.matrix.json.GsonUtil; + +import org.apache.commons.lang3.StringUtils; +import org.apache.http.client.methods.HttpGet; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Optional; + +public class MatrixHttpUser extends AMatrixHttpClient implements _MatrixUser { + + private Logger log = LoggerFactory.getLogger(MatrixHttpUser.class); + + private _MatrixID mxId; + + public MatrixHttpUser(MatrixClientContext context, _MatrixID mxId) { + super(context); + + this.mxId = mxId; + } + + @Override + public _MatrixID getId() { + return mxId; + } + + @Override + public Optional getName() { + URI path = getClientPathWithAccessToken("/profile/" + mxId.getId() + "/displayname"); + + MatrixHttpRequest request = new MatrixHttpRequest(new HttpGet(path)); + request.addIgnoredErrorCode(404); + String body = execute(request); + return extractAsStringFromBody(body, "displayname"); + } + + @Override + public Optional<_MatrixContent> getAvatar() { + URI path = getClientPathWithAccessToken("/profile/" + mxId.getId() + "/avatar_url"); + + MatrixHttpRequest request = new MatrixHttpRequest(new HttpGet(path)); + request.addIgnoredErrorCode(404); + String body = execute(request); + Optional uri = extractAsStringFromBody(body, "avatar_url"); + if (uri.isPresent()) { + try { + return Optional.of(new MatrixHttpContent(getContext(), new URI(uri.get()))); + } catch (URISyntaxException e) { + log.debug("{} is not a valid URI for avatar, returning empty", uri.get()); + } + } + return Optional.empty(); + } + + @Override + public Optional<_Presence> getPresence() { + URI path = getClientPathWithAccessToken("/presence/" + mxId.getId() + "/status"); + MatrixHttpRequest request = new MatrixHttpRequest(new HttpGet(path)); + request.addIgnoredErrorCode(404); + String body = execute(request); + if (StringUtils.isBlank(body)) { + return Optional.empty(); + } + + return Optional.of(new Presence(GsonUtil.parseObj(body))); + } +} diff --git a/src/main/java/io/kamax/matrix/client/MatrixPasswordLoginCredentials.java b/src/main/java/io/kamax/matrix/client/MatrixPasswordLoginCredentials.java new file mode 100644 index 0000000..e953b1a --- /dev/null +++ b/src/main/java/io/kamax/matrix/client/MatrixPasswordLoginCredentials.java @@ -0,0 +1,39 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Arne Augenstein + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.client; + +public class MatrixPasswordLoginCredentials { + private final String localPart; + private final String password; + + public MatrixPasswordLoginCredentials(String localPart, String password) { + this.localPart = localPart; + this.password = password; + } + + public String getLocalPart() { + return localPart; + } + + public String getPassword() { + return password; + } +} diff --git a/src/main/java/io/kamax/matrix/client/PresenceStatus.java b/src/main/java/io/kamax/matrix/client/PresenceStatus.java new file mode 100644 index 0000000..915560a --- /dev/null +++ b/src/main/java/io/kamax/matrix/client/PresenceStatus.java @@ -0,0 +1,45 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2018 Kamax Sàrl + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.client; + +import org.apache.commons.lang3.StringUtils; + +public enum PresenceStatus { + + Online("online"), + Offline("offline"), + Unavailable("unavailable"); + + private String id; + + PresenceStatus(String id) { + this.id = id; + } + + public String getId() { + return id; + } + + public boolean is(String status) { + return StringUtils.equals(id, status); + } + +} diff --git a/src/main/java/io/kamax/matrix/client/WellKnownAutoDiscoverySettings.java b/src/main/java/io/kamax/matrix/client/WellKnownAutoDiscoverySettings.java new file mode 100644 index 0000000..bb26491 --- /dev/null +++ b/src/main/java/io/kamax/matrix/client/WellKnownAutoDiscoverySettings.java @@ -0,0 +1,138 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2018 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.client; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; + +import io.kamax.matrix.json.GsonUtil; +import io.kamax.matrix.json.InvalidJsonException; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +public class WellKnownAutoDiscoverySettings implements _AutoDiscoverySettings { + + private final Logger log = LoggerFactory.getLogger(WellKnownAutoDiscoverySettings.class); + + private JsonObject raw; + + private List hsBaseUrls = new ArrayList<>(); + private List isBaseUrls = new ArrayList<>(); + + /** + * Build .well-known auto-discovery settings from a .well-known source. + * + * @param raw + * The raw JSON data + * @throws IllegalArgumentException + * if the data is invalid and couldn't be parsed. + */ + public WellKnownAutoDiscoverySettings(String raw) { + try { + setRaw(GsonUtil.parseObj(raw)); + } catch (JsonParseException | InvalidJsonException e) { + throw new IllegalArgumentException("Invalid JSON data for .well-known string"); + } + } + + private void setRaw(JsonObject raw) { + this.raw = raw; + process(); + } + + private Optional getUrl(String url) { + try { + return Optional.of(new URL(url)); + } catch (MalformedURLException e) { + log.warn("Ignoring invalid Base URL entry in well-known: {} - {}", url, e.getMessage()); + return Optional.empty(); + } + } + + private List getUrls(JsonArray array) { + List urls = new ArrayList<>(); + + array.forEach(el -> { + if (!el.isJsonPrimitive()) { + log.warn("Ignoring invalid Base URL entry in well-known: {} - Not a string", GsonUtil.get().toJson(el)); + return; + } + + getUrl(el.getAsString()).ifPresent(urls::add); + }); + + return urls; + } + + private List processUrls(JsonObject base, String key) { + List urls = new ArrayList<>(); + + GsonUtil.findObj(base, key).ifPresent(cfg -> { + log.info("Found data"); + + GsonUtil.findArray(cfg, "base_urls").ifPresent(arr -> { + log.info("Found base URL(s)"); + urls.addAll(getUrls(arr)); + }); + + if (urls.isEmpty()) { + GsonUtil.findString(cfg, "base_url").flatMap(this::getUrl).ifPresent(urls::add); + } + }); + + return urls; + } + + private void process() { + log.info("Processing Homeserver Base URLs"); + hsBaseUrls = processUrls(raw, "m.homeserver"); + log.info("Found {} valid URL(s)", hsBaseUrls.size()); + + log.info("Processing Identity server Base URLs"); + isBaseUrls = processUrls(raw, "m.identity_server"); + log.info("Found {} valid URL(s)", isBaseUrls.size()); + } + + @Override + public JsonObject getRaw() { + return raw; + } + + @Override + public List getHsBaseUrls() { + return Collections.unmodifiableList(hsBaseUrls); + } + + @Override + public List getIsBaseUrls() { + return Collections.unmodifiableList(isBaseUrls); + } + +} diff --git a/src/main/java/io/kamax/matrix/client/_AutoDiscoverySettings.java b/src/main/java/io/kamax/matrix/client/_AutoDiscoverySettings.java new file mode 100644 index 0000000..20c53ee --- /dev/null +++ b/src/main/java/io/kamax/matrix/client/_AutoDiscoverySettings.java @@ -0,0 +1,36 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2018 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.client; + +import com.google.gson.JsonObject; + +import java.net.URL; +import java.util.List; + +public interface _AutoDiscoverySettings { + + JsonObject getRaw(); + + List getHsBaseUrls(); + + List getIsBaseUrls(); + +} diff --git a/src/main/java/io/kamax/matrix/client/_MatrixClient.java b/src/main/java/io/kamax/matrix/client/_MatrixClient.java new file mode 100644 index 0000000..80f7930 --- /dev/null +++ b/src/main/java/io/kamax/matrix/client/_MatrixClient.java @@ -0,0 +1,54 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.client; + +import io.kamax.matrix._MatrixID; +import io.kamax.matrix._MatrixUser; +import io.kamax.matrix.hs._MatrixRoom; +import io.kamax.matrix.room.RoomAlias; +import io.kamax.matrix.room._RoomAliasLookup; +import io.kamax.matrix.room._RoomCreationOptions; + +import java.util.Optional; + +public interface _MatrixClient extends _MatrixClientRaw { + + void setDisplayName(String name); + + _RoomAliasLookup lookup(RoomAlias alias); + + _MatrixRoom createRoom(_RoomCreationOptions options); + + _MatrixRoom getRoom(String roomId); + + _MatrixRoom joinRoom(String roomIdOrAlias); + + _MatrixUser getUser(_MatrixID mxId); + + Optional getDeviceId(); + + void login(MatrixPasswordLoginCredentials credentials); + + void logout(); + + _SyncData sync(_SyncOptions options); + +} diff --git a/src/main/java/io/kamax/matrix/client/_MatrixClientRaw.java b/src/main/java/io/kamax/matrix/client/_MatrixClientRaw.java new file mode 100644 index 0000000..a4ac7b7 --- /dev/null +++ b/src/main/java/io/kamax/matrix/client/_MatrixClientRaw.java @@ -0,0 +1,51 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.client; + +import io.kamax.matrix._MatrixID; +import io.kamax.matrix.hs._MatrixHomeserver; + +import java.util.List; +import java.util.Optional; + +public interface _MatrixClientRaw { + + MatrixClientContext getContext(); + + _MatrixHomeserver getHomeserver(); + + Optional getAccessToken(); + + Optional<_MatrixID> getUser(); + + Optional<_AutoDiscoverySettings> discoverSettings(); + + // FIXME + // we should maybe have a dedicated object for HS related items and be merged into getHomeserver() which is only + // holding state at this point and is not functional + List getHomeApiVersions(); + + // FIXME + // we should maybe have a dedicated object for IS related items. Will reconsider when implementing + // other part of the IS API + boolean validateIsBaseUrl(); + +} diff --git a/src/main/java/io/kamax/matrix/client/_Presence.java b/src/main/java/io/kamax/matrix/client/_Presence.java new file mode 100644 index 0000000..819ef5c --- /dev/null +++ b/src/main/java/io/kamax/matrix/client/_Presence.java @@ -0,0 +1,31 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2018 Kamax Sàrl + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.client; + +import java.time.Instant; + +public interface _Presence { + + String getStatus(); + + Instant getLastActive(); + +} diff --git a/src/main/java/io/kamax/matrix/client/_SyncData.java b/src/main/java/io/kamax/matrix/client/_SyncData.java new file mode 100644 index 0000000..5d83eef --- /dev/null +++ b/src/main/java/io/kamax/matrix/client/_SyncData.java @@ -0,0 +1,185 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2018 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.client; + +import com.google.gson.JsonObject; + +import io.kamax.matrix.event._MatrixEvent; +import io.kamax.matrix.event._MatrixStateEvent; + +import java.util.List; +import java.util.Set; + +/** + * Representation of the data when performing a sync call on the Matrix Client API. + */ +public interface _SyncData { + + interface State { + + /** + * The state of the room. + * + * @return a list of state events. + */ + List<_MatrixStateEvent> getEvents(); + + } + + interface Timeline { + + /** + * Events that happened in the sync window. + * + * @return List of events. + */ + List<_MatrixEvent> getEvents(); + + /** + * If the number of events returned was limited by the sync filter. + * + * @return true if the number of events was limited, false if not. + */ + boolean isLimited(); + + /** + * Token that can be supplied to fetch previous events for the associated room. + * + * @return the token. + */ + String getPreviousBatchToken(); + } + + interface InvitedRoom { + + /** + * The ID of the room the user was invited to. + * + * @return the room ID. + */ + String getId(); + + /** + * The state of the room at the invite event. + * + * @return a list of state events. + */ + State getState(); + + } + + interface JoinedRoom { + + /** + * The ID of the room the user is joined to. + * + * @return the room id. + */ + String getId(); + + /** + * State changes prior the start of the timeline. + * + * @return a list of state events. + */ + State getState(); + + /** + * The room timeline for this sync batch. + * + * @return the timeline. + */ + Timeline getTimeline(); + + } + + interface LeftRoom { + + /** + * The ID of the room the user is joined to. + * + * @return the room id. + */ + String getId(); + + /** + * State changes prior the start of the timeline. + * + * @return a list of state events. + */ + State getState(); + + /** + * The room timeline up to the leave event. + * + * @return the timeline. + */ + Timeline getTimeline(); + + } + + interface Rooms { + + /** + * Rooms the user was invited to within this sync window. + * + * @return Set of InvitedRoom objects. + */ + Set getInvited(); + + /** + * Rooms the user was joined in within this sync window. + * + * @return Set of JoinedRoom objects. + */ + Set getJoined(); + + /** + * Rooms the user left from within this sync window. + * + * @return Set of LeftRoom objects. + */ + Set getLeft(); + + } + + /** + * The batch token to supply in the next sync call. + * + * @return the batch token. + */ + String nextBatchToken(); + + /** + * Update to the rooms. + * + * @return rooms object. + */ + Rooms getRooms(); + + /** + * The raw JSON data for this object. + * + * @return the JSON data. + */ + JsonObject getJson(); + +} diff --git a/src/main/java/io/kamax/matrix/client/_SyncOptions.java b/src/main/java/io/kamax/matrix/client/_SyncOptions.java new file mode 100644 index 0000000..1ac4f9c --- /dev/null +++ b/src/main/java/io/kamax/matrix/client/_SyncOptions.java @@ -0,0 +1,65 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2018 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.client; + +import java.util.Optional; + +/** + * Possible options that can be passed to the sync call. + */ +public interface _SyncOptions { + + /** + * The point of time to continue the sync from. + * + * @return A token that was provided in a previous sync call, if set. + */ + Optional getSince(); + + /** + * The filter to use for the sync. + * + * @return The ID or raw JSON filter, if set. + */ + Optional getFilter(); + + /** + * If the full state should be included in the sync. + * + * @return The full state option, if set. + */ + Optional withFullState(); + + /** + * If the client should automatically be marked as online. + * + * @return The set presence option, if set. + */ + Optional getSetPresence(); + + /** + * The maximum time to wait, in milliseconds, before ending the sync call. + * + * @return The timeout option, if set. + */ + Optional getTimeout(); + +} diff --git a/src/main/java/io/kamax/matrix/client/as/MatrixApplicationServiceClient.java b/src/main/java/io/kamax/matrix/client/as/MatrixApplicationServiceClient.java new file mode 100644 index 0000000..323359e --- /dev/null +++ b/src/main/java/io/kamax/matrix/client/as/MatrixApplicationServiceClient.java @@ -0,0 +1,64 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.client.as; + +import io.kamax.matrix.client.MatrixClientContext; +import io.kamax.matrix.client._MatrixClient; +import io.kamax.matrix.client.regular.MatrixHttpClient; +import io.kamax.matrix.json.VirtualUserRegistrationBody; + +import org.apache.http.client.methods.HttpPost; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.net.URI; + +public class MatrixApplicationServiceClient extends MatrixHttpClient implements _MatrixApplicationServiceClient { + + private Logger log = LoggerFactory.getLogger(MatrixApplicationServiceClient.class); + + public MatrixApplicationServiceClient(MatrixClientContext context) { + super(context); + } + + private MatrixHttpClient createClient(String localpart) { + MatrixClientContext context = new MatrixClientContext(getContext()).setUserWithLocalpart(localpart) + .setVirtual(true); + return new MatrixHttpClient(context); + } + + @Override + public _MatrixClient createUser(String localpart) { + log.debug("Creating new user {}", localpart); + URI path = getClientPathWithAccessToken("/register"); + HttpPost req = new HttpPost(path); + req.setEntity(getJsonEntity(new VirtualUserRegistrationBody(localpart))); + execute(req); + + return createClient(localpart); + } + + @Override + public _MatrixClient getUser(String localpart) { + return createClient(localpart); + } + +} diff --git a/src/main/java/io/kamax/matrix/client/as/_MatrixApplicationServiceClient.java b/src/main/java/io/kamax/matrix/client/as/_MatrixApplicationServiceClient.java new file mode 100644 index 0000000..9761b4a --- /dev/null +++ b/src/main/java/io/kamax/matrix/client/as/_MatrixApplicationServiceClient.java @@ -0,0 +1,31 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.client.as; + +import io.kamax.matrix.client._MatrixClient; + +public interface _MatrixApplicationServiceClient extends _MatrixClient { + + _MatrixClient createUser(String localpart); + + _MatrixClient getUser(String localpart); + +} diff --git a/src/main/java/io/kamax/matrix/client/regular/MatrixHttpClient.java b/src/main/java/io/kamax/matrix/client/regular/MatrixHttpClient.java new file mode 100644 index 0000000..74d782f --- /dev/null +++ b/src/main/java/io/kamax/matrix/client/regular/MatrixHttpClient.java @@ -0,0 +1,163 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.client.regular; + +import com.google.gson.JsonObject; + +import io.kamax.matrix.MatrixID; +import io.kamax.matrix._MatrixID; +import io.kamax.matrix._MatrixUser; +import io.kamax.matrix.client.*; +import io.kamax.matrix.hs._MatrixRoom; +import io.kamax.matrix.json.*; +import io.kamax.matrix.room.RoomAlias; +import io.kamax.matrix.room.RoomAliasLookup; +import io.kamax.matrix.room._RoomAliasLookup; +import io.kamax.matrix.room._RoomCreationOptions; + +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.client.utils.URIBuilder; + +import java.net.URI; +import java.util.Optional; + +public class MatrixHttpClient extends AMatrixHttpClient implements _MatrixClient { + + public MatrixHttpClient(String domain) { + super(domain); + } + + public MatrixHttpClient(MatrixClientContext context) { + super(context); + } + + protected _MatrixID getMatrixId(String localpart) { + return new MatrixID(localpart, getHomeserver().getDomain()); + } + + @Override + protected URIBuilder getClientPathBuilder(String action) { + URIBuilder builder = super.getClientPathBuilder(action); + context.getUser().ifPresent(user -> builder.setPath(builder.getPath().replace("{userId}", user.getId()))); + return builder; + } + + @Override + public void setDisplayName(String name) { + URI path = getClientPathWithAccessToken("/profile/{userId}/displayname"); + HttpPut req = new HttpPut(path); + req.setEntity(getJsonEntity(new UserDisplaynameSetBody(name))); + execute(req); + } + + @Override + public _RoomAliasLookup lookup(RoomAlias alias) { + URI path = getClientPath("/directory/room/" + alias.getId()); + HttpGet req = new HttpGet(path); + String resBody = execute(req); + RoomAliasLookupJson lookup = GsonUtil.get().fromJson(resBody, RoomAliasLookupJson.class); + return new RoomAliasLookup(lookup.getRoomId(), alias.getId(), lookup.getServers()); + } + + @Override + public _MatrixRoom createRoom(_RoomCreationOptions options) { + URI path = getClientPathWithAccessToken("/createRoom"); + HttpPost req = new HttpPost(path); + req.setEntity(getJsonEntity(new RoomCreationRequestJson(options))); + + String resBody = execute(req); + String roomId = GsonUtil.get().fromJson(resBody, RoomCreationResponseJson.class).getRoomId(); + return getRoom(roomId); + } + + @Override + public _MatrixRoom getRoom(String roomId) { + return new MatrixHttpRoom(getContext(), roomId); + } + + @Override + public _MatrixRoom joinRoom(String roomIdOrAlias) { + URI path = getClientPathWithAccessToken("/join/ " + roomIdOrAlias); + HttpPost req = new HttpPost(path); + req.setEntity(getJsonEntity(new JsonObject())); + + String resBody = execute(req); + String roomId = GsonUtil.get().fromJson(resBody, RoomCreationResponseJson.class).getRoomId(); + return getRoom(roomId); + } + + @Override + public _MatrixUser getUser(_MatrixID mxId) { + return new MatrixHttpUser(getContext(), mxId); + } + + @Override + public Optional getDeviceId() { + return Optional.ofNullable(context.getDeviceId()); + } + + @Override + public void login(MatrixPasswordLoginCredentials credentials) { + HttpPost request = new HttpPost(getClientPath("/login")); + if (getDeviceId().isPresent()) { + request.setEntity(getJsonEntity( + new LoginPostBody(credentials.getLocalPart(), credentials.getPassword(), getDeviceId().get()))); + } else { + request.setEntity(getJsonEntity(new LoginPostBody(credentials.getLocalPart(), credentials.getPassword()))); + } + + String body = execute(request); + LoginResponse response = gson.fromJson(body, LoginResponse.class); + context.setToken(response.getAccessToken()); + context.setDeviceId(response.getDeviceId()); + context.setUser(new MatrixID(response.getUserId())); + + // FIXME spec returns hostname which we might not be the same as what has been used in baseUrl to login. Must + // update internals accordingly + } + + @Override + public void logout() { + URI path = getClientPathWithAccessToken("/logout"); + HttpPost req = new HttpPost(path); + execute(req); + context.setToken(null); + context.setUser(null); + context.setDeviceId(null); + } + + @Override + public _SyncData sync(_SyncOptions options) { + URIBuilder path = getClientPathBuilder("/sync"); + + path.addParameter("timeout", options.getTimeout().map(Long::intValue).orElse(30000).toString()); + options.getSince().ifPresent(since -> path.addParameter("since", since)); + options.getFilter().ifPresent(filter -> path.addParameter("filter", filter)); + options.withFullState().ifPresent(state -> path.addParameter("full_state", state ? "true" : "false")); + options.getSetPresence().ifPresent(presence -> path.addParameter("presence", presence)); + + String body = execute(new HttpGet(getWithAccessToken(path))); + return new SyncDataJson(GsonUtil.parseObj(body)); + } + +} diff --git a/src/main/java/io/kamax/matrix/client/regular/Presence.java b/src/main/java/io/kamax/matrix/client/regular/Presence.java new file mode 100644 index 0000000..efc2c19 --- /dev/null +++ b/src/main/java/io/kamax/matrix/client/regular/Presence.java @@ -0,0 +1,50 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2018 Kamax Sàrl + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.client.regular; + +import com.google.gson.JsonObject; + +import io.kamax.matrix.client._Presence; +import io.kamax.matrix.json.GsonUtil; + +import java.time.Instant; + +public class Presence implements _Presence { + + private String status; + private Instant lastActive; + + public Presence(JsonObject json) { + this.status = GsonUtil.getStringOrThrow(json, "presence"); + this.lastActive = Instant.ofEpochMilli(GsonUtil.getLong(json, "last_active_ago")); + } + + @Override + public String getStatus() { + return status; + } + + @Override + public Instant getLastActive() { + return lastActive; + } + +} diff --git a/src/main/java/io/kamax/matrix/client/regular/SyncDataJson.java b/src/main/java/io/kamax/matrix/client/regular/SyncDataJson.java new file mode 100644 index 0000000..3a52ae2 --- /dev/null +++ b/src/main/java/io/kamax/matrix/client/regular/SyncDataJson.java @@ -0,0 +1,264 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2018 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.client.regular; + +import com.google.gson.JsonObject; + +import io.kamax.matrix.MatrixID; +import io.kamax.matrix._MatrixID; +import io.kamax.matrix.client._SyncData; +import io.kamax.matrix.event.EventKey; +import io.kamax.matrix.event._MatrixEvent; +import io.kamax.matrix.event._MatrixStateEvent; +import io.kamax.matrix.json.MatrixJsonObject; + +import java.time.Instant; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class SyncDataJson extends MatrixJsonObject implements _SyncData { + + public class MatrixEventJson extends MatrixJsonObject implements _MatrixEvent { + + public MatrixEventJson(JsonObject obj) { + super(obj); + } + + @Override + public String getId() { + return findString(EventKey.Id.get()).orElse(""); // FIXME refactor event structure + } + + @Override + public String getType() { + return getString(EventKey.Type.get()); + } + + @Override + public Instant getTime() { + return Instant.ofEpochMilli(getLong(EventKey.Timestamp.get())); + } + + @Override + public _MatrixID getSender() { + return MatrixID.from(getString(EventKey.Sender.get())).acceptable(); + } + } + + public class MatrixStateEventJson extends MatrixEventJson implements _MatrixStateEvent { + + public MatrixStateEventJson(JsonObject obj) { + super(obj); + } + + @Override + public String getStateKey() { + return getString(EventKey.StateKey.get()); + } + + } + + public class StateJson extends MatrixJsonObject implements _SyncData.State { + + private List<_MatrixStateEvent> events = new ArrayList<>(); + + public StateJson(JsonObject obj) { + super(obj); + + findArray("events").ifPresent(array -> array.forEach(el -> { + events.add(new MatrixStateEventJson(asObj(el))); + })); + } + + @Override + public List<_MatrixStateEvent> getEvents() { + return events; + } + } + + public class TimelineJson extends MatrixJsonObject implements _SyncData.Timeline { + + private List<_MatrixEvent> events = new ArrayList<>(); + + public TimelineJson(JsonObject obj) { + super(obj); + + findArray("events").ifPresent(array -> array.forEach(el -> { + events.add(new MatrixEventJson(asObj(el))); + })); + } + + @Override + public List<_MatrixEvent> getEvents() { + return events; + } + + @Override + public boolean isLimited() { + return findString("limited").map("true"::equals).orElse(false); + } + + @Override + public String getPreviousBatchToken() { + return getString("prev_batch"); + } + } + + public class InvitedRoomJson extends MatrixJsonObject implements _SyncData.InvitedRoom { + + private String id; + private State state; + + public InvitedRoomJson(String id, JsonObject data) { + super(data); + this.id = id; + this.state = new StateJson(findObj("state").orElseGet(JsonObject::new)); + } + + @Override + public String getId() { + return id; + } + + @Override + public State getState() { + return state; + } + } + + public class JoinedRoomJson extends MatrixJsonObject implements _SyncData.JoinedRoom { + + private String id; + private State state; + private Timeline timeline; + + public JoinedRoomJson(String id, JsonObject data) { + super(data); + this.id = id; + this.state = new StateJson(findObj("state").orElseGet(JsonObject::new)); + this.timeline = new TimelineJson(findObj("timeline").orElseGet(JsonObject::new)); + } + + @Override + public String getId() { + return id; + } + + @Override + public State getState() { + return state; + } + + @Override + public Timeline getTimeline() { + return timeline; + } + } + + public class LeftRoomJson extends MatrixJsonObject implements _SyncData.LeftRoom { + + private String id; + private State state; + private Timeline timeline; + + public LeftRoomJson(String id, JsonObject data) { + super(data); + this.id = id; + this.state = new StateJson(findObj("state").orElseGet(JsonObject::new)); + this.timeline = new TimelineJson(findObj("timeline").orElseGet(JsonObject::new)); + } + + @Override + public String getId() { + return id; + } + + @Override + public State getState() { + return state; + } + + @Override + public Timeline getTimeline() { + return timeline; + } + } + + public class RoomsJson extends MatrixJsonObject implements _SyncData.Rooms { + + private Set invited = new HashSet<>(); + private Set joined = new HashSet<>(); + private Set left = new HashSet<>(); + + public RoomsJson(JsonObject obj) { + super(obj); + findObj("invite").ifPresent(o -> o.entrySet().forEach(entry -> { + invited.add(new InvitedRoomJson(entry.getKey(), asObj(entry.getValue()))); + })); + + findObj("join").ifPresent(o -> o.entrySet().forEach(entry -> { + joined.add(new JoinedRoomJson(entry.getKey(), asObj(entry.getValue()))); + })); + + findObj("leave").ifPresent(o -> o.entrySet().forEach(entry -> { + left.add(new LeftRoomJson(entry.getKey(), asObj(entry.getValue()))); + })); + } + + @Override + public Set getInvited() { + return invited; + } + + @Override + public Set getJoined() { + return joined; + } + + @Override + public Set getLeft() { + return left; + } + + } + + private String nextBatch; + private RoomsJson rooms; + + public SyncDataJson(JsonObject data) { + super(data); + nextBatch = getString("next_batch"); + rooms = new RoomsJson(findObj("rooms").orElseGet(JsonObject::new)); + } + + @Override + public String nextBatchToken() { + return nextBatch; + } + + @Override + public Rooms getRooms() { + return rooms; + } + +} diff --git a/src/main/java/io/kamax/matrix/client/regular/SyncOptions.java b/src/main/java/io/kamax/matrix/client/regular/SyncOptions.java new file mode 100644 index 0000000..582820d --- /dev/null +++ b/src/main/java/io/kamax/matrix/client/regular/SyncOptions.java @@ -0,0 +1,103 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2018 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.client.regular; + +import io.kamax.matrix.client._SyncOptions; + +import java.util.Optional; + +public class SyncOptions implements _SyncOptions { + + public static class Builder { + + private final SyncOptions obj; + + public Builder() { + this.obj = new SyncOptions(); + } + + public SyncOptions get() { + return obj; + } + + public Builder setSince(String since) { + obj.since = since; + return this; + } + + public Builder setFilter(String filter) { + obj.filter = filter; + return this; + } + + public Builder setWithFullState(boolean withFullState) { + obj.fullState = withFullState; + return this; + } + + public Builder setPresence(boolean setPresence) { + obj.setPresence = setPresence ? null : "offline"; + return this; + } + + public Builder setTimeout(long timeout) { + obj.timeout = timeout; + return this; + } + + } + + public static Builder build() { + return new Builder(); + } + + private String since; + private String filter; + private Boolean fullState; + private String setPresence; + private Long timeout; + + @Override + public Optional getSince() { + return Optional.ofNullable(since); + } + + @Override + public Optional getFilter() { + return Optional.ofNullable(filter); + } + + @Override + public Optional withFullState() { + return Optional.ofNullable(fullState); + } + + @Override + public Optional getSetPresence() { + return Optional.ofNullable(setPresence); + } + + @Override + public Optional getTimeout() { + return Optional.ofNullable(timeout); + } + +} diff --git a/src/main/java/io/kamax/matrix/codec/MxBase64.java b/src/main/java/io/kamax/matrix/codec/MxBase64.java new file mode 100644 index 0000000..cd34d63 --- /dev/null +++ b/src/main/java/io/kamax/matrix/codec/MxBase64.java @@ -0,0 +1,36 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.codec; + +import java.nio.charset.StandardCharsets; +import java.util.Base64; + +public class MxBase64 { + + public static String encode(byte[] data) { + return Base64.getEncoder().withoutPadding().encodeToString(data); + } + + public static String encode(String data) { + return encode(data.getBytes(StandardCharsets.UTF_8)); + } + +} diff --git a/src/main/java/io/kamax/matrix/codec/MxSha256.java b/src/main/java/io/kamax/matrix/codec/MxSha256.java new file mode 100644 index 0000000..d025025 --- /dev/null +++ b/src/main/java/io/kamax/matrix/codec/MxSha256.java @@ -0,0 +1,47 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.codec; + +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +public class MxSha256 { + + private MessageDigest md; + + public MxSha256() { + try { + md = MessageDigest.getInstance("SHA-256"); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + } + + public String hash(byte[] data) { + return MxBase64.encode(md.digest(data)); + } + + public String hash(String data) { + return hash(data.getBytes(StandardCharsets.UTF_8)); + } + +} diff --git a/src/main/java/io/kamax/matrix/event/EventKey.java b/src/main/java/io/kamax/matrix/event/EventKey.java new file mode 100644 index 0000000..2c5cbd9 --- /dev/null +++ b/src/main/java/io/kamax/matrix/event/EventKey.java @@ -0,0 +1,88 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2018 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.event; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +import io.kamax.matrix.MalformedEventException; +import io.kamax.matrix.json.GsonUtil; + +import java.util.Optional; + +public enum EventKey { + + AuthEvents("auth_events"), + Content("content"), + Depth("depth"), + Hashes("hashes"), + Id("event_id"), + Origin("origin"), + Timestamp("origin_server_ts"), + PreviousEvents("prev_events"), + PreviousState("prev_state"), + RoomId("room_id"), + Sender("sender"), + Signatures("signatures"), + StateKey("state_key"), + Type("type"), + Membership("membership"), + Unsigned("unsigned"); + + private String key; + + EventKey(String key) { + this.key = key; + } + + public String get() { + return key; + } + + public JsonObject getObj(JsonObject o) { + return findObj(o).orElseThrow(() -> new MalformedEventException(key)); + } + + public JsonElement getElement(JsonObject o) { + return GsonUtil.findElement(o, key).orElseThrow(() -> new MalformedEventException(key)); + } + + public Optional findObj(JsonObject o) { + return GsonUtil.findObj(o, key); + } + + public Optional findString(JsonObject o) { + return GsonUtil.findString(o, key); + } + + public String getString(JsonObject o) { + return findString(o).orElseThrow(() -> new MalformedEventException(key)); + } + + public String getStringOrNull(JsonObject o) { + return GsonUtil.getStringOrNull(o, key); + } + + public long getLong(JsonObject o) { + return GsonUtil.getLong(o, key); + } + +} diff --git a/src/main/java/io/kamax/matrix/event/_MatrixEvent.java b/src/main/java/io/kamax/matrix/event/_MatrixEvent.java new file mode 100644 index 0000000..529fd14 --- /dev/null +++ b/src/main/java/io/kamax/matrix/event/_MatrixEvent.java @@ -0,0 +1,41 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.event; + +import com.google.gson.JsonObject; + +import io.kamax.matrix._MatrixID; + +import java.time.Instant; + +public interface _MatrixEvent { + + String getId(); + + String getType(); + + Instant getTime(); + + _MatrixID getSender(); + + JsonObject getJson(); + +} diff --git a/src/main/java/io/kamax/matrix/event/_MatrixStateEvent.java b/src/main/java/io/kamax/matrix/event/_MatrixStateEvent.java new file mode 100644 index 0000000..8e69f63 --- /dev/null +++ b/src/main/java/io/kamax/matrix/event/_MatrixStateEvent.java @@ -0,0 +1,27 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2018 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.event; + +public interface _MatrixStateEvent extends _MatrixEvent { + + String getStateKey(); + +} diff --git a/src/main/java/io/kamax/matrix/event/_RoomEvent.java b/src/main/java/io/kamax/matrix/event/_RoomEvent.java new file mode 100644 index 0000000..bace02c --- /dev/null +++ b/src/main/java/io/kamax/matrix/event/_RoomEvent.java @@ -0,0 +1,27 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.event; + +public interface _RoomEvent extends _MatrixEvent { + + String getRoomId(); + +} diff --git a/src/main/java/io/kamax/matrix/event/_RoomMembershipEvent.java b/src/main/java/io/kamax/matrix/event/_RoomMembershipEvent.java new file mode 100644 index 0000000..5e7f20a --- /dev/null +++ b/src/main/java/io/kamax/matrix/event/_RoomMembershipEvent.java @@ -0,0 +1,37 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.event; + +import io.kamax.matrix._MatrixID; + +import java.util.Optional; + +public interface _RoomMembershipEvent extends _RoomEvent { + + String getMembership(); + + Optional getAvatarUrl(); + + Optional getDisplayName(); + + _MatrixID getInvitee(); + +} diff --git a/src/main/java/io/kamax/matrix/event/_RoomMessageEvent.java b/src/main/java/io/kamax/matrix/event/_RoomMessageEvent.java new file mode 100644 index 0000000..510ef96 --- /dev/null +++ b/src/main/java/io/kamax/matrix/event/_RoomMessageEvent.java @@ -0,0 +1,35 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.event; + +import java.util.Optional; + +public interface _RoomMessageEvent extends _RoomEvent { + + String getBody(); + + String getBodyType(); + + Optional getFormat(); + + Optional getFormattedBody(); + +} diff --git a/src/main/java/io/kamax/matrix/hs/MatrixHomeserver.java b/src/main/java/io/kamax/matrix/hs/MatrixHomeserver.java new file mode 100644 index 0000000..b3f2273 --- /dev/null +++ b/src/main/java/io/kamax/matrix/hs/MatrixHomeserver.java @@ -0,0 +1,66 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.hs; + +import org.apache.http.client.utils.URIBuilder; + +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; + +public class MatrixHomeserver implements _MatrixHomeserver { + + private String domain; + private URL base; + + private static URL getURL(String url) { + try { + return new URL(url); + } catch (MalformedURLException e) { + throw new IllegalArgumentException(e); + } + } + + public MatrixHomeserver(String domain, URL baseUrl) { + this.domain = domain; + this.base = baseUrl; + } + + public MatrixHomeserver(String domain, String baseUrl) { + this(domain, getURL(baseUrl)); + } + + @Override + public String getDomain() { + return domain; + } + + @Override + public URL getBaseEndpoint() { + return base; + } + + @Override + public URIBuilder getBaseEndpointBuilder() { + return new URIBuilder(URI.create(base.toString())); + } + +} diff --git a/src/main/java/io/kamax/matrix/hs/RoomMembership.java b/src/main/java/io/kamax/matrix/hs/RoomMembership.java new file mode 100644 index 0000000..ddab147 --- /dev/null +++ b/src/main/java/io/kamax/matrix/hs/RoomMembership.java @@ -0,0 +1,45 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.hs; + +public enum RoomMembership { + + Invite("invite"), + Join("join"), + Leave("leave"), + Ban("ban"), + Knock("knock"); + + private String id; + + RoomMembership(String id) { + this.id = id; + } + + public String get() { + return id; + } + + public boolean is(String id) { + return this.id.contentEquals(id); + } + +} diff --git a/src/main/java/io/kamax/matrix/hs/_MatrixHomeserver.java b/src/main/java/io/kamax/matrix/hs/_MatrixHomeserver.java new file mode 100644 index 0000000..30435c2 --- /dev/null +++ b/src/main/java/io/kamax/matrix/hs/_MatrixHomeserver.java @@ -0,0 +1,35 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.hs; + +import org.apache.http.client.utils.URIBuilder; + +import java.net.URL; + +public interface _MatrixHomeserver { + + String getDomain(); + + URL getBaseEndpoint(); + + URIBuilder getBaseEndpointBuilder(); + +} diff --git a/src/main/java/io/kamax/matrix/hs/_MatrixRoom.java b/src/main/java/io/kamax/matrix/hs/_MatrixRoom.java new file mode 100644 index 0000000..25ba012 --- /dev/null +++ b/src/main/java/io/kamax/matrix/hs/_MatrixRoom.java @@ -0,0 +1,58 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.hs; + +import io.kamax.matrix._MatrixID; +import io.kamax.matrix.room._MatrixRoomMessageChunk; +import io.kamax.matrix.room._MatrixRoomMessageChunkOptions; + +import java.util.List; +import java.util.Optional; + +public interface _MatrixRoom { + + _MatrixHomeserver getHomeserver(); + + String getAddress(); + + Optional getName(); + + Optional getTopic(); + + void join(); + + void leave(); + + void sendText(String message); + + void sendFormattedText(String formatted, String rawFallback); + + void sendNotice(String message); + + void sendNotice(String formatted, String plain); + + void invite(_MatrixID mxId); + + List<_MatrixID> getJoinedUsers(); + + _MatrixRoomMessageChunk getMessages(_MatrixRoomMessageChunkOptions options); + +} diff --git a/src/main/java/io/kamax/matrix/is/_IdentityServer.java b/src/main/java/io/kamax/matrix/is/_IdentityServer.java new file mode 100644 index 0000000..428bed9 --- /dev/null +++ b/src/main/java/io/kamax/matrix/is/_IdentityServer.java @@ -0,0 +1,35 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.is; + +import io.kamax.matrix._ThreePid; +import io.kamax.matrix._ThreePidMapping; + +import java.util.List; +import java.util.Optional; + +public interface _IdentityServer { + + Optional<_ThreePidMapping> find(_ThreePid threePid); + + List<_ThreePidMapping> find(List<_ThreePid> threePidList); + +} diff --git a/src/main/java/io/kamax/matrix/json/GsonUtil.java b/src/main/java/io/kamax/matrix/json/GsonUtil.java new file mode 100644 index 0000000..72d0b2c --- /dev/null +++ b/src/main/java/io/kamax/matrix/json/GsonUtil.java @@ -0,0 +1,179 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2018 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.json; + +import com.google.gson.*; + +import java.util.*; +import java.util.stream.Collectors; + +public class GsonUtil { + + private static Gson instance = build(); + private static Gson instancePretty = buildPretty(); + + private static GsonBuilder buildImpl() { + return new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) + .disableHtmlEscaping(); + } + + public static Gson buildPretty() { + return buildImpl().setPrettyPrinting().create(); + } + + public static Gson build() { + return buildImpl().create(); + } + + public static JsonArray asArray(List elements) { + JsonArray a = new JsonArray(); + elements.forEach(a::add); + return a; + } + + public static JsonArray asArrayObj(List elements) { + return asArray(elements.stream().map(e -> get().toJsonTree(e)).collect(Collectors.toList())); + } + + public static JsonArray asArray(String... elements) { + return asArray(Arrays.stream(elements).map(JsonPrimitive::new).collect(Collectors.toList())); + } + + public static JsonArray asArray(Collection elements) { + JsonArray a = new JsonArray(); + elements.forEach(a::add); + return a; + } + + public static List asList(JsonArray a, Class c) { + List l = new ArrayList<>(); + a.forEach(v -> l.add(GsonUtil.get().fromJson(v, c))); + return l; + } + + public static List asList(JsonObject obj, String member, Class c) { + return asList(getArray(obj, member), c); + } + + public static JsonObject makeObj(Object o) { + return instance.toJsonTree(o).getAsJsonObject(); + } + + public static JsonObject makeObj(String key, Object value) { + return makeObj(key, instance.toJsonTree(value)); + } + + public static JsonObject makeObj(String key, JsonElement el) { + JsonObject obj = new JsonObject(); + obj.add(key, el); + return obj; + } + + public static Gson get() { + return instance; + } + + public static Gson getPretty() { + return instancePretty; + } + + public static String getPrettyForLog(Object o) { + return System.lineSeparator() + getPretty().toJson(o); + } + + public static JsonElement parse(String s) { + try { + return new JsonParser().parse(s); + } catch (JsonParseException e) { + throw new InvalidJsonException(e); + } + } + + public static JsonObject parseObj(String s) { + try { + return parse(s).getAsJsonObject(); + } catch (IllegalStateException e) { + throw new InvalidJsonException("Not an object"); + } + } + + public static JsonArray getArray(JsonObject obj, String member) { + return findArray(obj, member).orElseThrow(() -> new InvalidJsonException("Not an array")); + } + + public static JsonObject getObj(JsonObject obj, String member) { + return findObj(obj, member).orElseThrow(() -> new InvalidJsonException("No object for member " + member)); + } + + public static Optional findString(JsonObject o, String key) { + return findPrimitive(o, key).map(JsonPrimitive::getAsString); + } + + public static String getStringOrNull(JsonObject o, String key) { + JsonElement el = o.get(key); + if (el != null && el.isJsonPrimitive()) { + return el.getAsString(); + } else { + return null; + } + } + + public static String getStringOrThrow(JsonObject obj, String member) { + if (!obj.has(member)) { + throw new InvalidJsonException(member + " key is missing"); + } + + return obj.get(member).getAsString(); + } + + public static Optional findElement(JsonObject o, String key) { + return Optional.ofNullable(o.get(key)); + } + + public static Optional findPrimitive(JsonObject o, String key) { + return findElement(o, key).map(el -> el.isJsonPrimitive() ? el.getAsJsonPrimitive() : null); + } + + public static JsonPrimitive getPrimitive(JsonObject o, String key) { + return findPrimitive(o, key).orElseThrow(() -> new InvalidJsonException("No primitive value for key " + key)); + } + + public static Optional findLong(JsonObject o, String key) { + return findPrimitive(o, key).map(JsonPrimitive::getAsLong); + } + + public static long getLong(JsonObject o, String key) { + return findLong(o, key).orElseThrow(() -> new InvalidJsonException("No numeric value for key " + key)); + } + + public static Optional findObj(JsonObject o, String key) { + if (!o.has(key)) { + return Optional.empty(); + } + + return Optional.ofNullable(o.getAsJsonObject(key)); + } + + public static Optional findArray(JsonObject o, String key) { + return findElement(o, key).filter(JsonElement::isJsonArray).map(JsonElement::getAsJsonArray); + } + +} diff --git a/src/main/java/io/kamax/matrix/json/InvalidJsonException.java b/src/main/java/io/kamax/matrix/json/InvalidJsonException.java new file mode 100644 index 0000000..61d507d --- /dev/null +++ b/src/main/java/io/kamax/matrix/json/InvalidJsonException.java @@ -0,0 +1,35 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2018 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.json; + +import io.kamax.matrix.MatrixException; + +public class InvalidJsonException extends MatrixException { + + public InvalidJsonException(Throwable t) { + super("M_BAD_JSON", t.getMessage(), t); + } + + public InvalidJsonException(String error) { + super("M_BAD_JSON", error); + } + +} diff --git a/src/main/java/io/kamax/matrix/json/JsonCanonicalException.java b/src/main/java/io/kamax/matrix/json/JsonCanonicalException.java new file mode 100644 index 0000000..033aaba --- /dev/null +++ b/src/main/java/io/kamax/matrix/json/JsonCanonicalException.java @@ -0,0 +1,33 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.json; + +public class JsonCanonicalException extends RuntimeException { + + public JsonCanonicalException(String message) { + super(message); + } + + public JsonCanonicalException(Throwable t) { + super(t); + } + +} diff --git a/src/main/java/io/kamax/matrix/json/LoginPostBody.java b/src/main/java/io/kamax/matrix/json/LoginPostBody.java new file mode 100644 index 0000000..5707290 --- /dev/null +++ b/src/main/java/io/kamax/matrix/json/LoginPostBody.java @@ -0,0 +1,38 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Arne Augenstein + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.json; + +public class LoginPostBody { + private String type = "m.login.password"; + private String user; + private String password; + private String device_id; + + public LoginPostBody(String user, String password) { + this.user = user; + this.password = password; + } + + public LoginPostBody(String user, String password, String device_id) { + this(user, password); + this.device_id = device_id; + } +} diff --git a/src/main/java/io/kamax/matrix/json/LoginResponse.java b/src/main/java/io/kamax/matrix/json/LoginResponse.java new file mode 100644 index 0000000..5ac958c --- /dev/null +++ b/src/main/java/io/kamax/matrix/json/LoginResponse.java @@ -0,0 +1,45 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Arne Augenstein + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.json; + +public class LoginResponse { + + private String access_token; + private String home_server; + private String user_id; + private String device_id; + + public String getAccessToken() { + return access_token; + } + + public String getHomeServer() { + return home_server; + } + + public String getUserId() { + return user_id; + } + + public String getDeviceId() { + return device_id; + } +} diff --git a/src/main/java/io/kamax/matrix/json/MatrixJson.java b/src/main/java/io/kamax/matrix/json/MatrixJson.java new file mode 100644 index 0000000..86637a9 --- /dev/null +++ b/src/main/java/io/kamax/matrix/json/MatrixJson.java @@ -0,0 +1,115 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.json; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.google.gson.stream.JsonWriter; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.nio.charset.StandardCharsets; +import java.util.Comparator; +import java.util.Map; + +public class MatrixJson { + + // Needed to avoid silly try/catch block in lambdas + // We only use ByteArray streams, so IOException will not happen (unless irrecoverable situation like OOM) + private static class JsonWriterUnchecked extends JsonWriter { + + public JsonWriterUnchecked(Writer out) { + super(out); + } + + @Override + public JsonWriter name(String value) { + try { + return super.name(value); + } catch (IOException e) { + throw new JsonCanonicalException(e); + } + } + } + + private static JsonParser parser = new JsonParser(); + + private static void encodeCanonical(JsonObject el, JsonWriterUnchecked writer) throws IOException { + writer.beginObject(); + el.entrySet().stream().sorted(Comparator.comparing(Map.Entry::getKey)).forEachOrdered(entry -> { + writer.name(entry.getKey()); + encodeCanonicalElement(entry.getValue(), writer); + }); + writer.endObject(); + } + + private static void encodeCanonicalArray(JsonArray array, JsonWriterUnchecked writer) throws IOException { + writer.beginArray(); + array.forEach(el -> encodeCanonicalElement(el, writer)); + writer.endArray(); + } + + private static void encodeCanonicalElement(JsonElement el, JsonWriterUnchecked writer) { + try { + if (el.isJsonObject()) encodeCanonical(el.getAsJsonObject(), writer); + else if (el.isJsonPrimitive()) writer.jsonValue(el.toString()); + else if (el.isJsonArray()) encodeCanonicalArray(el.getAsJsonArray(), writer); + else if (el.isJsonNull()) writer.nullValue(); + else throw new JsonCanonicalException("Unexpected JSON type, this is a bug, report!"); + } catch (IOException e) { + throw new JsonCanonicalException(e); + } + } + + public static String encodeCanonical(JsonObject obj) { + try { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + JsonWriterUnchecked writer = new JsonWriterUnchecked(new OutputStreamWriter(out, StandardCharsets.UTF_8)); + writer.setIndent(""); + writer.setHtmlSafe(false); + writer.setLenient(false); + + encodeCanonical(obj, writer); + writer.close(); + return out.toString(StandardCharsets.UTF_8.name()); + } catch (IOException e) { + throw new JsonCanonicalException(e); + } + } + + public static String encodeCanonical(String data) { + JsonElement el = parser.parse(data); + if (!el.isJsonObject()) { + /* + * TODO seems implied because of how signing/checking signatures is done and because of + * https://matrix.to/#/!XqBunHwQIXUiqCaoxq:matrix.org/$15075894901530229RWcIi:matrix.org + * with the "whole object". + */ + throw new JsonCanonicalException("Not a JSON object, cannot encode canonical"); + } + return encodeCanonical(el.getAsJsonObject()); + } + +} diff --git a/src/main/java/io/kamax/matrix/json/MatrixJsonEventFactory.java b/src/main/java/io/kamax/matrix/json/MatrixJsonEventFactory.java new file mode 100644 index 0000000..08f8026 --- /dev/null +++ b/src/main/java/io/kamax/matrix/json/MatrixJsonEventFactory.java @@ -0,0 +1,44 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.json; + +import com.google.gson.JsonObject; + +import io.kamax.matrix.event._MatrixEvent; +import io.kamax.matrix.json.event.MatrixJsonEvent; +import io.kamax.matrix.json.event.MatrixJsonRoomMembershipEvent; +import io.kamax.matrix.json.event.MatrixJsonRoomMessageEvent; + +public class MatrixJsonEventFactory { + + public static _MatrixEvent get(JsonObject obj) { + String type = obj.get("type").getAsString(); + + if ("m.room.member".contentEquals(type)) { + return new MatrixJsonRoomMembershipEvent(obj); + } else if ("m.room.message".contentEquals(type)) { + return new MatrixJsonRoomMessageEvent(obj); + } else { + return new MatrixJsonEvent(obj); + } + } + +} diff --git a/src/main/java/io/kamax/matrix/json/MatrixJsonObject.java b/src/main/java/io/kamax/matrix/json/MatrixJsonObject.java new file mode 100644 index 0000000..d87eb31 --- /dev/null +++ b/src/main/java/io/kamax/matrix/json/MatrixJsonObject.java @@ -0,0 +1,90 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.json; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; + +import java.util.Optional; + +public class MatrixJsonObject { + + private JsonObject obj; + + public MatrixJsonObject(JsonObject obj) { + this.obj = obj; + } + + protected Optional findString(String field) { + return GsonUtil.findString(obj, field); + } + + protected String getString(String field) { + return GsonUtil.getStringOrNull(obj, field); + } + + protected String getStringOrNull(JsonObject obj, String field) { + return GsonUtil.findString(obj, field).orElse(null); + } + + protected String getStringOrNull(String field) { + return getStringOrNull(obj, field); + } + + protected int getInt(String field) { + return GsonUtil.getPrimitive(obj, field).getAsInt(); + } + + protected int getInt(String field, int failover) { + return GsonUtil.findPrimitive(obj, field).map(JsonPrimitive::getAsInt).orElse(failover); + } + + protected long getLong(String field) { + return GsonUtil.getLong(obj, field); + } + + protected JsonObject asObj(JsonElement el) { + if (!el.isJsonObject()) { + throw new IllegalArgumentException("Not a JSON object"); + } + + return el.getAsJsonObject(); + } + + protected JsonObject getObj(String field) { + return GsonUtil.getObj(obj, field); + } + + protected Optional findObj(String field) { + return GsonUtil.findObj(obj, field); + } + + protected Optional findArray(String field) { + return GsonUtil.findArray(obj, field); + } + + public JsonObject getJson() { + return obj; + } + +} diff --git a/src/main/java/io/kamax/matrix/json/RoomAliasLookupJson.java b/src/main/java/io/kamax/matrix/json/RoomAliasLookupJson.java new file mode 100644 index 0000000..71aa756 --- /dev/null +++ b/src/main/java/io/kamax/matrix/json/RoomAliasLookupJson.java @@ -0,0 +1,46 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2018 Kamax Sàrl + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.json; + +import java.util.List; + +public class RoomAliasLookupJson { + + private String roomId; + private List servers; + + public String getRoomId() { + return roomId; + } + + public void setRoomId(String roomId) { + this.roomId = roomId; + } + + public List getServers() { + return servers; + } + + public void setServers(List servers) { + this.servers = servers; + } + +} diff --git a/src/main/java/io/kamax/matrix/json/RoomCreationRequestJson.java b/src/main/java/io/kamax/matrix/json/RoomCreationRequestJson.java new file mode 100644 index 0000000..870f199 --- /dev/null +++ b/src/main/java/io/kamax/matrix/json/RoomCreationRequestJson.java @@ -0,0 +1,57 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2018 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.json; + +import com.google.gson.JsonElement; + +import io.kamax.matrix._MatrixID; +import io.kamax.matrix.room._RoomCreationOptions; + +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +public class RoomCreationRequestJson { + + private String visibility; + private String roomAliasName; + private String name; + private String topic; + private Set invite; + private Map creationContent; + private String preset; + private Boolean isDirect; + private Boolean guestCanJoin; + + public RoomCreationRequestJson(_RoomCreationOptions options) { + this.visibility = options.getVisibility().orElse(null); + this.roomAliasName = options.getAliasName().orElse(null); + this.name = options.getName().orElse(null); + this.topic = options.getTopic().orElse(null); + this.invite = options.getInvites().filter(ids -> !ids.isEmpty()) + .map(ids -> ids.stream().map(_MatrixID::getId).collect(Collectors.toSet())).orElse(null); + this.creationContent = options.getCreationContent().filter(c -> !c.isEmpty()).orElse(null); + this.preset = options.getPreset().orElse(null); + this.isDirect = options.isDirect().orElse(null); + this.guestCanJoin = options.isGuestCanJoin().orElse(null); + } + +} diff --git a/src/main/java/io/kamax/matrix/json/RoomCreationResponseJson.java b/src/main/java/io/kamax/matrix/json/RoomCreationResponseJson.java new file mode 100644 index 0000000..730ca63 --- /dev/null +++ b/src/main/java/io/kamax/matrix/json/RoomCreationResponseJson.java @@ -0,0 +1,31 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2018 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.json; + +public class RoomCreationResponseJson { + + private String roomId; + + public String getRoomId() { + return roomId; + } + +} diff --git a/src/main/java/io/kamax/matrix/json/RoomMessageChunkResponseJson.java b/src/main/java/io/kamax/matrix/json/RoomMessageChunkResponseJson.java new file mode 100644 index 0000000..d85fa2a --- /dev/null +++ b/src/main/java/io/kamax/matrix/json/RoomMessageChunkResponseJson.java @@ -0,0 +1,45 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2018 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.json; + +import com.google.gson.JsonObject; + +import java.util.List; + +public class RoomMessageChunkResponseJson { + + private String start; + private String end; + private List chunk; + + public String getStart() { + return start; + } + + public String getEnd() { + return end; + } + + public List getChunk() { + return chunk; + } + +} diff --git a/src/main/java/io/kamax/matrix/json/RoomMessageFormattedTextPutBody.java b/src/main/java/io/kamax/matrix/json/RoomMessageFormattedTextPutBody.java new file mode 100644 index 0000000..5da99e4 --- /dev/null +++ b/src/main/java/io/kamax/matrix/json/RoomMessageFormattedTextPutBody.java @@ -0,0 +1,48 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.json; + +public class RoomMessageFormattedTextPutBody extends RoomMessageTextPutBody { + + private String formatted_body; + private String format = "org.matrix.custom.html"; + + public RoomMessageFormattedTextPutBody(String body, String formattedBody) { + super(body); + + this.formatted_body = formattedBody; + } + + public RoomMessageFormattedTextPutBody(String msgtype, String body, String formattedBody) { + super(msgtype, body); + + this.formatted_body = formattedBody; + } + + public String getFormatted_body() { + return formatted_body; + } + + public String getFormat() { + return format; + } + +} diff --git a/src/main/java/io/kamax/matrix/json/RoomMessageTextPutBody.java b/src/main/java/io/kamax/matrix/json/RoomMessageTextPutBody.java new file mode 100644 index 0000000..b4cf625 --- /dev/null +++ b/src/main/java/io/kamax/matrix/json/RoomMessageTextPutBody.java @@ -0,0 +1,45 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.json; + +public class RoomMessageTextPutBody { + + private String msgtype = "m.text"; + private String body; + + public RoomMessageTextPutBody(String body) { + this.body = body; + } + + public RoomMessageTextPutBody(String msgType, String body) { + this(body); + this.msgtype = msgType; + } + + public String getMsgtype() { + return msgtype; + } + + public String getBody() { + return body; + } + +} diff --git a/src/main/java/io/kamax/matrix/json/UserDisplaynameSetBody.java b/src/main/java/io/kamax/matrix/json/UserDisplaynameSetBody.java new file mode 100644 index 0000000..7864b5f --- /dev/null +++ b/src/main/java/io/kamax/matrix/json/UserDisplaynameSetBody.java @@ -0,0 +1,31 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.json; + +public class UserDisplaynameSetBody { + + private String displayname; + + public UserDisplaynameSetBody(String displayname) { + this.displayname = displayname; + } + +} diff --git a/src/main/java/io/kamax/matrix/json/VirtualUserRegistrationBody.java b/src/main/java/io/kamax/matrix/json/VirtualUserRegistrationBody.java new file mode 100644 index 0000000..7880f48 --- /dev/null +++ b/src/main/java/io/kamax/matrix/json/VirtualUserRegistrationBody.java @@ -0,0 +1,40 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.json; + +public class VirtualUserRegistrationBody { + + private String type = "m.login.application_server"; + private String username; + + public VirtualUserRegistrationBody(String username) { + this.username = username; + } + + public String getUsername() { + return username; + } + + public String getType() { + return type; + } + +} diff --git a/src/main/java/io/kamax/matrix/json/event/MatrixJsonEvent.java b/src/main/java/io/kamax/matrix/json/event/MatrixJsonEvent.java new file mode 100644 index 0000000..bbde81b --- /dev/null +++ b/src/main/java/io/kamax/matrix/json/event/MatrixJsonEvent.java @@ -0,0 +1,70 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.json.event; + +import com.google.gson.JsonObject; + +import io.kamax.matrix.MatrixID; +import io.kamax.matrix._MatrixID; +import io.kamax.matrix.event._MatrixEvent; +import io.kamax.matrix.json.MatrixJsonObject; + +import java.time.Instant; + +public class MatrixJsonEvent extends MatrixJsonObject implements _MatrixEvent { + + private String id; + private String type; + private Instant time; + private int age; + private _MatrixID sender; + + public MatrixJsonEvent(JsonObject obj) { + super(obj); + + id = getString("event_id"); + type = getString("type"); + time = Instant.ofEpochMilli(obj.get("origin_server_ts").getAsLong()); + age = getInt("age", -1); + sender = MatrixID.asAcceptable(getString("sender")); + } + + @Override + public String getId() { + return id; + } + + @Override + public String getType() { + return type; + } + + @Override + public Instant getTime() { + return time; + } + + @Override + public _MatrixID getSender() { + return sender; + } + +} diff --git a/src/main/java/io/kamax/matrix/json/event/MatrixJsonRoomEvent.java b/src/main/java/io/kamax/matrix/json/event/MatrixJsonRoomEvent.java new file mode 100644 index 0000000..a9f48ca --- /dev/null +++ b/src/main/java/io/kamax/matrix/json/event/MatrixJsonRoomEvent.java @@ -0,0 +1,42 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.json.event; + +import com.google.gson.JsonObject; + +import io.kamax.matrix.event._RoomEvent; + +public class MatrixJsonRoomEvent extends MatrixJsonEvent implements _RoomEvent { + + private String roomId; + + public MatrixJsonRoomEvent(JsonObject obj) { + super(obj); + + roomId = getString("room_id"); + } + + @Override + public String getRoomId() { + return roomId; + } + +} diff --git a/src/main/java/io/kamax/matrix/json/event/MatrixJsonRoomMembershipEvent.java b/src/main/java/io/kamax/matrix/json/event/MatrixJsonRoomMembershipEvent.java new file mode 100644 index 0000000..05f2e9c --- /dev/null +++ b/src/main/java/io/kamax/matrix/json/event/MatrixJsonRoomMembershipEvent.java @@ -0,0 +1,104 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.json.event; + +import com.google.gson.JsonObject; + +import io.kamax.matrix.MatrixID; +import io.kamax.matrix._MatrixID; +import io.kamax.matrix.event._RoomMembershipEvent; +import io.kamax.matrix.json.MatrixJsonObject; + +import java.util.Optional; + +public class MatrixJsonRoomMembershipEvent extends MatrixJsonRoomEvent implements _RoomMembershipEvent { + + private Content content; + private _MatrixID invitee; + + public MatrixJsonRoomMembershipEvent(JsonObject obj) { + super(obj); + + content = new Content(getObj("content")); + invitee = new MatrixID(getString("state_key")); + } + + @Override + public String getMembership() { + return content.getMembership(); + } + + @Override + public Optional getAvatarUrl() { + return Optional.ofNullable(content.getAvatar()); + } + + @Override + public Optional getDisplayName() { + return Optional.ofNullable(content.getDisplayName()); + } + + @Override + public _MatrixID getInvitee() { + return invitee; + } + + private class Content extends MatrixJsonObject { + + private String membership; + private String avatar; + private String displayName; + + Content(JsonObject obj) { + super(obj); + + setMembership(getString("membership")); + setAvatar(avatar = getStringOrNull("avatar_url")); + setDisplayName(displayName = getStringOrNull("displayname")); + } + + String getMembership() { + return membership; + } + + void setMembership(String membership) { + this.membership = membership; + } + + String getAvatar() { + return avatar; + } + + void setAvatar(String avatar) { + this.avatar = avatar; + } + + String getDisplayName() { + return displayName; + } + + void setDisplayName(String displayName) { + this.displayName = displayName; + } + + } + +} diff --git a/src/main/java/io/kamax/matrix/json/event/MatrixJsonRoomMessageEvent.java b/src/main/java/io/kamax/matrix/json/event/MatrixJsonRoomMessageEvent.java new file mode 100644 index 0000000..173f82c --- /dev/null +++ b/src/main/java/io/kamax/matrix/json/event/MatrixJsonRoomMessageEvent.java @@ -0,0 +1,60 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.json.event; + +import com.google.gson.JsonObject; + +import io.kamax.matrix.event._RoomMessageEvent; +import io.kamax.matrix.json.GsonUtil; + +import java.util.Optional; + +public class MatrixJsonRoomMessageEvent extends MatrixJsonRoomEvent implements _RoomMessageEvent { + + private JsonObject content; + + public MatrixJsonRoomMessageEvent(JsonObject obj) { + super(obj); + + this.content = obj.getAsJsonObject("content"); + } + + @Override + public String getBody() { + return content.get("body").getAsString(); + } + + @Override + public String getBodyType() { + return content.has("msgtype") ? content.get("msgtype").getAsString() : null; + } + + @Override + public Optional getFormat() { + return GsonUtil.findString(content, "format"); + } + + @Override + public Optional getFormattedBody() { + return GsonUtil.findString(content, "formatted_body"); + } + +} diff --git a/src/main/java/io/kamax/matrix/room/MatrixRoomMessageChunk.java b/src/main/java/io/kamax/matrix/room/MatrixRoomMessageChunk.java new file mode 100644 index 0000000..387f7af --- /dev/null +++ b/src/main/java/io/kamax/matrix/room/MatrixRoomMessageChunk.java @@ -0,0 +1,54 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2018 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.room; + +import io.kamax.matrix.event._MatrixEvent; + +import java.util.List; + +public class MatrixRoomMessageChunk implements _MatrixRoomMessageChunk { + + private String startToken; + private String endToken; + private List<_MatrixEvent> events; + + public MatrixRoomMessageChunk(String startToken, String endToken, List<_MatrixEvent> events) { + this.startToken = startToken; + this.endToken = endToken; + this.events = events; + } + + @Override + public String getStartToken() { + return startToken; + } + + @Override + public String getEndToken() { + return endToken; + } + + @Override + public List<_MatrixEvent> getEvents() { + return events; + } + +} diff --git a/src/main/java/io/kamax/matrix/room/MatrixRoomMessageChunkOptions.java b/src/main/java/io/kamax/matrix/room/MatrixRoomMessageChunkOptions.java new file mode 100644 index 0000000..09d8e3a --- /dev/null +++ b/src/main/java/io/kamax/matrix/room/MatrixRoomMessageChunkOptions.java @@ -0,0 +1,94 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2018 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.room; + +import java.util.Optional; + +public class MatrixRoomMessageChunkOptions implements _MatrixRoomMessageChunkOptions { + + public static class Builder { + + private MatrixRoomMessageChunkOptions obj; + + public Builder() { + this.obj = new MatrixRoomMessageChunkOptions(); + } + + public Builder setFromToken(String token) { + obj.from = token; + return this; + } + + public Builder setToToken(String token) { + obj.to = token; + return this; + } + + public Builder setDirection(String direction) { + obj.dir = direction; + return this; + } + + public Builder setDirection(_MatrixRoomMessageChunkOptions.Direction direction) { + return setDirection(direction.get()); + } + + public Builder setLimit(long limit) { + obj.limit = limit; + return this; + } + + public MatrixRoomMessageChunkOptions get() { + return obj; + } + + } + + public static Builder build() { + return new Builder(); + } + + private String from; + private String to; + private String dir; + private Long limit; + + @Override + public String getFromToken() { + return from; + } + + @Override + public Optional getToToken() { + return Optional.ofNullable(to); + } + + @Override + public String getDirection() { + return dir; + } + + @Override + public Optional getLimit() { + return Optional.ofNullable(limit); + } + +} diff --git a/src/main/java/io/kamax/matrix/room/RoomAlias.java b/src/main/java/io/kamax/matrix/room/RoomAlias.java new file mode 100644 index 0000000..5265caf --- /dev/null +++ b/src/main/java/io/kamax/matrix/room/RoomAlias.java @@ -0,0 +1,82 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2018 Kamax Sàrl + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.room; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class RoomAlias { + + private static final String sigill = "#"; + private static final Pattern idPattern = Pattern.compile(sigill + "(.+?):(.+)"); + + private String id; + private String localpart; + private String domain; + + public static RoomAlias from(String localpart, String domain) { + return from(sigill + localpart + ":" + domain); + } + + public static RoomAlias from(String id) { + if (id.length() > 255) { + throw new IllegalArgumentException("Room aliases cannot be longer than 255 characters"); + } + + Matcher m = idPattern.matcher(id); + if (!m.matches()) { + throw new IllegalArgumentException(id + " is not a valid Room alias"); + } + + RoomAlias r = new RoomAlias(); + r.id = id; + r.localpart = m.group(1); + r.domain = m.group(2); + + return r; + } + + public static boolean is(String id) { + try { + from(id); + return true; + } catch (IllegalArgumentException e) { + return false; + } + } + + private RoomAlias() { + // cannot instantiate directly + } + + public String getId() { + return id; + } + + public String getLocalpart() { + return localpart; + } + + public String getDomain() { + return domain; + } + +} diff --git a/src/main/java/io/kamax/matrix/room/RoomAliasLookup.java b/src/main/java/io/kamax/matrix/room/RoomAliasLookup.java new file mode 100644 index 0000000..da5ece1 --- /dev/null +++ b/src/main/java/io/kamax/matrix/room/RoomAliasLookup.java @@ -0,0 +1,41 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2018 Kamax Sàrl + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.room; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public class RoomAliasLookup extends RoomAliasMapping implements _RoomAliasLookup { + + private List servers; + + public RoomAliasLookup(String id, String alias, Collection servers) { + super(id, alias); + this.servers = new ArrayList<>(servers); + } + + @Override + public List getServers() { + return servers; + } + +} diff --git a/src/main/java/io/kamax/matrix/room/RoomAliasMapping.java b/src/main/java/io/kamax/matrix/room/RoomAliasMapping.java new file mode 100644 index 0000000..3108c51 --- /dev/null +++ b/src/main/java/io/kamax/matrix/room/RoomAliasMapping.java @@ -0,0 +1,43 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2018 Kamax Sàrl + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.room; + +public class RoomAliasMapping implements _RoomAliasMapping { + + private String id; + private String alias; + + public RoomAliasMapping(String id, String alias) { + this.id = id; + this.alias = alias; + } + + @Override + public String getId() { + return id; + } + + @Override + public String getAlias() { + return alias; + } + +} diff --git a/src/main/java/io/kamax/matrix/room/RoomCreationOptions.java b/src/main/java/io/kamax/matrix/room/RoomCreationOptions.java new file mode 100644 index 0000000..4f998b3 --- /dev/null +++ b/src/main/java/io/kamax/matrix/room/RoomCreationOptions.java @@ -0,0 +1,160 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2018 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.room; + +import com.google.gson.JsonElement; + +import io.kamax.matrix._MatrixID; + +import java.util.*; + +public class RoomCreationOptions implements _RoomCreationOptions { + + public static class Builder { + + private RoomCreationOptions obj; + + public Builder() { + this.obj = new RoomCreationOptions(); + } + + public Builder setVisibility(String visibility) { + obj.visibility = visibility; + return this; + } + + public Builder setVisibility(RoomDirectoryVisibility visibility) { + return setVisibility(visibility.get()); + } + + public Builder setAliasName(String aliasName) { + obj.aliasName = aliasName; + return this; + } + + public Builder setName(String name) { + obj.name = name; + return this; + } + + public Builder setTopic(String topic) { + obj.topic = topic; + return this; + } + + public Builder setInvites(Set<_MatrixID> invites) { + obj.invites = Collections.unmodifiableSet(new HashSet<>(invites)); + return this; + } + + public Builder setCreationContent(Map creationContent) { + obj.creationContent = Collections.unmodifiableMap(new HashMap<>(creationContent)); + return this; + } + + public Builder setPreset(String preset) { + obj.preset = preset; + return this; + } + + public Builder setPreset(RoomCreationPreset preset) { + return setPreset(preset.get()); + } + + public Builder setDirect(boolean isDirect) { + obj.isDirect = isDirect; + return this; + } + + public Builder setGuestCanJoin(boolean guestCanJoin) { + obj.guestCanJoin = guestCanJoin; + return this; + } + + public RoomCreationOptions get() { + return obj; + } + } + + public static Builder build() { + return new Builder(); + } + + public static RoomCreationOptions none() { + return build().get(); + } + + private String visibility; + private String aliasName; + private String name; + private String topic; + private Set<_MatrixID> invites = new HashSet<>(); + private Map creationContent = new HashMap<>(); + private String preset; + private Boolean isDirect; + private Boolean guestCanJoin; + + @Override + public Optional getVisibility() { + return Optional.ofNullable(visibility); + } + + @Override + public Optional getAliasName() { + return Optional.ofNullable(aliasName); + } + + @Override + public Optional getName() { + return Optional.ofNullable(name); + } + + @Override + public Optional getTopic() { + return Optional.ofNullable(topic); + } + + @Override + public Optional> getInvites() { + return Optional.ofNullable(invites); + } + + @Override + public Optional> getCreationContent() { + return Optional.ofNullable(creationContent); + } + + @Override + public Optional getPreset() { + return Optional.ofNullable(preset); + } + + @Override + public Optional isDirect() { + return Optional.ofNullable(isDirect); + } + + @Override + public Optional isGuestCanJoin() { + return Optional.ofNullable(guestCanJoin); + } + +} diff --git a/src/main/java/io/kamax/matrix/room/RoomCreationPreset.java b/src/main/java/io/kamax/matrix/room/RoomCreationPreset.java new file mode 100644 index 0000000..3b8313c --- /dev/null +++ b/src/main/java/io/kamax/matrix/room/RoomCreationPreset.java @@ -0,0 +1,65 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2018 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.room; + +/** + * Room creation presets available in the specification. + */ +public enum RoomCreationPreset { + + /** + * The following room state will be set: + * - join_rules is set to invite. + * - history_visibility is set to shared. + */ + Private("private_chat"), + + /** + * The following room state will be set: + * - join_rules is set to invite. + * - history_visibility is set to shared. + * - All invitees are given the same power level as the room creator. + */ + TrustedPrivate("trusted_private_chat"), + + /** + * The following room state will be set: + * - join_rules is set to public. + * - history_visibility is set to shared. + */ + PublicChat("public_chat"); + + private String id; + + RoomCreationPreset(String id) { + this.id = id; + } + + /** + * Get the Matrix value for this setting. + * + * @return the value. + */ + public String get() { + return id; + } + +} diff --git a/src/main/java/io/kamax/matrix/room/RoomDirectoryVisibility.java b/src/main/java/io/kamax/matrix/room/RoomDirectoryVisibility.java new file mode 100644 index 0000000..89a1192 --- /dev/null +++ b/src/main/java/io/kamax/matrix/room/RoomDirectoryVisibility.java @@ -0,0 +1,53 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2018 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.room; + +/** + * Room Directory visibility status available in the specification. + */ +public enum RoomDirectoryVisibility { + + /** + * The room will not be visible in the directory. + */ + Private("private"), + + /** + * The room will be visible by anyone, without authentication. + */ + Public("public"); + + private String id; + + RoomDirectoryVisibility(String id) { + this.id = id; + } + + /** + * Get the Matrix value for this setting. + * + * @return the value. + */ + public String get() { + return id; + } + +} diff --git a/src/main/java/io/kamax/matrix/room/_MatrixRoomMessageChunk.java b/src/main/java/io/kamax/matrix/room/_MatrixRoomMessageChunk.java new file mode 100644 index 0000000..23cbaf2 --- /dev/null +++ b/src/main/java/io/kamax/matrix/room/_MatrixRoomMessageChunk.java @@ -0,0 +1,53 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2018 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.room; + +import io.kamax.matrix.event._MatrixEvent; + +import java.util.List; + +/** + * Room messages pagination chunk. + */ +public interface _MatrixRoomMessageChunk { + + /** + * The token the pagination starts from. + * + * @return the token. + */ + String getStartToken(); + + /** + * The token the pagination ends at. + * + * @return the token. + */ + String getEndToken(); + + /** + * A list of room events. + * + * @return the list. + */ + List<_MatrixEvent> getEvents(); + +} diff --git a/src/main/java/io/kamax/matrix/room/_MatrixRoomMessageChunkOptions.java b/src/main/java/io/kamax/matrix/room/_MatrixRoomMessageChunkOptions.java new file mode 100644 index 0000000..7c37e10 --- /dev/null +++ b/src/main/java/io/kamax/matrix/room/_MatrixRoomMessageChunkOptions.java @@ -0,0 +1,90 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2018 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.room; + +import java.util.Optional; + +/** + * Possible options that can be passed to the room messages chunk call. + */ +public interface _MatrixRoomMessageChunkOptions { + + /** + * The direction to return events from. + */ + enum Direction { + + /** + * Fetch events backward. + */ + Backward("b"), + + /** + * Fetch events forward. + */ + Forward("f"); + + private String id; + + Direction(String id) { + this.id = id; + } + + /** + * Get the protocol value. + * + * @return the value. + */ + public String get() { + return id; + } + + } + + /** + * The token to start returning events from. + * + * @return the token. + */ + String getFromToken(); + + /** + * The token to stop returning events at, if any. + * + * @return the token. + */ + Optional getToToken(); + + /** + * The direction to return events from. + * + * @return the direction. + */ + String getDirection(); + + /** + * The maximum number of events to return. + * + * @return the value. + */ + Optional getLimit(); + +} diff --git a/src/main/java/io/kamax/matrix/room/_RoomAliasLookup.java b/src/main/java/io/kamax/matrix/room/_RoomAliasLookup.java new file mode 100644 index 0000000..6361454 --- /dev/null +++ b/src/main/java/io/kamax/matrix/room/_RoomAliasLookup.java @@ -0,0 +1,29 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2018 Kamax Sàrl + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.room; + +import java.util.List; + +public interface _RoomAliasLookup extends _RoomAliasMapping { + + List getServers(); + +} diff --git a/src/main/java/io/kamax/matrix/room/_RoomAliasMapping.java b/src/main/java/io/kamax/matrix/room/_RoomAliasMapping.java new file mode 100644 index 0000000..48137c0 --- /dev/null +++ b/src/main/java/io/kamax/matrix/room/_RoomAliasMapping.java @@ -0,0 +1,29 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2018 Kamax Sàrl + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.room; + +public interface _RoomAliasMapping { + + String getId(); + + String getAlias(); + +} diff --git a/src/main/java/io/kamax/matrix/room/_RoomCreationOptions.java b/src/main/java/io/kamax/matrix/room/_RoomCreationOptions.java new file mode 100644 index 0000000..42757e2 --- /dev/null +++ b/src/main/java/io/kamax/matrix/room/_RoomCreationOptions.java @@ -0,0 +1,79 @@ +package io.kamax.matrix.room; + +import com.google.gson.JsonElement; + +import io.kamax.matrix._MatrixID; + +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +/** + * Possible options that can be passed to the room creation call. + */ +public interface _RoomCreationOptions { + + /** + * Get the room directory visibility. + * + * @return the optional value. + */ + Optional getVisibility(); + + /** + * Get the desired room alias local part. + * + * @return the optional value. + */ + Optional getAliasName(); + + /** + * Get the room name. + * + * @return the optional value. + */ + Optional getName(); + + /** + * Get the room topic. + * + * @return the optional value. + */ + Optional getTopic(); + + /** + * Get the list of user Matrix IDs to invite to the room. + * + * @return the optional value. + */ + Optional> getInvites(); + + /** + * Get the extra keys to be added to the content of the m.room.create event. + * + * @return the optional value. + */ + Optional> getCreationContent(); + + /** + * Get the convenience parameter for setting various default state events. + * + * @return the optional value. + */ + Optional getPreset(); + + /** + * What the is_direct flag on the m.room.member event for the invites should be set to. + * + * @return the optional value. + */ + Optional isDirect(); + + /** + * Get guest allowance to join the room. + * + * @return the optional value. + */ + Optional isGuestCanJoin(); + +} diff --git a/src/main/java/io/kamax/matrix/sign/KeyFileStore.java b/src/main/java/io/kamax/matrix/sign/KeyFileStore.java new file mode 100644 index 0000000..558117a --- /dev/null +++ b/src/main/java/io/kamax/matrix/sign/KeyFileStore.java @@ -0,0 +1,78 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.sign; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.lang3.StringUtils; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.Optional; + +public class KeyFileStore implements _KeyStore { + + private final Charset charset = StandardCharsets.ISO_8859_1; + + private File file; + + public KeyFileStore(String path) { + File file = new File(path); + if (!file.exists()) { + return; + } + + if (file.isDirectory()) { + throw new IllegalArgumentException("Signing key file storage " + path + " is a directory"); + } + + if (!file.isFile()) { + throw new IllegalArgumentException("Signing key file storage " + path + " is not a regular file"); + } + + if (!file.canRead()) { + throw new IllegalArgumentException("Signing key file storage " + path + " is not readable"); + } + + this.file = file; + } + + @Override + public Optional load() { + try { + String key = FileUtils.readFileToString(file, charset); + return StringUtils.isBlank(key) ? Optional.empty() : Optional.of(key); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public void store(String key) { + try { + FileUtils.writeStringToFile(file, key, charset); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + +} diff --git a/src/main/java/io/kamax/matrix/sign/KeyManager.java b/src/main/java/io/kamax/matrix/sign/KeyManager.java new file mode 100644 index 0000000..6c200ff --- /dev/null +++ b/src/main/java/io/kamax/matrix/sign/KeyManager.java @@ -0,0 +1,93 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.sign; + +import io.kamax.matrix.codec.MxBase64; + +import java.security.KeyPair; +import java.security.PrivateKey; +import java.util.ArrayList; +import java.util.Base64; +import java.util.List; + + +import net.i2p.crypto.eddsa.EdDSAPrivateKey; +import net.i2p.crypto.eddsa.EdDSAPublicKey; +import net.i2p.crypto.eddsa.KeyPairGenerator; +import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable; +import net.i2p.crypto.eddsa.spec.EdDSAParameterSpec; +import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec; +import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec; + +public class KeyManager { + + public static KeyManager fromFile(String path) { + return new KeyManager(new KeyFileStore(path)); + } + + public static KeyManager fromMemory() { + return new KeyManager(new KeyMemoryStore()); + } + + private EdDSAParameterSpec keySpecs; + private List keys; + + public KeyManager(_KeyStore store) { + keySpecs = EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.CURVE_ED25519_SHA512); + keys = new ArrayList<>(); + + String seedBase64 = store.load().orElseGet(() -> { + KeyPair pair = (new KeyPairGenerator()).generateKeyPair(); + String keyEncoded = MxBase64.encode(pair.getPrivate().getEncoded()); + store.store(keyEncoded); + return keyEncoded; + }); + byte[] seed = Base64.getDecoder().decode(seedBase64); + EdDSAPrivateKeySpec privKeySpec = new EdDSAPrivateKeySpec(seed, keySpecs); + EdDSAPublicKeySpec pubKeySpec = new EdDSAPublicKeySpec(privKeySpec.getA(), keySpecs); + keys.add(new KeyPair(new EdDSAPublicKey(pubKeySpec), new EdDSAPrivateKey(privKeySpec))); + } + + public int getCurrentIndex() { + return 0; + } + + public KeyPair getKeys(int index) { + return keys.get(index); + } + + public PrivateKey getPrivateKey(int index) { + return getKeys(index).getPrivate(); + } + + public EdDSAPublicKey getPublicKey(int index) { + return (EdDSAPublicKey) getKeys(index).getPublic(); + } + + public EdDSAParameterSpec getSpecs() { + return keySpecs; + } + + public String getPublicKeyBase64(int index) { + return MxBase64.encode(getPublicKey(index).getAbyte()); + } + +} diff --git a/src/main/java/io/kamax/matrix/sign/KeyMemoryStore.java b/src/main/java/io/kamax/matrix/sign/KeyMemoryStore.java new file mode 100644 index 0000000..74b013c --- /dev/null +++ b/src/main/java/io/kamax/matrix/sign/KeyMemoryStore.java @@ -0,0 +1,46 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.sign; + +import java.util.Optional; + +public class KeyMemoryStore implements _KeyStore { + + private String data; + + public KeyMemoryStore() { + } + + public KeyMemoryStore(String data) { + this.data = data; + } + + @Override + public Optional load() { + return Optional.ofNullable(data); + } + + @Override + public void store(String key) { + data = key; + } + +} diff --git a/src/main/java/io/kamax/matrix/sign/SignatureManager.java b/src/main/java/io/kamax/matrix/sign/SignatureManager.java new file mode 100644 index 0000000..3a3bf6a --- /dev/null +++ b/src/main/java/io/kamax/matrix/sign/SignatureManager.java @@ -0,0 +1,80 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.sign; + +import com.google.gson.JsonObject; + +import io.kamax.matrix.codec.MxBase64; +import io.kamax.matrix.json.MatrixJson; + +import java.security.InvalidKeyException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.SignatureException; + + +import net.i2p.crypto.eddsa.EdDSAEngine; + +public class SignatureManager { + + private KeyManager keyMgr; + private String domain; + + private EdDSAEngine signEngine; + + public SignatureManager(KeyManager keyMgr, String domain) { + this.keyMgr = keyMgr; + this.domain = domain; + + try { + signEngine = new EdDSAEngine(MessageDigest.getInstance(keyMgr.getSpecs().getHashAlgorithm())); + signEngine.initSign(keyMgr.getPrivateKey(keyMgr.getCurrentIndex())); + } catch (NoSuchAlgorithmException | InvalidKeyException e) { + throw new RuntimeException(e); + } + } + + public String sign(JsonObject obj) { + return sign(MatrixJson.encodeCanonical(obj)); + } + + public String sign(String message) { + try { + byte[] signRaw = signEngine.signOneShot(message.getBytes()); + return MxBase64.encode(signRaw); + } catch (SignatureException e) { + throw new RuntimeException(e); + } + } + + public JsonObject signMessageGson(String message) { + String sign = sign(message); + + JsonObject keySignature = new JsonObject(); + // FIXME should create a signing key object what would give this ed and index values + keySignature.addProperty("ed25519:" + keyMgr.getCurrentIndex(), sign); + JsonObject signature = new JsonObject(); + signature.add(domain, keySignature); + + return signature; + } + +} diff --git a/src/main/java/io/kamax/matrix/sign/_KeyStore.java b/src/main/java/io/kamax/matrix/sign/_KeyStore.java new file mode 100644 index 0000000..e5bf1cd --- /dev/null +++ b/src/main/java/io/kamax/matrix/sign/_KeyStore.java @@ -0,0 +1,31 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.sign; + +import java.util.Optional; + +public interface _KeyStore { + + Optional load(); + + void store(String key); + +} diff --git a/src/test/java/io/kamax/matrix/AMatrixHttpUserTest.java b/src/test/java/io/kamax/matrix/AMatrixHttpUserTest.java new file mode 100644 index 0000000..6879d05 --- /dev/null +++ b/src/test/java/io/kamax/matrix/AMatrixHttpUserTest.java @@ -0,0 +1,95 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Arne Augenstein + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix; + +import io.kamax.matrix.client.MatrixClientContext; +import io.kamax.matrix.client.MatrixClientRequestException; +import io.kamax.matrix.client.MatrixHttpTest; +import io.kamax.matrix.client.MatrixHttpUser; + +import org.junit.Test; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Optional; + +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsEqual.equalTo; +import static org.junit.Assert.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public abstract class AMatrixHttpUserTest extends MatrixHttpTest { + protected String avatarMediaUrl = "mxc://matrix.org/wefh34uihSDRGhw34"; + + @Test + public void getName() throws URISyntaxException { + assertThat(createUserObject().getName(), is(equalTo(Optional.of(username)))); + } + + @Test + public void getNameNotFound() throws URISyntaxException { + assertThat(createUserObject().getName(), is(equalTo(Optional.empty()))); + } + + @Test + public void getNameAccessDenied() throws URISyntaxException { + MatrixClientRequestException e = assertThrows(MatrixClientRequestException.class, createUserObject()::getName); + checkErrorInfoAccessDenied(e); + } + + @Test + public void getNameRateLimited() throws URISyntaxException { + MatrixClientRequestException e = assertThrows(MatrixClientRequestException.class, createUserObject()::getName); + checkErrorInfoRateLimited(e); + } + + @Test + public void getAvatar() throws URISyntaxException { + Optional<_MatrixContent> matrixContent = createUserObject().getAvatar(); + assertTrue(matrixContent.isPresent()); + assertThat(matrixContent.get().getAddress(), is(equalTo(new URI(avatarMediaUrl)))); + } + + @Test + public void getAvatarNotFound() throws URISyntaxException { + assertThat(createUserObject().getAvatar(), is(equalTo(Optional.empty()))); + } + + @Test + public void getAvatarAccessDenied() throws URISyntaxException { + MatrixClientRequestException e = assertThrows(MatrixClientRequestException.class, + createUserObject()::getAvatar); + checkErrorInfoAccessDenied(e); + } + + @Test + public void getAvatarRateLimited() throws URISyntaxException { + MatrixClientRequestException e = assertThrows(MatrixClientRequestException.class, + createUserObject()::getAvatar); + checkErrorInfoRateLimited(e); + } + + private MatrixHttpUser createUserObject() throws URISyntaxException { + MatrixClientContext context = getOrCreateClientContext(); + return new MatrixHttpUser(context, context.getUser().get()); + } +} diff --git a/src/test/java/io/kamax/matrix/LoggingDependencyTest.java b/src/test/java/io/kamax/matrix/LoggingDependencyTest.java new file mode 100644 index 0000000..fad226f --- /dev/null +++ b/src/test/java/io/kamax/matrix/LoggingDependencyTest.java @@ -0,0 +1,43 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Arne Augenstein + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ +package io.kamax.matrix; + +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.helpers.NOPLoggerFactory; + +import java.net.URISyntaxException; + +/** + * A small test class, intended to verify that the logging framework has + * a suitable logging implementation. + */ +public class LoggingDependencyTest { + @Test + public void login() throws URISyntaxException { + if (LoggerFactory.getILoggerFactory() instanceof NOPLoggerFactory) { + Assert.fail("No logging implementation found, using fallback NOP logger"); + } + Logger logger = LoggerFactory.getLogger(""); + logger.info("If you see this info in the logger, everything is alright"); + } +} diff --git a/src/test/java/io/kamax/matrix/MatrixHttpUserWiremockTest.java b/src/test/java/io/kamax/matrix/MatrixHttpUserWiremockTest.java new file mode 100644 index 0000000..f28cd84 --- /dev/null +++ b/src/test/java/io/kamax/matrix/MatrixHttpUserWiremockTest.java @@ -0,0 +1,92 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Arne Augenstein + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix; + +import org.junit.Test; + +import java.net.URISyntaxException; + +import static com.github.tomakehurst.wiremock.client.WireMock.*; + +public class MatrixHttpUserWiremockTest extends AMatrixHttpUserTest { + private String nameUrl = String.format("/_matrix/client/r0/profile/%s/displayname", user.getId()) + tokenParameter; + private String nameResponse = String.format("{\"displayname\": \"%s\"}", username); + + private String avatarUrl = String.format("/_matrix/client/r0/profile/%s/avatar_url", user.getId()) + tokenParameter; + private String avatarResponse = String.format("{\"avatar_url\": \"%s\"}", avatarMediaUrl); + + @Override + public void login() throws URISyntaxException { + } + + @Override + public void logout() { + } + + @Test + public void getName() throws URISyntaxException { + stubFor(get(urlEqualTo(nameUrl)).willReturn(aResponse().withStatus(200).withBody(nameResponse))); + super.getName(); + } + + @Test + public void getNameNotFound() throws URISyntaxException { + stubFor(get(urlEqualTo(nameUrl)).willReturn(aResponse().withStatus(404).withBody(errorNotFoundResponse))); + super.getNameNotFound(); + } + + @Test + public void getNameAccessDenied() throws URISyntaxException { + stubFor(get(urlEqualTo(nameUrl)).willReturn(aResponse().withStatus(403).withBody(errorAccessDeniedResponse))); + super.getNameAccessDenied(); + } + + @Test + public void getNameRateLimited() throws URISyntaxException { + stubFor(get(urlEqualTo(nameUrl)).willReturn(aResponse().withStatus(429).withBody(errorRateLimitedResponse))); + super.getNameRateLimited(); + } + + @Test + public void getAvatar() throws URISyntaxException { + stubFor(get(urlEqualTo(avatarUrl)).willReturn(aResponse().withStatus(200).withBody(avatarResponse))); + super.getAvatar(); + } + + @Test + public void getAvatarNotFound() throws URISyntaxException { + stubFor(get(urlEqualTo(avatarUrl)).willReturn(aResponse().withStatus(404).withBody(errorNotFoundResponse))); + super.getAvatarNotFound(); + } + + @Test + public void getAvatarAccessDenied() throws URISyntaxException { + stubFor(get(urlEqualTo(avatarUrl)).willReturn(aResponse().withStatus(403).withBody(errorAccessDeniedResponse))); + super.getAvatarAccessDenied(); + } + + @Test + public void getAvatarRateLimited() throws URISyntaxException { + stubFor(get(urlEqualTo(avatarUrl)).willReturn(aResponse().withStatus(429).withBody(errorRateLimitedResponse))); + super.getAvatarRateLimited(); + } + +} diff --git a/src/test/java/io/kamax/matrix/MatrixIDTest.java b/src/test/java/io/kamax/matrix/MatrixIDTest.java new file mode 100644 index 0000000..45dcdff --- /dev/null +++ b/src/test/java/io/kamax/matrix/MatrixIDTest.java @@ -0,0 +1,91 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix; + +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + +public class MatrixIDTest { + + private static String validMxId1 = "@john.doe:example.org"; + private static String validMxId2 = "@john.doe:example.com"; + private static String validMxId3 = "@JoHn.dOe:ExamPLE.ORG"; + private static String validMxid4 = "@john:example.org:8449"; + private static String validMxid5 = "@john:::1:8449"; + + private static String invalidMxId1 = "john.doe:example.org"; + private static String invalidMxId2 = "@john.doeexample.org"; + private static String invalidMxId3 = "john.doe"; + private static String invalidMxId4 = "@:"; + private static String invalidMxId5 = "@john.doe:"; + + @Test + public void validMatrixIDs() { + _MatrixID mxId1 = new MatrixID(validMxId1); + _MatrixID mxId3 = new MatrixID(validMxId3); + _MatrixID mxId4 = new MatrixID(validMxid4); + _MatrixID mxId5 = new MatrixID(validMxid5); + assertTrue(validMxId1.contentEquals(mxId1.getId())); + assertTrue("john.doe".contentEquals(mxId1.getLocalPart())); + assertTrue("example.org".contentEquals(mxId1.getDomain())); + assertTrue("example.org:8449".contentEquals(mxId4.getDomain())); + assertTrue("::1:8449".contentEquals(mxId5.getDomain())); + } + + @Test + public void validateEqual() { + _MatrixID mxId1 = new MatrixID(validMxId1); + _MatrixID mxId2 = new MatrixID(validMxId1); + _MatrixID mxId3 = new MatrixID(validMxId2); + + assertTrue(mxId1.equals(mxId2)); + assertTrue(mxId2.equals(mxId1)); + assertTrue(!mxId1.equals(mxId3)); + assertTrue(!mxId2.equals(mxId3)); + } + + @Test(expected = IllegalArgumentException.class) + public void invalidMatrixIDs1() { + new MatrixID(invalidMxId1); + } + + @Test(expected = IllegalArgumentException.class) + public void invalidMatrixIDs2() { + new MatrixID(invalidMxId2); + } + + @Test(expected = IllegalArgumentException.class) + public void invalidMatrixIDs3() { + new MatrixID(invalidMxId3); + } + + @Test(expected = IllegalArgumentException.class) + public void invalidMatrixIDs4() { + new MatrixID(invalidMxId4); + } + + @Test(expected = IllegalArgumentException.class) + public void invalidMatrixIDs5() { + new MatrixID(invalidMxId5); + } + +} diff --git a/src/test/java/io/kamax/matrix/ThreePidTest.java b/src/test/java/io/kamax/matrix/ThreePidTest.java new file mode 100644 index 0000000..4205808 --- /dev/null +++ b/src/test/java/io/kamax/matrix/ThreePidTest.java @@ -0,0 +1,55 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix; + +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + +public class ThreePidTest { + + private static String medium1 = "email"; + private static String address1 = "john.doe@example.org"; + private static String medium2 = "msisdn"; + private static String address2 = "123456789"; + + @Test + public void basic() { + _ThreePid tp1 = new ThreePid(medium1, address1); + assertTrue(medium1.contentEquals(tp1.getMedium())); + assertTrue(address1.contentEquals(tp1.getAddress())); + } + + @Test + public void equal() { + _ThreePid tp11 = new ThreePid(medium1, address1); + _ThreePid tp12 = new ThreePid(medium1, address1); + _ThreePid tp21 = new ThreePid(medium2, address2); + _ThreePid tp22 = new ThreePid(medium2, address2); + + assertTrue(tp11.equals(tp12)); + assertTrue(tp12.equals(tp11)); + assertTrue(tp21.equals(tp22)); + assertTrue(tp22.equals(tp21)); + assertTrue(!tp11.equals(tp21)); + assertTrue(!tp22.equals(tp12)); + } +} diff --git a/src/test/java/io/kamax/matrix/client/AMatrixHttpContentTest.java b/src/test/java/io/kamax/matrix/client/AMatrixHttpContentTest.java new file mode 100644 index 0000000..8835ecd --- /dev/null +++ b/src/test/java/io/kamax/matrix/client/AMatrixHttpContentTest.java @@ -0,0 +1,149 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Arne Augenstein + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.client; + +import org.hamcrest.core.IsEqual; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Optional; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.*; + +/* + * TODO As the spec is outdated, I'm not sure if the error 403 can really happen in these test cases. This class has + * to be checked for correctness, when matrix's spec is updated. + */ +public abstract class AMatrixHttpContentTest extends MatrixHttpTest { + protected String bodyFilename = "textfile.txt"; + protected URI address = new URI("mxc://localhost/testpath/" + bodyFilename); + + public AMatrixHttpContentTest() throws URISyntaxException { + } + + @Test + public void isValid() throws URISyntaxException { + assertTrue(createContentObject().isValid()); + } + + @Test + public void isValidMissingContentType() throws URISyntaxException { + assertTrue(createContentObject().isValid()); + } + + @Test + public void isValidContentNotFound() throws URISyntaxException { + assertFalse(createContentObject().isValid()); + } + + @Test + public void isValidErrorAccessDenied() throws URISyntaxException { + assertFalse(createContentObject().isValid()); + } + + @Test + public void getType() throws URISyntaxException, IOException { + assertEquals(Optional.of("text/plain"), createContentObject().getType()); + } + + @Test + public void getTypeMissingContentType() throws URISyntaxException { + assertEquals(Optional.empty(), createContentObject().getType()); + } + + @Test + public void getTypeErrorContentNotFound() throws URISyntaxException, IOException { + MatrixHttpContent contentObject = createContentObject(); + assertFalse(contentObject.isValid()); + assertThrows(IllegalStateException.class, contentObject::getType); + } + + @Test + public void getTypeErrorAccessDenied() throws URISyntaxException, IOException { + MatrixHttpContent contentObject = createContentObject(); + assertFalse(contentObject.isValid()); + assertThrows(IllegalStateException.class, createContentObject()::getType); + } + + @Test + public void getData() throws URISyntaxException, IOException { + byte[] expectedResult = Files.readAllBytes(Paths.get(ClassLoader + .getSystemResource("wiremock" + File.separator + "__files" + File.separator + bodyFilename).toURI())); + assertThat(createContentObject().getData(), IsEqual.equalTo(expectedResult)); + } + + @Test + public void getDataMissingContentType() throws URISyntaxException, IOException { + byte[] expectedResult = Files.readAllBytes(Paths.get(ClassLoader + .getSystemResource("wiremock" + File.separator + "__files" + File.separator + bodyFilename).toURI())); + assertThat(createContentObject().getData(), IsEqual.equalTo(expectedResult)); + } + + @Test + public void getDataErrorContentNotFound() throws URISyntaxException, IOException { + MatrixHttpContent contentObject = createContentObject(); + assertFalse(contentObject.isValid()); + assertThrows(IllegalStateException.class, contentObject::getData); + } + + @Test + public void getDataErrorAccessDenied() throws URISyntaxException, IOException { + MatrixHttpContent contentObject = createContentObject(); + assertFalse(contentObject.isValid()); + assertThrows(IllegalStateException.class, contentObject::getData); + } + + @Test + public void getFilename() throws URISyntaxException, IOException { + assertEquals(Optional.of(bodyFilename), createContentObject().getFilename()); + } + + @Test + public void getFilenameMissingContentType() throws URISyntaxException { + assertEquals(Optional.empty(), createContentObject().getFilename()); + } + + @Test + public void getFilenameErrorContentNotFound() throws URISyntaxException, IOException { + MatrixHttpContent contentObject = createContentObject(); + assertFalse(contentObject.isValid()); + assertThrows(IllegalStateException.class, contentObject::getFilename); + } + + @Test + public void getFilenameErrorAccessDenied() throws URISyntaxException, IOException { + MatrixHttpContent contentObject = createContentObject(); + assertFalse(contentObject.isValid()); + assertThrows(IllegalStateException.class, contentObject::getFilename); + } + + private MatrixHttpContent createContentObject() throws URISyntaxException { + MatrixClientContext context = getOrCreateClientContext(); + return new MatrixHttpContent(context, address); + } + +} diff --git a/src/test/java/io/kamax/matrix/client/AMatrixHttpRoomTest.java b/src/test/java/io/kamax/matrix/client/AMatrixHttpRoomTest.java new file mode 100644 index 0000000..457f5ef --- /dev/null +++ b/src/test/java/io/kamax/matrix/client/AMatrixHttpRoomTest.java @@ -0,0 +1,189 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Arne Augenstein + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.client; + +import io.kamax.matrix.MatrixID; +import io.kamax.matrix._MatrixID; + +import org.hamcrest.core.IsEqual; +import org.junit.Test; + +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import static org.junit.Assert.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public abstract class AMatrixHttpRoomTest extends MatrixHttpTest { + protected String roomId = "roomId892347847"; + protected String eventId = "YUwRidLecu"; + + protected String nameOfRoom = "test room"; + protected String testTopic = "test topic"; + protected String testText = "test text"; + protected String joinedUser1 = "@test:testserver.org"; + protected String joinedUser2 = "@test2:testserver.org"; + + @Test + public void getName() throws URISyntaxException { + assertThat(createRoomObject().getName(), IsEqual.equalTo(Optional.of(nameOfRoom))); + } + + @Test + public void getEmptyName() throws URISyntaxException { + assertThat(createRoomObject().getName(), IsEqual.equalTo(Optional.empty())); + } + + @Test + public void getNameAccessDenied() throws URISyntaxException { + MatrixClientRequestException e = assertThrows(MatrixClientRequestException.class, createRoomObject()::getName); + checkErrorInfoAccessDenied(e); + } + + @Test + public void getNameRateLimited() throws URISyntaxException { + MatrixClientRequestException e = assertThrows(MatrixClientRequestException.class, createRoomObject()::getName); + checkErrorInfoRateLimited(e); + } + + @Test + public void getTopic() throws URISyntaxException { + assertThat(createRoomObject().getTopic(), IsEqual.equalTo(Optional.of(testTopic))); + } + + @Test + public void getEmptyTopic() throws URISyntaxException { + assertThat(createRoomObject().getTopic(), IsEqual.equalTo(Optional.empty())); + } + + @Test + public void getTopicAccessDenied() throws URISyntaxException { + MatrixClientRequestException e = assertThrows(MatrixClientRequestException.class, createRoomObject()::getTopic); + checkErrorInfoAccessDenied(e); + } + + @Test + public void getTopicRateLimited() throws URISyntaxException { + MatrixClientRequestException e = assertThrows(MatrixClientRequestException.class, createRoomObject()::getTopic); + checkErrorInfoRateLimited(e); + } + + @Test + public void join() throws URISyntaxException { + createRoomObject().join(); + } + + @Test + public void joinRoomNotFound() throws URISyntaxException { + MatrixClientRequestException e = assertThrows(MatrixClientRequestException.class, createRoomObject()::join); + checkErrorInfoNotFound(e); + } + + @Test + public void joinAccessDenied() throws URISyntaxException { + MatrixClientRequestException e = assertThrows(MatrixClientRequestException.class, createRoomObject()::join); + checkErrorInfoAccessDenied(e); + } + + @Test + public void joinRateLimited() throws URISyntaxException { + MatrixClientRequestException e = assertThrows(MatrixClientRequestException.class, createRoomObject()::join); + checkErrorInfoRateLimited(e); + } + + @Test + public void leave() throws URISyntaxException { + createRoomObject().leave(); + } + + @Test + public void leaveAccessDenied() throws URISyntaxException { + MatrixClientRequestException e = assertThrows(MatrixClientRequestException.class, createRoomObject()::leave); + checkErrorInfoAccessDenied(e); + } + + @Test + public void leaveRoomNotFound() throws URISyntaxException { + createRoomObject().leave(); + } + + @Test + public void leaveRateLimited() throws URISyntaxException { + MatrixClientRequestException e = assertThrows(MatrixClientRequestException.class, createRoomObject()::leave); + checkErrorInfoRateLimited(e); + } + + @Test + public void sendText() throws URISyntaxException { + createRoomObject().sendText(testText); + } + + @Test + public void sendTextAccessDenied() throws URISyntaxException { + MatrixClientRequestException e = assertThrows(MatrixClientRequestException.class, + () -> createRoomObject().sendText(testText)); + checkErrorInfoAccessDenied(e); + } + + @Test + public void sendTextRoomNotFound() throws URISyntaxException { + MatrixClientRequestException e = assertThrows(MatrixClientRequestException.class, + () -> createRoomObject().sendText(testText)); + checkErrorInfoNotFound(e); + } + + @Test + public void sendTextRateLimited() throws URISyntaxException { + MatrixClientRequestException e = assertThrows(MatrixClientRequestException.class, + () -> createRoomObject().sendText(testText)); + checkErrorInfoRateLimited(e); + } + + @Test + public void getJoinedUsers() throws URISyntaxException { + List<_MatrixID> expectedResult = new ArrayList<>(); + expectedResult.add(new MatrixID(joinedUser1)); + expectedResult.add(new MatrixID(joinedUser2)); + + assertThat(createRoomObject().getJoinedUsers(), IsEqual.equalTo(expectedResult)); + } + + @Test + public void getJoinedUsersRoomNotFound() throws URISyntaxException { + MatrixClientRequestException e = assertThrows(MatrixClientRequestException.class, + createRoomObject()::getJoinedUsers); + checkErrorInfoNotFound(e); + } + + @Test + public void getJoinedUsersRateLimited() throws URISyntaxException { + MatrixClientRequestException e = assertThrows(MatrixClientRequestException.class, + createRoomObject()::getJoinedUsers); + checkErrorInfoRateLimited(e); + } + + private MatrixHttpRoom createRoomObject() throws URISyntaxException { + MatrixClientContext context = getOrCreateClientContext(); + return new MatrixHttpRoom(context, roomId); + } +} diff --git a/src/test/java/io/kamax/matrix/client/MatrixHttpContentWiremockTest.java b/src/test/java/io/kamax/matrix/client/MatrixHttpContentWiremockTest.java new file mode 100644 index 0000000..101cd29 --- /dev/null +++ b/src/test/java/io/kamax/matrix/client/MatrixHttpContentWiremockTest.java @@ -0,0 +1,175 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Arne Augenstein + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.client; + +import org.junit.Test; + +import java.io.IOException; +import java.net.URISyntaxException; + +import static com.github.tomakehurst.wiremock.client.WireMock.*; + +public class MatrixHttpContentWiremockTest extends AMatrixHttpContentTest { + private String downloadUrl = "/_matrix/media/v1/download/" + address.getHost() + address.getPath() + tokenParameter; + + public MatrixHttpContentWiremockTest() throws URISyntaxException { + } + + @Override + public void login() throws URISyntaxException { + } + + @Override + public void logout() { + } + + @Test + public void isValid() throws URISyntaxException { + stubFor(get(urlEqualTo(downloadUrl)).willReturn( + aResponse().withStatus(200).withBodyFile(bodyFilename).withHeader("Content-Type", "text/plain"))); + super.isValid(); + } + + @Test + public void isValidMissingContentType() throws URISyntaxException { + stubFor(get(urlEqualTo(downloadUrl)).willReturn(aResponse().withStatus(200).withBodyFile(bodyFilename))); + super.isValidMissingContentType(); + } + + @Test + public void isValidContentNotFound() throws URISyntaxException { + stubFor(get(urlEqualTo(downloadUrl)).willReturn(aResponse().withStatus(404).withBody(errorNotFoundResponse))); + super.isValidContentNotFound(); + } + + @Test + public void isValidErrorAccessDenied() throws URISyntaxException { + stubFor(get(urlEqualTo(downloadUrl)) + .willReturn(aResponse().withStatus(403).withBody(errorAccessDeniedResponse))); + super.isValidErrorAccessDenied(); + } + + @Test + public void getType() throws URISyntaxException, IOException { + stubFor(get(urlEqualTo(downloadUrl)).willReturn( + aResponse().withStatus(200).withBodyFile(bodyFilename).withHeader("Content-Type", "text/plain"))); + super.getType(); + } + + @Test + public void getTypeMissingContentType() throws URISyntaxException { + stubFor(get(urlEqualTo(downloadUrl)).willReturn(aResponse().withStatus(200).withBodyFile(bodyFilename))); + super.getTypeMissingContentType(); + } + + @Test + public void getTypeErrorContentNotFound() throws URISyntaxException, IOException { + stubFor(get(urlEqualTo(downloadUrl)).willReturn(aResponse().withStatus(404).withBody(errorNotFoundResponse))); + super.getTypeErrorContentNotFound(); + } + + @Test + public void getTypeErrorAccessDenied() throws URISyntaxException, IOException { + stubFor(get(urlEqualTo(downloadUrl)) + .willReturn(aResponse().withStatus(403).withBody(errorAccessDeniedResponse))); + super.getTypeErrorAccessDenied(); + } + + @Test + public void getData() throws URISyntaxException, IOException { + stubFor(get(urlEqualTo(downloadUrl)).willReturn( + aResponse().withStatus(200).withBodyFile(bodyFilename).withHeader("Content-Type", "text/plain"))); + super.getData(); + } + + @Test + public void getDataMissingContentType() throws URISyntaxException, IOException { + stubFor(get(urlEqualTo(downloadUrl)).willReturn(aResponse().withStatus(200).withBodyFile(bodyFilename))); + super.getDataMissingContentType(); + } + + @Test + public void getDataErrorContentNotFound() throws URISyntaxException, IOException { + stubFor(get(urlEqualTo(downloadUrl)).willReturn(aResponse().withStatus(404).withBody(errorNotFoundResponse))); + super.getDataErrorContentNotFound(); + } + + @Test + public void getDataErrorAccessDenied() throws URISyntaxException, IOException { + stubFor(get(urlEqualTo(downloadUrl)) + .willReturn(aResponse().withStatus(403).withBody(errorAccessDeniedResponse))); + super.getDataErrorAccessDenied(); + } + + @Test + public void getFilename() throws URISyntaxException, IOException { + stubFor(get(urlEqualTo(downloadUrl)).willReturn( + aResponse().withStatus(200).withBodyFile(bodyFilename).withHeader("Content-Type", "text/plain") + .withHeader("Content-Disposition", String.format("filename=%s;", bodyFilename)))); + super.getFilename(); + } + + @Test + public void getFilename2() throws URISyntaxException, IOException { + stubFor(get(urlEqualTo(downloadUrl)).willReturn( + aResponse().withStatus(200).withBodyFile(bodyFilename).withHeader("Content-Type", "text/plain") + .withHeader("Content-Disposition", String.format("filename=\"%s\";", bodyFilename)))); + super.getFilename(); + } + + @Test + public void getFilename3() throws URISyntaxException, IOException { + + stubFor(get(urlEqualTo(downloadUrl)).willReturn( + aResponse().withStatus(200).withBodyFile(bodyFilename).withHeader("Content-Type", "text/plain") + .withHeader("Content-Disposition", String.format("filename=\"%s\"", bodyFilename)))); + super.getFilename(); + } + + @Test + public void getFilename4() throws URISyntaxException, IOException { + stubFor(get(urlEqualTo(downloadUrl)).willReturn( + aResponse().withStatus(200).withBodyFile(bodyFilename).withHeader("Content-Type", "text/plain") + .withHeader("Content-Disposition", String.format("filename=%s", bodyFilename)))); + super.getFilename(); + } + + @Test + public void getFilenameMissingContentType() throws URISyntaxException { + stubFor(get(urlEqualTo(downloadUrl)).willReturn( + aResponse().withStatus(200).withBodyFile(bodyFilename).withHeader("Content-Type", "text/plain"))); + super.getFilenameMissingContentType(); + } + + @Test + public void getFilenameErrorContentNotFound() throws URISyntaxException, IOException { + stubFor(get(urlEqualTo(downloadUrl)).willReturn(aResponse().withStatus(404).withBody(errorNotFoundResponse))); + super.getFilenameErrorContentNotFound(); + } + + @Test + public void getFilenameErrorAccessDenied() throws URISyntaxException, IOException { + stubFor(get(urlEqualTo(downloadUrl)) + .willReturn(aResponse().withStatus(403).withBody(errorAccessDeniedResponse))); + super.getFilenameErrorAccessDenied(); + } + +} diff --git a/src/test/java/io/kamax/matrix/client/MatrixHttpRoomWiremockTest.java b/src/test/java/io/kamax/matrix/client/MatrixHttpRoomWiremockTest.java new file mode 100644 index 0000000..a6c2679 --- /dev/null +++ b/src/test/java/io/kamax/matrix/client/MatrixHttpRoomWiremockTest.java @@ -0,0 +1,201 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Arne Augenstein + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.client; + +import org.junit.Test; + +import java.net.URISyntaxException; + +import static com.github.tomakehurst.wiremock.client.WireMock.*; + +public class MatrixHttpRoomWiremockTest extends AMatrixHttpRoomTest { + private String nameUrl = String.format("/_matrix/client/r0/rooms/%s/state/m.room.name", roomId) + tokenParameter; + private String nameResponse = String.format("{\"name\": \"%s\"}", nameOfRoom); + + private String topicUrl = String.format("/_matrix/client/r0/rooms/%s/state/m.room.topic", roomId) + tokenParameter; + private String topicResponse = String.format("{\"topic\": \"%s\"}", testTopic); + + private String joinUrl = String.format("/_matrix/client/r0/rooms/%s/join", roomId) + tokenParameter; + private String joinResponse = String.format("{\"roomId\": \"%s\"}", roomId); + + private String leaveUrl = String.format("/_matrix/client/r0/rooms/%s/leave", roomId) + tokenParameter; + private String leaveResponse = String.format("{\"roomId\": \"%s\"}", roomId); + + private String sendTextUrl = String.format("/_matrix/client/r0/rooms/%s/send/m.room.message/([0-9.]+)\\", roomId) + + tokenParameter; + private String sendTextResponse = String.format("{\"event_id\": \"%s\"}", eventId) + tokenParameter; + + private String getJoinedUsersUrl = String.format("/_matrix/client/r0/rooms/%s/joined_members", roomId) + + tokenParameter; + private String getJoinedUsersResponse = String.format("{\"joined\": {\"%s\": \"1\", \"%s\": \"2\"}}", joinedUser1, + joinedUser2); + + @Override + public void login() throws URISyntaxException { + } + + @Override + public void logout() { + } + + @Test + public void getName() throws URISyntaxException { + stubFor(get(urlEqualTo(nameUrl)).willReturn(aResponse().withStatus(200).withBody(nameResponse))); + super.getName(); + } + + @Test + public void getEmptyName() throws URISyntaxException { + stubFor(get(urlEqualTo(nameUrl)).willReturn(aResponse().withStatus(404).withBody(errorNotFoundResponse))); + super.getEmptyName(); + } + + @Test + public void getNameAccessDenied() throws URISyntaxException { + stubFor(get(urlEqualTo(nameUrl)).willReturn(aResponse().withStatus(403).withBody(errorAccessDeniedResponse))); + super.getNameAccessDenied(); + } + + @Test + public void getNameRateLimited() throws URISyntaxException { + stubFor(get(urlEqualTo(nameUrl)).willReturn(aResponse().withStatus(429).withBody(errorRateLimitedResponse))); + super.getNameRateLimited(); + } + + @Test + public void getTopic() throws URISyntaxException { + stubFor(get(urlEqualTo(topicUrl)).willReturn(aResponse().withStatus(200).withBody(topicResponse))); + super.getTopic(); + } + + @Test + public void getEmptyTopic() throws URISyntaxException { + stubFor(get(urlEqualTo(topicUrl)).willReturn(aResponse().withStatus(404).withBody(errorNotFoundResponse))); + super.getEmptyTopic(); + } + + @Test + public void getTopicAccessDenied() throws URISyntaxException { + stubFor(get(urlEqualTo(topicUrl)).willReturn(aResponse().withStatus(403).withBody(errorAccessDeniedResponse))); + super.getTopicAccessDenied(); + } + + @Test + public void getTopicRateLimited() throws URISyntaxException { + stubFor(get(urlEqualTo(topicUrl)).willReturn(aResponse().withStatus(429).withBody(errorRateLimitedResponse))); + super.getTopicRateLimited(); + } + + @Test + public void join() throws URISyntaxException { + stubFor(post(urlEqualTo(joinUrl)).willReturn(aResponse().withStatus(200).withBody(joinResponse))); + super.join(); + } + + @Test + public void joinRoomNotFound() throws URISyntaxException { + stubFor(post(urlEqualTo(joinUrl)).willReturn(aResponse().withStatus(404).withBody(errorNotFoundResponse))); + super.joinRoomNotFound(); + } + + @Test + public void joinAccessDenied() throws URISyntaxException { + stubFor(post(urlEqualTo(joinUrl)).willReturn(aResponse().withStatus(403).withBody(errorAccessDeniedResponse))); + super.joinAccessDenied(); + } + + @Test + public void joinRateLimited() throws URISyntaxException { + stubFor(post(urlEqualTo(joinUrl)).willReturn(aResponse().withStatus(429).withBody(errorRateLimitedResponse))); + super.joinRateLimited(); + } + + @Test + public void leave() throws URISyntaxException { + stubFor(post(urlEqualTo(leaveUrl)).willReturn(aResponse().withStatus(200).withBody(leaveResponse))); + super.leave(); + } + + @Test + public void leaveAccessDenied() throws URISyntaxException { + stubFor(post(urlEqualTo(leaveUrl)).willReturn(aResponse().withStatus(403).withBody(errorAccessDeniedResponse))); + super.leaveAccessDenied(); + } + + @Test + public void leaveRoomNotFound() throws URISyntaxException { + stubFor(post(urlEqualTo(leaveUrl)).willReturn(aResponse().withStatus(404).withBody(errorNotFoundResponse))); + super.leaveRoomNotFound(); + } + + @Test + public void leaveRateLimited() throws URISyntaxException { + stubFor(post(urlEqualTo(leaveUrl)).willReturn(aResponse().withStatus(429).withBody(errorRateLimitedResponse))); + super.leaveRateLimited(); + } + + @Test + public void sendText() throws URISyntaxException { + stubFor(put(urlMatching(sendTextUrl)).willReturn(aResponse().withStatus(200).withBody(sendTextResponse))); + super.sendText(); + } + + @Test + public void sendTextAccessDenied() throws URISyntaxException { + stubFor(put(urlMatching(sendTextUrl)) + .willReturn(aResponse().withStatus(403).withBody(errorAccessDeniedResponse))); + super.sendTextAccessDenied(); + } + + @Test + public void sendTextRoomNotFound() throws URISyntaxException { + stubFor(put(urlMatching(sendTextUrl)).willReturn(aResponse().withStatus(404).withBody(errorNotFoundResponse))); + super.sendTextRoomNotFound(); + } + + @Test + public void sendTextRateLimited() throws URISyntaxException { + stubFor(put(urlMatching(sendTextUrl)) + .willReturn(aResponse().withStatus(429).withBody(errorRateLimitedResponse))); + super.sendTextRateLimited(); + } + + @Test + public void getJoinedUsers() throws URISyntaxException { + stubFor(get(urlEqualTo(getJoinedUsersUrl)) + .willReturn(aResponse().withStatus(200).withBody(getJoinedUsersResponse))); + super.getJoinedUsers(); + } + + @Test + public void getJoinedUsersRoomNotFound() throws URISyntaxException { + stubFor(get(urlEqualTo(getJoinedUsersUrl)) + .willReturn(aResponse().withStatus(404).withBody(errorNotFoundResponse))); + super.getJoinedUsersRoomNotFound(); + } + + @Test + public void getJoinedUsersRateLimited() throws URISyntaxException { + stubFor(get(urlEqualTo(getJoinedUsersUrl)) + .willReturn(aResponse().withStatus(429).withBody(errorRateLimitedResponse))); + super.getJoinedUsersRateLimited(); + } +} diff --git a/src/test/java/io/kamax/matrix/client/MatrixHttpTest.java b/src/test/java/io/kamax/matrix/client/MatrixHttpTest.java new file mode 100644 index 0000000..0ddd064 --- /dev/null +++ b/src/test/java/io/kamax/matrix/client/MatrixHttpTest.java @@ -0,0 +1,161 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Arne Augenstein + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.client; + +import com.github.tomakehurst.wiremock.junit.WireMockRule; + +import io.kamax.matrix.MatrixErrorInfo; +import io.kamax.matrix.MatrixID; +import io.kamax.matrix.client.regular.MatrixHttpClient; +import io.kamax.matrix.hs.MatrixHomeserver; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URISyntaxException; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; + +import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options; +import static junit.framework.TestCase.assertEquals; + +import static org.junit.Assert.assertTrue; + +public class MatrixHttpTest { + protected String testToken = "testToken"; + protected String tokenParameter = "?access_token=" + testToken; + protected int port = 8098; + protected String resourcePath = "src/test/resources/wiremock"; + + protected String domain = "localhost"; + protected String hostname = "localhost"; + protected String baseUrl = "http://" + hostname + ":" + port; + protected String username = "testuser"; + protected String password = "MostSecretPasswordEver"; + protected MatrixID user = new MatrixID(username, domain); + + protected String errorResponseTemplate = "{\"errcode\": \"%s\", \"error\": \"%s\"}"; + + protected String errcodeForbidden = "M_FORBIDDEN"; + private String errorAccessDenied = "Access denied."; + protected String errorAccessDeniedResponse = String.format(errorResponseTemplate, errcodeForbidden, + errorAccessDenied); + + private String errcodeNotFound = "M_NOT_FOUND"; + private String errorNotFound = "Element not found."; + protected String errorNotFoundResponse = String.format(errorResponseTemplate, errcodeNotFound, errorNotFound); + + private String errcodeRateLimited = "M_LIMIT_EXCEEDED"; + private String errorRateLimited = "Too many requests have been sent in a short period of time. Wait a while then try again."; + protected String errorRateLimitedResponse = String.format(errorResponseTemplate, errcodeRateLimited, + errorRateLimited); + + /** + * This method logs in to a homeserver, if the appropriate config file is present. It has to be commented out in + * Wiremock test cases. + * + * @throws URISyntaxException + */ + @Before + public void login() throws URISyntaxException { + InputStream configFile = readConfigFile(); + if (configFile != null) { + MatrixHomeserver homeserver = new MatrixHomeserver(domain, baseUrl); + MatrixClientContext context = new MatrixClientContext(homeserver); + MatrixPasswordLoginCredentials credentials = new MatrixPasswordLoginCredentials(username, password); + + client = new MatrixHttpClient(context); + client.login(credentials); + testToken = client.getAccessTokenOrThrow(); + } + } + + protected InputStream readConfigFile() { + InputStream configFile = this.getClass().getResourceAsStream("/HomeserverTest.conf"); + if (configFile != null) { + try (BufferedReader buffer = new BufferedReader(new InputStreamReader(configFile))) { + Map configValues = buffer.lines() + .filter(line -> !line.startsWith("#") && !line.isEmpty()).collect( + Collectors.toMap(line -> line.split("=")[0].trim(), line -> line.split("=")[1].trim())); + + port = Integer.valueOf(configValues.get("Port")); + hostname = configValues.get("Hostname"); + domain = configValues.get("Domain"); + baseUrl = "https://" + hostname + ":" + port; + username = configValues.get("Username"); + password = configValues.get("Password"); + user = new MatrixID(username, domain); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + return configFile; + } + + /** + * This method logs out of a homeserver, if the appropriate config file is present. It has to be commented out in + * Wiremock test cases. + */ + @After + public void logout() { + if (client != null) { + client.logout(); + client = null; + } + } + + @Rule + public WireMockRule wireMockRule = new WireMockRule(options().port(port).usingFilesUnderDirectory(resourcePath)); + protected MatrixHttpClient client; + + protected MatrixClientContext getOrCreateClientContext() { + if (client != null) { + return client.getContext(); + } else { + MatrixHomeserver hs = new MatrixHomeserver(domain, baseUrl); + return new MatrixClientContext(hs, user, testToken); + } + } + + protected void checkErrorInfoAccessDenied(MatrixClientRequestException e) { + checkErrorInfo(errcodeForbidden, errorAccessDenied, e.getError()); + } + + protected void checkErrorInfoNotFound(MatrixClientRequestException e) { + checkErrorInfo(errcodeNotFound, errorNotFound, e.getError()); + } + + protected void checkErrorInfoRateLimited(MatrixClientRequestException e) { + checkErrorInfo(errcodeRateLimited, errorRateLimited, e.getError()); + } + + protected void checkErrorInfo(String errcode, String error, Optional errorOptional) { + assertTrue(errorOptional.isPresent()); + assertEquals(errcode, errorOptional.get().getErrcode()); + assertEquals(error, errorOptional.get().getError()); + } +} diff --git a/src/test/java/io/kamax/matrix/client/as/MatrixApplicationServiceClientTest.java b/src/test/java/io/kamax/matrix/client/as/MatrixApplicationServiceClientTest.java new file mode 100644 index 0000000..ff1d8f3 --- /dev/null +++ b/src/test/java/io/kamax/matrix/client/as/MatrixApplicationServiceClientTest.java @@ -0,0 +1,76 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Arne Augenstein + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.client.as; + +import io.kamax.matrix.client.MatrixClientContext; +import io.kamax.matrix.client.MatrixClientRequestException; +import io.kamax.matrix.client.MatrixHttpTest; + +import java.net.MalformedURLException; +import java.net.URL; + +import static com.github.tomakehurst.wiremock.client.WireMock.*; + +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class MatrixApplicationServiceClientTest extends MatrixHttpTest { + private String createUserUrl = "/_matrix/client/r0/register" + tokenParameter; + private String testUser = "testUser"; + + @Override + public void login() { + } + + @Override + public void logout() { + } + + // @Test + // FIXME re-enable + public void createUser() throws MalformedURLException { + stubFor(post(urlEqualTo(createUserUrl)).willReturn(aResponse().withStatus(200))); + createClientObject().createUser(testUser); + } + + // @Test + // FIXME re-enable + public void createUserErrorRateLimited() { + stubFor(post(urlEqualTo(createUserUrl)) + .willReturn(aResponse().withStatus(429).withBody(errorRateLimitedResponse))); + + MatrixClientRequestException e = assertThrows(MatrixClientRequestException.class, + () -> createClientObject().createUser(testUser)); + checkErrorInfoRateLimited(e); + } + + private MatrixApplicationServiceClient createClientObject() throws MalformedURLException { + String domain = "localhost"; + String baseUrl = "http://localhost:" + port; + + MatrixClientContext context = new MatrixClientContext(); + context.setDomain("localhost"); + context.setHsBaseUrl(new URL(baseUrl)); + context.setUserWithLocalpart("testuser"); + + return new MatrixApplicationServiceClient(context); + } + +} diff --git a/src/test/java/io/kamax/matrix/client/regular/AMatrixHttpClientLoginTest.java b/src/test/java/io/kamax/matrix/client/regular/AMatrixHttpClientLoginTest.java new file mode 100644 index 0000000..eaf6c7e --- /dev/null +++ b/src/test/java/io/kamax/matrix/client/regular/AMatrixHttpClientLoginTest.java @@ -0,0 +1,105 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Arne Augenstein + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.client.regular; + +import io.kamax.matrix.client.MatrixClientContext; +import io.kamax.matrix.client.MatrixClientRequestException; +import io.kamax.matrix.client.MatrixHttpTest; +import io.kamax.matrix.client.MatrixPasswordLoginCredentials; +import io.kamax.matrix.hs.MatrixHomeserver; + +import org.junit.Test; +import org.junit.platform.commons.util.StringUtils; + +import java.net.URISyntaxException; + +import static org.junit.jupiter.api.Assertions.*; + +public abstract class AMatrixHttpClientLoginTest extends MatrixHttpTest { + protected String wrongPassword = "wrongPassword"; + + protected String errorInvalidPassword = "Invalid password"; + protected String errorInvalidPasswordResponse = String.format(errorResponseTemplate, errcodeForbidden, + errorInvalidPassword); + + @Override + public void logout() { + } + + @Override + public void login() { + } + + @Test + public void loginAndLogout() throws URISyntaxException { + MatrixHomeserver hs = new MatrixHomeserver(domain, baseUrl); + MatrixClientContext context = new MatrixClientContext(hs); + MatrixHttpClient client = new MatrixHttpClient(context); + + MatrixPasswordLoginCredentials credentials = new MatrixPasswordLoginCredentials(user.getLocalPart(), password); + client.login(credentials); + + assertTrue(StringUtils.isNotBlank(client.getAccessToken().get())); + assertTrue(StringUtils.isNotBlank(client.getDeviceId().get())); + assertTrue(StringUtils.isNotBlank(client.getUser().get().getId())); + + client.logout(); + } + + @Test + public void loginWithDeviceIdAndLogout() throws URISyntaxException { + MatrixHomeserver hs = new MatrixHomeserver(domain, baseUrl); + MatrixClientContext context = new MatrixClientContext(hs); + MatrixHttpClient client = new MatrixHttpClient(context); + + MatrixPasswordLoginCredentials credentials = new MatrixPasswordLoginCredentials(user.getLocalPart(), password); + client.login(credentials); + + String deviceId = client.getDeviceId().get(); + + client.logout(); + + context = new MatrixClientContext(hs).setDeviceId(deviceId); + client = new MatrixHttpClient(context); + client.login(credentials); + + assertTrue(StringUtils.isNotBlank(client.getAccessToken().get())); + assertTrue(StringUtils.isNotBlank(client.getDeviceId().get())); + assertTrue(StringUtils.isNotBlank(client.getUser().get().getId())); + assertEquals(deviceId, client.getDeviceId().get()); + + client.logout(); + } + + @Test + public void loginWrongPassword() throws URISyntaxException { + MatrixHomeserver hs = new MatrixHomeserver(domain, baseUrl); + MatrixClientContext context = new MatrixClientContext(hs); + MatrixHttpClient client = new MatrixHttpClient(context); + + MatrixPasswordLoginCredentials credentials = new MatrixPasswordLoginCredentials(user.getLocalPart(), + wrongPassword); + MatrixClientRequestException e = assertThrows(MatrixClientRequestException.class, + () -> client.login(credentials)); + checkErrorInfo(errcodeForbidden, "Invalid password", e.getError()); + } + +} diff --git a/src/test/java/io/kamax/matrix/client/regular/AMatrixHttpClientSyncTest.java b/src/test/java/io/kamax/matrix/client/regular/AMatrixHttpClientSyncTest.java new file mode 100644 index 0000000..82a2d6b --- /dev/null +++ b/src/test/java/io/kamax/matrix/client/regular/AMatrixHttpClientSyncTest.java @@ -0,0 +1,60 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2018 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.client.regular; + +import io.kamax.matrix.client.MatrixHttpTest; +import io.kamax.matrix.client._SyncData; + +import org.junit.platform.commons.util.StringUtils; + +import static junit.framework.TestCase.assertTrue; + +import static org.junit.Assert.assertNotNull; + +public abstract class AMatrixHttpClientSyncTest extends MatrixHttpTest { + + private MatrixHttpClient client; + + protected void setClient(MatrixHttpClient client) { + this.client = client; + } + + private void validateSyncData(_SyncData data) { + assertNotNull(data); + assertTrue(StringUtils.isNotBlank(data.nextBatchToken())); + assertNotNull(data.getRooms()); + assertNotNull(data.getRooms().getInvited()); + assertNotNull(data.getRooms().getJoined()); + assertNotNull(data.getRooms().getLeft()); + } + + public void getInitialSync() throws Exception { + _SyncData data = client.sync(SyncOptions.build().get()); + validateSyncData(data); + } + + public void getSeveralSync() throws Exception { + _SyncData data = client.sync(SyncOptions.build().get()); + data = client.sync(SyncOptions.build().setSince(data.nextBatchToken()).setTimeout(0).get()); + validateSyncData(data); + } + +} diff --git a/src/test/java/io/kamax/matrix/client/regular/AMatrixHttpClientTest.java b/src/test/java/io/kamax/matrix/client/regular/AMatrixHttpClientTest.java new file mode 100644 index 0000000..4dc250f --- /dev/null +++ b/src/test/java/io/kamax/matrix/client/regular/AMatrixHttpClientTest.java @@ -0,0 +1,52 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Arne Augenstein + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.client.regular; + +import io.kamax.matrix.client.MatrixClientContext; +import io.kamax.matrix.client.MatrixClientRequestException; +import io.kamax.matrix.client.MatrixHttpTest; + +import org.junit.Test; + +import java.net.URISyntaxException; + +import static org.junit.jupiter.api.Assertions.assertThrows; + +public abstract class AMatrixHttpClientTest extends MatrixHttpTest { + protected String displayName = "display name"; + + @Test + public void setDisplayName() throws URISyntaxException { + createClientObject().setDisplayName(displayName); + } + + @Test + public void setDisplayNameErrorRateLimited() throws URISyntaxException { + MatrixClientRequestException e = assertThrows(MatrixClientRequestException.class, + () -> createClientObject().setDisplayName(displayName)); + checkErrorInfoRateLimited(e); + } + + private MatrixHttpClient createClientObject() throws URISyntaxException { + MatrixClientContext context = getOrCreateClientContext(); + return new MatrixHttpClient(context); + } +} diff --git a/src/test/java/io/kamax/matrix/client/regular/MatrixHttpClientInviteByMxidWiremockTest.java b/src/test/java/io/kamax/matrix/client/regular/MatrixHttpClientInviteByMxidWiremockTest.java new file mode 100644 index 0000000..97c77b0 --- /dev/null +++ b/src/test/java/io/kamax/matrix/client/regular/MatrixHttpClientInviteByMxidWiremockTest.java @@ -0,0 +1,53 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2018 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.client.regular; + +import io.kamax.matrix.MatrixID; +import io.kamax.matrix.client.MatrixClientContext; +import io.kamax.matrix.client.MatrixHttpTest; +import io.kamax.matrix.hs.MatrixHomeserver; + +import org.junit.Test; + +import static com.github.tomakehurst.wiremock.client.WireMock.*; + +public class MatrixHttpClientInviteByMxidWiremockTest extends MatrixHttpTest { + + private final String roomId = "!id:" + domain; + private final String path = "/_matrix/client/r0/rooms/" + roomId + "/invite"; + + private String getJson() { + return "{}"; + } + + @Test + public void doInvite() throws Exception { + stubFor(post(urlPathEqualTo(path)).willReturn(aResponse().withStatus(200).withBody(getJson()))); + + MatrixHomeserver hs = new MatrixHomeserver(domain, baseUrl); + MatrixClientContext context = new MatrixClientContext(hs, MatrixID.from("bob", domain).valid(), "test"); + MatrixHttpClient client = new MatrixHttpClient(context); + client.getRoom(roomId).invite(MatrixID.from("alice", domain).valid()); + + verify(postRequestedFor(urlPathEqualTo(path))); + } + +} diff --git a/src/test/java/io/kamax/matrix/client/regular/MatrixHttpClientLoginWiremockTest.java b/src/test/java/io/kamax/matrix/client/regular/MatrixHttpClientLoginWiremockTest.java new file mode 100644 index 0000000..d672163 --- /dev/null +++ b/src/test/java/io/kamax/matrix/client/regular/MatrixHttpClientLoginWiremockTest.java @@ -0,0 +1,92 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Arne Augenstein + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ +package io.kamax.matrix.client.regular; + +import org.junit.Test; + +import java.net.URISyntaxException; + +import static com.github.tomakehurst.wiremock.client.WireMock.*; + +public class MatrixHttpClientLoginWiremockTest extends AMatrixHttpClientLoginTest { + private String loginUrl = "/_matrix/client/r0/login"; + private String logoutUrl = "/_matrix/client/r0/logout" + tokenParameter; + private String deviceId = "testDeviceId_892377"; + + @Test + @Override + public void loginAndLogout() throws URISyntaxException { + stubFor(post(urlEqualTo(loginUrl)) + .withRequestBody(equalToJson("{\"type\": \"m.login.password\"," + // + "\"user\": \"" + user.getLocalPart() + "\"," + // + "\"password\": \"" + password + "\"}")) + .willReturn(aResponse().withStatus(200) + .withBody("{\"user_id\": \"" + user.getId() + "\"," + // + "\"access_token\": \"" + testToken + "\"," + // + "\"home_server\": \"" + hostname + "\"," + // + "\"device_id\": \"" + deviceId + "\"}"))); + + stubFor(post(urlEqualTo(logoutUrl))); + + super.loginAndLogout(); + } + + @Test + @Override + public void loginWithDeviceIdAndLogout() throws URISyntaxException { + stubFor(post(urlEqualTo(loginUrl)) + .withRequestBody(equalToJson("{\"type\": \"m.login.password\"," + // + "\"user\": \"" + user.getLocalPart() + "\"," + // + "\"password\": \"" + password + "\"}")) + .willReturn(aResponse().withStatus(200) + .withBody("{\"user_id\": \"" + user.getId() + "\"," + // + "\"access_token\": \"" + testToken + "\"," + // + "\"home_server\": \"" + hostname + "\"," + // + "\"device_id\": \"" + deviceId + "\"}"))); + + stubFor(post(urlEqualTo(logoutUrl))); + + stubFor(post(urlEqualTo(loginUrl)) + .withRequestBody(equalToJson("{\"type\": \"m.login.password\"," + // + "\"user\": \"" + user.getLocalPart() + "\"," + // + "\"password\": \"" + password + "\"," + // + "\"device_id\": \"" + deviceId + "\"}")) + .willReturn(aResponse().withStatus(200) + .withBody("{\"user_id\": \"" + user.getId() + "\"," + // + "\"access_token\": \"" + testToken + "\"," + // + "\"home_server\": \"" + hostname + "\"," + // + "\"device_id\": \"" + deviceId + "\"}"))); + + super.loginWithDeviceIdAndLogout(); + } + + @Test + @Override + public void loginWrongPassword() throws URISyntaxException { + stubFor(post(urlEqualTo(loginUrl)) + .withRequestBody(equalToJson("{\"type\": \"m.login.password\"," + // + "\"user\": \"" + user.getLocalPart() + "\"," + // + "\"password\": \"" + wrongPassword + "\"}")) + .willReturn(aResponse().withStatus(403).withBody(errorInvalidPasswordResponse))); + + super.loginWrongPassword(); + } + +} diff --git a/src/test/java/io/kamax/matrix/client/regular/MatrixHttpClientSyncWiremockTest.java b/src/test/java/io/kamax/matrix/client/regular/MatrixHttpClientSyncWiremockTest.java new file mode 100644 index 0000000..d8d9884 --- /dev/null +++ b/src/test/java/io/kamax/matrix/client/regular/MatrixHttpClientSyncWiremockTest.java @@ -0,0 +1,83 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2018 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.client.regular; + +import io.kamax.matrix.MatrixID; +import io.kamax.matrix.client.MatrixClientContext; +import io.kamax.matrix.hs.MatrixHomeserver; + +import org.apache.commons.io.IOUtils; +import org.junit.Test; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; + +import static com.github.tomakehurst.wiremock.client.WireMock.*; + +public class MatrixHttpClientSyncWiremockTest extends AMatrixHttpClientSyncTest { + + private final String syncPath = "/_matrix/client/r0/sync"; + + private String getJson() { + try { + InputStream is = new FileInputStream("src/test/resources/json/client/syncInitial.json"); + return IOUtils.toString(is, StandardCharsets.UTF_8); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Test + @Override + public void getInitialSync() throws Exception { + stubFor(get(urlPathEqualTo(syncPath)).willReturn(aResponse().withStatus(200).withBody(getJson()))); + + MatrixHomeserver hs = new MatrixHomeserver(domain, baseUrl); + MatrixClientContext context = new MatrixClientContext(hs, MatrixID.asValid("@user:localhost"), "test"); + MatrixHttpClient client = new MatrixHttpClient(context); + setClient(client); + + super.getInitialSync(); + + verify(getRequestedFor(urlPathEqualTo(syncPath))); + } + + @Test + @Override + public void getSeveralSync() throws Exception { + stubFor(get(urlPathEqualTo(syncPath)).willReturn(aResponse().withStatus(200).withBody(getJson()))); + stubFor(get(urlPathEqualTo(syncPath)).withQueryParam("access_token", equalTo("test")) + .withQueryParam("timeout", equalTo("0")).willReturn(aResponse().withStatus(200).withBody(getJson()))); + + MatrixHomeserver hs = new MatrixHomeserver(domain, baseUrl); + MatrixClientContext context = new MatrixClientContext(hs, MatrixID.asValid("@user:localhost"), "test"); + MatrixHttpClient client = new MatrixHttpClient(context); + setClient(client); + + super.getSeveralSync(); + + verify(getRequestedFor(urlPathEqualTo(syncPath))); + verify(getRequestedFor(urlPathEqualTo(syncPath)).withQueryParam("timeout", equalTo("0"))); + } + +} diff --git a/src/test/java/io/kamax/matrix/client/regular/MatrixHttpClientWiremockTest.java b/src/test/java/io/kamax/matrix/client/regular/MatrixHttpClientWiremockTest.java new file mode 100644 index 0000000..1deb75d --- /dev/null +++ b/src/test/java/io/kamax/matrix/client/regular/MatrixHttpClientWiremockTest.java @@ -0,0 +1,56 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Arne Augenstein + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.client.regular; + +import org.junit.Test; + +import java.net.URISyntaxException; + +import static com.github.tomakehurst.wiremock.client.WireMock.*; + +public class MatrixHttpClientWiremockTest extends AMatrixHttpClientTest { + private String setDisplaynameUrl = String.format("/_matrix/client/r0/profile/%s/displayname", + getOrCreateClientContext().getUser().get().getId()) + tokenParameter; + + public MatrixHttpClientWiremockTest() throws URISyntaxException { + } + + @Override + public void login() throws URISyntaxException { + } + + @Override + public void logout() { + } + + @Test + public void setDisplayName() throws URISyntaxException { + stubFor(put(urlEqualTo(setDisplaynameUrl)).willReturn(aResponse().withStatus(200))); + super.setDisplayName(); + } + + @Test + public void setDisplayNameErrorRateLimited() throws URISyntaxException { + stubFor(put(urlEqualTo(setDisplaynameUrl)) + .willReturn(aResponse().withStatus(429).withBody(errorRateLimitedResponse))); + super.setDisplayNameErrorRateLimited(); + } +} diff --git a/src/test/java/io/kamax/matrix/client/regular/RoomCreateWiremockTest.java b/src/test/java/io/kamax/matrix/client/regular/RoomCreateWiremockTest.java new file mode 100644 index 0000000..0023fa3 --- /dev/null +++ b/src/test/java/io/kamax/matrix/client/regular/RoomCreateWiremockTest.java @@ -0,0 +1,62 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2018 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.client.regular; + +import com.google.gson.JsonObject; + +import io.kamax.matrix.MatrixID; +import io.kamax.matrix.client.MatrixClientContext; +import io.kamax.matrix.client.MatrixHttpTest; +import io.kamax.matrix.hs.MatrixHomeserver; +import io.kamax.matrix.hs._MatrixRoom; +import io.kamax.matrix.json.GsonUtil; +import io.kamax.matrix.room.RoomCreationOptions; + +import org.apache.commons.lang3.StringUtils; +import org.junit.Test; + +import static com.github.tomakehurst.wiremock.client.WireMock.*; +import static junit.framework.TestCase.assertTrue; + +public class RoomCreateWiremockTest extends MatrixHttpTest { + + private final String syncPath = "/_matrix/client/r0/createRoom"; + + @Test + public void createRoomWithNoOption() throws Exception { + String roomId = "!roomId:" + domain; + JsonObject resBody = new JsonObject(); + resBody.addProperty("room_id", roomId); + String resBodyRaw = GsonUtil.get().toJson(resBody); + stubFor(post(urlPathEqualTo("/_matrix/client/r0/createRoom")) + .willReturn(aResponse().withStatus(200).withBody(resBodyRaw))); + + MatrixHomeserver hs = new MatrixHomeserver(domain, baseUrl); + MatrixClientContext context = new MatrixClientContext(hs, MatrixID.asValid("@user:localhost"), "test"); + MatrixHttpClient client = new MatrixHttpClient(context); + + _MatrixRoom room = client.createRoom(RoomCreationOptions.none()); + assertTrue(StringUtils.equals(room.getAddress(), roomId)); + + verify(postRequestedFor(urlPathEqualTo(syncPath))); + } + +} diff --git a/src/test/java/io/kamax/matrix/client/regular/SyncDataJsonTest.java b/src/test/java/io/kamax/matrix/client/regular/SyncDataJsonTest.java new file mode 100644 index 0000000..54faeb4 --- /dev/null +++ b/src/test/java/io/kamax/matrix/client/regular/SyncDataJsonTest.java @@ -0,0 +1,50 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2018 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.client.regular; + +import io.kamax.matrix.json.GsonUtil; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; +import org.junit.Test; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; + +import static junit.framework.TestCase.assertTrue; + +public class SyncDataJsonTest { + + @Test + public void readValidJson() throws IOException { + InputStream is = new FileInputStream("src/test/resources/json/client/syncInitial.json"); + String rawJson = IOUtils.toString(is, StandardCharsets.UTF_8); + SyncDataJson data = new SyncDataJson(GsonUtil.parseObj(rawJson)); + + assertTrue(StringUtils.equals(data.nextBatchToken(), "s70_301_72_2_36_1_1_5_1")); + assertTrue(!data.getRooms().getInvited().isEmpty()); + assertTrue(!data.getRooms().getJoined().isEmpty()); + assertTrue(data.getRooms().getLeft().isEmpty()); + } + +} diff --git a/src/test/java/io/kamax/matrix/json/MatrixJsonTest.java b/src/test/java/io/kamax/matrix/json/MatrixJsonTest.java new file mode 100644 index 0000000..3080c16 --- /dev/null +++ b/src/test/java/io/kamax/matrix/json/MatrixJsonTest.java @@ -0,0 +1,94 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.json; + +import org.junit.Test; + +import java.io.IOException; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class MatrixJsonTest { + + @Test + public void encodeCanonicalEmptyObject() throws IOException { + String s = MatrixJson.encodeCanonical("{}"); + assertTrue("{}".equals(s), s); + } + + @Test + public void encodeCanonicalObjectCanonical() throws IOException { + String s = MatrixJson.encodeCanonical("{\"a\":\"1\",\"b\":\"2\"}\n"); + assertTrue("{\"a\":\"1\",\"b\":\"2\"}".equals(s), s); + } + + @Test + public void encodeCanonicalObjectNotCanonical() throws IOException { + String s = MatrixJson.encodeCanonical("{\"b\":\"2\",\"a\":\"1\"}"); + assertTrue("{\"a\":\"1\",\"b\":\"2\"}".equals(s), s); + + } + + @Test + public void encodeCanonicalJsonWithLineFeeds() { + String s = MatrixJson.encodeCanonical("{\n" + " \"one\": 1,\n" + " \"two\": \"Two\"\n" + "}"); + assertTrue("{\"one\":1,\"two\":\"Two\"}".equals(s), s); + } + + @Test + public void encodeCanonicalComplicatedObject() { + String s = MatrixJson.encodeCanonical("{\n" + " \"auth\": {\n" + " \"success\": true,\n" + + " \"mxid\": \"@john.doe:example.com\",\n" + " \"profile\": {\n" + + " \"display_name\": \"John Doe\",\n" + " \"three_pids\": [\n" + " {\n" + + " \"medium\": \"email\",\n" + " \"address\": \"john.doe@example.org\"\n" + + " },\n" + " {\n" + " \"medium\": \"msisdn\",\n" + + " \"address\": \"123456789\"\n" + " }\n" + " ]\n" + " }\n" + " }\n" + "}\n"); + + assertTrue(("{\"auth\":{\"mxid\":\"@john.doe:example.com\",\"profile\":{\"display_name\":\"John Doe\"," + + "\"three_pids\":[{\"address\":\"john.doe@example.org\",\"medium\":\"email\"}," + + "{\"address\":\"123456789\",\"medium\":\"msisdn\"}]},\"success\":true}}").equals(s), s); + } + + @Test + public void encodeCanonicalSimpleUtf8Canonical() { + String s = MatrixJson.encodeCanonical("{\"a\":\"日本語\"}"); + assertTrue("{\"a\":\"日本語\"}".equals(s), s); + } + + @Test + public void encodeCanonicalSimpleUtf8NotCanonical() { + String s = MatrixJson.encodeCanonical("{\"本\":2,\"日\":1}"); + assertTrue("{\"日\":1,\"本\":2}".equals(s), s); + } + + @Test + public void encodeCanonicalUtf8Escaped() { + String s = MatrixJson.encodeCanonical("{\"a\":\"\\u65E5\"}"); + assertTrue("{\"a\":\"日\"}".equals(s), s); + } + + @Test + public void encodeCanonicalNull() { + String s = MatrixJson.encodeCanonical("{\"a\":null}"); + assertTrue("{\"a\":null}".equals(s), s); + } + +} diff --git a/src/test/java/io/kamax/matrix/sign/KeyFileStoreTest.java b/src/test/java/io/kamax/matrix/sign/KeyFileStoreTest.java new file mode 100644 index 0000000..95b7894 --- /dev/null +++ b/src/test/java/io/kamax/matrix/sign/KeyFileStoreTest.java @@ -0,0 +1,43 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.sign; + +import org.junit.Test; + +import java.io.File; +import java.io.IOException; + +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsEqual.*; +import static org.junit.Assert.assertThat; + +public class KeyFileStoreTest { + + private final String key = "YJDBA9Xnr2sVqXD9Vj7XVUnmFZcZrlw8Md7kMW+3XA1"; + + @Test + public void test() throws IOException { + KeyFileStore store = new KeyFileStore(File.createTempFile("matrix-java-sdkSignTest", ".key").getPath()); + store.store(key); + assertThat(key, is(equalTo(store.load().orElse("")))); + } + +} diff --git a/src/test/java/io/kamax/matrix/sign/SignatureManagerTest.java b/src/test/java/io/kamax/matrix/sign/SignatureManagerTest.java new file mode 100644 index 0000000..860e461 --- /dev/null +++ b/src/test/java/io/kamax/matrix/sign/SignatureManagerTest.java @@ -0,0 +1,69 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Maxime Dor + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.sign; + +import com.google.gson.JsonObject; + +import org.junit.BeforeClass; +import org.junit.Test; + +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsEqual.*; +import static org.junit.Assert.assertThat; + +public class SignatureManagerTest { + + private static SignatureManager signMgr; + + @BeforeClass + public static void beforeClass() { + signMgr = new SignatureManager( + new KeyManager(new KeyMemoryStore("YJDBA9Xnr2sVqXD9Vj7XVUnmFZcZrlw8Md7kMW+3XA1")), "domain"); + } + + @Test + public void emptyObject() { + assertThat(signMgr.sign("{}"), + is(equalTo("K8280/U9SSy9IVtjBuVeLr+HpOB4BQFWbg+UZaADMtTdGYI7Geitb76LTrr5QV/7Xg4ahLwYGYZzuHGZKM5ZAQ"))); + } + + @Test + public void simpleObject() { + assertThat(signMgr.sign("{\"one\":1,\"two\":\"Two\"}"), + is(equalTo("KqmLSbO39/Bzb0QIYE82zqLwsA+PDzYIpIRA2sRQ4sL53+sN6/fpNSoqE7BP7vBZhG6kYdD13EIMJpvhJI+6Bw"))); + } + + @Test + public void test() { + SignatureManager mgr = new SignatureManager( + new KeyManager(new KeyMemoryStore("1QblgjFeL3IxoY4DKOR7p5mL5sQTC0ChmeMJlqb4d5M")), + "synapse.local.kamax.io"); + JsonObject o = new JsonObject(); + o.addProperty("method", "GET"); + o.addProperty("uri", "/_matrix/federation/v1/query/directory?room_alias=%23a%3Amxhsd.local.kamax.io%3A8447"); + o.addProperty("origin", "synapse.local.kamax.io"); + o.addProperty("destination", "mxhsd.local.kamax.io:8447"); + String signature = mgr.sign(o); + assertThat(signature, + is(equalTo("SEMGSOJEsoalrBfHqPO2QrSlbLaUYLHLk4e3q4IJ2JbgvCynT1onp7QF1U4Sl3G3NzybrgdnVvpqcaEgV0WPCw"))); + } + +} diff --git a/src/test/resources/json/client/syncInitial.json b/src/test/resources/json/client/syncInitial.json new file mode 100644 index 0000000..3cf8768 --- /dev/null +++ b/src/test/resources/json/client/syncInitial.json @@ -0,0 +1,614 @@ +{ + "account_data": { + "events": [ + { + "content": { + "device": {}, + "global": { + "content": [ + { + "actions": [ + "notify", + { + "set_tweak": "sound", + "value": "default" + }, + { + "set_tweak": "highlight" + } + ], + "default": true, + "enabled": true, + "pattern": "user", + "rule_id": ".m.rule.contains_user_name" + } + ], + "override": [ + { + "actions": [ + "dont_notify" + ], + "conditions": [], + "default": true, + "enabled": false, + "rule_id": ".m.rule.master" + }, + { + "actions": [ + "dont_notify" + ], + "conditions": [ + { + "key": "content.msgtype", + "kind": "event_match", + "pattern": "m.notice" + } + ], + "default": true, + "enabled": true, + "rule_id": ".m.rule.suppress_notices" + }, + { + "actions": [ + "notify", + { + "set_tweak": "sound", + "value": "default" + }, + { + "set_tweak": "highlight", + "value": false + } + ], + "conditions": [ + { + "key": "type", + "kind": "event_match", + "pattern": "m.room.member" + }, + { + "key": "content.membership", + "kind": "event_match", + "pattern": "invite" + }, + { + "key": "state_key", + "kind": "event_match", + "pattern": "@user:synapse.local.kamax.io" + } + ], + "default": true, + "enabled": true, + "rule_id": ".m.rule.invite_for_me" + }, + { + "actions": [ + "dont_notify" + ], + "conditions": [ + { + "key": "type", + "kind": "event_match", + "pattern": "m.room.member" + } + ], + "default": true, + "enabled": true, + "rule_id": ".m.rule.member_event" + }, + { + "actions": [ + "notify", + { + "set_tweak": "sound", + "value": "default" + }, + { + "set_tweak": "highlight" + } + ], + "conditions": [ + { + "kind": "contains_display_name" + } + ], + "default": true, + "enabled": true, + "rule_id": ".m.rule.contains_display_name" + }, + { + "actions": [ + "notify", + { + "set_tweak": "highlight", + "value": true + } + ], + "conditions": [ + { + "key": "content.body", + "kind": "event_match", + "pattern": "@room" + }, + { + "key": "room", + "kind": "sender_notification_permission" + } + ], + "default": true, + "enabled": true, + "rule_id": ".m.rule.roomnotif" + } + ], + "room": [], + "sender": [], + "underride": [ + { + "actions": [ + "notify", + { + "set_tweak": "sound", + "value": "ring" + }, + { + "set_tweak": "highlight", + "value": false + } + ], + "conditions": [ + { + "key": "type", + "kind": "event_match", + "pattern": "m.call.invite" + } + ], + "default": true, + "enabled": true, + "rule_id": ".m.rule.call" + }, + { + "actions": [ + "notify", + { + "set_tweak": "sound", + "value": "default" + }, + { + "set_tweak": "highlight", + "value": false + } + ], + "conditions": [ + { + "is": "2", + "kind": "room_member_count" + }, + { + "key": "type", + "kind": "event_match", + "pattern": "m.room.message" + } + ], + "default": true, + "enabled": true, + "rule_id": ".m.rule.room_one_to_one" + }, + { + "actions": [ + "notify", + { + "set_tweak": "sound", + "value": "default" + }, + { + "set_tweak": "highlight", + "value": false + } + ], + "conditions": [ + { + "is": "2", + "kind": "room_member_count" + }, + { + "key": "type", + "kind": "event_match", + "pattern": "m.room.encrypted" + } + ], + "default": true, + "enabled": true, + "rule_id": ".m.rule.encrypted_room_one_to_one" + }, + { + "actions": [ + "notify", + { + "set_tweak": "highlight", + "value": false + } + ], + "conditions": [ + { + "key": "type", + "kind": "event_match", + "pattern": "m.room.message" + } + ], + "default": true, + "enabled": true, + "rule_id": ".m.rule.message" + }, + { + "actions": [ + "notify", + { + "set_tweak": "highlight", + "value": false + } + ], + "conditions": [ + { + "key": "type", + "kind": "event_match", + "pattern": "m.room.encrypted" + } + ], + "default": true, + "enabled": true, + "rule_id": ".m.rule.encrypted" + } + ] + } + }, + "type": "m.push_rules" + } + ] + }, + "device_lists": { + "changed": [], + "left": [] + }, + "device_one_time_keys_count": { + "signed_curve25519": 50 + }, + "groups": { + "invite": {}, + "join": {}, + "leave": {} + }, + "next_batch": "s70_301_72_2_36_1_1_5_1", + "presence": { + "events": [ + { + "content": { + "currently_active": true, + "last_active_ago": 6, + "presence": "online" + }, + "sender": "@user:synapse.local.kamax.io", + "type": "m.presence" + } + ] + }, + "rooms": { + "invite": { + "!sKXtjLhFyymcVWDNuS:synapse.local.kamax.io": { + "invite_state": { + "events": [ + { + "content": { + "join_rule": "invite" + }, + "sender": "@user1:synapse.local.kamax.io", + "state_key": "", + "type": "m.room.join_rules" + }, + { + "content": { + "avatar_url": null, + "displayname": "user1", + "membership": "join" + }, + "sender": "@user1:synapse.local.kamax.io", + "state_key": "@user1:synapse.local.kamax.io", + "type": "m.room.member" + }, + { + "content": { + "avatar_url": null, + "displayname": "user", + "membership": "invite" + }, + "event_id": "$151873502072wyKmm:synapse.local.kamax.io", + "membership": "invite", + "origin_server_ts": 1518735020331, + "sender": "@user1:synapse.local.kamax.io", + "state_key": "@user:synapse.local.kamax.io", + "type": "m.room.member", + "unsigned": { + "age": 107139 + } + } + ] + } + } + }, + "join": { + "!KctOqwskWrXZIfCoEq:synapse.local.kamax.io": { + "account_data": { + "events": [ + { + "content": { + "event_id": "$151873504082FsAsX:synapse.local.kamax.io" + }, + "type": "m.fully_read" + } + ] + }, + "ephemeral": { + "events": [ + { + "content": { + "user_ids": [] + }, + "type": "m.typing" + } + ] + }, + "state": { + "events": [ + { + "content": { + "join_rule": "invite" + }, + "event_id": "$15187348984DMKLE:synapse.local.kamax.io", + "origin_server_ts": 1518734898734, + "sender": "@user:synapse.local.kamax.io", + "state_key": "", + "type": "m.room.join_rules", + "unsigned": { + "age": 228736 + } + }, + { + "content": { + "guest_access": "can_join" + }, + "event_id": "$15187348986NDVXj:synapse.local.kamax.io", + "origin_server_ts": 1518734898871, + "sender": "@user:synapse.local.kamax.io", + "state_key": "", + "type": "m.room.guest_access", + "unsigned": { + "age": 228599 + } + }, + { + "content": { + "creator": "@user:synapse.local.kamax.io" + }, + "event_id": "$15187348981QFhLu:synapse.local.kamax.io", + "origin_server_ts": 1518734898574, + "sender": "@user:synapse.local.kamax.io", + "state_key": "", + "type": "m.room.create", + "unsigned": { + "age": 228896 + } + }, + { + "content": { + "avatar_url": null, + "displayname": "user", + "membership": "join" + }, + "event_id": "$15187348982xNmgY:synapse.local.kamax.io", + "membership": "join", + "origin_server_ts": 1518734898610, + "sender": "@user:synapse.local.kamax.io", + "state_key": "@user:synapse.local.kamax.io", + "type": "m.room.member", + "unsigned": { + "age": 228860 + } + }, + { + "content": { + "history_visibility": "shared" + }, + "event_id": "$15187348985sKxWB:synapse.local.kamax.io", + "origin_server_ts": 1518734898825, + "sender": "@user:synapse.local.kamax.io", + "state_key": "", + "type": "m.room.history_visibility", + "unsigned": { + "age": 228645 + } + }, + { + "content": { + "ban": 50, + "events": { + "m.room.avatar": 50, + "m.room.canonical_alias": 50, + "m.room.history_visibility": 100, + "m.room.name": 50, + "m.room.power_levels": 100 + }, + "events_default": 0, + "invite": 0, + "kick": 50, + "redact": 50, + "state_default": 50, + "users": { + "@user:synapse.local.kamax.io": 100 + }, + "users_default": 0 + }, + "event_id": "$15187348983yhWHj:synapse.local.kamax.io", + "origin_server_ts": 1518734898656, + "sender": "@user:synapse.local.kamax.io", + "state_key": "", + "type": "m.room.power_levels", + "unsigned": { + "age": 228814 + } + } + ] + }, + "timeline": { + "events": [ + { + "content": { + "body": "0", + "msgtype": "m.text" + }, + "event_id": "$151873499556eltks:synapse.local.kamax.io", + "origin_server_ts": 1518734995565, + "sender": "@user:synapse.local.kamax.io", + "type": "m.room.message", + "unsigned": { + "age": 131905, + "transaction_id": "m1518734925742.26" + } + }, + { + "content": { + "body": "1", + "msgtype": "m.text" + }, + "event_id": "$151873500058XGoUq:synapse.local.kamax.io", + "origin_server_ts": 1518735000601, + "sender": "@user:synapse.local.kamax.io", + "type": "m.room.message", + "unsigned": { + "age": 126869, + "transaction_id": "m1518734926600.27" + } + }, + { + "content": { + "body": "2", + "msgtype": "m.text" + }, + "event_id": "$151873500560dBVkH:synapse.local.kamax.io", + "origin_server_ts": 1518735005559, + "sender": "@user:synapse.local.kamax.io", + "type": "m.room.message", + "unsigned": { + "age": 121911, + "transaction_id": "m1518734927224.28" + } + }, + { + "content": { + "body": "3", + "msgtype": "m.text" + }, + "event_id": "$151873501068SVPIh:synapse.local.kamax.io", + "origin_server_ts": 1518735010556, + "sender": "@user:synapse.local.kamax.io", + "type": "m.room.message", + "unsigned": { + "age": 116914, + "transaction_id": "m1518734927730.29" + } + }, + { + "content": { + "body": "4", + "msgtype": "m.text" + }, + "event_id": "$151873501570ghvSe:synapse.local.kamax.io", + "origin_server_ts": 1518735015568, + "sender": "@user:synapse.local.kamax.io", + "type": "m.room.message", + "unsigned": { + "age": 111902, + "transaction_id": "m1518734928220.30" + } + }, + { + "content": { + "body": "5", + "msgtype": "m.text" + }, + "event_id": "$151873502073xOCWH:synapse.local.kamax.io", + "origin_server_ts": 1518735020570, + "sender": "@user:synapse.local.kamax.io", + "type": "m.room.message", + "unsigned": { + "age": 106900, + "transaction_id": "m1518734929066.31" + } + }, + { + "content": { + "body": "6", + "msgtype": "m.text" + }, + "event_id": "$151873502576wKFoA:synapse.local.kamax.io", + "origin_server_ts": 1518735025559, + "sender": "@user:synapse.local.kamax.io", + "type": "m.room.message", + "unsigned": { + "age": 101911, + "transaction_id": "m1518734929542.32" + } + }, + { + "content": { + "body": "7", + "msgtype": "m.text" + }, + "event_id": "$151873503078mPqaN:synapse.local.kamax.io", + "origin_server_ts": 1518735030576, + "sender": "@user:synapse.local.kamax.io", + "type": "m.room.message", + "unsigned": { + "age": 96894, + "transaction_id": "m1518734930141.33" + } + }, + { + "content": { + "body": "8", + "msgtype": "m.text" + }, + "event_id": "$151873503580HWbKx:synapse.local.kamax.io", + "origin_server_ts": 1518735035574, + "sender": "@user:synapse.local.kamax.io", + "type": "m.room.message", + "unsigned": { + "age": 91896, + "transaction_id": "m1518734930731.34" + } + }, + { + "content": { + "body": "9", + "msgtype": "m.text" + }, + "event_id": "$151873504082FsAsX:synapse.local.kamax.io", + "origin_server_ts": 1518735040568, + "sender": "@user:synapse.local.kamax.io", + "type": "m.room.message", + "unsigned": { + "age": 86902, + "transaction_id": "m1518734932231.35" + } + } + ], + "limited": true, + "prev_batch": "t33-51_301_72_2_36_1_1_5_1" + }, + "unread_notifications": {} + } + }, + "leave": {} + }, + "to_device": { + "events": [] + } +} diff --git a/src/test/resources/wiremock/__files/textfile.txt b/src/test/resources/wiremock/__files/textfile.txt new file mode 100644 index 0000000..53b68c0 --- /dev/null +++ b/src/test/resources/wiremock/__files/textfile.txt @@ -0,0 +1 @@ +text file with test text \ No newline at end of file diff --git a/src/testInt/java/io/kamax/matrix/MatrixHttpUserTest.java b/src/testInt/java/io/kamax/matrix/MatrixHttpUserTest.java new file mode 100644 index 0000000..e5cc545 --- /dev/null +++ b/src/testInt/java/io/kamax/matrix/MatrixHttpUserTest.java @@ -0,0 +1,25 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Arne Augenstein + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix; + +public class MatrixHttpUserTest extends AMatrixHttpUserTest { + +} diff --git a/src/testInt/java/io/kamax/matrix/client/MatrixHttpContentTest.java b/src/testInt/java/io/kamax/matrix/client/MatrixHttpContentTest.java new file mode 100644 index 0000000..cf53baf --- /dev/null +++ b/src/testInt/java/io/kamax/matrix/client/MatrixHttpContentTest.java @@ -0,0 +1,29 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Arne Augenstein + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.client; + +import java.net.URISyntaxException; + +public class MatrixHttpContentTest extends AMatrixHttpContentTest { + + public MatrixHttpContentTest() throws URISyntaxException { + } +} diff --git a/src/testInt/java/io/kamax/matrix/client/MatrixHttpRoomTest.java b/src/testInt/java/io/kamax/matrix/client/MatrixHttpRoomTest.java new file mode 100644 index 0000000..4b9c7e2 --- /dev/null +++ b/src/testInt/java/io/kamax/matrix/client/MatrixHttpRoomTest.java @@ -0,0 +1,25 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Arne Augenstein + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.client; + +public class MatrixHttpRoomTest extends AMatrixHttpRoomTest { + +} diff --git a/src/testInt/java/io/kamax/matrix/client/regular/MatrixHttpClientLoginTest.java b/src/testInt/java/io/kamax/matrix/client/regular/MatrixHttpClientLoginTest.java new file mode 100644 index 0000000..6372f93 --- /dev/null +++ b/src/testInt/java/io/kamax/matrix/client/regular/MatrixHttpClientLoginTest.java @@ -0,0 +1,32 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Arne Augenstein + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ +package io.kamax.matrix.client.regular; + +import org.junit.Before; + +import java.net.URISyntaxException; + +public class MatrixHttpClientLoginTest extends AMatrixHttpClientLoginTest { + @Before + public void prepareLogin() throws URISyntaxException { + readConfigFile(); + } + +} diff --git a/src/testInt/java/io/kamax/matrix/client/regular/MatrixHttpClientTest.java b/src/testInt/java/io/kamax/matrix/client/regular/MatrixHttpClientTest.java new file mode 100644 index 0000000..6ab777e --- /dev/null +++ b/src/testInt/java/io/kamax/matrix/client/regular/MatrixHttpClientTest.java @@ -0,0 +1,24 @@ +/* + * matrix-java-sdk - Matrix Client SDK for Java + * Copyright (C) 2017 Arne Augenstein + * + * https://www.kamax.io/ + * + * 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 3 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, see . + */ + +package io.kamax.matrix.client.regular; + +public class MatrixHttpClientTest extends AMatrixHttpClientTest { +} diff --git a/src/testInt/resources/.gitignore b/src/testInt/resources/.gitignore new file mode 100644 index 0000000..d3e7d11 --- /dev/null +++ b/src/testInt/resources/.gitignore @@ -0,0 +1 @@ +HomeserverTest.conf diff --git a/src/testInt/resources/HomeserverTest.conf_template b/src/testInt/resources/HomeserverTest.conf_template new file mode 100644 index 0000000..2745e2f --- /dev/null +++ b/src/testInt/resources/HomeserverTest.conf_template @@ -0,0 +1,11 @@ +# If you want to run these tests against a real homeserver, please fill out the necessary information below and +# rename this file to test.conf + +# Server information +Domain = localhost +Hostname = localhost +Port = 443 + +# User credentials +Username = xxx +Password = xxx \ No newline at end of file