├── .gitignore ├── .idea ├── libraries │ └── jwt_generator.xml └── sbt.xml ├── LICENSE ├── README.md ├── Samples ├── production │ └── zapi-cloud │ │ ├── .gitignore │ │ ├── .idea │ │ ├── libraries │ │ │ ├── json_20180813.xml │ │ │ └── jwt_generator.xml │ │ ├── modules.xml │ │ ├── sbt.xml │ │ └── vcs.xml │ │ ├── LICENSE │ │ ├── README.md │ │ └── generator │ │ ├── java │ │ ├── compiled │ │ │ └── jwt-generator.jar │ │ ├── pom.xml │ │ ├── src │ │ │ └── main │ │ │ │ └── resources │ │ │ │ ├── ZConfigConstants.properties │ │ │ │ └── jira-rest-java-client-core-2.0.1.jar │ │ └── target │ │ │ ├── classes │ │ │ └── ZConfigConstants.properties │ │ │ ├── maven-archiver │ │ │ └── pom.properties │ │ │ ├── maven-status │ │ │ └── maven-compiler-plugin │ │ │ │ ├── compile │ │ │ │ └── default-compile │ │ │ │ │ ├── createdFiles.lst │ │ │ │ │ └── inputFiles.lst │ │ │ │ └── testCompile │ │ │ │ └── default-testCompile │ │ │ │ ├── createdFiles.lst │ │ │ │ └── inputFiles.lst │ │ │ ├── zfj-cloud-rest-client-1.1-jar-with-dependencies.jar │ │ │ ├── zfj-cloud-rest-client-1.1.jar │ │ │ ├── zfj-cloud-rest-client-1.2-jar-with-dependencies.jar │ │ │ ├── zfj-cloud-rest-client-1.2.jar │ │ │ ├── zfj-cloud-rest-client-1.3-jar-with-dependencies.jar │ │ │ └── zfj-cloud-rest-client-1.3.jar │ │ └── python │ │ ├── CycleTest.py │ │ ├── README.md │ │ ├── models │ │ ├── Cycle.py │ │ └── __init__.py │ │ └── util │ │ ├── JWTGenerator.py │ │ └── __init__.py └── src │ └── com │ └── thed │ └── zapi │ └── cloud │ └── sample │ ├── CreateCycleAndAddTests.java │ ├── CreateTestWithTestSteps.java │ ├── CycleExecutionReportByVersion.java │ ├── FetchExecuteUpdate.java │ └── sampleJwtGenerator.java └── generator ├── java ├── compiled │ └── jwt-generator.jar ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── thed │ │ │ └── zephyr │ │ │ └── cloud │ │ │ └── rest │ │ │ ├── ZFJCloudRestClient.java │ │ │ ├── client │ │ │ ├── JwtAuthorizationGenerator.java │ │ │ ├── JwtGenerator.java │ │ │ └── impl │ │ │ │ └── JwtGeneratorImpl.java │ │ │ ├── exception │ │ │ └── JobProgressException.java │ │ │ └── model │ │ │ └── ZConfig.java │ └── resources │ │ ├── ZConfigConstants.properties │ │ └── jira-rest-java-client-core-2.0.1.jar │ └── test │ └── java │ └── com │ └── thed │ └── zephyr │ ├── GenerateJWTTest.java │ └── util │ └── AbstractTest.java └── python ├── CycleTest.py ├── README.md ├── models ├── Cycle.py ├── __init__.py └── __pycache__ │ ├── Cycle.cpython-35.pyc │ └── __init__.cpython-35.pyc └── util ├── JWTGenerator.py ├── JWTGenerator.pyc ├── __init__.py ├── __init__.pyc └── __pycache__ ├── JWTGenerator.cpython-35.pyc └── __init__.cpython-35.pyc /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | # Mobile Tools for Java (J2ME) 4 | .mtj.tmp/ 5 | 6 | # Package Files # 7 | *.war 8 | *.ear 9 | 10 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 11 | hs_err_pid* 12 | -------------------------------------------------------------------------------- /.idea/libraries/jwt_generator.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/sbt.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # zapi-cloud 2 | 3 | Following the scheduled migration weekend, you will need to regenerate the API keys again and also pass in accountId instead of UserKey in the JWT Token.
4 | 5 | zfj-cloud-rest-client-1.2-jar-with-dependencies.jar should only be used by customer who has received the scheduled migration email. The artifact can be updated after the scheduled downtime is over. 6 | 7 | 8 | For all other customers who have not recevied scheduled migration email should continue to use the old artifact (zfj-cloud-rest-client-1.1-jar-with-dependencies.jar) until you receive the scheduled migration email. 9 | -------------------------------------------------------------------------------- /Samples/production/zapi-cloud/.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | # Mobile Tools for Java (J2ME) 4 | .mtj.tmp/ 5 | 6 | # Package Files # 7 | *.war 8 | *.ear 9 | 10 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 11 | hs_err_pid* 12 | -------------------------------------------------------------------------------- /Samples/production/zapi-cloud/.idea/libraries/json_20180813.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Samples/production/zapi-cloud/.idea/libraries/jwt_generator.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Samples/production/zapi-cloud/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Samples/production/zapi-cloud/.idea/sbt.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /Samples/production/zapi-cloud/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Samples/production/zapi-cloud/LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Samples/production/zapi-cloud/README.md: -------------------------------------------------------------------------------- 1 | # zapi-cloud -------------------------------------------------------------------------------- /Samples/production/zapi-cloud/generator/java/compiled/jwt-generator.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zephyrdeveloper/zapi-cloud/63d4a586cd2cd3d86f94988d800d69cd2e158b68/Samples/production/zapi-cloud/generator/java/compiled/jwt-generator.jar -------------------------------------------------------------------------------- /Samples/production/zapi-cloud/generator/java/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | com.thed.zephyr.connect 7 | zfj-cloud-rest-client 8 | 1.3 9 | 10 | 11 | atlassian-public1 12 | https://maven.atlassian.com/repository/public 13 | 14 | true 15 | never 16 | warn 17 | 18 | 19 | true 20 | warn 21 | 22 | 23 | 24 | atlassian-public2 25 | https://m2proxy.atlassian.com/repository/public 26 | 27 | true 28 | daily 29 | warn 30 | 31 | 32 | true 33 | warn 34 | 35 | 36 | 37 | atlassian-public3 38 | https://maven.atlassian.com/content/groups/public 39 | 40 | true 41 | daily 42 | warn 43 | 44 | 45 | true 46 | warn 47 | 48 | 49 | 50 | 51 | 52 | 53 | org.apache.maven.plugins 54 | maven-compiler-plugin 55 | 3.5.1 56 | 57 | 1.8 58 | 1.8 59 | 60 | 61 | 62 | maven-assembly-plugin 63 | 64 | 65 | package 66 | 67 | single 68 | 69 | 70 | 71 | 72 | 73 | jar-with-dependencies 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | com.atlassian.jira 82 | jira-rest-java-client-core 83 | 2.0.1 84 | system 85 | ${project.basedir}/src/main/resources/jira-rest-java-client-core-2.0.1.jar 86 | 87 | 88 | com.google.guava 89 | guava 90 | 91 | 92 | 93 | 94 | com.google.guava 95 | guava 96 | 14.0.1 97 | 98 | 99 | commons-configuration 100 | commons-configuration 101 | 1.10 102 | 103 | 121 | 122 | org.json 123 | json 124 | 20180130 125 | 126 | 127 | org.apache.commons 128 | commons-lang3 129 | 3.0 130 | 131 | 132 | com.fasterxml.jackson.core 133 | jackson-annotations 134 | 2.9.0 135 | 136 | 137 | com.fasterxml.jackson.core 138 | jackson-databind 139 | 2.9.9 140 | 141 | 142 | com.atlassian.connect 143 | ac-play-java_2.10 144 | 0.10.1 145 | 146 | 147 | com.typesafe.play 148 | filters-helpers_2.10 149 | 150 | 151 | com.typesafe.play 152 | play-cache_2.10 153 | 154 | 155 | com.typesafe.play 156 | play-java-jdbc_2.10 157 | 158 | 159 | com.typesafe.play 160 | play-java-jpa_2.10 161 | 162 | 163 | com.typesafe.play 164 | play-java_2.10 165 | 166 | 167 | com.typesafe.play 168 | play_2.10 169 | 170 | 171 | commons-codec 172 | commons-codec 173 | 174 | 175 | org.bouncycastle 176 | bcprov-jdk16 177 | 178 | 179 | org.hibernate 180 | hibernate-entitymanager 181 | 182 | 183 | org.scala-lang 184 | scala-library 185 | 186 | 187 | postgresql 188 | postgresql 189 | 190 | 191 | xml-apis 192 | xml-apis 193 | 194 | 195 | com.typesafe.play 196 | play-test_2.10 197 | 198 | 199 | 200 | org.hamcrest 201 | hamcrest-all 202 | 203 | 204 | 205 | org.mockito 206 | mockito-core 207 | 208 | 209 | 210 | 211 | org.slf4j 212 | slf4j-api 213 | 1.7.19 214 | 215 | 216 | 217 | junit 218 | junit 219 | 4.11 220 | test 221 | 222 | 223 | org.slf4j 224 | slf4j-jdk14 225 | 1.7.19 226 | test 227 | 228 | 229 | org.apache.commons 230 | commons-io 231 | 1.3.2 232 | test 233 | 234 | 235 | 236 | 237 | UTF-8 238 | 239 | 240 | 241 | 242 | -------------------------------------------------------------------------------- /Samples/production/zapi-cloud/generator/java/src/main/resources/ZConfigConstants.properties: -------------------------------------------------------------------------------- 1 | jiraHostKey = amlyYTowNDQ2NzNjMi1kNGU0LTQzY2UtYTVhMi00OTRlZWU3YzJhYzYgMTIzNDU2OjEyMzRhYmNkLTEyMzQtYWJjZC0xMjM0LTEyMzRhYmNkMTIzNA== 2 | jiraBaseURL = http://127.0.0.1:2990 3 | sharedSecret = bm1Y8M3GyFEuzQeCYcK_hSEFA59FYTlzgMfUJ3DM11Y 4 | 5 | zephyrBaseURL = http://127.0.0.1:9000 6 | secretKey = bm1Y8M3GyFEuzQeCYcK_hSEFA59FYTlzgMfUJ3DM11Y 7 | accessKey = amlyYTowNDQ2NzNjMi1kNGU0LTQzY2UtYTVhMi00OTRlZWU3YzJhYzYgMTIzNDU2OjEyMzRhYmNkLTEyMzQtYWJjZC0xMjM0LTEyMzRhYmNkMTIzNA== 8 | appKey = com.thed.zephyr.cloud 9 | 10 | accountId = 123456:1234abcd-1234-abcd-1234-1234abcd1234 11 | 12 | -------------------------------------------------------------------------------- /Samples/production/zapi-cloud/generator/java/src/main/resources/jira-rest-java-client-core-2.0.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zephyrdeveloper/zapi-cloud/63d4a586cd2cd3d86f94988d800d69cd2e158b68/Samples/production/zapi-cloud/generator/java/src/main/resources/jira-rest-java-client-core-2.0.1.jar -------------------------------------------------------------------------------- /Samples/production/zapi-cloud/generator/java/target/classes/ZConfigConstants.properties: -------------------------------------------------------------------------------- 1 | jiraHostKey = amlyYTowNDQ2NzNjMi1kNGU0LTQzY2UtYTVhMi00OTRlZWU3YzJhYzYgYWRtaW4 2 | jiraBaseURL = http://127.0.0.1:2990 3 | sharedSecret = bm1Y8M3GyFEuzQeCYcK_hSEFA59FYTlzgMfUJ3DM11Y 4 | 5 | zephyrBaseURL = http://127.0.0.1:9000 6 | secretKey = bm1Y8M3GyFEuzQeCYcK_hSEFA59FYTlzgMfUJ3DM11Y 7 | accessKey = amlyYTowNDQ2NzNjMi1kNGU0LTQzY2UtYTVhMi00OTRlZWU3YzJhYzYgYWRtaW4 8 | appKey = com.thed.zephyr.cloud 9 | 10 | accountId = accountId 11 | 12 | -------------------------------------------------------------------------------- /Samples/production/zapi-cloud/generator/java/target/maven-archiver/pom.properties: -------------------------------------------------------------------------------- 1 | #Generated by Maven 2 | #Mon Nov 19 10:40:47 PST 2018 3 | version=1.2 4 | groupId=com.thed.zephyr.connect 5 | artifactId=zfj-cloud-rest-client 6 | -------------------------------------------------------------------------------- /Samples/production/zapi-cloud/generator/java/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst: -------------------------------------------------------------------------------- 1 | com/thed/zephyr/cloud/rest/client/impl/JwtGeneratorImpl$1$1.class 2 | com/thed/zephyr/cloud/rest/ZFJCloudRestClient.class 3 | com/thed/zephyr/cloud/rest/ZFJCloudRestClient$Builder.class 4 | generator/java/src/main/java/com/thed/zephyr/cloud/rest/exception/JobProgressException.class 5 | com/thed/zephyr/cloud/rest/client/impl/JwtGeneratorImpl.class 6 | com/thed/zephyr/cloud/rest/client/JwtAuthorizationGenerator.class 7 | com/thed/zephyr/cloud/rest/model/ZConfig$1.class 8 | com/thed/zephyr/cloud/rest/model/ZConfig.class 9 | com/thed/zephyr/cloud/rest/client/JwtGenerator.class 10 | com/thed/zephyr/cloud/rest/model/ZConfig$ZConfigBuilder.class 11 | com/thed/zephyr/cloud/rest/ZFJCloudRestClient$1.class 12 | com/thed/zephyr/cloud/rest/client/JwtAuthorizationGenerator$1.class 13 | com/thed/zephyr/cloud/rest/client/impl/JwtGeneratorImpl$1.class 14 | -------------------------------------------------------------------------------- /Samples/production/zapi-cloud/generator/java/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst: -------------------------------------------------------------------------------- 1 | /Users/masudurrahman/zapi-cloud/generator/java/src/main/java/com/thed/zephyr/cloud/rest/model/ZConfig.java 2 | /Users/masudurrahman/zapi-cloud/generator/java/src/main/java/com/thed/zephyr/cloud/rest/client/JwtAuthorizationGenerator.java 3 | /Users/masudurrahman/zapi-cloud/generator/java/src/main/java/com/thed/zephyr/cloud/rest/client/JwtGenerator.java 4 | /Users/masudurrahman/zapi-cloud/generator/java/src/main/java/com/thed/zephyr/cloud/rest/exception/JobProgressException.java 5 | /Users/masudurrahman/zapi-cloud/generator/java/src/main/java/com/thed/zephyr/cloud/rest/client/impl/JwtGeneratorImpl.java 6 | /Users/masudurrahman/zapi-cloud/generator/java/src/main/java/com/thed/zephyr/cloud/rest/ZFJCloudRestClient.java 7 | -------------------------------------------------------------------------------- /Samples/production/zapi-cloud/generator/java/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst: -------------------------------------------------------------------------------- 1 | com/thed/zephyr/GenerateJWTTest.class 2 | com/thed/zephyr/util/AbstractTest.class 3 | -------------------------------------------------------------------------------- /Samples/production/zapi-cloud/generator/java/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst: -------------------------------------------------------------------------------- 1 | /Users/masudurrahman/zapi-cloud/generator/java/src/test/java/com/thed/zephyr/util/AbstractTest.java 2 | /Users/masudurrahman/zapi-cloud/generator/java/src/test/java/com/thed/zephyr/GenerateJWTTest.java 3 | -------------------------------------------------------------------------------- /Samples/production/zapi-cloud/generator/java/target/zfj-cloud-rest-client-1.1-jar-with-dependencies.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zephyrdeveloper/zapi-cloud/63d4a586cd2cd3d86f94988d800d69cd2e158b68/Samples/production/zapi-cloud/generator/java/target/zfj-cloud-rest-client-1.1-jar-with-dependencies.jar -------------------------------------------------------------------------------- /Samples/production/zapi-cloud/generator/java/target/zfj-cloud-rest-client-1.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zephyrdeveloper/zapi-cloud/63d4a586cd2cd3d86f94988d800d69cd2e158b68/Samples/production/zapi-cloud/generator/java/target/zfj-cloud-rest-client-1.1.jar -------------------------------------------------------------------------------- /Samples/production/zapi-cloud/generator/java/target/zfj-cloud-rest-client-1.2-jar-with-dependencies.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zephyrdeveloper/zapi-cloud/63d4a586cd2cd3d86f94988d800d69cd2e158b68/Samples/production/zapi-cloud/generator/java/target/zfj-cloud-rest-client-1.2-jar-with-dependencies.jar -------------------------------------------------------------------------------- /Samples/production/zapi-cloud/generator/java/target/zfj-cloud-rest-client-1.2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zephyrdeveloper/zapi-cloud/63d4a586cd2cd3d86f94988d800d69cd2e158b68/Samples/production/zapi-cloud/generator/java/target/zfj-cloud-rest-client-1.2.jar -------------------------------------------------------------------------------- /Samples/production/zapi-cloud/generator/java/target/zfj-cloud-rest-client-1.3-jar-with-dependencies.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zephyrdeveloper/zapi-cloud/63d4a586cd2cd3d86f94988d800d69cd2e158b68/Samples/production/zapi-cloud/generator/java/target/zfj-cloud-rest-client-1.3-jar-with-dependencies.jar -------------------------------------------------------------------------------- /Samples/production/zapi-cloud/generator/java/target/zfj-cloud-rest-client-1.3.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zephyrdeveloper/zapi-cloud/63d4a586cd2cd3d86f94988d800d69cd2e158b68/Samples/production/zapi-cloud/generator/java/target/zfj-cloud-rest-client-1.3.jar -------------------------------------------------------------------------------- /Samples/production/zapi-cloud/generator/python/CycleTest.py: -------------------------------------------------------------------------------- 1 | import json 2 | import jwt 3 | import time 4 | import hashlib 5 | import requests 6 | 7 | 8 | def is_json(data): 9 | try: 10 | json.loads(data) 11 | except ValueError: 12 | return False 13 | return True 14 | 15 | 16 | # USER 17 | ACCOUNT_ID = '123456:1234abcd-1234-abcd-1234-1234abcd1234' 18 | 19 | # ACCESS KEY from navigation >> Tests >> API Keys 20 | ACCESS_KEY = 'amlyYTplN2UyNjFjNC02MTM4LTRiZWEtYWRiNy1lYmMyMjk0ZmZlMGUgYWRtaW4' 21 | 22 | # ACCESS KEY from navigation >> Tests >> API Keys 23 | SECRET_KEY = '01wOEb-ZpIruI_QoAPSHirjBXsZRA3LDuLpnw0OHP-8' 24 | 25 | # JWT EXPIRE how long token been to be active? 3600 == 1 hour 26 | JWT_EXPIRE = 3600 27 | 28 | # BASE URL for Zephyr for Jira Cloud 29 | BASE_URL = 'http://localhost:9000' 30 | 31 | # RELATIVE PATH for token generation and make request to api 32 | RELATIVE_PATH = '/public/rest/api/1.0/cycle' 33 | 34 | # CANONICAL PATH (Http Method & Relative Path & Query String) 35 | CANONICAL_PATH = 'POST&'+RELATIVE_PATH+'&' 36 | 37 | # TOKEN HEADER: to generate jwt token 38 | payload_token = { 39 | 'sub': ACCOUNT_ID, 40 | 'qsh': hashlib.sha256(CANONICAL_PATH.encode('utf-8')).hexdigest(), 41 | 'iss': ACCESS_KEY, 42 | 'exp': int(time.time())+JWT_EXPIRE, 43 | 'iat': int(time.time()) 44 | } 45 | 46 | # GENERATE TOKEN 47 | token = jwt.encode(payload_token, SECRET_KEY, algorithm='HS256').strip().decode('utf-8') 48 | 49 | # REQUEST HEADER: to authenticate and authorize api 50 | headers = { 51 | 'Authorization': 'JWT '+token, 52 | 'Content-Type': 'application/json', 53 | 'zapiAccessKey': ACCESS_KEY 54 | } 55 | 56 | # REQUEST HEADER: to create cycle 57 | headers = { 58 | 'Authorization': 'JWT '+token, 59 | 'Content-Type': 'application/json', 60 | 'zapiAccessKey': ACCESS_KEY 61 | } 62 | 63 | # REQUEST PAYLOAD: to create cycle 64 | cycle = { 65 | 'name': 'Sample Cycle', 66 | 'projectId': 10000, 67 | 'versionId': -1 68 | } 69 | 70 | # MAKE REQUEST: 71 | raw_result = requests.post(BASE_URL + RELATIVE_PATH, headers=headers, json=cycle) 72 | if is_json(raw_result.text): 73 | 74 | # JSON RESPONSE: convert response to JSON 75 | json_result = json.loads(raw_result.text) 76 | 77 | # PRINT RESPONSE: pretty print with 4 indent 78 | print(json.dumps(json_result, indent=4, sort_keys=True)) 79 | 80 | else: 81 | print(raw_result.text) 82 | -------------------------------------------------------------------------------- /Samples/production/zapi-cloud/generator/python/README.md: -------------------------------------------------------------------------------- 1 | # zapi_py 2 | zephyr for jira cloud api 3 | 4 | 5 | # Instructions 6 | 1. Download this folder 7 | 8 | 2. Make sure you have Python + pip installed, if not download these. (and make sure they are on your PATH :) ) 9 | 10 | 3. Use pip to install the following two libraries: 11 | pip install PyJWT 12 | pip install requests 13 | 14 | 4. Change the values in CycleTest.py 15 | ACCOUNT_ID -> your Atlassian Account ID, go to your profile page in Jira and the last part of the URL will be your ID 16 | e.g. https://yourcompany.atlassian.net/people/4d0bca695f7d9121cd2ac29f -> your id is 4d0bca695f7d9121cd2ac29f 17 | ACCESS_KEY -> from navigation >> Tests >> API KEYS 18 | SECRET_KEY -> from navigation >> Tests >> API KEYS 19 | BASE_URL -> https://prod-api.zephyr4jiracloud.com/connect 20 | 21 | Note: if you want to test using another request, make sure you set the right HTTP method on both line 35 & line 71 (by calling the correct method: requests.get, requests.post etc...) 22 | 23 | 5. Run CycleTest.py using the following command: 24 | python CycleTest.py 25 | -------------------------------------------------------------------------------- /Samples/production/zapi-cloud/generator/python/models/Cycle.py: -------------------------------------------------------------------------------- 1 | 2 | class Cycle(object): 3 | 4 | def __init__(self, name, environment, build, version_id, project_id, description, sprint_id): 5 | self.name = name 6 | self.environment = environment 7 | self.build = build 8 | self.versionId = version_id 9 | self.projectId = project_id 10 | self.description = description 11 | self.sprintId = sprint_id 12 | self.createdBy = None 13 | self.createdByAccountId = None 14 | self.modifiedBy = None 15 | self.modifiedByAccountId = None 16 | self.startDate = None 17 | self.endDate = None 18 | -------------------------------------------------------------------------------- /Samples/production/zapi-cloud/generator/python/models/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zephyrdeveloper/zapi-cloud/63d4a586cd2cd3d86f94988d800d69cd2e158b68/Samples/production/zapi-cloud/generator/python/models/__init__.py -------------------------------------------------------------------------------- /Samples/production/zapi-cloud/generator/python/util/JWTGenerator.py: -------------------------------------------------------------------------------- 1 | import jwt 2 | import time 3 | import hashlib 4 | 5 | 6 | class JWTGenerator: 7 | 8 | def __init__(self, account_id, access_key, secret_key, canonical_path): 9 | self.account_id = account_id 10 | self.access_key = access_key 11 | self.secret_key = secret_key 12 | self.expire = 3600 13 | self.canonical_path = canonical_path 14 | 15 | @property 16 | def jwt(self): 17 | payload = { 18 | 'sub': self.account_id, 19 | 'qsh': hashlib.sha256(self.canonical_path.encode('utf-8')).hexdigest(), 20 | 'iss': self.access_key, 21 | 'exp': time.time()+self.expire, 22 | 'iat': time.time() 23 | } 24 | token = jwt.encode(payload, self.secret_key, algorithm='HS256') 25 | return token 26 | 27 | @property 28 | def headers(self): 29 | headers = { 30 | 'Authorization': 'JWT '+self.jwt(), 31 | 'Content-Type': 'application/json', 32 | 'zapiAccessKey': self.access_key 33 | } 34 | return headers 35 | 36 | -------------------------------------------------------------------------------- /Samples/production/zapi-cloud/generator/python/util/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zephyrdeveloper/zapi-cloud/63d4a586cd2cd3d86f94988d800d69cd2e158b68/Samples/production/zapi-cloud/generator/python/util/__init__.py -------------------------------------------------------------------------------- /Samples/src/com/thed/zapi/cloud/sample/CreateCycleAndAddTests.java: -------------------------------------------------------------------------------- 1 | /* D SOFTWARE INCORPORATED 2 | * Copyright 2007-2011 D Software Incorporated 3 | * All Rights Reserved. 4 | * 5 | * NOTICE: D Software permits you to use, modify, and distribute this 6 | file 7 | * in accordance with the terms of the license agreement accompanying 8 | it. 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an “AS IS? BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 13 | implied. 14 | */ 15 | /* 16 | * This is a sample of what can be done by using API's with Zephyr through 17 | the JAVA coding language. 18 | * By creating the .java files, you can import them 19 | into your workspace and then call them in your custom program. 20 | * 21 | * Eclipse Java EE IDE for Web Developers. 22 | Version: Neon Release (4.6.0) 23 | Build id: 20160613-1800 24 | * Java- Java JDK 1.8.0_101 25 | * 26 | * Author: Swapna Kumar Vemula, Product Support Engineer, D Software Inc. 27 | */ 28 | package com.thed.zapi.cloud.sample; 29 | 30 | import java.io.IOException; 31 | import java.io.InputStream; 32 | import java.io.UnsupportedEncodingException; 33 | import java.net.URI; 34 | import java.net.URISyntaxException; 35 | 36 | import org.apache.http.HttpEntity; 37 | import org.apache.http.HttpResponse; 38 | import org.apache.http.ParseException; 39 | import org.apache.http.client.ClientProtocolException; 40 | import org.apache.http.client.HttpClient; 41 | import org.apache.http.client.methods.HttpPost; 42 | import org.apache.http.entity.StringEntity; 43 | import org.apache.http.impl.client.DefaultHttpClient; 44 | import org.apache.http.util.EntityUtils; 45 | import org.json.JSONException; 46 | import org.json.JSONObject; 47 | 48 | import com.thed.zephyr.cloud.rest.ZFJCloudRestClient; 49 | import com.thed.zephyr.cloud.rest.client.JwtGenerator; 50 | import com.thed.zephyr.cloud.rest.exception.JobProgressException; 51 | 52 | public class CreateCycleAndAddTests { 53 | 54 | public static void main(String[] args) throws URISyntaxException, JobProgressException, JSONException, IllegalStateException, IOException { 55 | // Replace zephyr baseurl shared with the user for ZAPI Cloud 56 | String zephyrBaseUrl = ""; 57 | // zephyr accessKey , we can get from Addons >> zapi section 58 | String accessKey = "YjE2MjdjMGEtNzExNy0zYjY1LWFkMzQtNjcwMDM3OTljOGkbWluIGFkbWlu"; 59 | // zephyr secretKey , we can get from Addons >> zapi section 60 | String secretKey = "qufnbimi96Ob2hq3ISF08yZ8HmQw4c1eHGeGlk"; 61 | String accountId = "accountId"; 62 | ZFJCloudRestClient client = ZFJCloudRestClient.restBuilder(zephyrBaseUrl, accessKey, secretKey, accountId) 63 | .build(); 64 | 65 | /** Declare the Variables here **/ 66 | Long projectId = 10100l; 67 | Long versionId = -1l; 68 | String cycleName = "Test Cycle -- API DEMO"; 69 | String cycleDescription = "Created by ZAPI CLOUD API"; 70 | 71 | String createCycleUri = zephyrBaseUrl + "/public/rest/api/1.0/cycle?expand=&clonedCycleId="; 72 | 73 | /** Cycle Object created - DO NOT EDIT **/ 74 | JSONObject createCycleObj = new JSONObject(); 75 | createCycleObj.put("name", cycleName); 76 | createCycleObj.put("description", cycleDescription); 77 | createCycleObj.put("startDate", System.currentTimeMillis()); 78 | createCycleObj.put("projectId", projectId); 79 | createCycleObj.put("versionId", versionId); 80 | 81 | StringEntity cycleJSON = null; 82 | try { 83 | cycleJSON = new StringEntity(createCycleObj.toString()); 84 | } catch (UnsupportedEncodingException e1) { 85 | e1.printStackTrace(); 86 | } 87 | CreateCycleAndAddTests cc = new CreateCycleAndAddTests(); 88 | String cycleID = cc.createCycle(createCycleUri, client, accessKey, cycleJSON); 89 | System.out.println("Cycle Created with Cycle Id :" + cycleID); 90 | 91 | /** 92 | * Add tests to Cycle IssueId's 93 | * 94 | */ 95 | 96 | String addTestsUri = zephyrBaseUrl + "/public/rest/api/1.0/executions/add/cycle/" + cycleID; 97 | String[] issueIds = { "SUP-1", "TUR-1" }; //Issue Id's to be added to Test Cycle, add more issueKeys separated by comma 98 | 99 | JSONObject addTestsObj = new JSONObject(); 100 | addTestsObj.put("issues", issueIds); 101 | addTestsObj.put("method", "1"); 102 | addTestsObj.put("projectId", projectId); 103 | addTestsObj.put("versionId", versionId); 104 | 105 | StringEntity addTestsJSON = null; 106 | try { 107 | addTestsJSON = new StringEntity(addTestsObj.toString()); 108 | } catch (UnsupportedEncodingException e1) { 109 | e1.printStackTrace(); 110 | } 111 | String ID = cc.addTestsToCycle(addTestsUri, client, accessKey, addTestsJSON); 112 | System.out.println("Tests added successfully "); 113 | } 114 | 115 | public String createCycle(String uriStr, ZFJCloudRestClient client, String accessKey, StringEntity cycleJSON) 116 | throws URISyntaxException, JSONException { 117 | 118 | URI uri = new URI(uriStr); 119 | int expirationInSec = 360; 120 | JwtGenerator jwtGenerator = client.getJwtGenerator(); 121 | String jwt = jwtGenerator.generateJWT("POST", uri, expirationInSec); 122 | System.out.println(uri.toString()); 123 | System.out.println(jwt); 124 | 125 | HttpResponse response = null; 126 | HttpClient restClient = new DefaultHttpClient(); 127 | 128 | HttpPost createCycleReq = new HttpPost(uri); 129 | createCycleReq.addHeader("Content-Type", "application/json"); 130 | createCycleReq.addHeader("Authorization", jwt); 131 | createCycleReq.addHeader("zapiAccessKey", accessKey); 132 | createCycleReq.setEntity(cycleJSON); 133 | 134 | try { 135 | response = restClient.execute(createCycleReq); 136 | } catch (ClientProtocolException e) { 137 | e.printStackTrace(); 138 | } catch (IOException e) { 139 | e.printStackTrace(); 140 | } 141 | 142 | int statusCode = response.getStatusLine().getStatusCode(); 143 | System.out.println(statusCode); 144 | String cycleId = "-1"; 145 | if (statusCode >= 200 && statusCode < 300) { 146 | HttpEntity entity = response.getEntity(); 147 | String string = null; 148 | try { 149 | string = EntityUtils.toString(entity); 150 | JSONObject cycleObj = new JSONObject(string); 151 | cycleId = cycleObj.getString("id"); 152 | } catch (ParseException e) { 153 | e.printStackTrace(); 154 | } catch (IOException e) { 155 | e.printStackTrace(); 156 | } 157 | 158 | } else { 159 | try { 160 | throw new ClientProtocolException("Unexpected response status: " + statusCode); 161 | } catch (ClientProtocolException e) { 162 | e.printStackTrace(); 163 | } 164 | } 165 | return cycleId; 166 | } 167 | 168 | public String addTestsToCycle(String uriStr, ZFJCloudRestClient client, String accessKey, StringEntity addTestsJSON) 169 | throws URISyntaxException, JSONException, IllegalStateException, IOException { 170 | 171 | URI uri = new URI(uriStr); 172 | int expirationInSec = 360; 173 | JwtGenerator jwtGenerator = client.getJwtGenerator(); 174 | String jwt = jwtGenerator.generateJWT("POST", uri, expirationInSec); 175 | System.out.println(uri.toString()); 176 | System.out.println(jwt); 177 | 178 | HttpResponse response = null; 179 | HttpClient restClient = new DefaultHttpClient(); 180 | 181 | HttpPost addTestsReq = new HttpPost(uri); 182 | addTestsReq.addHeader("Content-Type", "application/json"); 183 | addTestsReq.addHeader("Authorization", jwt); 184 | addTestsReq.addHeader("zapiAccessKey", accessKey); 185 | addTestsReq.setEntity(addTestsJSON); 186 | 187 | try { 188 | response = restClient.execute(addTestsReq); 189 | } catch (ClientProtocolException e) { 190 | e.printStackTrace(); 191 | } catch (IOException e) { 192 | e.printStackTrace(); 193 | } 194 | 195 | int statusCode = response.getStatusLine().getStatusCode(); 196 | System.out.println(statusCode); 197 | System.out.println(response.toString()); 198 | String string = null; 199 | if (statusCode >= 200 && statusCode < 300) { 200 | HttpEntity entity = response.getEntity(); 201 | try { 202 | string = EntityUtils.toString(entity); 203 | //System.out.println(string); 204 | JSONObject cycleObj = new JSONObject(entity); 205 | //System.out.println(cycleObj.toString()); 206 | } catch (ParseException e) { 207 | e.printStackTrace(); 208 | } catch (IOException e) { 209 | e.printStackTrace(); 210 | } 211 | 212 | } else { 213 | try { 214 | throw new ClientProtocolException("Unexpected response status: " + statusCode); 215 | } catch (ClientProtocolException e) { 216 | e.printStackTrace(); 217 | } 218 | } 219 | return string; 220 | } 221 | 222 | } 223 | -------------------------------------------------------------------------------- /Samples/src/com/thed/zapi/cloud/sample/CreateTestWithTestSteps.java: -------------------------------------------------------------------------------- 1 | /* D SOFTWARE INCORPORATED 2 | * Copyright 2007-2011 D Software Incorporated 3 | * All Rights Reserved. 4 | * 5 | * NOTICE: D Software permits you to use, modify, and distribute this 6 | file 7 | * in accordance with the terms of the license agreement accompanying 8 | it. 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an “AS IS? BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 13 | implied. 14 | */ 15 | /* 16 | * This is a sample of what can be done by using API's with Zephyr through 17 | the JAVA coding language. 18 | * By creating the .java files, you can import them 19 | into your workspace and then call them in your custom program. 20 | * 21 | * Eclipse Java EE IDE for Web Developers. 22 | Version: Neon Release (4.6.0) 23 | Build id: 20160613-1800 24 | * Java- Java JDK 1.8.0_101 25 | * 26 | * Author: Swapna Kumar Vemula, Product Support Engineer, D Software Inc. 27 | */ 28 | package com.thed.zapi.cloud.sample; 29 | 30 | import java.io.IOException; 31 | import java.io.UnsupportedEncodingException; 32 | import java.net.URI; 33 | import java.net.URISyntaxException; 34 | 35 | import org.apache.http.Header; 36 | import org.apache.http.HttpEntity; 37 | import org.apache.http.HttpHeaders; 38 | import org.apache.http.HttpResponse; 39 | import org.apache.http.ParseException; 40 | import org.apache.http.client.ClientProtocolException; 41 | import org.apache.http.client.HttpClient; 42 | import org.apache.http.client.methods.HttpPost; 43 | import org.apache.http.entity.StringEntity; 44 | import org.apache.http.impl.client.DefaultHttpClient; 45 | import org.apache.http.message.BasicHeader; 46 | import org.apache.http.util.EntityUtils; 47 | import org.json.JSONArray; 48 | import org.json.JSONException; 49 | import org.json.JSONObject; 50 | 51 | import com.thed.zephyr.cloud.rest.ZFJCloudRestClient; 52 | import com.thed.zephyr.cloud.rest.client.JwtGenerator; 53 | 54 | public class CreateTestWithTestSteps { 55 | 56 | private static String API_CREATE_TEST = "{SERVER}/rest/api/2/issue"; 57 | private static String API_CREATE_TEST_STEP = "{SERVER}/public/rest/api/1.0/teststep/"; 58 | 59 | /** Declare JIRA,Zephyr URL,access and secret Keys */ 60 | // Jira Cloud URL for the instance 61 | private static String jiraBaseURL = "https://demo.atlassian.net"; 62 | // Replace zephyr baseurl shared with the user for ZAPI Cloud Installation 63 | private static String zephyrBaseUrl = ""; 64 | // zephyr accessKey , we can get from Addons >> zapi section 65 | private static String accessKey = "YjE2MjdjMGEtNzExNy0zYjY1LWFkMzQtNjcwMDM3MxIGFkbWluIGFkbWlu"; 66 | // zephyr secretKey , we can get from Addons >> zapi section 67 | private static String secretKey = "qufnbimi96Ob2hq3ISF08yZRHmQw4c1eHGeGlk"; 68 | 69 | /** Declare parameter values here */ 70 | 71 | private static String userName = "admin"; 72 | private static String accountId = "accountId"; 73 | private static String password = "password"; 74 | private static String projectId = "10100"; 75 | private static String issueTypeId = "10005"; 76 | 77 | static ZFJCloudRestClient client = ZFJCloudRestClient.restBuilder(zephyrBaseUrl, accessKey, secretKey, accountId) 78 | .build(); 79 | JwtGenerator jwtGenerator = client.getJwtGenerator(); 80 | 81 | public static void main(String[] args) throws JSONException, URISyntaxException, ParseException, IOException { 82 | final String createTestUri = API_CREATE_TEST.replace("{SERVER}", jiraBaseURL); 83 | final String createTestStepUri = API_CREATE_TEST_STEP.replace("{SERVER}", zephyrBaseUrl); 84 | 85 | /** 86 | * Create Test Parameters, declare Create Test Issue fields Declare more 87 | * field objects if required 88 | */ 89 | 90 | JSONObject projectObj = new JSONObject(); 91 | projectObj.put("id", projectId); // Project ID where the Test to be 92 | // Created 93 | 94 | JSONObject issueTypeObj = new JSONObject(); 95 | issueTypeObj.put("id", issueTypeId); // IssueType ID which is Test isse 96 | // type 97 | 98 | JSONObject assigneeObj = new JSONObject(); 99 | assigneeObj.put("name", userName); // Username of the assignee 100 | 101 | JSONObject reporterObj = new JSONObject(); 102 | reporterObj.put("name", userName); // Username of the Reporter 103 | 104 | String testSummary = "Sample Test case With Steps created through ZAPI Cloud"; // Test 105 | // Case 106 | // Summary/Name 107 | 108 | /** 109 | * Create JSON payload to POST Add more field objects if required 110 | * 111 | * ***DONOT EDIT BELOW *** 112 | */ 113 | 114 | JSONObject fieldsObj = new JSONObject(); 115 | fieldsObj.put("project", projectObj); 116 | fieldsObj.put("summary", testSummary); 117 | fieldsObj.put("issuetype", issueTypeObj); 118 | fieldsObj.put("assignee", assigneeObj); 119 | fieldsObj.put("reporter", reporterObj); 120 | 121 | JSONObject createTestObj = new JSONObject(); 122 | createTestObj.put("fields", fieldsObj); 123 | System.out.println(createTestObj.toString()); 124 | byte[] bytesEncoded = Base64.encodeBase64((userName + ":" + password).getBytes()); 125 | String authorizationHeader = "Basic " + new String(bytesEncoded); 126 | Header header = new BasicHeader(HttpHeaders.AUTHORIZATION, authorizationHeader); 127 | 128 | StringEntity createTestJSON = null; 129 | try { 130 | createTestJSON = new StringEntity(createTestObj.toString()); 131 | } catch (UnsupportedEncodingException e1) { 132 | e1.printStackTrace(); 133 | } 134 | 135 | HttpResponse response = null; 136 | HttpClient restClient = new DefaultHttpClient(); 137 | try { 138 | // System.out.println(issueSearchURL); 139 | HttpPost createTestReq = new HttpPost(createTestUri); 140 | createTestReq.addHeader(header); 141 | createTestReq.addHeader("Content-Type", "application/json"); 142 | createTestReq.setEntity(createTestJSON); 143 | 144 | response = restClient.execute(createTestReq); 145 | } catch (ClientProtocolException e) { 146 | e.printStackTrace(); 147 | } catch (IOException e) { 148 | e.printStackTrace(); 149 | } 150 | String testId = null; 151 | int statusCode = response.getStatusLine().getStatusCode(); 152 | // System.out.println(statusCode); 153 | HttpEntity entity1 = response.getEntity(); 154 | if (statusCode >= 200 && statusCode < 300) { 155 | 156 | String string1 = null; 157 | try { 158 | string1 = EntityUtils.toString(entity1); 159 | System.out.println(string1); 160 | } catch (ParseException e) { 161 | e.printStackTrace(); 162 | } catch (IOException e) { 163 | e.printStackTrace(); 164 | } 165 | 166 | JSONObject createTestResp = new JSONObject(string1); 167 | testId = createTestResp.getString("id"); 168 | System.out.println("testId :" + testId); 169 | } else { 170 | 171 | try { 172 | String string = null; 173 | string = EntityUtils.toString(entity1); 174 | JSONObject executionResponseObj = new JSONObject(string); 175 | System.out.println(executionResponseObj.toString()); 176 | throw new ClientProtocolException("Unexpected response status: " + statusCode); 177 | 178 | } catch (ClientProtocolException e) { 179 | e.printStackTrace(); 180 | } 181 | } 182 | 183 | /** Create test Steps ***/ 184 | 185 | /** 186 | * Create Steps Replace the step,data,result values as required 187 | */ 188 | 189 | JSONObject testStepJsonObj = new JSONObject(); 190 | testStepJsonObj.put("step", "Sample Test Step"); 191 | testStepJsonObj.put("data", "Sample Test Data"); 192 | testStepJsonObj.put("result", "Sample Expected Result"); 193 | 194 | /** DONOT EDIT FROM HERE ***/ 195 | 196 | StringEntity createTestStepJSON = null; 197 | try { 198 | createTestStepJSON = new StringEntity(testStepJsonObj.toString()); 199 | } catch (UnsupportedEncodingException e1) { 200 | e1.printStackTrace(); 201 | } 202 | String finalURL = createTestStepUri + testId + "?projectId=" + projectId; 203 | URI uri = new URI(finalURL); 204 | int expirationInSec = 360; 205 | JwtGenerator jwtGenerator = client.getJwtGenerator(); 206 | String jwt = jwtGenerator.generateJWT("POST", uri, expirationInSec); 207 | System.out.println(uri.toString()); 208 | System.out.println(jwt); 209 | 210 | HttpResponse responseTestStep = null; 211 | 212 | HttpPost addTestStepReq = new HttpPost(uri); 213 | addTestStepReq.addHeader("Content-Type", "application/json"); 214 | addTestStepReq.addHeader("Authorization", jwt); 215 | addTestStepReq.addHeader("zapiAccessKey", accessKey); 216 | addTestStepReq.setEntity(createTestStepJSON); 217 | 218 | try { 219 | responseTestStep = restClient.execute(addTestStepReq); 220 | } catch (ClientProtocolException e) { 221 | e.printStackTrace(); 222 | } catch (IOException e) { 223 | e.printStackTrace(); 224 | } 225 | 226 | int testStepStatusCode = responseTestStep.getStatusLine().getStatusCode(); 227 | System.out.println(testStepStatusCode); 228 | System.out.println(response.toString()); 229 | 230 | if (statusCode >= 200 && statusCode < 300) { 231 | HttpEntity entity = responseTestStep.getEntity(); 232 | String string = null; 233 | String stepId = null; 234 | try { 235 | string = EntityUtils.toString(entity); 236 | JSONObject testStepObj = new JSONObject(string); 237 | stepId = testStepObj.getString("id"); 238 | System.out.println("stepId :" + stepId); 239 | System.out.println(testStepObj.toString()); 240 | } catch (ParseException e) { 241 | e.printStackTrace(); 242 | } catch (IOException e) { 243 | e.printStackTrace(); 244 | } 245 | 246 | } else { 247 | try { 248 | throw new ClientProtocolException("Unexpected response status: " + statusCode); 249 | } catch (ClientProtocolException e) { 250 | e.printStackTrace(); 251 | } 252 | } 253 | 254 | } 255 | } 256 | -------------------------------------------------------------------------------- /Samples/src/com/thed/zapi/cloud/sample/CycleExecutionReportByVersion.java: -------------------------------------------------------------------------------- 1 | /* D SOFTWARE INCORPORATED 2 | * Copyright 2007-2011 D Software Incorporated 3 | * All Rights Reserved. 4 | * 5 | * NOTICE: D Software permits you to use, modify, and distribute this 6 | file 7 | * in accordance with the terms of the license agreement accompanying 8 | it. 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an “AS IS? BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 13 | implied. 14 | */ 15 | /* 16 | * This is a sample of what can be done by using API's with Zephyr through 17 | the JAVA coding language. 18 | * By creating the .java files, you can import them 19 | into your workspace and then call them in your custom program. 20 | * 21 | * Eclipse Java EE IDE for Web Developers. 22 | Version: Neon Release (4.6.0) 23 | Build id: 20160613-1800 24 | * Java- Java JDK 1.8.0_101 25 | * 26 | * Author: Swapna Kumar Vemula, Product Support Engineer, D Software Inc. 27 | */ 28 | package com.thed.zapi.cloud.sample; 29 | 30 | import java.io.FileWriter; 31 | import java.io.IOException; 32 | import java.net.URI; 33 | import java.net.URISyntaxException; 34 | import java.util.HashMap; 35 | import java.util.Map; 36 | 37 | import org.apache.http.HttpEntity; 38 | import org.apache.http.HttpResponse; 39 | import org.apache.http.ParseException; 40 | import org.apache.http.client.ClientProtocolException; 41 | import org.apache.http.client.HttpClient; 42 | import org.apache.http.client.methods.HttpGet; 43 | import org.apache.http.impl.client.DefaultHttpClient; 44 | import org.apache.http.util.EntityUtils; 45 | import org.json.JSONArray; 46 | import org.json.JSONException; 47 | import org.json.JSONObject; 48 | 49 | import com.atlassian.jira.rest.client.internal.json.JsonArrayParser; 50 | import com.nimbusds.jose.util.JSONObjectUtils; 51 | import com.thed.zephyr.cloud.rest.ZFJCloudRestClient; 52 | import com.thed.zephyr.cloud.rest.client.JwtGenerator; 53 | 54 | import net.minidev.json.JSONUtil; 55 | 56 | public class CycleExecutionReportByVersion { 57 | public static void main(String[] args) throws JSONException, URISyntaxException, ParseException, IOException { 58 | 59 | String API_GET_EXECUTIONS = "{SERVER}/public/rest/api/1.0/executions/search/cycle/"; 60 | String API_GET_CYCLES = "{SERVER}/public/rest/api/1.0/cycles/search?"; 61 | // Delimiter used in CSV file 62 | final String NEW_LINE_SEPARATOR = "\n"; 63 | final String fileName = "F:\\cycleExecutionReport.csv"; 64 | 65 | /** Declare JIRA,Zephyr URL,access and secret Keys */ 66 | // JIRA Cloud URL of the instance 67 | String jiraBaseURL = "https://demo.atlassian.net"; 68 | // Replace zephyr baseurl shared with the user for ZAPI Cloud Installation 69 | String zephyrBaseUrl = ""; 70 | // zephyr accessKey , we can get from Addons >> zapi section 71 | String accessKey = "YjE2MjdjMGEtNzExNy0zYjY1LWFkMzQtNjcwMDM3OTljFkbWluIGFkbWlu"; 72 | // zephyr secretKey , we can get from Addons >> zapi section 73 | String secretKey = "qufnbimi96Ob2hq3ISF08yZ8Qw4c1eHGeGlk"; 74 | 75 | /** Declare parameter values here */ 76 | String accountId = "accountId"; 77 | String versionId = "-1"; 78 | String projectId = "10100"; 79 | String projectName = "Support"; 80 | String versionName = "Unscheduled"; 81 | 82 | ZFJCloudRestClient client = ZFJCloudRestClient.restBuilder(zephyrBaseUrl, accessKey, secretKey, accountId) 83 | .build(); 84 | /** 85 | * Get List of Cycles by Project and Version 86 | */ 87 | 88 | final String getCyclesUri = API_GET_CYCLES.replace("{SERVER}", zephyrBaseUrl) + "projectId=" + projectId 89 | + "&versionId=" + versionId; 90 | 91 | Map cycles = getCyclesByProjectVersion(getCyclesUri, client, accessKey); 92 | // System.out.println("cycles :"+ cycles.toString()); 93 | 94 | /** 95 | * Iterating over the Cycles and writing the report to CSV 96 | * 97 | */ 98 | 99 | FileWriter fileWriter = null; 100 | System.out.println("Writing CSV file....."); 101 | try { 102 | fileWriter = new FileWriter(fileName); 103 | 104 | // Write the CSV file header 105 | 106 | fileWriter.append("Cycle Execution Report By Version and Project"); 107 | fileWriter.append(NEW_LINE_SEPARATOR); 108 | fileWriter.append("PROJECT:" + "," + projectName); 109 | fileWriter.append(NEW_LINE_SEPARATOR); 110 | fileWriter.append("VERSION:" + "," + versionName); 111 | fileWriter.append(NEW_LINE_SEPARATOR); 112 | 113 | JSONArray executions; 114 | int totalUnexecutedCount = 0; 115 | int totalExecutionCount = 0; 116 | 117 | for (String key : cycles.keySet()) { 118 | int executionCount = 0; 119 | int unexecutedCount = 0; 120 | final String getExecutionsUri = API_GET_EXECUTIONS.replace("{SERVER}", zephyrBaseUrl) + key 121 | + "?projectId=" + projectId + "&versionId=" + versionId; 122 | fileWriter.append("Cycle:" + "," + cycles.get(key)); 123 | fileWriter.append(NEW_LINE_SEPARATOR); 124 | executions = getExecutionsByCycleId(getExecutionsUri, client, accessKey); 125 | // System.out.println("executions :" + executions.toString()); 126 | 127 | HashMap counter = new HashMap(); 128 | 129 | String[] statusName = new String[executions.length()]; 130 | for (int i = 0; i < executions.length(); i++) { 131 | JSONObject executionObj = executions.getJSONObject(i).getJSONObject("execution"); 132 | // System.out.println("executionObj 133 | // "+executionObj.toString()); 134 | JSONObject statusObj = executionObj.getJSONObject("status"); 135 | // System.out.println("statusObj :"+statusObj.toString()); 136 | statusName[i] = statusObj.getString("name"); 137 | } 138 | 139 | if (statusName.length != 0) { 140 | // System.out.println(statusName.toString()); 141 | for (String a : statusName) { 142 | if (counter.containsKey(a)) { 143 | int oldValue = counter.get(a); 144 | counter.put(a, oldValue + 1); 145 | } else { 146 | counter.put(a, 1); 147 | } 148 | } 149 | for (String status : counter.keySet()) { 150 | fileWriter.append(" " + "," + " " + "," + status + "," + counter.get(status)); 151 | fileWriter.append(NEW_LINE_SEPARATOR); 152 | if (status.equalsIgnoreCase("UNEXECUTED")) { 153 | unexecutedCount += counter.get(status); 154 | } else { 155 | executionCount += counter.get(status); 156 | } 157 | 158 | } 159 | } 160 | totalExecutionCount += executionCount; 161 | totalUnexecutedCount += unexecutedCount; 162 | 163 | fileWriter.append(NEW_LINE_SEPARATOR); 164 | } 165 | 166 | fileWriter.append(NEW_LINE_SEPARATOR); 167 | fileWriter.append("TOTAL CYCLES:" + "," + cycles.size()); 168 | fileWriter.append(NEW_LINE_SEPARATOR); 169 | fileWriter.append("TOTAL EXECUTIONS:" + "," + totalExecutionCount); 170 | fileWriter.append(NEW_LINE_SEPARATOR); 171 | fileWriter.append("TOTAL ASSIGNED:" + "," + (totalUnexecutedCount + totalExecutionCount)); 172 | 173 | System.out.println("CSV file was created successfully !!!"); 174 | } catch (Exception e) { 175 | System.out.println("Error in CsvFileWriter !!!"); 176 | e.printStackTrace(); 177 | } finally { 178 | try { 179 | fileWriter.flush(); 180 | fileWriter.close(); 181 | } catch (IOException e) { 182 | System.out.println("Error while flushing/closing fileWriter !!!"); 183 | e.printStackTrace(); 184 | } 185 | } 186 | 187 | } 188 | 189 | private static Map getCyclesByProjectVersion(String getCyclesUri, ZFJCloudRestClient client, 190 | String accessKey) throws URISyntaxException, JSONException { 191 | // TODO Auto-generated method stub 192 | 193 | Map cycleMap = new HashMap(); 194 | URI uri = new URI(getCyclesUri); 195 | int expirationInSec = 360; 196 | JwtGenerator jwtGenerator = client.getJwtGenerator(); 197 | String jwt = jwtGenerator.generateJWT("GET", uri, expirationInSec); 198 | // System.out.println(uri.toString()); 199 | // System.out.println(jwt); 200 | 201 | HttpResponse response = null; 202 | HttpClient restClient = new DefaultHttpClient(); 203 | HttpGet httpGet = new HttpGet(uri); 204 | httpGet.setHeader("Authorization", jwt); 205 | httpGet.setHeader("zapiAccessKey", accessKey); 206 | 207 | try { 208 | response = restClient.execute(httpGet); 209 | } catch (ClientProtocolException e1) { 210 | // TODO Auto-generated catch block 211 | e1.printStackTrace(); 212 | } catch (IOException e1) { 213 | // TODO Auto-generated catch block 214 | e1.printStackTrace(); 215 | } 216 | 217 | int statusCode = response.getStatusLine().getStatusCode(); 218 | // System.out.println(statusCode); 219 | 220 | if (statusCode >= 200 && statusCode < 300) { 221 | HttpEntity entity1 = response.getEntity(); 222 | String string1 = null; 223 | try { 224 | string1 = EntityUtils.toString(entity1); 225 | } catch (ParseException e) { 226 | e.printStackTrace(); 227 | } catch (IOException e) { 228 | e.printStackTrace(); 229 | } 230 | 231 | // System.out.println(string1); 232 | JSONArray cyclesArray = new JSONArray(string1); 233 | for (int i = 0; i < cyclesArray.length(); i++) { 234 | JSONObject cycleObj = cyclesArray.getJSONObject(i); 235 | String cycleID = cycleObj.getString("id"); 236 | String cycleName = cycleObj.getString("name"); 237 | cycleMap.put(cycleID, cycleName); 238 | // System.out.println(IssuesArray.length()); 239 | } 240 | 241 | } 242 | return cycleMap; 243 | } 244 | 245 | private static JSONArray getExecutionsByCycleId(String uriStr, ZFJCloudRestClient client, String accessKey) 246 | throws URISyntaxException, JSONException { 247 | JSONArray IssuesArray = null; 248 | URI uri = new URI(uriStr); 249 | int expirationInSec = 360; 250 | JwtGenerator jwtGenerator = client.getJwtGenerator(); 251 | String jwt = jwtGenerator.generateJWT("GET", uri, expirationInSec); 252 | // System.out.println(uri.toString()); 253 | // System.out.println(jwt); 254 | 255 | HttpResponse response = null; 256 | HttpClient restClient = new DefaultHttpClient(); 257 | HttpGet httpGet = new HttpGet(uri); 258 | httpGet.setHeader("Authorization", jwt); 259 | httpGet.setHeader("zapiAccessKey", accessKey); 260 | 261 | try { 262 | response = restClient.execute(httpGet); 263 | } catch (ClientProtocolException e1) { 264 | // TODO Auto-generated catch block 265 | e1.printStackTrace(); 266 | } catch (IOException e1) { 267 | // TODO Auto-generated catch block 268 | e1.printStackTrace(); 269 | } 270 | 271 | int statusCode = response.getStatusLine().getStatusCode(); 272 | // System.out.println(statusCode); 273 | 274 | if (statusCode >= 200 && statusCode < 300) { 275 | HttpEntity entity1 = response.getEntity(); 276 | String string1 = null; 277 | try { 278 | string1 = EntityUtils.toString(entity1); 279 | } catch (ParseException e) { 280 | e.printStackTrace(); 281 | } catch (IOException e) { 282 | e.printStackTrace(); 283 | } 284 | 285 | // System.out.println(string1); 286 | JSONObject allIssues = new JSONObject(string1); 287 | IssuesArray = allIssues.getJSONArray("searchObjectList"); 288 | // System.out.println(IssuesArray.length()); 289 | 290 | } 291 | return IssuesArray; 292 | } 293 | 294 | } 295 | -------------------------------------------------------------------------------- /Samples/src/com/thed/zapi/cloud/sample/FetchExecuteUpdate.java: -------------------------------------------------------------------------------- 1 | /* D SOFTWARE INCORPORATED 2 | * Copyright 2007-2011 D Software Incorporated 3 | * All Rights Reserved. 4 | * 5 | * NOTICE: D Software permits you to use, modify, and distribute this 6 | file 7 | * in accordance with the terms of the license agreement accompanying 8 | it. 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an “AS IS? BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 13 | implied. 14 | */ 15 | /* 16 | * This is a sample of what can be done by using API's with Zephyr through 17 | the JAVA coding language. 18 | * By creating the .java files, you can import them 19 | into your workspace and then call them in your custom program. 20 | * 21 | * Eclipse Java EE IDE for Web Developers. 22 | Version: Neon Release (4.6.0) 23 | Build id: 20160613-1800 24 | * Java- Java JDK 1.8.0_101 25 | * 26 | * Author: Swapna Kumar Vemula, Product Support Engineer, D Software Inc. 27 | */ 28 | package com.thed.zapi.cloud.sample; 29 | 30 | import java.io.IOException; 31 | import java.io.UnsupportedEncodingException; 32 | import java.net.URI; 33 | import java.net.URISyntaxException; 34 | import java.util.HashMap; 35 | import java.util.Map; 36 | 37 | import org.apache.http.Header; 38 | import org.apache.http.HttpEntity; 39 | import org.apache.http.HttpHeaders; 40 | import org.apache.http.HttpResponse; 41 | import org.apache.http.ParseException; 42 | import org.apache.http.client.ClientProtocolException; 43 | import org.apache.http.client.HttpClient; 44 | import org.apache.http.client.methods.HttpGet; 45 | import org.apache.http.client.methods.HttpPost; 46 | import org.apache.http.client.methods.HttpPut; 47 | import org.apache.http.entity.StringEntity; 48 | import org.apache.http.impl.client.DefaultHttpClient; 49 | import org.apache.http.message.BasicHeader; 50 | import org.apache.http.util.EntityUtils; 51 | 52 | import com.thed.zephyr.cloud.rest.ZFJCloudRestClient; 53 | import com.thed.zephyr.cloud.rest.client.JwtGenerator; 54 | 55 | public class FetchExecuteUpdate { 56 | private static String API_SEARCH_ISSUES = "{SERVER}/rest/api/2/search"; 57 | private static String API_ADD_TESTS = "{SERVER}/public/rest/api/1.0/executions/add/cycle/"; 58 | private static String API_GET_EXECUTIONS = "{SERVER}/public/rest/api/1.0/executions/search/cycle/"; 59 | private static String API_UPDATE_EXECUTION = "{SERVER}/public/rest/api/1.0/execution/"; 60 | 61 | /** Declare JIRA,Zephyr URL,access and secret Keys */ 62 | 63 | // JIRA Cloud URL of the instance 64 | private static String jiraBaseURL = "https://demo.atlassian.net"; 65 | // Replace zephyr baseurl shared with the user for ZAPI Cloud Installation 66 | private static String zephyrBaseUrl = ""; 67 | // zephyr accessKey , we can get from Addons >> zapi section 68 | private static String accessKey = "YjE2MjdjMGEtNzExNy0zYjY1LWFkMzQtNjcwMDOGMxIGFkbWluIGFkbWlu"; 69 | // zephyr secretKey , we can get from Addons >> zapi section 70 | private static String secretKey = "qufnbimi96Ob2hq3ISnUvDRHmQw4c1eHGeGlk"; 71 | 72 | /** Declare parameter values here */ 73 | private static String userName = "admin"; 74 | private static String accountId = "accountId"; 75 | private static String password = "password"; 76 | private static String cycleId = "-1"; 77 | private static String versionId = "-1"; 78 | private static String projectId = "10100"; 79 | 80 | static ZFJCloudRestClient client = ZFJCloudRestClient.restBuilder(zephyrBaseUrl, accessKey, secretKey, accountId) 81 | .build(); 82 | JwtGenerator jwtGenerator = client.getJwtGenerator(); 83 | 84 | public static void main(String[] args) throws JSONException, URISyntaxException, ParseException, IOException { 85 | final String issueSearchUri = API_SEARCH_ISSUES.replace("{SERVER}", jiraBaseURL); 86 | 87 | /** 88 | * Get Test Issues by JQL 89 | * 90 | */ 91 | 92 | //Json object for JQL search 93 | JSONObject jqlJsonObj = new JSONObject(); 94 | jqlJsonObj.put("jql", "project = SUP"); // Replace the value with Valid JQL 95 | jqlJsonObj.put("startAt", 0); 96 | jqlJsonObj.put("maxResults", 21); // maxResults to be returned by search 97 | jqlJsonObj.put("fieldsByKeys", false); 98 | 99 | String[] IssueIds = getIssuesByJQL(issueSearchUri, userName, password, jqlJsonObj); 100 | // System.out.println(ArrayUtils.toString(IssueIds)); 101 | 102 | /** 103 | * Add tests to Cycle 104 | * 105 | */ 106 | 107 | final String addTestsUri = API_ADD_TESTS.replace("{SERVER}", zephyrBaseUrl) + cycleId; 108 | 109 | /** Create JSON object by providing input values */ 110 | String[] IssueIds = new String[25]; 111 | JSONObject addTestsObj = new JSONObject(); 112 | addTestsObj.put("issues", IssueIds); 113 | addTestsObj.put("method", "1"); 114 | addTestsObj.put("projectId", projectId); 115 | addTestsObj.put("versionId", versionId); 116 | 117 | StringEntity addTestsJSON = null; 118 | try { 119 | addTestsJSON = new StringEntity(addTestsObj.toString()); 120 | } catch (UnsupportedEncodingException e1) { 121 | e1.printStackTrace(); 122 | } 123 | addTestsToCycle(addTestsUri, client, accessKey, addTestsJSON); 124 | 125 | /** 126 | * Get Execution Id's by CycleId and Add them to Ad Hoc cycle of 127 | * UnScheduled Version 128 | * 129 | */ 130 | Map executionIds = new HashMap(); 131 | final String getExecutionsUri = API_GET_EXECUTIONS.replace("{SERVER}", zephyrBaseUrl) + cycleId + "?projectId=" 132 | + projectId + "&versionId=" + versionId; 133 | 134 | executionIds = getExecutionsByCycleId(getExecutionsUri, client, accessKey); 135 | 136 | /** 137 | * Bulk Update Executions with Status by Execution Id 138 | * 139 | */ 140 | 141 | JSONObject statusObj = new JSONObject(); 142 | statusObj.put("id", "1"); 143 | 144 | JSONObject executeTestsObj = new JSONObject(); 145 | executeTestsObj.put("status", statusObj); 146 | executeTestsObj.put("cycleId", cycleId); 147 | executeTestsObj.put("projectId", projectId); 148 | executeTestsObj.put("versionId", versionId); 149 | executeTestsObj.put("comment", "Executed by ZAPI Cloud"); 150 | 151 | for (String key : executionIds.keySet()) { 152 | final String updateExecutionUri = API_UPDATE_EXECUTION.replace("{SERVER}", zephyrBaseUrl) + key; 153 | // System.out.println(updateExecutionUri); 154 | // System.out.println(executionIds.get(key)); 155 | executeTestsObj.put("issueId", executionIds.get(key)); 156 | // System.out.println(executeTestsObj.toString()); 157 | StringEntity executeTestsJSON = null; 158 | try { 159 | executeTestsJSON = new StringEntity(executeTestsObj.toString()); 160 | } catch (UnsupportedEncodingException e1) { 161 | e1.printStackTrace(); 162 | } 163 | updateExecutions(updateExecutionUri, client, accessKey, executeTestsJSON); 164 | } 165 | 166 | } 167 | 168 | private static String[] getIssuesByJQL(String issueSearchURL, String userName, String password, 169 | JSONObject jqlJsonObj) throws JSONException { 170 | 171 | byte[] bytesEncoded = Base64.encodeBase64((userName + ":" + password).getBytes()); 172 | String authorizationHeader = "Basic " + new String(bytesEncoded); 173 | Header header = new BasicHeader(HttpHeaders.AUTHORIZATION, authorizationHeader); 174 | 175 | String[] issueIds = new String[jqlJsonObj.getInt("maxResults")]; 176 | 177 | StringEntity jqlJSON = null; 178 | try { 179 | jqlJSON = new StringEntity(jqlJsonObj.toString()); 180 | } catch (UnsupportedEncodingException e1) { 181 | e1.printStackTrace(); 182 | } 183 | 184 | HttpResponse response = null; 185 | HttpClient restClient = new DefaultHttpClient(); 186 | try { 187 | // System.out.println(issueSearchURL); 188 | HttpPost createProjectReq = new HttpPost(issueSearchURL); 189 | createProjectReq.addHeader(header); 190 | createProjectReq.addHeader("Content-Type", "application/json"); 191 | createProjectReq.setEntity(jqlJSON); 192 | 193 | response = restClient.execute(createProjectReq); 194 | } catch (ClientProtocolException e) { 195 | e.printStackTrace(); 196 | } catch (IOException e) { 197 | e.printStackTrace(); 198 | } 199 | 200 | int statusCode = response.getStatusLine().getStatusCode(); 201 | // System.out.println(statusCode); 202 | 203 | if (statusCode >= 200 && statusCode < 300) { 204 | HttpEntity entity1 = response.getEntity(); 205 | String string1 = null; 206 | try { 207 | string1 = EntityUtils.toString(entity1); 208 | } catch (ParseException e) { 209 | e.printStackTrace(); 210 | } catch (IOException e) { 211 | e.printStackTrace(); 212 | } 213 | 214 | System.out.println(string1); 215 | JSONObject allIssues = new JSONObject(string1); 216 | JSONArray IssuesArray = allIssues.getJSONArray("issues"); 217 | // System.out.println(IssuesArray.length()); 218 | if (IssuesArray.length() == 0) { 219 | return issueIds; 220 | } 221 | 222 | for (int j = 0; j < IssuesArray.length() ; j++) { 223 | JSONObject jobj = IssuesArray.getJSONObject(j); 224 | String issueId = jobj.getString("id"); 225 | issueIds[j] = issueId; 226 | } 227 | } 228 | return issueIds; 229 | } 230 | 231 | public static void addTestsToCycle(String uriStr, ZFJCloudRestClient client, String accessKey, 232 | StringEntity addTestsJSON) throws URISyntaxException, JSONException { 233 | 234 | URI uri = new URI(uriStr); 235 | int expirationInSec = 360; 236 | JwtGenerator jwtGenerator = client.getJwtGenerator(); 237 | String jwt = jwtGenerator.generateJWT("POST", uri, expirationInSec); 238 | // System.out.println(uri.toString()); 239 | // System.out.println(jwt); 240 | 241 | HttpResponse response = null; 242 | HttpClient restClient = new DefaultHttpClient(); 243 | 244 | HttpPost addTestsReq = new HttpPost(uri); 245 | addTestsReq.addHeader("Content-Type", "application/json"); 246 | addTestsReq.addHeader("Authorization", jwt); 247 | addTestsReq.addHeader("zapiAccessKey", accessKey); 248 | addTestsReq.setEntity(addTestsJSON); 249 | 250 | try { 251 | response = restClient.execute(addTestsReq); 252 | } catch (ClientProtocolException e) { 253 | e.printStackTrace(); 254 | } catch (IOException e) { 255 | e.printStackTrace(); 256 | } 257 | 258 | int statusCode = response.getStatusLine().getStatusCode(); 259 | // System.out.println(statusCode); 260 | // System.out.println(response.toString()); 261 | if (statusCode >= 200 && statusCode < 300) { 262 | System.out.println("Tests added Successfully"); 263 | } else { 264 | try { 265 | throw new ClientProtocolException("Unexpected response status: " + statusCode); 266 | } catch (ClientProtocolException e) { 267 | e.printStackTrace(); 268 | } 269 | } 270 | } 271 | 272 | private static Map getExecutionsByCycleId(String uriStr, ZFJCloudRestClient client, 273 | String accessKey) throws URISyntaxException, JSONException { 274 | Map executionIds = new HashMap(); 275 | URI uri = new URI(uriStr); 276 | int expirationInSec = 360; 277 | JwtGenerator jwtGenerator = client.getJwtGenerator(); 278 | String jwt = jwtGenerator.generateJWT("GET", uri, expirationInSec); 279 | // System.out.println(uri.toString()); 280 | // System.out.println(jwt); 281 | 282 | HttpResponse response = null; 283 | HttpClient restClient = new DefaultHttpClient(); 284 | HttpGet httpGet = new HttpGet(uri); 285 | httpGet.setHeader("Authorization", jwt); 286 | httpGet.setHeader("zapiAccessKey", accessKey); 287 | 288 | try { 289 | response = restClient.execute(httpGet); 290 | } catch (ClientProtocolException e1) { 291 | // TODO Auto-generated catch block 292 | e1.printStackTrace(); 293 | } catch (IOException e1) { 294 | // TODO Auto-generated catch block 295 | e1.printStackTrace(); 296 | } 297 | 298 | int statusCode = response.getStatusLine().getStatusCode(); 299 | // System.out.println(statusCode); 300 | 301 | if (statusCode >= 200 && statusCode < 300) { 302 | HttpEntity entity1 = response.getEntity(); 303 | String string1 = null; 304 | try { 305 | string1 = EntityUtils.toString(entity1); 306 | } catch (ParseException e) { 307 | e.printStackTrace(); 308 | } catch (IOException e) { 309 | e.printStackTrace(); 310 | } 311 | 312 | // System.out.println(string1); 313 | JSONObject allIssues = new JSONObject(string1); 314 | JSONArray IssuesArray = allIssues.getJSONArray("searchObjectList"); 315 | // System.out.println(IssuesArray.length()); 316 | if (IssuesArray.length() == 0) { 317 | return executionIds; 318 | } 319 | for (int j = 0; j <= IssuesArray.length() - 1; j++) { 320 | JSONObject jobj = IssuesArray.getJSONObject(j); 321 | JSONObject jobj2 = jobj.getJSONObject("execution"); 322 | String executionId = jobj2.getString("id"); 323 | long IssueId = jobj2.getLong("issueId"); 324 | executionIds.put(executionId, String.valueOf(IssueId)); 325 | } 326 | } 327 | return executionIds; 328 | } 329 | 330 | public static String updateExecutions(String uriStr, ZFJCloudRestClient client, String accessKey, 331 | StringEntity executionJSON) throws URISyntaxException, JSONException, ParseException, IOException { 332 | 333 | URI uri = new URI(uriStr); 334 | int expirationInSec = 360; 335 | JwtGenerator jwtGenerator = client.getJwtGenerator(); 336 | String jwt = jwtGenerator.generateJWT("PUT", uri, expirationInSec); 337 | // System.out.println(uri.toString()); 338 | // System.out.println(jwt); 339 | 340 | HttpResponse response = null; 341 | HttpClient restClient = new DefaultHttpClient(); 342 | 343 | HttpPut executeTest = new HttpPut(uri); 344 | executeTest.addHeader("Content-Type", "application/json"); 345 | executeTest.addHeader("Authorization", jwt); 346 | executeTest.addHeader("zapiAccessKey", accessKey); 347 | executeTest.setEntity(executionJSON); 348 | 349 | try { 350 | response = restClient.execute(executeTest); 351 | } catch (ClientProtocolException e) { 352 | e.printStackTrace(); 353 | } catch (IOException e) { 354 | e.printStackTrace(); 355 | } 356 | 357 | int statusCode = response.getStatusLine().getStatusCode(); 358 | // System.out.println(statusCode); 359 | String executionStatus = "No Test Executed"; 360 | // System.out.println(response.toString()); 361 | HttpEntity entity = response.getEntity(); 362 | 363 | if (statusCode >= 200 && statusCode < 300) { 364 | String string = null; 365 | try { 366 | string = EntityUtils.toString(entity); 367 | JSONObject executionResponseObj = new JSONObject(string); 368 | JSONObject descriptionResponseObj = executionResponseObj.getJSONObject("execution"); 369 | JSONObject statusResponseObj = descriptionResponseObj.getJSONObject("status"); 370 | executionStatus = statusResponseObj.getString("description"); 371 | System.out.println(executionResponseObj.get("issueKey") + "--" + executionStatus); 372 | } catch (ParseException e) { 373 | e.printStackTrace(); 374 | } catch (IOException e) { 375 | e.printStackTrace(); 376 | } 377 | 378 | } else { 379 | 380 | try { 381 | String string = null; 382 | string = EntityUtils.toString(entity); 383 | JSONObject executionResponseObj = new JSONObject(string); 384 | cycleId = executionResponseObj.getString("clientMessage"); 385 | // System.out.println(executionResponseObj.toString()); 386 | throw new ClientProtocolException("Unexpected response status: " + statusCode); 387 | 388 | } catch (ClientProtocolException e) { 389 | e.printStackTrace(); 390 | } 391 | } 392 | return executionStatus; 393 | } 394 | } 395 | -------------------------------------------------------------------------------- /Samples/src/com/thed/zapi/cloud/sample/sampleJwtGenerator.java: -------------------------------------------------------------------------------- 1 | /* D SOFTWARE INCORPORATED 2 | * Copyright 2007-2011 D Software Incorporated 3 | * All Rights Reserved. 4 | * 5 | * NOTICE: D Software permits you to use, modify, and distribute this 6 | file 7 | * in accordance with the terms of the license agreement accompanying 8 | it. 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an “AS IS? BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 13 | implied. 14 | */ 15 | /* 16 | * This is a sample of what can be done by using API's with Zephyr through 17 | the JAVA coding language. 18 | * By creating the .java files, you can import them 19 | into your workspace and then call them in your custom program. 20 | * 21 | * Eclipse Java EE IDE for Web Developers. 22 | Version: Neon Release (4.6.0) 23 | Build id: 20160613-1800 24 | * Java- Java JDK 1.8.0_101 25 | * 26 | * Author: Swapna Kumar Vemula, Product Support Engineer, D Software Inc. 27 | */ 28 | 29 | package com.thed.zapi.cloud.sample; 30 | 31 | import java.io.IOException; 32 | import java.io.UnsupportedEncodingException; 33 | import java.net.URI; 34 | import java.net.URISyntaxException; 35 | 36 | import org.apache.http.HttpEntity; 37 | import org.apache.http.HttpResponse; 38 | import org.apache.http.ParseException; 39 | import org.apache.http.client.ClientProtocolException; 40 | import org.apache.http.client.HttpClient; 41 | import org.apache.http.client.methods.HttpGet; 42 | import org.apache.http.entity.StringEntity; 43 | import org.apache.http.impl.client.DefaultHttpClient; 44 | import org.apache.http.util.EntityUtils; 45 | 46 | import com.thed.zephyr.cloud.rest.ZFJCloudRestClient; 47 | import com.thed.zephyr.cloud.rest.client.JwtGenerator; 48 | 49 | /** 50 | * @author swapna.vemula 12-Dec-2016 51 | * 52 | */ 53 | public class sampleJwtGenerator { 54 | 55 | /** 56 | * @param args 57 | * @author Created by swapna.vemula on 12-Dec-2016. 58 | * @throws URISyntaxException 59 | * @throws JobProgressException 60 | * @throws JSONException 61 | * @throws IOException 62 | * @throws IllegalStateException 63 | */ 64 | public static void main(String[] args) throws URISyntaxException, IllegalStateException, IOException { 65 | // Replace Zephyr BaseUrl with the shared with ZAPI Cloud Installation 66 | String zephyrBaseUrl = ""; 67 | // zephyr accessKey , we can get from Addons >> zapi section 68 | String accessKey = "YjE2MjdjMGEtNzExNy0zYjY1LWFkMzQtNjcwMDM3IGI0NjI3YzBhLTUxMTctMzM2NS1hZDM0IGFkbWlu"; 69 | // zephyr secretKey , we can get from Addons >> zapi section 70 | String secretKey = "qufnbimi96Ob2hq3ISF08yZ8nUvDRHmQwHGeGlk"; 71 | // Jira accountId 72 | String accountId = "accountId"; 73 | ZFJCloudRestClient client = ZFJCloudRestClient.restBuilder(zephyrBaseUrl, accessKey, secretKey, accountId).build(); 74 | JwtGenerator jwtGenerator = client.getJwtGenerator(); 75 | 76 | // API to which the JWT token has to be generated 77 | String createCycleUri = zephyrBaseUrl + "/public/rest/api/1.0/cycle?expand=&clonedCycleId="; 78 | 79 | URI uri = new URI(createCycleUri); 80 | int expirationInSec = 360; 81 | String jwt = jwtGenerator.generateJWT("GET", uri, expirationInSec); 82 | 83 | // Print the URL and JWT token to be used for making the REST call 84 | System.out.println("FINAL API : " +uri.toString()); 85 | System.out.println("JWT Token : " +jwt); 86 | 87 | 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /generator/java/compiled/jwt-generator.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zephyrdeveloper/zapi-cloud/63d4a586cd2cd3d86f94988d800d69cd2e158b68/generator/java/compiled/jwt-generator.jar -------------------------------------------------------------------------------- /generator/java/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | com.thed.zephyr.connect 7 | zfj-cloud-rest-client 8 | 1.3 9 | 10 | 11 | atlassian-public1 12 | https://maven.atlassian.com/repository/public 13 | 14 | true 15 | never 16 | warn 17 | 18 | 19 | true 20 | warn 21 | 22 | 23 | 24 | atlassian-public2 25 | https://m2proxy.atlassian.com/repository/public 26 | 27 | true 28 | daily 29 | warn 30 | 31 | 32 | true 33 | warn 34 | 35 | 36 | 37 | atlassian-public3 38 | https://maven.atlassian.com/content/groups/public 39 | 40 | true 41 | daily 42 | warn 43 | 44 | 45 | true 46 | warn 47 | 48 | 49 | 50 | 51 | 52 | 53 | org.apache.maven.plugins 54 | maven-compiler-plugin 55 | 3.5.1 56 | 57 | 1.8 58 | 1.8 59 | 60 | 61 | 62 | maven-assembly-plugin 63 | 64 | 65 | package 66 | 67 | single 68 | 69 | 70 | 71 | 72 | 73 | jar-with-dependencies 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | com.atlassian.jira 82 | jira-rest-java-client-core 83 | 2.0.1 84 | system 85 | ${project.basedir}/src/main/resources/jira-rest-java-client-core-2.0.1.jar 86 | 87 | 88 | com.google.guava 89 | guava 90 | 91 | 92 | 93 | 94 | com.google.guava 95 | guava 96 | 14.0.1 97 | 98 | 99 | commons-configuration 100 | commons-configuration 101 | 1.10 102 | 103 | 121 | 122 | org.json 123 | json 124 | 20180130 125 | 126 | 127 | org.apache.commons 128 | commons-lang3 129 | 3.0 130 | 131 | 132 | com.fasterxml.jackson.core 133 | jackson-annotations 134 | 2.9.0 135 | 136 | 137 | com.fasterxml.jackson.core 138 | jackson-databind 139 | 2.9.9 140 | 141 | 142 | com.atlassian.connect 143 | ac-play-java_2.10 144 | 0.10.1 145 | 146 | 147 | com.typesafe.play 148 | filters-helpers_2.10 149 | 150 | 151 | com.typesafe.play 152 | play-cache_2.10 153 | 154 | 155 | com.typesafe.play 156 | play-java-jdbc_2.10 157 | 158 | 159 | com.typesafe.play 160 | play-java-jpa_2.10 161 | 162 | 163 | com.typesafe.play 164 | play-java_2.10 165 | 166 | 167 | com.typesafe.play 168 | play_2.10 169 | 170 | 171 | commons-codec 172 | commons-codec 173 | 174 | 175 | org.bouncycastle 176 | bcprov-jdk16 177 | 178 | 179 | org.hibernate 180 | hibernate-entitymanager 181 | 182 | 183 | org.scala-lang 184 | scala-library 185 | 186 | 187 | postgresql 188 | postgresql 189 | 190 | 191 | xml-apis 192 | xml-apis 193 | 194 | 195 | com.typesafe.play 196 | play-test_2.10 197 | 198 | 199 | 200 | org.hamcrest 201 | hamcrest-all 202 | 203 | 204 | 205 | org.mockito 206 | mockito-core 207 | 208 | 209 | 210 | 211 | org.slf4j 212 | slf4j-api 213 | 1.7.19 214 | 215 | 216 | 217 | junit 218 | junit 219 | 4.11 220 | test 221 | 222 | 223 | org.slf4j 224 | slf4j-jdk14 225 | 1.7.19 226 | test 227 | 228 | 229 | org.apache.commons 230 | commons-io 231 | 1.3.2 232 | test 233 | 234 | 235 | 236 | 237 | UTF-8 238 | 239 | 240 | 241 | 242 | -------------------------------------------------------------------------------- /generator/java/src/main/java/com/thed/zephyr/cloud/rest/ZFJCloudRestClient.java: -------------------------------------------------------------------------------- 1 | package com.thed.zephyr.cloud.rest; 2 | 3 | import com.thed.zephyr.cloud.rest.client.*; 4 | import com.thed.zephyr.cloud.rest.client.impl.*; 5 | import com.thed.zephyr.cloud.rest.model.ZConfig; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | 10 | /** 11 | * Created by aliakseimatsarski on 3/25/16. 12 | */ 13 | public class ZFJCloudRestClient { 14 | 15 | private JwtGenerator jwtGenerator; 16 | 17 | private Logger log = LoggerFactory.getLogger(ZFJCloudRestClient.class); 18 | 19 | private ZFJCloudRestClient() { 20 | } 21 | 22 | public static Builder restBuilder(String zephyrBaseUrl, String accessKey, String secretKey, String accountId){ 23 | return new ZFJCloudRestClient().new Builder(zephyrBaseUrl, accessKey, secretKey, accountId); 24 | } 25 | 26 | public JwtGenerator getJwtGenerator(){ 27 | return jwtGenerator; 28 | } 29 | 30 | public class Builder { 31 | 32 | private String accessKey; 33 | private String secretKey; 34 | private String accountId; 35 | private String zephyrBaseUrl; 36 | 37 | private Builder(String zephyrBaseUrl, String accessKey, 38 | String secretKey, String accountId) { 39 | this.zephyrBaseUrl = zephyrBaseUrl; 40 | this.accessKey = accessKey; 41 | this.secretKey = secretKey; 42 | this.accountId = accountId; 43 | } 44 | 45 | public ZFJCloudRestClient build() { 46 | ZConfig zConfig = new ZConfig(accessKey, secretKey, accountId, zephyrBaseUrl); 47 | jwtGenerator = new JwtGeneratorImpl(zConfig); 48 | 49 | return ZFJCloudRestClient.this; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /generator/java/src/main/java/com/thed/zephyr/cloud/rest/client/JwtAuthorizationGenerator.java: -------------------------------------------------------------------------------- 1 | package com.thed.zephyr.cloud.rest.client; 2 | 3 | import com.atlassian.connect.play.java.AC; 4 | import com.atlassian.connect.play.java.AcHost; 5 | import com.atlassian.connect.play.java.http.HttpMethod; 6 | import com.atlassian.fugue.Option; 7 | import com.atlassian.jwt.SigningAlgorithm; 8 | import com.atlassian.jwt.core.TimeUtil; 9 | import com.atlassian.jwt.core.writer.JsonSmartJwtJsonBuilder; 10 | import com.atlassian.jwt.core.writer.JwtClaimsBuilder; 11 | import com.atlassian.jwt.exception.JwtIssuerLacksSharedSecretException; 12 | import com.atlassian.jwt.exception.JwtSigningException; 13 | import com.atlassian.jwt.exception.JwtUnknownIssuerException; 14 | import com.atlassian.jwt.httpclient.CanonicalHttpUriRequest; 15 | import com.atlassian.jwt.writer.JwtJsonBuilder; 16 | import com.atlassian.jwt.writer.JwtWriter; 17 | import com.atlassian.jwt.writer.JwtWriterFactory; 18 | import com.google.common.base.Function; 19 | import com.google.common.base.Preconditions; 20 | import com.google.common.collect.Maps; 21 | import java.io.UnsupportedEncodingException; 22 | import java.net.URI; 23 | import java.net.URISyntaxException; 24 | import java.net.URLDecoder; 25 | import java.security.NoSuchAlgorithmException; 26 | import java.util.Arrays; 27 | import java.util.Collections; 28 | import java.util.HashMap; 29 | import java.util.List; 30 | import java.util.Map; 31 | import org.apache.commons.lang3.StringUtils; 32 | import org.apache.http.NameValuePair; 33 | import org.apache.http.message.BasicHeaderValueParser; 34 | import org.apache.http.message.ParserCursor; 35 | import org.apache.http.util.CharArrayBuffer; 36 | 37 | 38 | //@GeneratedAccessor 39 | //@RewrittenAccessor 40 | public class JwtAuthorizationGenerator { 41 | private static final char[] QUERY_DELIMITERS = new char[]{'&'}; 42 | private static final int JWT_EXPIRY_WINDOW_SECONDS_DEFAULT = 180; 43 | private final int jwtExpiryWindowSeconds; 44 | private final JwtWriterFactory jwtWriterFactory; 45 | 46 | public JwtAuthorizationGenerator(JwtWriterFactory jwtWriterFactory) { 47 | this(jwtWriterFactory, JWT_EXPIRY_WINDOW_SECONDS_DEFAULT); 48 | } 49 | 50 | public JwtAuthorizationGenerator(JwtWriterFactory jwtWriterFactory, int jwtExpiryWindowSeconds) { 51 | this.jwtWriterFactory = Preconditions.checkNotNull(jwtWriterFactory); 52 | this.jwtExpiryWindowSeconds = jwtExpiryWindowSeconds; 53 | } 54 | 55 | public Option generate(String httpMethodStr, String url, Map> parameters, AcHost acHost, Option accountId) throws JwtIssuerLacksSharedSecretException, JwtUnknownIssuerException, URISyntaxException { 56 | HttpMethod method = HttpMethod.valueOf(httpMethodStr); 57 | URI uri = new URI(url); 58 | String path = uri.getPath(); 59 | URI baseUrl = new URI(acHost.getBaseUrl()); 60 | String productContext = baseUrl.getPath(); 61 | String pathWithoutProductContext = path.substring(productContext.length()); 62 | // Utils.LOGGER.trace("Creating Jwt signature for:"); 63 | // Utils.LOGGER.trace(String.format("httpMethod: \'%s\'", new Object[]{httpMethodStr})); 64 | // Utils.LOGGER.trace(String.format("URL: \'%s\'", new Object[]{url})); 65 | // Utils.LOGGER.trace(String.format("acHost key: \'%s\'", new Object[]{acHost.getKey()})); 66 | // Utils.LOGGER.trace(String.format("accountId: \'%s\'", new Object[]{accountId})); 67 | // Utils.LOGGER.trace(String.format("Parameters: %s", new Object[]{parameters})); 68 | // Utils.LOGGER.trace(String.format("pathWithoutProductContext: \'%s\'", new Object[]{pathWithoutProductContext})); 69 | URI uriWithoutProductContext = new URI(uri.getScheme(), uri.getUserInfo(), uri.getHost(), uri.getPort(), pathWithoutProductContext, uri.getQuery(), uri.getFragment()); 70 | // Utils.LOGGER.trace(String.format("uriWithoutProductContext: \'%s\'", new Object[]{uriWithoutProductContext})); 71 | return this.generate(method, uriWithoutProductContext, parameters, acHost, accountId); 72 | } 73 | 74 | public Option generate(HttpMethod httpMethod, URI url, Map> parameters, AcHost acHost, Option accountId) throws JwtIssuerLacksSharedSecretException, JwtUnknownIssuerException { 75 | Preconditions.checkArgument(null != parameters, "Parameters Map argument cannot be null"); 76 | Preconditions.checkNotNull(acHost); 77 | Map paramsAsArrays = Maps.transformValues(parameters, new Function, String[]>() { 78 | @Override 79 | public String[] apply(List input) { 80 | return (String[]) ((List) Preconditions.checkNotNull(input)).toArray(new String[input.size()]); 81 | } 82 | }); 83 | 84 | return Option.some("JWT " + this.encodeJwt(httpMethod, url, paramsAsArrays, (String)accountId.getOrNull(), acHost)); 85 | } 86 | 87 | private String encodeJwt(HttpMethod httpMethod, URI targetPath, Map params, String accountId, AcHost acHost) throws JwtUnknownIssuerException, JwtIssuerLacksSharedSecretException { 88 | Preconditions.checkArgument(null != httpMethod, "HttpMethod argument cannot be null"); 89 | Preconditions.checkArgument(null != targetPath, "URI argument cannot be null"); 90 | JwtJsonBuilder jsonBuilder = (new JsonSmartJwtJsonBuilder()).issuedAt(TimeUtil.currentTimeSeconds()).expirationTime(TimeUtil.currentTimePlusNSeconds((long)this.jwtExpiryWindowSeconds)).issuer(AC.PLUGIN_KEY).audience(acHost.getKey()); 91 | if(null != accountId) { 92 | jsonBuilder = jsonBuilder.subject(accountId); 93 | } 94 | 95 | Object completeParams = params; 96 | 97 | try { 98 | if(!StringUtils.isEmpty(targetPath.getQuery())) { 99 | completeParams = new HashMap(params); 100 | ((Map)completeParams).putAll(constructParameterMap(targetPath)); 101 | } 102 | 103 | CanonicalHttpUriRequest e = new CanonicalHttpUriRequest(httpMethod.toString(), targetPath.getPath(), "", (Map)completeParams); 104 | // Utils.LOGGER.debug("Canonical request is: " + CanonicalRequestUtil.toVerboseString(e)); 105 | JwtClaimsBuilder.appendHttpRequestClaims(jsonBuilder, e); 106 | } catch (UnsupportedEncodingException var9) { 107 | throw new RuntimeException(var9); 108 | } catch (NoSuchAlgorithmException var10) { 109 | throw new RuntimeException(var10); 110 | } 111 | 112 | return this.issueJwt(jsonBuilder.build(), acHost); 113 | } 114 | 115 | private String issueJwt(String jsonPayload, AcHost acHost) throws JwtSigningException, JwtIssuerLacksSharedSecretException, JwtUnknownIssuerException { 116 | return this.getJwtWriter(acHost).jsonToJwt(jsonPayload); 117 | } 118 | 119 | private JwtWriter getJwtWriter(AcHost acHost) throws JwtUnknownIssuerException, JwtIssuerLacksSharedSecretException { 120 | return this.jwtWriterFactory.macSigningWriter(SigningAlgorithm.HS256, acHost.getSharedSecret()); 121 | } 122 | 123 | private static Map constructParameterMap(URI uri) throws UnsupportedEncodingException { 124 | String query = uri.getQuery(); 125 | if(query == null) { 126 | return Collections.emptyMap(); 127 | } else { 128 | HashMap queryParams = new HashMap(); 129 | CharArrayBuffer buffer = new CharArrayBuffer(query.length()); 130 | buffer.append(query); 131 | ParserCursor cursor = new ParserCursor(0, buffer.length()); 132 | 133 | while(!cursor.atEnd()) { 134 | NameValuePair nameValuePair = BasicHeaderValueParser.DEFAULT.parseNameValuePair(buffer, cursor, QUERY_DELIMITERS); 135 | if(!StringUtils.isEmpty(nameValuePair.getName())) { 136 | String decodedName = urlDecode(nameValuePair.getName()); 137 | String decodedValue = urlDecode(nameValuePair.getValue()); 138 | String[] oldValues = (String[])queryParams.get(decodedName); 139 | String[] newValues = null == oldValues?new String[1]:(String[]) Arrays.copyOf(oldValues, oldValues.length + 1); 140 | newValues[newValues.length - 1] = decodedValue; 141 | queryParams.put(decodedName, newValues); 142 | } 143 | } 144 | 145 | return queryParams; 146 | } 147 | } 148 | 149 | private static String urlDecode(String content) throws UnsupportedEncodingException { 150 | return null == content?null: URLDecoder.decode(content, "UTF-8"); 151 | } 152 | } -------------------------------------------------------------------------------- /generator/java/src/main/java/com/thed/zephyr/cloud/rest/client/JwtGenerator.java: -------------------------------------------------------------------------------- 1 | package com.thed.zephyr.cloud.rest.client; 2 | 3 | import java.net.URI; 4 | 5 | /** 6 | * Created by aliakseimatsarski on 11/3/16. 7 | */ 8 | public interface JwtGenerator { 9 | 10 | String generateJWT(String requestMethod, URI uri, int jwtExpiryWindowSeconds); 11 | } 12 | -------------------------------------------------------------------------------- /generator/java/src/main/java/com/thed/zephyr/cloud/rest/client/impl/JwtGeneratorImpl.java: -------------------------------------------------------------------------------- 1 | package com.thed.zephyr.cloud.rest.client.impl; 2 | 3 | import com.atlassian.connect.play.java.AcHost; 4 | import com.atlassian.connect.play.java.http.HttpMethod; 5 | import com.atlassian.fugue.Option; 6 | import com.atlassian.jwt.SigningAlgorithm; 7 | import com.atlassian.jwt.core.TimeUtil; 8 | import com.atlassian.jwt.core.writer.JsonSmartJwtJsonBuilder; 9 | import com.atlassian.jwt.core.writer.JwtClaimsBuilder; 10 | import com.atlassian.jwt.core.writer.NimbusJwtWriterFactory; 11 | import com.atlassian.jwt.exception.JwtIssuerLacksSharedSecretException; 12 | import com.atlassian.jwt.exception.JwtSigningException; 13 | import com.atlassian.jwt.exception.JwtUnknownIssuerException; 14 | import com.atlassian.jwt.httpclient.CanonicalHttpUriRequest; 15 | import com.atlassian.jwt.writer.JwtJsonBuilder; 16 | import com.atlassian.jwt.writer.JwtWriter; 17 | import com.atlassian.jwt.writer.JwtWriterFactory; 18 | import com.google.common.base.Function; 19 | import com.google.common.collect.Maps; 20 | import com.thed.zephyr.cloud.rest.client.JwtGenerator; 21 | import com.thed.zephyr.cloud.rest.client.JwtAuthorizationGenerator; 22 | import com.thed.zephyr.cloud.rest.model.ZConfig; 23 | import net.minidev.json.JSONObject; 24 | import org.apache.commons.lang3.StringUtils; 25 | import org.apache.http.NameValuePair; 26 | import org.apache.http.message.BasicHeaderValueParser; 27 | import org.apache.http.message.ParserCursor; 28 | import org.apache.http.util.CharArrayBuffer; 29 | 30 | import java.io.UnsupportedEncodingException; 31 | import java.net.URI; 32 | import java.net.URISyntaxException; 33 | import java.net.URLDecoder; 34 | import java.security.NoSuchAlgorithmException; 35 | import java.util.*; 36 | 37 | import static com.atlassian.jwt.JwtConstants.HttpRequests.JWT_AUTH_HEADER_PREFIX; 38 | import static com.google.common.base.Preconditions.checkArgument; 39 | import static com.google.common.base.Preconditions.checkNotNull; 40 | 41 | /** 42 | * Created by aliakseimatsarski on 11/3/16. 43 | */ 44 | public class JwtGeneratorImpl implements JwtGenerator { 45 | 46 | private ZConfig zConfig; 47 | 48 | public JwtGeneratorImpl(ZConfig zConfig) { 49 | this.zConfig = zConfig; 50 | } 51 | 52 | @Override 53 | public String generateJWT(String requestMethod, URI uri, int jwtExpiryWindowSeconds) { 54 | final JwtWriterFactory jwtWriterFactory = new NimbusJwtWriterFactory(); 55 | final char[] QUERY_DELIMITERS = new char[]{'&'}; 56 | // final int jwtExpiryWindowSeconds = 60 * 3; 57 | final JwtAuthorizationGenerator jwtAuthorisationGenerator = new JwtAuthorizationGenerator(jwtWriterFactory, jwtExpiryWindowSeconds) { 58 | 59 | public Option generate(HttpMethod httpMethod, URI url, Map> parameters, AcHost acHost, 60 | Option userId) 61 | throws JwtIssuerLacksSharedSecretException, JwtUnknownIssuerException { 62 | 63 | checkArgument(null != parameters, "Parameters Map argument cannot be null"); 64 | checkNotNull(acHost); 65 | 66 | Map paramsAsArrays = Maps.transformValues(parameters, new Function, String[]>() { 67 | @Override 68 | public String[] apply(List input) { 69 | return checkNotNull(input).toArray(new String[input.size()]); 70 | } 71 | }); 72 | return Option.some(JWT_AUTH_HEADER_PREFIX + encodeJwt(httpMethod, url, paramsAsArrays, userId.getOrNull(), 73 | acHost)); 74 | } 75 | 76 | private String encodeJwt(HttpMethod httpMethod, URI targetPath, Map params, String accountId, 77 | AcHost acHost) throws JwtUnknownIssuerException, JwtIssuerLacksSharedSecretException { 78 | checkArgument(null != httpMethod, "HttpMethod argument cannot be null"); 79 | checkArgument(null != targetPath, "URI argument cannot be null"); 80 | 81 | JwtJsonBuilder jsonBuilder = new JsonSmartJwtJsonBuilder() 82 | .issuedAt(TimeUtil.currentTimeSeconds()) 83 | .expirationTime(TimeUtil.currentTimePlusNSeconds(jwtExpiryWindowSeconds)) 84 | .issuer(zConfig.host.getKey()); 85 | 86 | 87 | 88 | if (null != accountId) { 89 | jsonBuilder = jsonBuilder.subject(accountId); 90 | } 91 | 92 | Map completeParams = params; 93 | 94 | try { 95 | if (!StringUtils.isEmpty(targetPath.getQuery())) { 96 | completeParams = new HashMap(params); 97 | completeParams.putAll(constructParameterMap(targetPath)); 98 | } 99 | 100 | CanonicalHttpUriRequest canonicalHttpUriRequest = new CanonicalHttpUriRequest(httpMethod.toString(), 101 | targetPath.getPath(), "", completeParams); 102 | 103 | JwtClaimsBuilder.appendHttpRequestClaims(jsonBuilder, canonicalHttpUriRequest); 104 | } catch (UnsupportedEncodingException e) { 105 | throw new RuntimeException(e); 106 | } catch (NoSuchAlgorithmException e) { 107 | throw new RuntimeException(e); 108 | } 109 | String build = jsonBuilder.build(); 110 | return issueJwt(build, zConfig); 111 | } 112 | 113 | private String issueJwt(String jsonPayload, ZConfig config) throws JwtSigningException, JwtIssuerLacksSharedSecretException, JwtUnknownIssuerException { 114 | return getJwtWriter(config).jsonToJwt(jsonPayload); 115 | } 116 | 117 | private JwtWriter getJwtWriter(ZConfig config) throws JwtUnknownIssuerException, JwtIssuerLacksSharedSecretException { 118 | return jwtWriterFactory.macSigningWriter(SigningAlgorithm.HS256, config.JIRA_SHARED_SECRET); 119 | } 120 | 121 | private Map constructParameterMap(URI uri) throws UnsupportedEncodingException { 122 | final String query = uri.getQuery(); 123 | if (query == null) { 124 | return Collections.emptyMap(); 125 | } 126 | Map queryParams = new HashMap(); 127 | CharArrayBuffer buffer = new CharArrayBuffer(query.length()); 128 | buffer.append(query); 129 | ParserCursor cursor = new ParserCursor(0, buffer.length()); 130 | 131 | while (!cursor.atEnd()) { 132 | NameValuePair nameValuePair = BasicHeaderValueParser.DEFAULT.parseNameValuePair(buffer, cursor, QUERY_DELIMITERS); 133 | if (!StringUtils.isEmpty(nameValuePair.getName())) { 134 | String decodedName = urlDecode(nameValuePair.getName()); 135 | String decodedValue = urlDecode(nameValuePair.getValue()); 136 | String[] oldValues = queryParams.get(decodedName); 137 | String[] newValues = null == oldValues ? new String[1] : Arrays.copyOf(oldValues, oldValues.length + 1); 138 | newValues[newValues.length - 1] = decodedValue; 139 | queryParams.put(decodedName, newValues); 140 | } 141 | } 142 | return queryParams; 143 | } 144 | 145 | private String urlDecode(final String content) throws UnsupportedEncodingException { 146 | return null == content ? null : URLDecoder.decode(content, "UTF-8"); 147 | } 148 | }; 149 | Option jwt = null; 150 | try { 151 | final URI uriWithoutProductContext = getUri(uri, zConfig.ZEPHYR_BASE_URL); 152 | 153 | jwt = jwtAuthorisationGenerator.generate(HttpMethod.valueOf(requestMethod), uriWithoutProductContext, new HashMap>(), zConfig.host, zConfig.ACCOUNT_ID); 154 | } catch (Exception e) { 155 | } 156 | final String authorizationHeaderValue = jwt.getOrNull(); 157 | 158 | return authorizationHeaderValue; 159 | } 160 | 161 | private URI getUri(URI uri, String baseUrlString) throws URISyntaxException { 162 | final String path = uri.getPath(); 163 | final URI baseUrl = new URI(baseUrlString); 164 | final String productContext = baseUrl.getPath(); 165 | final String pathWithoutProductContext = path.substring(productContext.length()); 166 | return new URI(uri.getScheme(), uri.getUserInfo(), uri.getHost(), uri.getPort(), 167 | pathWithoutProductContext, uri.getQuery(), uri.getFragment()); 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /generator/java/src/main/java/com/thed/zephyr/cloud/rest/exception/JobProgressException.java: -------------------------------------------------------------------------------- 1 | package generator.java.src.main.java.com.thed.zephyr.cloud.rest.exception; 2 | 3 | /** 4 | * Created by Masud on 11/19/18. 5 | */ 6 | public class JobProgressException extends Exception{ 7 | public JobProgressException() { 8 | } 9 | 10 | public JobProgressException(String message) { 11 | super(message); 12 | } 13 | 14 | public JobProgressException(String message, Throwable cause) { 15 | super(message, cause); 16 | } 17 | 18 | public JobProgressException(Throwable cause) { 19 | super(cause); 20 | } 21 | 22 | public JobProgressException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { 23 | super(message, cause, enableSuppression, writableStackTrace); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /generator/java/src/main/java/com/thed/zephyr/cloud/rest/model/ZConfig.java: -------------------------------------------------------------------------------- 1 | package com.thed.zephyr.cloud.rest.model; 2 | 3 | import com.atlassian.connect.play.java.AcHost; 4 | import com.atlassian.fugue.Option; 5 | import com.google.common.collect.ImmutableList; 6 | import org.apache.commons.configuration.ConfigurationException; 7 | import org.apache.commons.configuration.PropertiesConfiguration; 8 | 9 | import java.util.List; 10 | import java.util.Map; 11 | 12 | /** 13 | * Created by smangal on 12/18/14. 14 | */ 15 | public class ZConfig extends PropertiesConfiguration { 16 | 17 | public Option ACCOUNT_ID; 18 | public String JIRA_HOST_KEY; 19 | public String JIRA_BASE_URL; 20 | public String JIRA_SHARED_SECRET; 21 | 22 | public String ZEPHYR_BASE_URL; 23 | public String APP_KEY; 24 | public String SECRET_KEY; 25 | public String ACCESS_KEY; 26 | public AcHost host; 27 | 28 | final List reqdConfigKeys = ImmutableList.builder() 29 | .add("accountId") 30 | .add("jiraHostKey") 31 | .add("jiraBaseURL") 32 | .add("sharedSecret") 33 | .add("zephyrBaseURL") 34 | .add("accessKey") 35 | .add("secretKey") 36 | .add("appKey").build(); 37 | 38 | private ZConfig(){ 39 | } 40 | 41 | public ZConfig(String accessKey, String secretKey, String accountId, String zephyrBaseUrl) { 42 | JIRA_HOST_KEY = accessKey; 43 | JIRA_SHARED_SECRET = secretKey; 44 | 45 | ZEPHYR_BASE_URL = zephyrBaseUrl; 46 | ACCESS_KEY = accessKey; 47 | ACCOUNT_ID = Option.option(accountId); 48 | 49 | host = new AcHost(); 50 | host.setKey(JIRA_HOST_KEY); 51 | host.setBaseUrl(JIRA_BASE_URL); 52 | host.setSharedSecret(JIRA_SHARED_SECRET); 53 | 54 | } 55 | 56 | public ZConfig(String fileName) throws ConfigurationException { 57 | super(fileName); 58 | configure(); 59 | } 60 | 61 | public ZConfig(Map props) throws ConfigurationException { 62 | super(); 63 | for(Map.Entry prop : props.entrySet()) { 64 | this.addProperty(prop.getKey(), prop.getValue()); 65 | } 66 | configure(); 67 | } 68 | 69 | private void configure() throws ConfigurationException{ 70 | checkMandatoryPropertiesSet(); 71 | setLocalPropertyValues(); 72 | } 73 | 74 | private void checkMandatoryPropertiesSet() throws ConfigurationException { 75 | for (String key : reqdConfigKeys){ 76 | if (!this.containsKey(key)) { 77 | getLogger().fatal(key + "is required in ZFJ Cloud configration"); 78 | throw new ConfigurationException(key + "is required in ZFJ Cloud configration"); 79 | } 80 | } 81 | } 82 | 83 | public static class ZConfigBuilder{ 84 | 85 | private ZConfig zconfig; 86 | 87 | public ZConfigBuilder() { 88 | zconfig = new ZConfig(); 89 | } 90 | 91 | public ZConfigBuilder withJiraHostKey(String hostKey) { 92 | zconfig.addProperty("jiraHostKey", hostKey); 93 | return this; 94 | } 95 | 96 | public ZConfigBuilder withJIRABaseUrl(String baseUrl) { 97 | zconfig.addProperty("jiraBaseURL", baseUrl); 98 | return this; 99 | } 100 | 101 | public ZConfigBuilder withJIRASharedSecret(String sharedSecret) { 102 | zconfig.addProperty("sharedSecret", sharedSecret); 103 | return this; 104 | } 105 | 106 | public ZConfigBuilder withZephyrBaseUrl(String zephyrBaseUrl) { 107 | zconfig.addProperty("zephyrBaseURL", zephyrBaseUrl); 108 | return this; 109 | } 110 | 111 | public ZConfigBuilder withZephyrAppKey(String appKey) { 112 | zconfig.addProperty("appKey", appKey); 113 | return this; 114 | } 115 | 116 | public ZConfigBuilder withZephyrAccessKey(String accessKey) { 117 | zconfig.addProperty("accessKey", accessKey); 118 | return this; 119 | } 120 | 121 | public ZConfigBuilder withZephyrSecretKey(String secretKey) { 122 | zconfig.addProperty("secretKey", secretKey); 123 | return this; 124 | } 125 | 126 | 127 | public ZConfigBuilder withJiraAccountId(String accountId) { 128 | zconfig.addProperty("accountId", accountId); 129 | return this; 130 | } 131 | 132 | public ZConfig build() throws ConfigurationException{ 133 | zconfig.configure(); 134 | return zconfig; 135 | } 136 | } 137 | 138 | 139 | private void setLocalPropertyValues() { 140 | JIRA_HOST_KEY = this.getString("accessKey"); 141 | //JIRA_BASE_URL = this.getString("jiraBaseURL"); 142 | JIRA_SHARED_SECRET = this.getString("secretKey"); 143 | 144 | ZEPHYR_BASE_URL = this.getString("zephyrBaseURL"); 145 | //SECRET_KEY = this.getString("secretKey"); 146 | ACCESS_KEY = this.getString("accessKey"); 147 | //APP_KEY = this.getString("appKey"); 148 | 149 | ACCOUNT_ID = Option.some(this.getString("accountId")); 150 | 151 | host = new AcHost(); 152 | host.setKey(JIRA_HOST_KEY); 153 | host.setBaseUrl(JIRA_BASE_URL); 154 | host.setSharedSecret(JIRA_SHARED_SECRET); 155 | 156 | //host.setPublicKey("MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCQriXlBXjuybF3+jPDcYIbRfvZFlnH0Ci8gbINGFyx/I5bGupEyXpzbB6crlFNsY3Q+c7qT7rKOR7DJVLZX2APPAzTQhe06wjfEe1RJHdIjqCOio/VxipZAZWdmae4OWNMfo5zZ+NHb69z5qJjcYDv1EY+f2t7n323UAlwmZro9QIDAQAB"); 157 | // host.setSharedSecret("5bdcdc66-ded6-4fc7-ab38-82cb92a3986e"); 158 | 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /generator/java/src/main/resources/ZConfigConstants.properties: -------------------------------------------------------------------------------- 1 | jiraHostKey = amlyYTowNDQ2NzNjMi1kNGU0LTQzY2UtYTVhMi00OTRlZWU3YzJhYzYgYWRtaW4 2 | jiraBaseURL = http://127.0.0.1:2990 3 | sharedSecret = bm1Y8M3GyFEuzQeCYcK_hSEFA59FYTlzgMfUJ3DM11Y 4 | 5 | zephyrBaseURL = http://127.0.0.1:9000 6 | secretKey = bm1Y8M3GyFEuzQeCYcK_hSEFA59FYTlzgMfUJ3DM11Y 7 | accessKey = amlyYTowNDQ2NzNjMi1kNGU0LTQzY2UtYTVhMi00OTRlZWU3YzJhYzYgYWRtaW4 8 | appKey = com.thed.zephyr.cloud 9 | 10 | accountId = accountId 11 | 12 | -------------------------------------------------------------------------------- /generator/java/src/main/resources/jira-rest-java-client-core-2.0.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zephyrdeveloper/zapi-cloud/63d4a586cd2cd3d86f94988d800d69cd2e158b68/generator/java/src/main/resources/jira-rest-java-client-core-2.0.1.jar -------------------------------------------------------------------------------- /generator/java/src/test/java/com/thed/zephyr/GenerateJWTTest.java: -------------------------------------------------------------------------------- 1 | package com.thed.zephyr; 2 | 3 | import com.thed.zephyr.cloud.rest.client.JwtGenerator; 4 | import com.thed.zephyr.util.AbstractTest; 5 | import org.junit.BeforeClass; 6 | import org.junit.Test; 7 | 8 | import java.net.MalformedURLException; 9 | import java.net.URI; 10 | import java.net.URISyntaxException; 11 | import java.net.URL; 12 | 13 | /** 14 | * Created by aliakseimatsarski on 3/15/16. 15 | */ 16 | public class GenerateJWTTest extends AbstractTest { 17 | 18 | private static JwtGenerator jwtGenerator; 19 | 20 | @BeforeClass 21 | public static void setUp() throws Exception{ 22 | jwtGenerator = client.getJwtGenerator(); 23 | } 24 | 25 | //@Test 26 | public void testGenerateJWT() throws URISyntaxException { 27 | String urlStr = "https://ea7decb8.ngrok.io/public/rest/api/1.0/executions?projectId=10200&issueId=11105&offset=0&size=10"; 28 | URI url = new URI(urlStr); 29 | String jwt = jwtGenerator.generateJWT("GET", url, 3600); 30 | System.out.println("JWT " + jwt); 31 | } 32 | 33 | 34 | } 35 | -------------------------------------------------------------------------------- /generator/java/src/test/java/com/thed/zephyr/util/AbstractTest.java: -------------------------------------------------------------------------------- 1 | package com.thed.zephyr.util; 2 | 3 | import com.thed.zephyr.cloud.rest.ZFJCloudRestClient; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | 7 | /** 8 | * Created by aliakseimatsarski on 3/17/16. 9 | */ 10 | public class AbstractTest { 11 | 12 | final static String accessKey = "amlyYTo5OTY4ZGJiMy0yYzY3LTQyNzQtOGEyZC0wYjQwMGViOGQ0YjYgYWRtaW4gYWxleC1rZXk";/*replace with you credentials */ 13 | // final static String accessKey = "amlyYTo5OTY4ZGJiMy0yYzY3LTQyNzQtOGEyZC0wYjQwMGViOGQ0YjYgYWRtaW4"; 14 | 15 | final static String secretKey = "PCaxEBZKIkwRdHWocjuIIdbH2hRR7TvwL2RO5T7wjdY";/*replace with you credentials */ 16 | // final static String secretKey = "ezBkGY4V0fnNyE3mAMNl813rhxqM5c79fijbdlf3eZQ"; 17 | 18 | final static String accountId = "accountId"; 19 | final static String zephyrBaseUrl = "https://ea7decb8.ngrok.io"; 20 | public static ZFJCloudRestClient client; 21 | 22 | public Logger log = LoggerFactory.getLogger(AbstractTest.class); 23 | 24 | static { 25 | client = ZFJCloudRestClient.restBuilder(zephyrBaseUrl, accessKey, secretKey, accountId).build(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /generator/python/CycleTest.py: -------------------------------------------------------------------------------- 1 | import json 2 | import jwt 3 | import time 4 | import hashlib 5 | import requests 6 | 7 | 8 | def is_json(data): 9 | try: 10 | json.loads(data) 11 | except ValueError: 12 | return False 13 | return True 14 | 15 | 16 | 17 | # ACCOUNT ID 18 | ACCOUNT_ID = '123456:1234abcd-1234-abcd-1234-1234abcd1234' 19 | 20 | # ACCESS KEY from navigation >> Tests >> API Keys 21 | ACCESS_KEY = 'amlyYTplN2UyNjFjNC02MTM4LTRiZWEtYWRiNy1lYmMyMjk0ZmZlMGUgYWRtaW4' 22 | 23 | # ACCESS KEY from navigation >> Tests >> API Keys 24 | SECRET_KEY = '01wOEb-ZpIruI_QoAPSHirjBXsZRA3LDuLpnw0OHP-8' 25 | 26 | # JWT EXPIRE how long token been to be active? 3600 == 1 hour 27 | JWT_EXPIRE = 3600 28 | 29 | # BASE URL for Zephyr for Jira Cloud 30 | BASE_URL = 'http://localhost:9000' 31 | 32 | # RELATIVE PATH for token generation and make request to api 33 | RELATIVE_PATH = '/public/rest/api/1.0/cycle' 34 | 35 | # CANONICAL PATH (Http Method & Relative Path & Query String) 36 | CANONICAL_PATH = 'POST&'+RELATIVE_PATH+'&' 37 | 38 | # TOKEN HEADER: to generate jwt token 39 | payload_token = { 40 | 'sub': ACCOUNT_ID, 41 | 'qsh': hashlib.sha256(CANONICAL_PATH.encode('utf-8')).hexdigest(), 42 | 'iss': ACCESS_KEY, 43 | 'exp': int(time.time())+JWT_EXPIRE, 44 | 'iat': int(time.time()) 45 | } 46 | 47 | # GENERATE TOKEN 48 | token = jwt.encode(payload_token, SECRET_KEY, algorithm='HS256').strip().decode('utf-8') 49 | 50 | # REQUEST HEADER: to authenticate and authorize api 51 | headers = { 52 | 'Authorization': 'JWT '+token, 53 | 'Content-Type': 'application/json', 54 | 'zapiAccessKey': ACCESS_KEY 55 | } 56 | 57 | # REQUEST HEADER: to create cycle 58 | headers = { 59 | 'Authorization': 'JWT '+token, 60 | 'Content-Type': 'application/json', 61 | 'zapiAccessKey': ACCESS_KEY 62 | } 63 | 64 | # REQUEST PAYLOAD: to create cycle 65 | cycle = { 66 | 'name': 'Sample Cycle', 67 | 'projectId': 10000, 68 | 'versionId': -1 69 | } 70 | 71 | # MAKE REQUEST: 72 | raw_result = requests.post(BASE_URL + RELATIVE_PATH, headers=headers, json=cycle) 73 | if is_json(raw_result.text): 74 | 75 | # JSON RESPONSE: convert response to JSON 76 | json_result = json.loads(raw_result.text) 77 | 78 | # PRINT RESPONSE: pretty print with 4 indent 79 | print(json.dumps(json_result, indent=4, sort_keys=True)) 80 | 81 | else: 82 | print(raw_result.text) 83 | -------------------------------------------------------------------------------- /generator/python/README.md: -------------------------------------------------------------------------------- 1 | # zapi_py 2 | zephyr for jira cloud api 3 | -------------------------------------------------------------------------------- /generator/python/models/Cycle.py: -------------------------------------------------------------------------------- 1 | 2 | class Cycle(object): 3 | 4 | def __init__(self, name, environment, build, version_id, project_id, description, sprint_id): 5 | self.name = name 6 | self.environment = environment 7 | self.build = build 8 | self.versionId = version_id 9 | self.projectId = project_id 10 | self.description = description 11 | self.sprintId = sprint_id 12 | self.createdBy = None 13 | self.createdByAccountId = None 14 | self.modifiedBy = None 15 | self.modifiedByAccountId = None 16 | self.startDate = None 17 | self.endDate = None 18 | -------------------------------------------------------------------------------- /generator/python/models/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zephyrdeveloper/zapi-cloud/63d4a586cd2cd3d86f94988d800d69cd2e158b68/generator/python/models/__init__.py -------------------------------------------------------------------------------- /generator/python/models/__pycache__/Cycle.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zephyrdeveloper/zapi-cloud/63d4a586cd2cd3d86f94988d800d69cd2e158b68/generator/python/models/__pycache__/Cycle.cpython-35.pyc -------------------------------------------------------------------------------- /generator/python/models/__pycache__/__init__.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zephyrdeveloper/zapi-cloud/63d4a586cd2cd3d86f94988d800d69cd2e158b68/generator/python/models/__pycache__/__init__.cpython-35.pyc -------------------------------------------------------------------------------- /generator/python/util/JWTGenerator.py: -------------------------------------------------------------------------------- 1 | import jwt 2 | import time 3 | import hashlib 4 | 5 | 6 | class JWTGenerator: 7 | 8 | def __init__(self, account_id, access_key, secret_key, canonical_path): 9 | self.account_id = account_id 10 | self.access_key = access_key 11 | self.secret_key = secret_key 12 | self.expire = 3600 13 | self.canonical_path = canonical_path 14 | 15 | @property 16 | def jwt(self): 17 | payload = { 18 | 'sub': self.account_id, 19 | 'qsh': hashlib.sha256(self.canonical_path.encode('utf-8')).hexdigest(), 20 | 'iss': self.access_key, 21 | 'exp': time.time()+self.expire, 22 | 'iat': time.time() 23 | } 24 | token = jwt.encode(payload, self.secret_key, algorithm='HS256') 25 | return token 26 | 27 | @property 28 | def headers(self): 29 | headers = { 30 | 'Authorization': 'JWT '+self.jwt(), 31 | 'Content-Type': 'application/json', 32 | 'zapiAccessKey': self.access_key 33 | } 34 | return headers 35 | 36 | -------------------------------------------------------------------------------- /generator/python/util/JWTGenerator.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zephyrdeveloper/zapi-cloud/63d4a586cd2cd3d86f94988d800d69cd2e158b68/generator/python/util/JWTGenerator.pyc -------------------------------------------------------------------------------- /generator/python/util/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zephyrdeveloper/zapi-cloud/63d4a586cd2cd3d86f94988d800d69cd2e158b68/generator/python/util/__init__.py -------------------------------------------------------------------------------- /generator/python/util/__init__.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zephyrdeveloper/zapi-cloud/63d4a586cd2cd3d86f94988d800d69cd2e158b68/generator/python/util/__init__.pyc -------------------------------------------------------------------------------- /generator/python/util/__pycache__/JWTGenerator.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zephyrdeveloper/zapi-cloud/63d4a586cd2cd3d86f94988d800d69cd2e158b68/generator/python/util/__pycache__/JWTGenerator.cpython-35.pyc -------------------------------------------------------------------------------- /generator/python/util/__pycache__/__init__.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zephyrdeveloper/zapi-cloud/63d4a586cd2cd3d86f94988d800d69cd2e158b68/generator/python/util/__pycache__/__init__.cpython-35.pyc --------------------------------------------------------------------------------