├── .gitignore ├── CHANGELOG.rst ├── LICENSE ├── README.md ├── pom.xml └── src ├── CvmV3Demo.java ├── Demo.java ├── DynamicModuleDemo.java └── main └── java └── com └── qcloud ├── Common ├── Request.java └── Sign.java ├── Module ├── APIGateway.java ├── Account.java ├── Athena.java ├── Base.java ├── Batch.java ├── Bgpip.java ├── Bill.java ├── Bm.java ├── Bmeip.java ├── Bmlb.java ├── Bmvpc.java ├── Cbs.java ├── Cdb.java ├── Cdn.java ├── CloudAudit.java ├── Cmem.java ├── Cns.java ├── Cvm.java ├── Dfw.java ├── Eip.java ├── Emr.java ├── Feecenter.java ├── Image.java ├── Lb.java ├── Live.java ├── Market.java ├── Monitor.java ├── Morphling.java ├── Partners.java ├── Scaling.java ├── Scf.java ├── Sec.java ├── Snapshot.java ├── Sts.java ├── Tbaas.java ├── Tdsql.java ├── Tmt.java ├── Trade.java ├── Vod.java ├── Vpc.java ├── Wenzhi.java └── Yunsou.java ├── QcloudApiModuleCenter.java └── Utilities ├── Base64.java ├── Json ├── JSONArray.java ├── JSONException.java ├── JSONObject.java ├── JSONString.java ├── JSONStringer.java ├── JSONTokener.java └── JSONWriter.java ├── MD5.java └── SHA1.java /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | *.class 3 | .classpath 4 | .project 5 | .settings/ 6 | -------------------------------------------------------------------------------- /CHANGELOG.rst: -------------------------------------------------------------------------------- 1 | ========= 2 | CHANGELOG 3 | ========= 4 | 5 | latest (now) 6 | ============ 7 | 8 | * modify generateUrl(): previously the url just used for debug, now we use urlencode to make the generated url available to be requested directly, for get method only. Please note that due to Tencent cloud API's limit, the signature will be expired in 5 minutes. 9 | 10 | 2.0.7 (2018-07-18) 11 | ================== 12 | 13 | * support dymanic module: now if module is not explicitly presented in src/main/java/com/qcloud/Module, such as the ckafka product, you can use Morphling module with the dynamic module name, it will work as it is. 14 | 15 | 2.0.6 (2018-03-02) 16 | ================== 17 | 18 | * add tbaas module 19 | * add emr module 20 | * add athena module 21 | 22 | 2.0.5 (2017-01-22) 23 | ================== 24 | 25 | * add partners module 26 | * increase connect timeout (5s) and add read timeout (90s) 27 | 28 | 2.0.4 (2017-12-10) 29 | ================== 30 | 31 | * add tmt module 32 | * add apigateway module 33 | * add scf module 34 | * add dfw module 35 | * add cloudaudit module 36 | * add batch module 37 | 38 | 2.0.3 (2017-11-10) 39 | ================== 40 | 41 | * add bgpip module 42 | 43 | history 44 | ======= 45 | 46 | * [2017/11/12] 增加Bgpip模块 47 | * [2017/9/11] 增加Bmeip和Bmvpc模块 48 | * [2017/8/7] 增加Feecenter模块 49 | * [2017/7/31] 增加Bm和Bmlb模块 50 | * [2017/7/12] 回滚:不默认传Version参数 51 | * [2017/6.29] https请求支持SNI特性:访问api的域名放入server_name扩展字段中。 52 | * [5/19] 设置接口默认Version: 53 | Cvm模块新版本API已经上线,通过是否传Version区分新旧版本。SDK默认调用新接口,因此需要增加Version的默认设置。 54 | CvmAPI接口介绍见:https://www.qcloud.com/document/api/213/569 55 | * [3/10] 增加HmacSHA256签名算法的兼容。 56 | * [7/15] 增加Tdsql模块。 57 | -------------------------------------------------------------------------------- /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 | # qcloudapi-sdk-java 2 | 3 | qcloudapi-sdk-java是为了让Java开发者能够在自己的代码里更快捷方便的使用腾讯云的API而开发的SDK工具包。 4 | 5 | ## 资源 6 | 7 | * [公共参数](http://wiki.qcloud.com/wiki/%E5%85%AC%E5%85%B1%E5%8F%82%E6%95%B0) 8 | * [API列表](http://wiki.qcloud.com/wiki/API) 9 | * [错误码](http://wiki.qcloud.com/wiki/%E9%94%99%E8%AF%AF%E7%A0%81) 10 | 11 | ## 入门 12 | 13 | 1. 申请安全凭证。 14 | 在第一次使用云API之前,用户首先需要在腾讯云网站上申请安全凭证,安全凭证包括 SecretId 和 SecretKey, SecretId 是用于标识 API 调用者的身份,SecretKey是用于加密签名字符串和服务器端验证签名字符串的密钥。SecretKey 必须严格保管,避免泄露。 15 | 16 | 2. 下载SDK,放入到您的程序目录。或使用Maven。 17 | 3. SDK Maven使用示例,所有SDK版本可查看[此链接](https://mvnrepository.com/artifact/com.qcloud/qcloud-java-sdk)。 18 | 19 | ``` 20 | 21 | com.qcloud 22 | qcloud-java-sdk 23 | 2.0.6 24 | 25 | ``` 26 | 使用方法请参考下面的例子。 27 | 28 | ## 例子 29 | 30 | ### DescribeInstances 接口 31 | 32 | public class Demo { 33 | public static void main(String[] args) { 34 | /* 如果是循环调用下面举例的接口,需要从此处开始你的循环语句。切记! */ 35 | TreeMap config = new TreeMap(); 36 | config.put("SecretId", "你的secretId"); 37 | config.put("SecretKey", "你的secretKey"); 38 | /* 请求方法类型 POST、GET */ 39 | config.put("RequestMethod", "GET"); 40 | /* 区域参数,可选: gz:广州; sh:上海; hk:中国香港; ca:北美;等。 */ 41 | config.put("DefaultRegion", "gz"); 42 | 43 | /* 44 | * 你将要使用接口所在的模块,可以从 官网->云api文档->XXXX接口->接口描述->域名 45 | * 中获取,比如域名:cvm.api.qcloud.com,module就是new Cvm()。 46 | */ 47 | /* 48 | * DescribeInstances 49 | * 的api文档地址:http://www.qcloud.com/wiki/v2/DescribeInstances 50 | */ 51 | QcloudApiModuleCenter module = new QcloudApiModuleCenter(new Cvm(),config); 52 | TreeMap params = new TreeMap(); 53 | // 将需要输入的参数都放入 params 里面,必选参数是必填的。 54 | // DescribeInstances 接口的部分可选参数如下 55 | params.put("offset", 0); 56 | params.put("limit", 3); 57 | // 在这里指定所要用的签名算法,不指定默认为HmacSHA1 58 | // params.put("SignatureMethod", "HmacSHA256"); 59 | // generateUrl 方法生成请求串,但不发送请求。在正式请求中,可以删除下面这行代码。 60 | // 如果是POST方法,或者系统不支持UTF8编码,则仅会打印host+path信息。 61 | // System.out.println(module.generateUrl("DescribeInstances", params)); 62 | 63 | String result = null; 64 | try { 65 | // call 方法正式向指定的接口名发送请求,并把请求参数params传入,返回即是接口的请求结果。 66 | result = module.call("DescribeInstances", params); 67 | // 可以对返回的字符串进行json解析,您可以使用其他的json包进行解析,此处仅为示例 68 | JSONObject json_result = new JSONObject(result); 69 | System.out.println(json_result); 70 | } catch (Exception e) { 71 | System.out.println("error..." + e.getMessage()); 72 | } 73 | 74 | } 75 | } 76 | 77 | ## 动态模块 78 | 79 | 以前SDK需要把每一个产品都建一个类文件,指定域名,这虽然加强了合法性检查,但是新产品上线后,可能没有同步到SDK,造成开发者使用不便。 80 | 2.0.7及更高的版本支持动态模块,你可以直接按模块名初始化,例如: 81 | 82 | ``` 83 | import com.qcloud.Module.Morphling; 84 | 85 | ... 86 | 87 | // ckafka并未有定义文件,但你仍然可以通过Morphling这个类来指定初始化 88 | Morphling morphling = new Morphling("ckafka"); 89 | QcloudApiModuleCenter module = new QcloudApiModuleCenter(morphling, config); 90 | String action = "ListInstance"; 91 | 92 | ... 93 | ``` 94 | 95 | 这里ckafka并未有对应的类文件,但是仍然可以初始化成功并执行接下来的接口调用。注意,代码中实际上是把模块名拼接API的根域名进行调用的,而极个别的产品其模块名和域名不对应,典型的如cmq的域名首部是带地域信息的,此时模块名应该遵从域名首部。 96 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | com.qcloud 5 | qcloud-java-sdk 6 | jar 7 | 2.0.7 8 | qcloud-java-sdk 9 | http://www.qcloud.com 10 | Tencent Cloud Open API SDK for Java 11 | 12 | Copyright (C) Tencent Cloud 13 | All Rights Reserved. 14 | 15 | 版权所有 (C)腾讯云 16 | 17 | http://www.qcloud.com 18 | 19 | 20 | UTF-8 21 | 22 | 23 | 24 | 25 | 26 | org.apache.maven.plugins 27 | maven-compiler-plugin 28 | 2.3.2 29 | 30 | 1.6 31 | 1.6 32 | UTF-8 33 | 34 | 35 | 36 | 37 | org.apache.maven.plugins 38 | maven-jar-plugin 39 | 2.3.2 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | org.apache.maven.plugins 48 | maven-source-plugin 49 | 2.1 50 | 51 | 52 | attach-sources 53 | 54 | jar-no-fork 55 | 56 | 57 | 58 | 59 | 60 | 61 | org.apache.maven.plugins 62 | maven-javadoc-plugin 63 | 2.10.3 64 | 65 | 66 | attach-javadocs 67 | 68 | jar 69 | 70 | 71 | 72 | 73 | UTF-8 74 | 75 | 76 | 77 | 78 | org.apache.maven.plugins 79 | maven-gpg-plugin 80 | 1.6 81 | 82 | 83 | sign-artifacts 84 | verify 85 | 86 | sign 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | org.sonatype.plugins 100 | nexus-staging-maven-plugin 101 | 1.6.7 102 | true 103 | 104 | ossrh 105 | https://oss.sonatype.org/ 106 | true 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | ossrh 117 | https://oss.sonatype.org/content/repositories/snapshots 118 | 119 | 120 | ossrh 121 | https://oss.sonatype.org/service/local/staging/deploy/maven2/ 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | https://github.com/QcloudApi/qcloudapi-sdk-java.git 135 | 136 | 137 | 138 | 139 | alexjtxie 140 | alexjtxie 141 | alexjtxie@tencent.com 142 | 143 | 144 | 145 | -------------------------------------------------------------------------------- /src/CvmV3Demo.java: -------------------------------------------------------------------------------- 1 | import java.util.TreeMap; 2 | 3 | import com.qcloud.QcloudApiModuleCenter; 4 | import com.qcloud.Module.Cvm; 5 | 6 | public class CvmV3Demo { 7 | public static void main(String[] args) { 8 | // 从环境变量中读取信息,设置代理,如果没有代理则不需要设置 9 | System.setProperty("https.proxyHost", System.getenv("HTTPS_PROXY_HOST")); 10 | System.setProperty("https.proxyPort", System.getenv("HTTPS_PROXY_PORT")); 11 | TreeMap config = new TreeMap(); 12 | // 从环境变量中读取信息,设置密钥对,请不要把密钥对明文写在代码中以防泄漏 13 | // 如果读取环境变量失败,运行代码时将报java.lang.NullPointerException错误 14 | config.put("SecretId", System.getenv("QCLOUD_SECRET_ID")); 15 | config.put("SecretKey", System.getenv("QCLOUD_SECRET_KEY")); 16 | // 请求方法类型 POST、GET 17 | //config.put("RequestMethod", "POST"); 18 | // 区域参数,例如 ap-guangzhou 19 | // 参考:https://cloud.tencent.com/document/api/213/9456 20 | config.put("DefaultRegion", "ap-guangzhou"); 21 | // 在这里指定所要用的签名算法,不指定默认为 HmacSHA1 22 | config.put("SignatureMethod", "HmacSHA256"); 23 | 24 | // 示例服务:CVM 25 | // 示例:DescribeInstances 26 | // API 文档地址:https://cloud.tencent.com/document/api/213/9388 27 | QcloudApiModuleCenter module = new QcloudApiModuleCenter(new Cvm(), config); 28 | String action = "DescribeInstances"; 29 | 30 | TreeMap params = new TreeMap(); 31 | // 必须设置 Version = 2017-03-12 才能使用对应版本的 CVM API 32 | params.put("Version", "2017-03-12"); 33 | // 将需要输入的参数都放入 params 里面,必选参数是必填的。 34 | // DescribeInstances 接口的部分可选参数如下 35 | params.put("Offset", 0); 36 | params.put("Limit", 1); 37 | 38 | // generateUrl 方法生成请求串,可用于调试使用 39 | System.out.println(module.generateUrl(action, params)); 40 | String result = null; 41 | try { 42 | // call 方法正式向指定的接口名发送请求,并把请求参数 params 传入,返回即是接口的请求结果。 43 | result = module.call(action, params); 44 | System.out.println(result); 45 | } catch (Exception e) { 46 | System.out.println("error..." + e.getMessage()); 47 | } 48 | 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Demo.java: -------------------------------------------------------------------------------- 1 | import java.util.TreeMap; 2 | 3 | import com.qcloud.QcloudApiModuleCenter; 4 | import com.qcloud.Module.Cvm; 5 | 6 | public class Demo { 7 | public static void main(String[] args) { 8 | /* 如果是循环调用下面举例的接口,需要从此处开始你的循环语句。切记! */ 9 | TreeMap config = new TreeMap(); 10 | config.put("SecretId", "你的secretId"); 11 | config.put("SecretKey", "你的secretKey"); 12 | /* 请求方法类型 POST、GET */ 13 | config.put("RequestMethod", "GET"); 14 | /* 区域参数,可选: gz:广州; sh:上海; hk:香港; ca:北美;等。 */ 15 | config.put("DefaultRegion", "gz"); 16 | 17 | /* 18 | * 你将要使用接口所在的模块,可以从 官网->云api文档->XXXX接口->接口描述->域名 19 | * 中获取,比如域名:cvm.api.qcloud.com,module就是 new Cvm()。 20 | */ 21 | /* 22 | * 示例:DescribeInstances 23 | * 的api文档地址:http://www.qcloud.com/wiki/v2/DescribeInstances 24 | */ 25 | QcloudApiModuleCenter module = new QcloudApiModuleCenter(new Cvm(), 26 | config); 27 | 28 | TreeMap params = new TreeMap(); 29 | /* 将需要输入的参数都放入 params 里面,必选参数是必填的。 */ 30 | /* DescribeInstances 接口的部分可选参数如下 */ 31 | params.put("offset", 0); 32 | params.put("limit", 3); 33 | /*在这里指定所要用的签名算法,不指定默认为HmacSHA1*/ 34 | //params.put("SignatureMethod", "HmacSHA256"); 35 | 36 | /* generateUrl方法生成请求串,可用于调试使用 */ 37 | //System.out.println(module.generateUrl("DescribeInstances", params)); 38 | String result = null; 39 | try { 40 | /* call 方法正式向指定的接口名发送请求,并把请求参数params传入,返回即是接口的请求结果。 */ 41 | result = module.call("DescribeInstances", params); 42 | System.out.println(result); 43 | } catch (Exception e) { 44 | System.out.println("error..." + e.getMessage()); 45 | } 46 | 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/DynamicModuleDemo.java: -------------------------------------------------------------------------------- 1 | import java.util.TreeMap; 2 | 3 | import com.qcloud.QcloudApiModuleCenter; 4 | import com.qcloud.Module.Morphling; 5 | 6 | public class DynamicModuleDemo { 7 | public static void main(String[] args) { 8 | // 从环境变量中读取信息,设置代理,如果没有代理则不需要设置 9 | System.setProperty("https.proxyHost", System.getenv("HTTPS_PROXY_HOST")); 10 | System.setProperty("https.proxyPort", System.getenv("HTTPS_PROXY_PORT")); 11 | TreeMap config = new TreeMap(); 12 | // 从环境变量中读取信息,设置密钥对,请不要把密钥对明文写在代码中以防泄漏 13 | // 如果读取环境变量失败,运行代码时将报java.lang.NullPointerException错误 14 | config.put("SecretId", System.getenv("QCLOUD_SECRET_ID")); 15 | config.put("SecretKey", System.getenv("QCLOUD_SECRET_KEY")); 16 | // 请求方法类型 POST、GET 17 | // config.put("RequestMethod", "POST"); 18 | // 区域参数,例如 ap-guangzhou 19 | // 参考:https://cloud.tencent.com/document/api/213/9456 20 | config.put("DefaultRegion", "ap-guangzhou"); 21 | // 在这里指定所要用的签名算法,不指定默认为 HmacSHA1 22 | config.put("SignatureMethod", "HmacSHA256"); 23 | 24 | // 示例服务:CVM 25 | // 示例:DescribeInstances 26 | // API 文档地址:https://cloud.tencent.com/document/api/213/831 27 | Morphling morphling = new Morphling("cvm"); 28 | QcloudApiModuleCenter module = new QcloudApiModuleCenter(morphling, config); 29 | String action = "DescribeInstances"; 30 | 31 | TreeMap params = new TreeMap(); 32 | params.put("offset", 1); 33 | params.put("limit", 1); 34 | 35 | // generateUrl 方法生成请求串,可用于调试使用 36 | System.out.println(module.generateUrl(action, params)); 37 | String result = null; 38 | try { 39 | // call 方法正式向指定的接口名发送请求,并把请求参数 params 传入,返回即是接口的请求结果。 40 | result = module.call(action, params); 41 | System.out.println(result); 42 | } catch (Exception e) { 43 | System.out.println("error..." + e.getMessage()); 44 | } 45 | 46 | // 示例服务:ckafka 47 | // 示例:ListInstance 48 | // API 文档地址:https://cloud.tencent.com/document/product/597/10093 49 | 50 | // 你可以创建新的对象,此处演示使用旧对象切换不同的模块 51 | // module = new QcloudApiModuleCenter(new Morphling("ckafka"), config); 52 | morphling.morph("ckafka"); 53 | action = "ListInstance"; 54 | 55 | // 你应当根据接口定义重新设置params,但是此处恰好两个接口都支持offset和limit,因此可以直接使用 56 | System.out.println(module.generateUrl(action, params)); 57 | try { 58 | result = module.call(action, params); 59 | System.out.println(result); 60 | } catch (Exception e) { 61 | System.out.println("error..." + e.getMessage()); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Common/Request.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Common; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.DataInputStream; 5 | import java.io.DataOutputStream; 6 | import java.io.File; 7 | import java.io.FileInputStream; 8 | import java.io.InputStreamReader; 9 | import java.io.OutputStream; 10 | import java.io.UnsupportedEncodingException; 11 | import java.net.HttpURLConnection; 12 | import java.net.URL; 13 | import java.net.URLConnection; 14 | import java.net.URLEncoder; 15 | import java.util.Map; 16 | import java.util.Random; 17 | import java.util.TreeMap; 18 | 19 | import javax.net.ssl.HttpsURLConnection; 20 | 21 | import com.qcloud.Utilities.MD5; 22 | 23 | /** 24 | * 请求调用类 25 | * @author robinslsun 26 | */ 27 | public class Request { 28 | protected static String requestUrl = ""; 29 | protected static String rawResponse = ""; 30 | protected static String version = "SDK_JAVA_2.0.7"; 31 | protected static int connectTimeout = 5000; // ms 32 | protected static int readTimeout = 90000; // ms 33 | 34 | public static String getRequestUrl() { 35 | return requestUrl; 36 | } 37 | 38 | public static String getRawResponse() { 39 | return rawResponse; 40 | } 41 | 42 | public static String generateUrl(TreeMap params, 43 | String secretId, String secretKey, String requestMethod, 44 | String requestHost, String requestPath) { 45 | if (!params.containsKey("SecretId")) 46 | params.put("SecretId", secretId); 47 | 48 | if (!params.containsKey("Nonce")) 49 | params.put("Nonce", 50 | new Random().nextInt(java.lang.Integer.MAX_VALUE)); 51 | 52 | if (!params.containsKey("Timestamp")) 53 | params.put("Timestamp", System.currentTimeMillis() / 1000); 54 | 55 | params.put("RequestClient", version); 56 | 57 | String plainText = Sign.makeSignPlainText(params, requestMethod, 58 | requestHost, requestPath); 59 | 60 | String signatureMethod = "HmacSHA1"; 61 | if(params.containsKey("SignatureMethod") && params.get("SignatureMethod").toString().equals("HmacSHA256")) 62 | { 63 | signatureMethod = "HmacSHA256"; 64 | } 65 | 66 | try { 67 | params.put("Signature", Sign.sign(plainText, secretKey, signatureMethod)); 68 | } catch (Exception e) { 69 | e.printStackTrace(); 70 | } 71 | 72 | StringBuilder url = new StringBuilder("https://"); 73 | url.append(requestHost).append(requestPath).append("?"); 74 | if (requestMethod.equals("GET")) { 75 | for ( String k : params.keySet() ) { 76 | try { 77 | url.append(k.replace("_", ".")) 78 | .append("=") 79 | .append(URLEncoder.encode(params.get(k).toString(), "utf-8")) 80 | .append("&"); 81 | } catch (UnsupportedEncodingException e) { 82 | // 下面是一个错误的做法。 83 | // 本应该抛出异常让上层捕获处理,但是出于保持兼容性的考虑, 84 | // 并不想让这个方法升级后抛出一个未捕获的异常。 85 | // 而且之所以会有这个异常,是因为有些特殊系统未必支持utf-8, 86 | // 在这些系统上,其实根本无法正常调用云API, 87 | // 所以可以直接忽略,返回一个无用的信息即可。 88 | return "https://" + requestHost + requestPath; 89 | } 90 | } 91 | } 92 | 93 | return url.toString().substring(0, url.length() - 1); 94 | } 95 | 96 | public static String send(TreeMap params, String secretId, 97 | String secretKey, String requestMethod, String requestHost, 98 | String requestPath, String fileName) { 99 | if (!params.containsKey("SecretId")) 100 | params.put("SecretId", secretId); 101 | 102 | if (!params.containsKey("Nonce")) 103 | params.put("Nonce", 104 | new Random().nextInt(java.lang.Integer.MAX_VALUE)); 105 | 106 | if (!params.containsKey("Timestamp")) 107 | params.put("Timestamp", System.currentTimeMillis() / 1000); 108 | 109 | params.put("RequestClient", version); 110 | params.remove("Signature"); 111 | String plainText = Sign.makeSignPlainText(params, requestMethod, 112 | requestHost, requestPath); 113 | 114 | String signatureMethod = "HmacSHA1"; 115 | if(params.containsKey("SignatureMethod") && params.get("SignatureMethod").toString().equals("HmacSHA256")) 116 | { 117 | signatureMethod = "HmacSHA256"; 118 | } 119 | 120 | try { 121 | params.put("Signature", Sign.sign(plainText, secretKey, signatureMethod)); 122 | } catch (Exception e) { 123 | e.printStackTrace(); 124 | } 125 | 126 | String url = "https://" + requestHost + requestPath; 127 | 128 | return sendRequest(url, params, requestMethod, fileName); 129 | } 130 | 131 | public static String sendRequest(String url, 132 | Map requestParams, String requestMethod, 133 | String fileName) { 134 | String result = ""; 135 | BufferedReader in = null; 136 | String paramStr = ""; 137 | 138 | for (String key : requestParams.keySet()) { 139 | if (!paramStr.isEmpty()) { 140 | paramStr += '&'; 141 | } 142 | try { 143 | paramStr += key + '=' 144 | + URLEncoder.encode(requestParams.get(key).toString(),"utf-8"); 145 | } catch (UnsupportedEncodingException e) { 146 | result = "{\"code\":-2300,\"location\":\"com.qcloud.Common.Request:129\",\"message\":\"api sdk throw exception! " 147 | + e.toString().replace("\"", "\\\"") + "\"}"; 148 | } 149 | } 150 | 151 | try { 152 | 153 | if (requestMethod.equals("GET")) { 154 | if (url.indexOf('?') > 0) { 155 | url += '&' + paramStr; 156 | } else { 157 | url += '?' + paramStr; 158 | } 159 | } 160 | requestUrl = url; 161 | String BOUNDARY = "---------------------------" 162 | + MD5.stringToMD5( 163 | String.valueOf(System.currentTimeMillis())) 164 | .substring(0, 15); 165 | URL realUrl = new URL(url); 166 | URLConnection connection = null; 167 | if (url.toLowerCase().startsWith("https")) { 168 | HttpsURLConnection httpsConn = (HttpsURLConnection) realUrl 169 | .openConnection(); 170 | 171 | /*httpsConn.setHostnameVerifier(new HostnameVerifier() { 172 | public boolean verify(String hostname, SSLSession session) { 173 | return true; 174 | } 175 | });*/ 176 | connection = httpsConn; 177 | } else { 178 | connection = realUrl.openConnection(); 179 | } 180 | 181 | // 设置通用的请求属性 182 | connection.setRequestProperty("accept", "*/*"); 183 | connection.setRequestProperty("connection", "Keep-Alive"); 184 | connection.setRequestProperty("user-agent", 185 | "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); 186 | // 设置链接主机超时时间 187 | connection.setConnectTimeout(connectTimeout); 188 | connection.setReadTimeout(readTimeout); 189 | 190 | if (requestMethod.equals("POST")) { 191 | ((HttpURLConnection) connection).setRequestMethod("POST"); 192 | // 发送POST请求必须设置如下两行 193 | connection.setDoOutput(true); 194 | connection.setDoInput(true); 195 | connection.setRequestProperty("Content-Type", 196 | "multipart/form-data; boundary=" + BOUNDARY); 197 | OutputStream out = new DataOutputStream( 198 | connection.getOutputStream()); 199 | StringBuffer strBuf = new StringBuffer(); 200 | for (String key : requestParams.keySet()) { 201 | strBuf.append("\r\n").append("--").append(BOUNDARY) 202 | .append("\r\n"); 203 | strBuf.append("Content-Disposition: form-data; name=\"" 204 | + key + "\"\r\n\r\n"); 205 | strBuf.append(requestParams.get(key)); 206 | } 207 | out.write(strBuf.toString().getBytes()); 208 | if (fileName != null) { 209 | File file = new File(fileName); 210 | String filename = file.getName(); 211 | String contentType = URLConnection.getFileNameMap() 212 | .getContentTypeFor(fileName); 213 | 214 | strBuf = new StringBuffer(); 215 | strBuf.append("\r\n").append("--").append(BOUNDARY) 216 | .append("\r\n"); 217 | strBuf.append("Content-Disposition: form-data; name=\"entityFile\"; filename=\"" 218 | + filename + "\"\r\n"); 219 | strBuf.append("Content-Type:" + contentType + "\r\n\r\n"); 220 | 221 | out.write(strBuf.toString().getBytes()); 222 | 223 | DataInputStream ins = new DataInputStream( 224 | new FileInputStream(file)); 225 | int bytes = 0; 226 | byte[] bufferOut = new byte[1024]; 227 | while ((bytes = ins.read(bufferOut)) != -1) { 228 | out.write(bufferOut, 0, bytes); 229 | } 230 | ins.close(); 231 | } 232 | byte[] endData = ("\r\n--" + BOUNDARY + "--\r\n").getBytes(); 233 | out.write(endData); 234 | out.flush(); 235 | out.close(); 236 | } 237 | 238 | // 建立实际的连接 239 | connection.connect(); 240 | 241 | // 定义 BufferedReader输入流来读取URL的响应 242 | in = new BufferedReader(new InputStreamReader( 243 | connection.getInputStream())); 244 | 245 | String line; 246 | while ((line = in.readLine()) != null) { 247 | result += line; 248 | } 249 | 250 | } catch (Exception e) { 251 | result = "{\"code\":-2700,\"location\":\"com.qcloud.Common.Request:225\",\"message\":\"api sdk throw exception! " 252 | + e.toString().replace("\"", "\\\"") + "\"}"; 253 | } finally { 254 | // 使用finally块来关闭输入流 255 | try { 256 | if (in != null) { 257 | in.close(); 258 | } 259 | } catch (Exception e2) { 260 | result = "{\"code\":-2800,\"location\":\"com.qcloud.Common.Request:234\",\"message\":\"api sdk throw exception! " 261 | + e2.toString().replace("\"", "\\\"") + "\"}"; 262 | } 263 | } 264 | rawResponse = result; 265 | return result; 266 | } 267 | } 268 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Common/Sign.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Common; 2 | 3 | import java.io.UnsupportedEncodingException; 4 | import java.security.InvalidKeyException; 5 | import java.security.NoSuchAlgorithmException; 6 | import java.util.TreeMap; 7 | 8 | import javax.crypto.Mac; 9 | import javax.crypto.spec.SecretKeySpec; 10 | 11 | import com.qcloud.Utilities.Base64; 12 | 13 | public class Sign { 14 | // 编码方式 15 | private static final String CONTENT_CHARSET = "UTF-8"; 16 | 17 | // HMAC算法 18 | private static final String HMAC_ALGORITHM = "HmacSHA1"; 19 | 20 | /** 21 | * 签名 22 | * @author cicerochen@tencent.com 23 | * 24 | * @param signStr 被加密串 25 | * @param secret 加密密钥 26 | * @param signatureMethod 签名算法 27 | * 28 | * @return 签名结果 29 | */ 30 | public static String sign(String signStr, String secret, String signatureMethod) 31 | throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException 32 | { 33 | String sig = null; 34 | Mac mac1 = Mac.getInstance("HmacSHA1"); 35 | Mac mac2 = Mac.getInstance("HmacSHA256"); 36 | byte[] hash; 37 | if (signatureMethod.equals("HmacSHA256")){ 38 | SecretKeySpec secretKey = new SecretKeySpec(secret.getBytes(CONTENT_CHARSET), mac2.getAlgorithm()); 39 | mac2.init(secretKey); 40 | hash = mac2.doFinal(signStr.getBytes(CONTENT_CHARSET)); 41 | } 42 | else{ 43 | SecretKeySpec secretKey = new SecretKeySpec(secret.getBytes(CONTENT_CHARSET), mac1.getAlgorithm()); 44 | mac1.init(secretKey); 45 | hash = mac1.doFinal(signStr.getBytes(CONTENT_CHARSET)); 46 | } 47 | 48 | sig = new String(Base64.encode(hash)); 49 | return sig; 50 | } 51 | 52 | public static String makeSignPlainText(TreeMap requestParams, String requestMethod, String requestHost, String requestPath) { 53 | 54 | String retStr = ""; 55 | retStr += requestMethod; 56 | retStr += requestHost; 57 | retStr += requestPath; 58 | retStr += buildParamStr(requestParams, requestMethod); 59 | return retStr; 60 | } 61 | 62 | protected static String buildParamStr(TreeMap requestParams, String requestMethod) { 63 | 64 | String retStr = ""; 65 | for(String key: requestParams.keySet()) { 66 | String value = requestParams.get(key).toString(); 67 | //排除上传文件的参数 68 | if("POST".equals(requestMethod) && (! value.isEmpty()) && value.substring(0, 1).equals("@")){ 69 | continue; 70 | } 71 | if (retStr.length()==0) { 72 | retStr += '?'; 73 | } else { 74 | retStr += '&'; 75 | } 76 | retStr += key.replace("_", ".") + '=' + value; 77 | 78 | } 79 | return retStr; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Module/APIGateway.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Module; 2 | 3 | /* 4 | * see document: 6 | * https://cloud.tencent.com/document/product/628 7 | */ 8 | public class APIGateway extends Base { 9 | public APIGateway() { 10 | serverHost = "apigateway.api.qcloud.com"; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Module/Account.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Module; 2 | 3 | public class Account extends Base{ 4 | public Account(){ 5 | serverHost = "account.api.qcloud.com"; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Module/Athena.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Module; 2 | 3 | /* 4 | * Tencent Cloud Financial Intelligent Customer Service. 5 | *

6 | * see API document: 8 | * https://cloud.tencent.com/document/product/671/14381 9 | *

10 | */ 11 | public class Athena extends Base { 12 | public Athena(){ 13 | serverHost = "athena.api.qcloud.com"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Module/Base.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Module; 2 | 3 | import com.qcloud.Common.*; 4 | 5 | import java.util.TreeMap; 6 | 7 | public abstract class Base { 8 | protected String serverHost = ""; 9 | protected String serverUri = "/v2/index.php"; 10 | protected String secretId = ""; 11 | protected String secretKey = ""; 12 | protected String defaultRegion = ""; 13 | protected String requestMethod = "GET"; 14 | 15 | public void setConfig(TreeMap config) { 16 | if (config == null) 17 | return; 18 | for (String key : config.keySet()) { 19 | 20 | if(key.equals("SecretId")){ 21 | setConfigSecretId(config.get(key).toString()); 22 | } 23 | else if(key.equals("SecretKey")){ 24 | setConfigSecretKey(config.get(key).toString()); 25 | } 26 | else if(key.equals("DefaultRegion")){ 27 | setConfigDefaultRegion(config.get(key).toString()); 28 | } 29 | else if(key.equals("RequestMethod")){ 30 | setConfigRequestMethod(config.get(key).toString()); 31 | } 32 | } 33 | } 34 | 35 | public void setConfigSecretId(String secretId) { 36 | this.secretId = secretId; 37 | } 38 | 39 | public void setConfigSecretKey(String secretKey) { 40 | this.secretKey = secretKey; 41 | } 42 | 43 | public void setConfigDefaultRegion(String region) { 44 | this.defaultRegion = region; 45 | } 46 | 47 | public void setConfigRequestMethod(String method) { 48 | this.requestMethod = method; 49 | } 50 | 51 | public String getLastRequest() { 52 | return Request.getRequestUrl(); 53 | } 54 | 55 | public String getLastResponse() { 56 | return Request.getRawResponse(); 57 | } 58 | 59 | private String ucFirst(String word){ 60 | return word.replaceFirst(word.substring(0, 1), 61 | word.substring(0, 1).toUpperCase()); 62 | } 63 | 64 | public String generateUrl(String actionName, TreeMap params) { 65 | actionName = ucFirst(actionName); 66 | if(params == null) 67 | params = new TreeMap(); 68 | params.put("Action", actionName); 69 | if (!params.containsKey("Region")) { 70 | params.put("Region", defaultRegion); 71 | } 72 | return Request.generateUrl(params, secretId, secretKey, requestMethod, 73 | serverHost, serverUri); 74 | } 75 | 76 | public String call(String actionName, TreeMap params){ 77 | return call(actionName, params, null); 78 | } 79 | 80 | public String call(String actionName, TreeMap params, String fileName){ 81 | actionName = ucFirst(actionName); 82 | if(params == null) 83 | params = new TreeMap(); 84 | params.put("Action", actionName); 85 | if (!params.containsKey("Region")) { 86 | params.put("Region", defaultRegion); 87 | } 88 | String response = Request.send(params, secretId, secretKey, requestMethod, serverHost, serverUri, fileName); 89 | return response; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Module/Batch.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Module; 2 | 3 | /* 4 | * see document: 6 | * https://cloud.tencent.com/document/product/599 7 | */ 8 | public class Batch extends Base { 9 | public Batch(){ 10 | serverHost = "batch.api.qcloud.com"; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Module/Bgpip.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Module; 2 | 3 | public class Bgpip extends Base { 4 | public Bgpip(){ 5 | serverHost = "bgpip.api.qcloud.com"; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Module/Bill.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Module; 2 | 3 | public class Bill extends Base{ 4 | public Bill(){ 5 | serverHost = "bill.api.qcloud.com"; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Module/Bm.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Module; 2 | 3 | public class Bm extends Base{ 4 | public Bm(){ 5 | serverHost = "bm.api.qcloud.com"; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Module/Bmeip.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Module; 2 | 3 | public class Bmeip extends Base { 4 | public Bmeip(){ 5 | serverHost = "bmeip.api.qcloud.com"; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Module/Bmlb.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Module; 2 | 3 | public class Bmlb extends Base{ 4 | public Bmlb(){ 5 | serverHost = "bmlb.api.qcloud.com"; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Module/Bmvpc.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Module; 2 | 3 | public class Bmvpc extends Base { 4 | public Bmvpc(){ 5 | serverHost = "bmvpc.api.qcloud.com"; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Module/Cbs.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Module; 2 | 3 | public class Cbs extends Base { 4 | public Cbs(){ 5 | serverHost = "cbs.api.qcloud.com"; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Module/Cdb.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Module; 2 | 3 | public class Cdb extends Base { 4 | public Cdb(){ 5 | serverHost = "cdb.api.qcloud.com"; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Module/Cdn.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Module; 2 | 3 | import java.io.File; 4 | import java.io.FileNotFoundException; 5 | import java.io.IOException; 6 | import java.security.NoSuchAlgorithmException; 7 | import java.util.TreeMap; 8 | 9 | import com.qcloud.Utilities.MD5; 10 | 11 | public class Cdn extends Base { 12 | 13 | public Cdn(){ 14 | serverHost = "cdn.api.qcloud.com"; 15 | } 16 | 17 | public String UploadCdnEntity(TreeMap params) throws NoSuchAlgorithmException, IOException { 18 | String actionName = "UploadCdnEntity"; 19 | 20 | String entityFile = params.get("entityFile").toString(); 21 | params.remove("entityFile"); 22 | File file = new File(entityFile); 23 | if (!file.exists()) { 24 | throw new FileNotFoundException(); 25 | } 26 | 27 | if (!params.containsKey("entityFileMd5")) { 28 | params.put("entityFileMd5", MD5.fileNameToMD5(entityFile)); 29 | } 30 | 31 | return call(actionName, params, entityFile); 32 | } 33 | } -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Module/CloudAudit.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Module; 2 | 3 | /* 4 | * see document: 6 | * https://cloud.tencent.com/document/product/629 7 | */ 8 | public class CloudAudit extends Base { 9 | public CloudAudit(){ 10 | serverHost = "cloudaudit.api.qcloud.com"; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Module/Cmem.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Module; 2 | 3 | public class Cmem extends Base { 4 | //protected String serverHost = "cmem.api.qcloud.com"; 5 | public Cmem(){ 6 | serverHost = "cmem.api.qcloud.com"; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Module/Cns.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Module; 2 | 3 | public class Cns extends Base { 4 | public Cns(){ 5 | serverHost = "cns.api.qcloud.com"; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Module/Cvm.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Module; 2 | 3 | public class Cvm extends Base { 4 | //protected String serverHost = "cvm.api.qcloud.com"; 5 | public Cvm(){ 6 | serverHost = "cvm.api.qcloud.com"; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Module/Dfw.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Module; 2 | 3 | /* 4 | * Tencent Cloud security group related functionalities. 5 | *

6 | * see API document: 8 | * https://cloud.tencent.com/document/product/213/569 9 | *

10 | */ 11 | public class Dfw extends Base { 12 | public Dfw(){ 13 | serverHost = "dfw.api.qcloud.com"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Module/Eip.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Module; 2 | 3 | public class Eip extends Base { 4 | public Eip(){ 5 | serverHost = "eip.api.qcloud.com"; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Module/Emr.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Module; 2 | 3 | /* 4 | * Tencent Cloud Elastic Map Reduce. 5 | *

6 | * see API document: 8 | * https://cloud.tencent.com/document/product/589/10214 9 | *

10 | */ 11 | public class Emr extends Base { 12 | public Emr(){ 13 | serverHost = "emr.api.qcloud.com"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Module/Feecenter.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Module; 2 | 3 | public class Feecenter extends Base{ 4 | public Feecenter(){ 5 | serverHost = "feecenter.api.qcloud.com"; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Module/Image.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Module; 2 | 3 | public class Image extends Base { 4 | public Image(){ 5 | serverHost = "image.api.qcloud.com"; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Module/Lb.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Module; 2 | 3 | public class Lb extends Base { 4 | public Lb(){ 5 | serverHost = "lb.api.qcloud.com"; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Module/Live.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Module; 2 | 3 | public class Live extends Base { 4 | public Live(){ 5 | serverHost = "live.api.qcloud.com"; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Module/Market.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Module; 2 | 3 | public class Market extends Base { 4 | public Market(){ 5 | serverHost = "market.api.qcloud.com"; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Module/Monitor.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Module; 2 | 3 | public class Monitor extends Base { 4 | public Monitor(){ 5 | serverHost = "monitor.api.qcloud.com"; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Module/Morphling.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Module; 2 | 3 | public class Morphling extends Base { 4 | public Morphling(String module) { 5 | serverHost = module + ".api.qcloud.com"; 6 | } 7 | 8 | public void morph(String module) { 9 | serverHost = module + ".api.qcloud.com"; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Module/Partners.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Module; 2 | 3 | /* 4 | * 腾讯云渠道合作伙伴服务 5 | *

6 | * see document: 8 | * https://cloud.tencent.com/document/product/563 9 | *

10 | */ 11 | public class Partners extends Base { 12 | public Partners(){ 13 | serverHost = "partners.api.qcloud.com"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Module/Scaling.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Module; 2 | 3 | public class Scaling extends Base { 4 | public Scaling(){ 5 | serverHost = "scaling.api.qcloud.com"; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Module/Scf.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Module; 2 | 3 | /* 4 | * Serverless Cloud Function. 5 | *

6 | * see document: 8 | * https://cloud.tencent.com/document/product/583 9 | *

10 | */ 11 | public class Scf extends Base { 12 | public Scf(){ 13 | serverHost = "scf.api.qcloud.com"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Module/Sec.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Module; 2 | 3 | public class Sec extends Base { 4 | public Sec(){ 5 | serverHost = "csec.api.qcloud.com"; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Module/Snapshot.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Module; 2 | 3 | public class Snapshot extends Base { 4 | public Snapshot(){ 5 | serverHost = "snapshot.api.qcloud.com"; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Module/Sts.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Module; 2 | 3 | public class Sts extends Base { 4 | public Sts(){ 5 | serverHost = "sts.api.qcloud.com"; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Module/Tbaas.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Module; 2 | 3 | /* 4 | * Tencent Blockchain as a Service. 5 | *

6 | * see API document: 8 | * https://cloud.tencent.com/document/product/663/14024 9 | *

10 | */ 11 | public class Tbaas extends Base { 12 | public Tbaas(){ 13 | serverHost = "tbaas.api.qcloud.com"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Module/Tdsql.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Module; 2 | 3 | public class Tdsql extends Base { 4 | //protected String serverHost = "tdsql.api.qcloud.com"; 5 | public Tdsql(){ 6 | serverHost = "tdsql.api.qcloud.com"; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Module/Tmt.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Module; 2 | 3 | /* 4 | * Tencent Machine Translation. 5 | *

6 | * see document: 8 | * https://cloud.tencent.com/document/product/551 9 | *

10 | */ 11 | public class Tmt extends Base { 12 | public Tmt() { 13 | serverHost = "tmt.api.qcloud.com"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Module/Trade.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Module; 2 | 3 | public class Trade extends Base { 4 | public Trade(){ 5 | serverHost = "trade.api.qcloud.com"; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Module/Vod.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Module; 2 | 3 | public class Vod extends Base { 4 | public Vod(){ 5 | serverHost = "vod.api.qcloud.com"; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Module/Vpc.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Module; 2 | 3 | public class Vpc extends Base { 4 | public Vpc(){ 5 | serverHost = "vpc.api.qcloud.com"; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Module/Wenzhi.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Module; 2 | 3 | public class Wenzhi extends Base { 4 | public Wenzhi(){ 5 | serverHost = "wenzhi.api.qcloud.com"; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Module/Yunsou.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Module; 2 | 3 | public class Yunsou extends Base { 4 | public Yunsou(){ 5 | serverHost = "yunsou.api.qcloud.com"; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/QcloudApiModuleCenter.java: -------------------------------------------------------------------------------- 1 | package com.qcloud; 2 | 3 | import java.lang.reflect.Method; 4 | import java.util.TreeMap; 5 | 6 | import com.qcloud.Module.Base; 7 | 8 | /** 9 | * 模块调用类 10 | * @author robinslsun 11 | * 12 | */ 13 | public class QcloudApiModuleCenter { 14 | 15 | private Base module; 16 | 17 | /** 18 | * 构造模块调用类 19 | * @param module 实际模块实例 20 | * @param config 模块配置参数 21 | */ 22 | public QcloudApiModuleCenter(Base module, TreeMap config){ 23 | this.module = module; 24 | this.module.setConfig(config); 25 | } 26 | 27 | /** 28 | * 生成Api调用地址。 29 | * 仅支持GET方法,POST方法仅返回host+path信息,不支持utf8编码的机器上仅返回host+path信息。 30 | * @param actionName 模块动作名称 31 | * @param params 模块请求参数 32 | * @return Api调用地址 33 | */ 34 | public String generateUrl(String actionName, TreeMap params){ 35 | return module.generateUrl(actionName, params); 36 | } 37 | 38 | /** 39 | * Api调用 40 | * @param actionName 模块动作名称 41 | * @param params 模块请求参数 42 | * @return json字符串 43 | * @throws Exception 44 | */ 45 | public String call(String actionName, TreeMap params) throws Exception 46 | { 47 | for(Method method : module.getClass().getMethods()){ 48 | if(method.getName().equals(actionName)){ 49 | try { 50 | return (String) method.invoke(module, params); 51 | } catch (Exception e) { 52 | throw e; 53 | } 54 | } 55 | } 56 | return module.call(actionName, params); 57 | } 58 | 59 | public void setConfigSecretId(String secretId) { 60 | module.setConfigSecretId(secretId); 61 | } 62 | 63 | public void setConfigSecretKey(String secretKey) { 64 | module.setConfigSecretKey(secretKey); 65 | } 66 | 67 | public void setConfigDefaultRegion(String region) { 68 | module.setConfigDefaultRegion(region); 69 | } 70 | 71 | public void setConfigRequestMethod(String method) { 72 | module.setConfigRequestMethod(method); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Utilities/Base64.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Utilities; 2 | 3 | import java.io.UnsupportedEncodingException; 4 | 5 | public class Base64 { 6 | private static char[] base64EncodeChars = new char[] { 'A', 'B', 'C', 'D', 7 | 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 8 | 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 9 | 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 10 | 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', 11 | '4', '5', '6', '7', '8', '9', '+', '/' }; 12 | 13 | private static byte[] base64DecodeChars = new byte[] { -1, -1, -1, -1, -1, 14 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 15 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 16 | -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 17 | 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 18 | 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, 19 | -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 20 | 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, 21 | -1, -1 }; 22 | 23 | public static String encode(byte[] data) { 24 | StringBuffer sb = new StringBuffer(); 25 | int len = data.length; 26 | int i = 0; 27 | int b1, b2, b3; 28 | while (i < len) { 29 | b1 = data[i++] & 0xff; 30 | if (i == len) { 31 | sb.append(base64EncodeChars[b1 >>> 2]); 32 | sb.append(base64EncodeChars[(b1 & 0x3) << 4]); 33 | sb.append("=="); 34 | break; 35 | } 36 | b2 = data[i++] & 0xff; 37 | if (i == len) { 38 | sb.append(base64EncodeChars[b1 >>> 2]); 39 | sb.append(base64EncodeChars[((b1 & 0x03) << 4) 40 | | ((b2 & 0xf0) >>> 4)]); 41 | sb.append(base64EncodeChars[(b2 & 0x0f) << 2]); 42 | sb.append("="); 43 | break; 44 | } 45 | b3 = data[i++] & 0xff; 46 | sb.append(base64EncodeChars[b1 >>> 2]); 47 | sb.append(base64EncodeChars[((b1 & 0x03) << 4) 48 | | ((b2 & 0xf0) >>> 4)]); 49 | sb.append(base64EncodeChars[((b2 & 0x0f) << 2) 50 | | ((b3 & 0xc0) >>> 6)]); 51 | sb.append(base64EncodeChars[b3 & 0x3f]); 52 | } 53 | return sb.toString(); 54 | } 55 | 56 | public static byte[] decode(String str) throws UnsupportedEncodingException { 57 | StringBuffer sb = new StringBuffer(); 58 | byte[] data = str.getBytes("US-ASCII"); 59 | int len = data.length; 60 | int i = 0; 61 | int b1, b2, b3, b4; 62 | while (i < len) { 63 | /* b1 */ 64 | do { 65 | b1 = base64DecodeChars[data[i++]]; 66 | } while (i < len && b1 == -1); 67 | if (b1 == -1) 68 | break; 69 | /* b2 */ 70 | do { 71 | b2 = base64DecodeChars[data[i++]]; 72 | } while (i < len && b2 == -1); 73 | if (b2 == -1) 74 | break; 75 | sb.append((char) ((b1 << 2) | ((b2 & 0x30) >>> 4))); 76 | /* b3 */ 77 | do { 78 | b3 = data[i++]; 79 | if (b3 == 61) 80 | return sb.toString().getBytes("ISO-8859-1"); 81 | b3 = base64DecodeChars[b3]; 82 | } while (i < len && b3 == -1); 83 | if (b3 == -1) 84 | break; 85 | sb.append((char) (((b2 & 0x0f) << 4) | ((b3 & 0x3c) >>> 2))); 86 | /* b4 */ 87 | do { 88 | b4 = data[i++]; 89 | if (b4 == 61) 90 | return sb.toString().getBytes("ISO-8859-1"); 91 | b4 = base64DecodeChars[b4]; 92 | } while (i < len && b4 == -1); 93 | if (b4 == -1) 94 | break; 95 | sb.append((char) (((b3 & 0x03) << 6) | b4)); 96 | } 97 | return sb.toString().getBytes("ISO-8859-1"); 98 | } 99 | } -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Utilities/Json/JSONArray.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Utilities.Json; 2 | 3 | /* 4 | Copyright (c) 2002 JSON.org 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | The Software shall be used for Good, not Evil. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | */ 26 | 27 | import java.io.IOException; 28 | import java.io.StringWriter; 29 | import java.io.Writer; 30 | import java.lang.reflect.Array; 31 | import java.util.ArrayList; 32 | import java.util.Collection; 33 | import java.util.Iterator; 34 | import java.util.Map; 35 | 36 | /** 37 | * A JSONArray is an ordered sequence of values. Its external text form is a 38 | * string wrapped in square brackets with commas separating the values. The 39 | * internal form is an object having get and opt 40 | * methods for accessing the values by index, and put methods for 41 | * adding or replacing values. The values can be any of these types: 42 | * Boolean, JSONArray, JSONObject, 43 | * Number, String, or the 44 | * JSONObject.NULL object. 45 | *

46 | * The constructor can convert a JSON text into a Java object. The 47 | * toString method converts to JSON text. 48 | *

49 | * A get method returns a value if one can be found, and throws an 50 | * exception if one cannot be found. An opt method returns a 51 | * default value instead of throwing an exception, and so is useful for 52 | * obtaining optional values. 53 | *

54 | * The generic get() and opt() methods return an 55 | * object which you can cast or query for type. There are also typed 56 | * get and opt methods that do type checking and type 57 | * coercion for you. 58 | *

59 | * The texts produced by the toString methods strictly conform to 60 | * JSON syntax rules. The constructors are more forgiving in the texts they will 61 | * accept: 62 | *

    63 | *
  • An extra , (comma) may appear just 64 | * before the closing bracket.
  • 65 | *
  • The null value will be inserted when there is , 66 | *  (comma) elision.
  • 67 | *
  • Strings may be quoted with ' (single 68 | * quote).
  • 69 | *
  • Strings do not need to be quoted at all if they do not begin with a quote 70 | * or single quote, and if they do not contain leading or trailing spaces, and 71 | * if they do not contain any of these characters: 72 | * { } [ ] / \ : , # and if they do not look like numbers and 73 | * if they are not the reserved words true, false, or 74 | * null.
  • 75 | *
76 | * 77 | * @author JSON.org 78 | * @version 2014-05-03 79 | */ 80 | public class JSONArray { 81 | 82 | /** 83 | * The arrayList where the JSONArray's properties are kept. 84 | */ 85 | private final ArrayList myArrayList; 86 | 87 | /** 88 | * Construct an empty JSONArray. 89 | */ 90 | public JSONArray() { 91 | this.myArrayList = new ArrayList(); 92 | } 93 | 94 | /** 95 | * Construct a JSONArray from a JSONTokener. 96 | * 97 | * @param x 98 | * A JSONTokener 99 | * @throws JSONException 100 | * If there is a syntax error. 101 | */ 102 | public JSONArray(JSONTokener x) throws JSONException { 103 | this(); 104 | if (x.nextClean() != '[') { 105 | throw x.syntaxError("A JSONArray text must start with '['"); 106 | } 107 | if (x.nextClean() != ']') { 108 | x.back(); 109 | for (;;) { 110 | if (x.nextClean() == ',') { 111 | x.back(); 112 | this.myArrayList.add(JSONObject.NULL); 113 | } else { 114 | x.back(); 115 | this.myArrayList.add(x.nextValue()); 116 | } 117 | switch (x.nextClean()) { 118 | case ',': 119 | if (x.nextClean() == ']') { 120 | return; 121 | } 122 | x.back(); 123 | break; 124 | case ']': 125 | return; 126 | default: 127 | throw x.syntaxError("Expected a ',' or ']'"); 128 | } 129 | } 130 | } 131 | } 132 | 133 | /** 134 | * Construct a JSONArray from a source JSON text. 135 | * 136 | * @param source 137 | * A string that begins with [ (left 138 | * bracket) and ends with ] 139 | *  (right bracket). 140 | * @throws JSONException 141 | * If there is a syntax error. 142 | */ 143 | public JSONArray(String source) throws JSONException { 144 | this(new JSONTokener(source)); 145 | } 146 | 147 | /** 148 | * Construct a JSONArray from a Collection. 149 | * 150 | * @param collection 151 | * A Collection. 152 | */ 153 | public JSONArray(Collection collection) { 154 | this.myArrayList = new ArrayList(); 155 | if (collection != null) { 156 | Iterator iter = collection.iterator(); 157 | while (iter.hasNext()) { 158 | this.myArrayList.add(JSONObject.wrap(iter.next())); 159 | } 160 | } 161 | } 162 | 163 | /** 164 | * Construct a JSONArray from an array 165 | * 166 | * @throws JSONException 167 | * If not an array. 168 | */ 169 | public JSONArray(Object array) throws JSONException { 170 | this(); 171 | if (array.getClass().isArray()) { 172 | int length = Array.getLength(array); 173 | for (int i = 0; i < length; i += 1) { 174 | this.put(JSONObject.wrap(Array.get(array, i))); 175 | } 176 | } else { 177 | throw new JSONException( 178 | "JSONArray initial value should be a string or collection or array."); 179 | } 180 | } 181 | 182 | /** 183 | * Get the object value associated with an index. 184 | * 185 | * @param index 186 | * The index must be between 0 and length() - 1. 187 | * @return An object value. 188 | * @throws JSONException 189 | * If there is no value for the index. 190 | */ 191 | public Object get(int index) throws JSONException { 192 | Object object = this.opt(index); 193 | if (object == null) { 194 | throw new JSONException("JSONArray[" + index + "] not found."); 195 | } 196 | return object; 197 | } 198 | 199 | /** 200 | * Get the boolean value associated with an index. The string values "true" 201 | * and "false" are converted to boolean. 202 | * 203 | * @param index 204 | * The index must be between 0 and length() - 1. 205 | * @return The truth. 206 | * @throws JSONException 207 | * If there is no value for the index or if the value is not 208 | * convertible to boolean. 209 | */ 210 | public boolean getBoolean(int index) throws JSONException { 211 | Object object = this.get(index); 212 | if (object.equals(Boolean.FALSE) 213 | || (object instanceof String && ((String) object) 214 | .equalsIgnoreCase("false"))) { 215 | return false; 216 | } else if (object.equals(Boolean.TRUE) 217 | || (object instanceof String && ((String) object) 218 | .equalsIgnoreCase("true"))) { 219 | return true; 220 | } 221 | throw new JSONException("JSONArray[" + index + "] is not a boolean."); 222 | } 223 | 224 | /** 225 | * Get the double value associated with an index. 226 | * 227 | * @param index 228 | * The index must be between 0 and length() - 1. 229 | * @return The value. 230 | * @throws JSONException 231 | * If the key is not found or if the value cannot be converted 232 | * to a number. 233 | */ 234 | public double getDouble(int index) throws JSONException { 235 | Object object = this.get(index); 236 | try { 237 | return object instanceof Number ? ((Number) object).doubleValue() 238 | : Double.parseDouble((String) object); 239 | } catch (Exception e) { 240 | throw new JSONException("JSONArray[" + index + "] is not a number."); 241 | } 242 | } 243 | 244 | /** 245 | * Get the int value associated with an index. 246 | * 247 | * @param index 248 | * The index must be between 0 and length() - 1. 249 | * @return The value. 250 | * @throws JSONException 251 | * If the key is not found or if the value is not a number. 252 | */ 253 | public int getInt(int index) throws JSONException { 254 | Object object = this.get(index); 255 | try { 256 | return object instanceof Number ? ((Number) object).intValue() 257 | : Integer.parseInt((String) object); 258 | } catch (Exception e) { 259 | throw new JSONException("JSONArray[" + index + "] is not a number."); 260 | } 261 | } 262 | 263 | /** 264 | * Get the JSONArray associated with an index. 265 | * 266 | * @param index 267 | * The index must be between 0 and length() - 1. 268 | * @return A JSONArray value. 269 | * @throws JSONException 270 | * If there is no value for the index. or if the value is not a 271 | * JSONArray 272 | */ 273 | public JSONArray getJSONArray(int index) throws JSONException { 274 | Object object = this.get(index); 275 | if (object instanceof JSONArray) { 276 | return (JSONArray) object; 277 | } 278 | throw new JSONException("JSONArray[" + index + "] is not a JSONArray."); 279 | } 280 | 281 | /** 282 | * Get the JSONObject associated with an index. 283 | * 284 | * @param index 285 | * subscript 286 | * @return A JSONObject value. 287 | * @throws JSONException 288 | * If there is no value for the index or if the value is not a 289 | * JSONObject 290 | */ 291 | public JSONObject getJSONObject(int index) throws JSONException { 292 | Object object = this.get(index); 293 | if (object instanceof JSONObject) { 294 | return (JSONObject) object; 295 | } 296 | throw new JSONException("JSONArray[" + index + "] is not a JSONObject."); 297 | } 298 | 299 | /** 300 | * Get the long value associated with an index. 301 | * 302 | * @param index 303 | * The index must be between 0 and length() - 1. 304 | * @return The value. 305 | * @throws JSONException 306 | * If the key is not found or if the value cannot be converted 307 | * to a number. 308 | */ 309 | public long getLong(int index) throws JSONException { 310 | Object object = this.get(index); 311 | try { 312 | return object instanceof Number ? ((Number) object).longValue() 313 | : Long.parseLong((String) object); 314 | } catch (Exception e) { 315 | throw new JSONException("JSONArray[" + index + "] is not a number."); 316 | } 317 | } 318 | 319 | /** 320 | * Get the string associated with an index. 321 | * 322 | * @param index 323 | * The index must be between 0 and length() - 1. 324 | * @return A string value. 325 | * @throws JSONException 326 | * If there is no string value for the index. 327 | */ 328 | public String getString(int index) throws JSONException { 329 | Object object = this.get(index); 330 | if (object instanceof String) { 331 | return (String) object; 332 | } 333 | throw new JSONException("JSONArray[" + index + "] not a string."); 334 | } 335 | 336 | /** 337 | * Determine if the value is null. 338 | * 339 | * @param index 340 | * The index must be between 0 and length() - 1. 341 | * @return true if the value at the index is null, or if there is no value. 342 | */ 343 | public boolean isNull(int index) { 344 | return JSONObject.NULL.equals(this.opt(index)); 345 | } 346 | 347 | /** 348 | * Make a string from the contents of this JSONArray. The 349 | * separator string is inserted between each element. Warning: 350 | * This method assumes that the data structure is acyclical. 351 | * 352 | * @param separator 353 | * A string that will be inserted between the elements. 354 | * @return a string. 355 | * @throws JSONException 356 | * If the array contains an invalid number. 357 | */ 358 | public String join(String separator) throws JSONException { 359 | int len = this.length(); 360 | StringBuilder sb = new StringBuilder(); 361 | 362 | for (int i = 0; i < len; i += 1) { 363 | if (i > 0) { 364 | sb.append(separator); 365 | } 366 | sb.append(JSONObject.valueToString(this.myArrayList.get(i))); 367 | } 368 | return sb.toString(); 369 | } 370 | 371 | /** 372 | * Get the number of elements in the JSONArray, included nulls. 373 | * 374 | * @return The length (or size). 375 | */ 376 | public int length() { 377 | return this.myArrayList.size(); 378 | } 379 | 380 | /** 381 | * Get the optional object value associated with an index. 382 | * 383 | * @param index 384 | * The index must be between 0 and length() - 1. 385 | * @return An object value, or null if there is no object at that index. 386 | */ 387 | public Object opt(int index) { 388 | return (index < 0 || index >= this.length()) ? null : this.myArrayList 389 | .get(index); 390 | } 391 | 392 | /** 393 | * Get the optional boolean value associated with an index. It returns false 394 | * if there is no value at that index, or if the value is not Boolean.TRUE 395 | * or the String "true". 396 | * 397 | * @param index 398 | * The index must be between 0 and length() - 1. 399 | * @return The truth. 400 | */ 401 | public boolean optBoolean(int index) { 402 | return this.optBoolean(index, false); 403 | } 404 | 405 | /** 406 | * Get the optional boolean value associated with an index. It returns the 407 | * defaultValue if there is no value at that index or if it is not a Boolean 408 | * or the String "true" or "false" (case insensitive). 409 | * 410 | * @param index 411 | * The index must be between 0 and length() - 1. 412 | * @param defaultValue 413 | * A boolean default. 414 | * @return The truth. 415 | */ 416 | public boolean optBoolean(int index, boolean defaultValue) { 417 | try { 418 | return this.getBoolean(index); 419 | } catch (Exception e) { 420 | return defaultValue; 421 | } 422 | } 423 | 424 | /** 425 | * Get the optional double value associated with an index. NaN is returned 426 | * if there is no value for the index, or if the value is not a number and 427 | * cannot be converted to a number. 428 | * 429 | * @param index 430 | * The index must be between 0 and length() - 1. 431 | * @return The value. 432 | */ 433 | public double optDouble(int index) { 434 | return this.optDouble(index, Double.NaN); 435 | } 436 | 437 | /** 438 | * Get the optional double value associated with an index. The defaultValue 439 | * is returned if there is no value for the index, or if the value is not a 440 | * number and cannot be converted to a number. 441 | * 442 | * @param index 443 | * subscript 444 | * @param defaultValue 445 | * The default value. 446 | * @return The value. 447 | */ 448 | public double optDouble(int index, double defaultValue) { 449 | try { 450 | return this.getDouble(index); 451 | } catch (Exception e) { 452 | return defaultValue; 453 | } 454 | } 455 | 456 | /** 457 | * Get the optional int value associated with an index. Zero is returned if 458 | * there is no value for the index, or if the value is not a number and 459 | * cannot be converted to a number. 460 | * 461 | * @param index 462 | * The index must be between 0 and length() - 1. 463 | * @return The value. 464 | */ 465 | public int optInt(int index) { 466 | return this.optInt(index, 0); 467 | } 468 | 469 | /** 470 | * Get the optional int value associated with an index. The defaultValue is 471 | * returned if there is no value for the index, or if the value is not a 472 | * number and cannot be converted to a number. 473 | * 474 | * @param index 475 | * The index must be between 0 and length() - 1. 476 | * @param defaultValue 477 | * The default value. 478 | * @return The value. 479 | */ 480 | public int optInt(int index, int defaultValue) { 481 | try { 482 | return this.getInt(index); 483 | } catch (Exception e) { 484 | return defaultValue; 485 | } 486 | } 487 | 488 | /** 489 | * Get the optional JSONArray associated with an index. 490 | * 491 | * @param index 492 | * subscript 493 | * @return A JSONArray value, or null if the index has no value, or if the 494 | * value is not a JSONArray. 495 | */ 496 | public JSONArray optJSONArray(int index) { 497 | Object o = this.opt(index); 498 | return o instanceof JSONArray ? (JSONArray) o : null; 499 | } 500 | 501 | /** 502 | * Get the optional JSONObject associated with an index. Null is returned if 503 | * the key is not found, or null if the index has no value, or if the value 504 | * is not a JSONObject. 505 | * 506 | * @param index 507 | * The index must be between 0 and length() - 1. 508 | * @return A JSONObject value. 509 | */ 510 | public JSONObject optJSONObject(int index) { 511 | Object o = this.opt(index); 512 | return o instanceof JSONObject ? (JSONObject) o : null; 513 | } 514 | 515 | /** 516 | * Get the optional long value associated with an index. Zero is returned if 517 | * there is no value for the index, or if the value is not a number and 518 | * cannot be converted to a number. 519 | * 520 | * @param index 521 | * The index must be between 0 and length() - 1. 522 | * @return The value. 523 | */ 524 | public long optLong(int index) { 525 | return this.optLong(index, 0); 526 | } 527 | 528 | /** 529 | * Get the optional long value associated with an index. The defaultValue is 530 | * returned if there is no value for the index, or if the value is not a 531 | * number and cannot be converted to a number. 532 | * 533 | * @param index 534 | * The index must be between 0 and length() - 1. 535 | * @param defaultValue 536 | * The default value. 537 | * @return The value. 538 | */ 539 | public long optLong(int index, long defaultValue) { 540 | try { 541 | return this.getLong(index); 542 | } catch (Exception e) { 543 | return defaultValue; 544 | } 545 | } 546 | 547 | /** 548 | * Get the optional string value associated with an index. It returns an 549 | * empty string if there is no value at that index. If the value is not a 550 | * string and is not null, then it is coverted to a string. 551 | * 552 | * @param index 553 | * The index must be between 0 and length() - 1. 554 | * @return A String value. 555 | */ 556 | public String optString(int index) { 557 | return this.optString(index, ""); 558 | } 559 | 560 | /** 561 | * Get the optional string associated with an index. The defaultValue is 562 | * returned if the key is not found. 563 | * 564 | * @param index 565 | * The index must be between 0 and length() - 1. 566 | * @param defaultValue 567 | * The default value. 568 | * @return A String value. 569 | */ 570 | public String optString(int index, String defaultValue) { 571 | Object object = this.opt(index); 572 | return JSONObject.NULL.equals(object) ? defaultValue : object 573 | .toString(); 574 | } 575 | 576 | /** 577 | * Append a boolean value. This increases the array's length by one. 578 | * 579 | * @param value 580 | * A boolean value. 581 | * @return this. 582 | */ 583 | public JSONArray put(boolean value) { 584 | this.put(value ? Boolean.TRUE : Boolean.FALSE); 585 | return this; 586 | } 587 | 588 | /** 589 | * Put a value in the JSONArray, where the value will be a JSONArray which 590 | * is produced from a Collection. 591 | * 592 | * @param value 593 | * A Collection value. 594 | * @return this. 595 | */ 596 | public JSONArray put(Collection value) { 597 | this.put(new JSONArray(value)); 598 | return this; 599 | } 600 | 601 | /** 602 | * Append a double value. This increases the array's length by one. 603 | * 604 | * @param value 605 | * A double value. 606 | * @throws JSONException 607 | * if the value is not finite. 608 | * @return this. 609 | */ 610 | public JSONArray put(double value) throws JSONException { 611 | Double d = new Double(value); 612 | JSONObject.testValidity(d); 613 | this.put(d); 614 | return this; 615 | } 616 | 617 | /** 618 | * Append an int value. This increases the array's length by one. 619 | * 620 | * @param value 621 | * An int value. 622 | * @return this. 623 | */ 624 | public JSONArray put(int value) { 625 | this.put(new Integer(value)); 626 | return this; 627 | } 628 | 629 | /** 630 | * Append an long value. This increases the array's length by one. 631 | * 632 | * @param value 633 | * A long value. 634 | * @return this. 635 | */ 636 | public JSONArray put(long value) { 637 | this.put(new Long(value)); 638 | return this; 639 | } 640 | 641 | /** 642 | * Put a value in the JSONArray, where the value will be a JSONObject which 643 | * is produced from a Map. 644 | * 645 | * @param value 646 | * A Map value. 647 | * @return this. 648 | */ 649 | public JSONArray put(Map value) { 650 | this.put(new JSONObject(value)); 651 | return this; 652 | } 653 | 654 | /** 655 | * Append an object value. This increases the array's length by one. 656 | * 657 | * @param value 658 | * An object value. The value should be a Boolean, Double, 659 | * Integer, JSONArray, JSONObject, Long, or String, or the 660 | * JSONObject.NULL object. 661 | * @return this. 662 | */ 663 | public JSONArray put(Object value) { 664 | this.myArrayList.add(value); 665 | return this; 666 | } 667 | 668 | /** 669 | * Put or replace a boolean value in the JSONArray. If the index is greater 670 | * than the length of the JSONArray, then null elements will be added as 671 | * necessary to pad it out. 672 | * 673 | * @param index 674 | * The subscript. 675 | * @param value 676 | * A boolean value. 677 | * @return this. 678 | * @throws JSONException 679 | * If the index is negative. 680 | */ 681 | public JSONArray put(int index, boolean value) throws JSONException { 682 | this.put(index, value ? Boolean.TRUE : Boolean.FALSE); 683 | return this; 684 | } 685 | 686 | /** 687 | * Put a value in the JSONArray, where the value will be a JSONArray which 688 | * is produced from a Collection. 689 | * 690 | * @param index 691 | * The subscript. 692 | * @param value 693 | * A Collection value. 694 | * @return this. 695 | * @throws JSONException 696 | * If the index is negative or if the value is not finite. 697 | */ 698 | public JSONArray put(int index, Collection value) throws JSONException { 699 | this.put(index, new JSONArray(value)); 700 | return this; 701 | } 702 | 703 | /** 704 | * Put or replace a double value. If the index is greater than the length of 705 | * the JSONArray, then null elements will be added as necessary to pad it 706 | * out. 707 | * 708 | * @param index 709 | * The subscript. 710 | * @param value 711 | * A double value. 712 | * @return this. 713 | * @throws JSONException 714 | * If the index is negative or if the value is not finite. 715 | */ 716 | public JSONArray put(int index, double value) throws JSONException { 717 | this.put(index, new Double(value)); 718 | return this; 719 | } 720 | 721 | /** 722 | * Put or replace an int value. If the index is greater than the length of 723 | * the JSONArray, then null elements will be added as necessary to pad it 724 | * out. 725 | * 726 | * @param index 727 | * The subscript. 728 | * @param value 729 | * An int value. 730 | * @return this. 731 | * @throws JSONException 732 | * If the index is negative. 733 | */ 734 | public JSONArray put(int index, int value) throws JSONException { 735 | this.put(index, new Integer(value)); 736 | return this; 737 | } 738 | 739 | /** 740 | * Put or replace a long value. If the index is greater than the length of 741 | * the JSONArray, then null elements will be added as necessary to pad it 742 | * out. 743 | * 744 | * @param index 745 | * The subscript. 746 | * @param value 747 | * A long value. 748 | * @return this. 749 | * @throws JSONException 750 | * If the index is negative. 751 | */ 752 | public JSONArray put(int index, long value) throws JSONException { 753 | this.put(index, new Long(value)); 754 | return this; 755 | } 756 | 757 | /** 758 | * Put a value in the JSONArray, where the value will be a JSONObject that 759 | * is produced from a Map. 760 | * 761 | * @param index 762 | * The subscript. 763 | * @param value 764 | * The Map value. 765 | * @return this. 766 | * @throws JSONException 767 | * If the index is negative or if the the value is an invalid 768 | * number. 769 | */ 770 | public JSONArray put(int index, Map value) throws JSONException { 771 | this.put(index, new JSONObject(value)); 772 | return this; 773 | } 774 | 775 | /** 776 | * Put or replace an object value in the JSONArray. If the index is greater 777 | * than the length of the JSONArray, then null elements will be added as 778 | * necessary to pad it out. 779 | * 780 | * @param index 781 | * The subscript. 782 | * @param value 783 | * The value to put into the array. The value should be a 784 | * Boolean, Double, Integer, JSONArray, JSONObject, Long, or 785 | * String, or the JSONObject.NULL object. 786 | * @return this. 787 | * @throws JSONException 788 | * If the index is negative or if the the value is an invalid 789 | * number. 790 | */ 791 | public JSONArray put(int index, Object value) throws JSONException { 792 | JSONObject.testValidity(value); 793 | if (index < 0) { 794 | throw new JSONException("JSONArray[" + index + "] not found."); 795 | } 796 | if (index < this.length()) { 797 | this.myArrayList.set(index, value); 798 | } else { 799 | while (index != this.length()) { 800 | this.put(JSONObject.NULL); 801 | } 802 | this.put(value); 803 | } 804 | return this; 805 | } 806 | 807 | /** 808 | * Remove an index and close the hole. 809 | * 810 | * @param index 811 | * The index of the element to be removed. 812 | * @return The value that was associated with the index, or null if there 813 | * was no value. 814 | */ 815 | public Object remove(int index) { 816 | return index >= 0 && index < this.length() 817 | ? this.myArrayList.remove(index) 818 | : null; 819 | } 820 | 821 | /** 822 | * Determine if two JSONArrays are similar. 823 | * They must contain similar sequences. 824 | * 825 | * @param other The other JSONArray 826 | * @return true if they are equal 827 | */ 828 | public boolean similar(Object other) { 829 | if (!(other instanceof JSONArray)) { 830 | return false; 831 | } 832 | int len = this.length(); 833 | if (len != ((JSONArray)other).length()) { 834 | return false; 835 | } 836 | for (int i = 0; i < len; i += 1) { 837 | Object valueThis = this.get(i); 838 | Object valueOther = ((JSONArray)other).get(i); 839 | if (valueThis instanceof JSONObject) { 840 | if (!((JSONObject)valueThis).similar(valueOther)) { 841 | return false; 842 | } 843 | } else if (valueThis instanceof JSONArray) { 844 | if (!((JSONArray)valueThis).similar(valueOther)) { 845 | return false; 846 | } 847 | } else if (!valueThis.equals(valueOther)) { 848 | return false; 849 | } 850 | } 851 | return true; 852 | } 853 | 854 | /** 855 | * Produce a JSONObject by combining a JSONArray of names with the values of 856 | * this JSONArray. 857 | * 858 | * @param names 859 | * A JSONArray containing a list of key strings. These will be 860 | * paired with the values. 861 | * @return A JSONObject, or null if there are no names or if this JSONArray 862 | * has no values. 863 | * @throws JSONException 864 | * If any of the names are null. 865 | */ 866 | public JSONObject toJSONObject(JSONArray names) throws JSONException { 867 | if (names == null || names.length() == 0 || this.length() == 0) { 868 | return null; 869 | } 870 | JSONObject jo = new JSONObject(); 871 | for (int i = 0; i < names.length(); i += 1) { 872 | jo.put(names.getString(i), this.opt(i)); 873 | } 874 | return jo; 875 | } 876 | 877 | /** 878 | * Make a JSON text of this JSONArray. For compactness, no unnecessary 879 | * whitespace is added. If it is not possible to produce a syntactically 880 | * correct JSON text then null will be returned instead. This could occur if 881 | * the array contains an invalid number. 882 | *

883 | * Warning: This method assumes that the data structure is acyclical. 884 | * 885 | * @return a printable, displayable, transmittable representation of the 886 | * array. 887 | */ 888 | public String toString() { 889 | try { 890 | return this.toString(0); 891 | } catch (Exception e) { 892 | return null; 893 | } 894 | } 895 | 896 | /** 897 | * Make a prettyprinted JSON text of this JSONArray. Warning: This method 898 | * assumes that the data structure is acyclical. 899 | * 900 | * @param indentFactor 901 | * The number of spaces to add to each level of indentation. 902 | * @return a printable, displayable, transmittable representation of the 903 | * object, beginning with [ (left 904 | * bracket) and ending with ] 905 | *  (right bracket). 906 | * @throws JSONException 907 | */ 908 | public String toString(int indentFactor) throws JSONException { 909 | StringWriter sw = new StringWriter(); 910 | synchronized (sw.getBuffer()) { 911 | return this.write(sw, indentFactor, 0).toString(); 912 | } 913 | } 914 | 915 | /** 916 | * Write the contents of the JSONArray as JSON text to a writer. For 917 | * compactness, no whitespace is added. 918 | *

919 | * Warning: This method assumes that the data structure is acyclical. 920 | * 921 | * @return The writer. 922 | * @throws JSONException 923 | */ 924 | public Writer write(Writer writer) throws JSONException { 925 | return this.write(writer, 0, 0); 926 | } 927 | 928 | /** 929 | * Write the contents of the JSONArray as JSON text to a writer. For 930 | * compactness, no whitespace is added. 931 | *

932 | * Warning: This method assumes that the data structure is acyclical. 933 | * 934 | * @param indentFactor 935 | * The number of spaces to add to each level of indentation. 936 | * @param indent 937 | * The indention of the top level. 938 | * @return The writer. 939 | * @throws JSONException 940 | */ 941 | Writer write(Writer writer, int indentFactor, int indent) 942 | throws JSONException { 943 | try { 944 | boolean commanate = false; 945 | int length = this.length(); 946 | writer.write('['); 947 | 948 | if (length == 1) { 949 | JSONObject.writeValue(writer, this.myArrayList.get(0), 950 | indentFactor, indent); 951 | } else if (length != 0) { 952 | final int newindent = indent + indentFactor; 953 | 954 | for (int i = 0; i < length; i += 1) { 955 | if (commanate) { 956 | writer.write(','); 957 | } 958 | if (indentFactor > 0) { 959 | writer.write('\n'); 960 | } 961 | JSONObject.indent(writer, newindent); 962 | JSONObject.writeValue(writer, this.myArrayList.get(i), 963 | indentFactor, newindent); 964 | commanate = true; 965 | } 966 | if (indentFactor > 0) { 967 | writer.write('\n'); 968 | } 969 | JSONObject.indent(writer, indent); 970 | } 971 | writer.write(']'); 972 | return writer; 973 | } catch (IOException e) { 974 | throw new JSONException(e); 975 | } 976 | } 977 | } 978 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Utilities/Json/JSONException.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Utilities.Json; 2 | 3 | /** 4 | * The JSONException is thrown by the JSON.org classes when things are amiss. 5 | * 6 | * @author JSON.org 7 | * @version 2014-05-03 8 | */ 9 | public class JSONException extends RuntimeException { 10 | private static final long serialVersionUID = 0; 11 | private Throwable cause; 12 | 13 | /** 14 | * Constructs a JSONException with an explanatory message. 15 | * 16 | * @param message 17 | * Detail about the reason for the exception. 18 | */ 19 | public JSONException(String message) { 20 | super(message); 21 | } 22 | 23 | /** 24 | * Constructs a new JSONException with the specified cause. 25 | * @param cause The cause. 26 | */ 27 | public JSONException(Throwable cause) { 28 | super(cause.getMessage()); 29 | this.cause = cause; 30 | } 31 | 32 | /** 33 | * Returns the cause of this exception or null if the cause is nonexistent 34 | * or unknown. 35 | * 36 | * @return the cause of this exception or null if the cause is nonexistent 37 | * or unknown. 38 | */ 39 | @Override 40 | public Throwable getCause() { 41 | return this.cause; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Utilities/Json/JSONObject.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Utilities.Json; 2 | 3 | /* 4 | Copyright (c) 2002 JSON.org 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | The Software shall be used for Good, not Evil. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | */ 26 | 27 | import java.io.IOException; 28 | import java.io.StringWriter; 29 | import java.io.Writer; 30 | import java.lang.reflect.Field; 31 | import java.lang.reflect.Method; 32 | import java.lang.reflect.Modifier; 33 | import java.util.Collection; 34 | import java.util.Enumeration; 35 | import java.util.HashMap; 36 | import java.util.Iterator; 37 | import java.util.Locale; 38 | import java.util.Map; 39 | import java.util.Map.Entry; 40 | import java.util.ResourceBundle; 41 | import java.util.Set; 42 | 43 | /** 44 | * A JSONObject is an unordered collection of name/value pairs. Its external 45 | * form is a string wrapped in curly braces with colons between the names and 46 | * values, and commas between the values and names. The internal form is an 47 | * object having get and opt methods for accessing 48 | * the values by name, and put methods for adding or replacing 49 | * values by name. The values can be any of these types: Boolean, 50 | * JSONArray, JSONObject, Number, 51 | * String, or the JSONObject.NULL object. A 52 | * JSONObject constructor can be used to convert an external form JSON text 53 | * into an internal form whose values can be retrieved with the 54 | * get and opt methods, or to convert values into a 55 | * JSON text using the put and toString methods. A 56 | * get method returns a value if one can be found, and throws an 57 | * exception if one cannot be found. An opt method returns a 58 | * default value instead of throwing an exception, and so is useful for 59 | * obtaining optional values. 60 | *

61 | * The generic get() and opt() methods return an 62 | * object, which you can cast or query for type. There are also typed 63 | * get and opt methods that do type checking and type 64 | * coercion for you. The opt methods differ from the get methods in that they 65 | * do not throw. Instead, they return a specified value, such as null. 66 | *

67 | * The put methods add or replace values in an object. For 68 | * example, 69 | * 70 | *

  71 |  * myString = new JSONObject()
  72 |  *         .put("JSON", "Hello, World!").toString();
  73 |  * 
74 | * 75 | * produces the string {"JSON": "Hello, World"}. 76 | *

77 | * The texts produced by the toString methods strictly conform to 78 | * the JSON syntax rules. The constructors are more forgiving in the texts they 79 | * will accept: 80 | *

    81 | *
  • An extra , (comma) may appear just 82 | * before the closing brace.
  • 83 | *
  • Strings may be quoted with ' (single 84 | * quote).
  • 85 | *
  • Strings do not need to be quoted at all if they do not begin with a 86 | * quote or single quote, and if they do not contain leading or trailing 87 | * spaces, and if they do not contain any of these characters: 88 | * { } [ ] / \ : , # and if they do not look like numbers and 89 | * if they are not the reserved words true, false, 90 | * or null.
  • 91 | *
92 | * 93 | * @author JSON.org 94 | * @version 2015-05-05 95 | */ 96 | public class JSONObject { 97 | /** 98 | * JSONObject.NULL is equivalent to the value that JavaScript calls null, 99 | * whilst Java's null is equivalent to the value that JavaScript calls 100 | * undefined. 101 | */ 102 | private static final class Null { 103 | 104 | /** 105 | * There is only intended to be a single instance of the NULL object, 106 | * so the clone method returns itself. 107 | * 108 | * @return NULL. 109 | */ 110 | @Override 111 | protected final Object clone() { 112 | return this; 113 | } 114 | 115 | /** 116 | * A Null object is equal to the null value and to itself. 117 | * 118 | * @param object 119 | * An object to test for nullness. 120 | * @return true if the object parameter is the JSONObject.NULL object or 121 | * null. 122 | */ 123 | @Override 124 | public boolean equals(Object object) { 125 | return object == null || object == this; 126 | } 127 | 128 | /** 129 | * Get the "null" string value. 130 | * 131 | * @return The string "null". 132 | */ 133 | public String toString() { 134 | return "null"; 135 | } 136 | } 137 | 138 | /** 139 | * The map where the JSONObject's properties are kept. 140 | */ 141 | private final Map map; 142 | 143 | /** 144 | * It is sometimes more convenient and less ambiguous to have a 145 | * NULL object than to use Java's null value. 146 | * JSONObject.NULL.equals(null) returns true. 147 | * JSONObject.NULL.toString() returns "null". 148 | */ 149 | public static final Object NULL = new Null(); 150 | 151 | /** 152 | * Construct an empty JSONObject. 153 | */ 154 | public JSONObject() { 155 | this.map = new HashMap(); 156 | } 157 | 158 | /** 159 | * Construct a JSONObject from a subset of another JSONObject. An array of 160 | * strings is used to identify the keys that should be copied. Missing keys 161 | * are ignored. 162 | * 163 | * @param jo 164 | * A JSONObject. 165 | * @param names 166 | * An array of strings. 167 | * @throws JSONException 168 | * @exception JSONException 169 | * If a value is a non-finite number or if a name is 170 | * duplicated. 171 | */ 172 | public JSONObject(JSONObject jo, String[] names) { 173 | this(); 174 | for (int i = 0; i < names.length; i += 1) { 175 | try { 176 | this.putOnce(names[i], jo.opt(names[i])); 177 | } catch (Exception ignore) { 178 | } 179 | } 180 | } 181 | 182 | /** 183 | * Construct a JSONObject from a JSONTokener. 184 | * 185 | * @param x 186 | * A JSONTokener object containing the source string. 187 | * @throws JSONException 188 | * If there is a syntax error in the source string or a 189 | * duplicated key. 190 | */ 191 | public JSONObject(JSONTokener x) throws JSONException { 192 | this(); 193 | char c; 194 | String key; 195 | 196 | if (x.nextClean() != '{') { 197 | throw x.syntaxError("A JSONObject text must begin with '{'"); 198 | } 199 | for (;;) { 200 | c = x.nextClean(); 201 | switch (c) { 202 | case 0: 203 | throw x.syntaxError("A JSONObject text must end with '}'"); 204 | case '}': 205 | return; 206 | default: 207 | x.back(); 208 | key = x.nextValue().toString(); 209 | } 210 | 211 | // The key is followed by ':'. 212 | 213 | c = x.nextClean(); 214 | if (c != ':') { 215 | throw x.syntaxError("Expected a ':' after a key"); 216 | } 217 | this.putOnce(key, x.nextValue()); 218 | 219 | // Pairs are separated by ','. 220 | 221 | switch (x.nextClean()) { 222 | case ';': 223 | case ',': 224 | if (x.nextClean() == '}') { 225 | return; 226 | } 227 | x.back(); 228 | break; 229 | case '}': 230 | return; 231 | default: 232 | throw x.syntaxError("Expected a ',' or '}'"); 233 | } 234 | } 235 | } 236 | 237 | /** 238 | * Construct a JSONObject from a Map. 239 | * 240 | * @param map 241 | * A map object that can be used to initialize the contents of 242 | * the JSONObject. 243 | * @throws JSONException 244 | */ 245 | public JSONObject(Map map) { 246 | this.map = new HashMap(); 247 | if (map != null) { 248 | Iterator> i = map.entrySet().iterator(); 249 | while (i.hasNext()) { 250 | Entry entry = i.next(); 251 | Object value = entry.getValue(); 252 | if (value != null) { 253 | this.map.put(entry.getKey(), wrap(value)); 254 | } 255 | } 256 | } 257 | } 258 | 259 | /** 260 | * Construct a JSONObject from an Object using bean getters. It reflects on 261 | * all of the public methods of the object. For each of the methods with no 262 | * parameters and a name starting with "get" or 263 | * "is" followed by an uppercase letter, the method is invoked, 264 | * and a key and the value returned from the getter method are put into the 265 | * new JSONObject. 266 | * 267 | * The key is formed by removing the "get" or "is" 268 | * prefix. If the second remaining character is not upper case, then the 269 | * first character is converted to lower case. 270 | * 271 | * For example, if an object has a method named "getName", and 272 | * if the result of calling object.getName() is 273 | * "Larry Fine", then the JSONObject will contain 274 | * "name": "Larry Fine". 275 | * 276 | * @param bean 277 | * An object that has getter methods that should be used to make 278 | * a JSONObject. 279 | */ 280 | public JSONObject(Object bean) { 281 | this(); 282 | this.populateMap(bean); 283 | } 284 | 285 | /** 286 | * Construct a JSONObject from an Object, using reflection to find the 287 | * public members. The resulting JSONObject's keys will be the strings from 288 | * the names array, and the values will be the field values associated with 289 | * those keys in the object. If a key is not found or not visible, then it 290 | * will not be copied into the new JSONObject. 291 | * 292 | * @param object 293 | * An object that has fields that should be used to make a 294 | * JSONObject. 295 | * @param names 296 | * An array of strings, the names of the fields to be obtained 297 | * from the object. 298 | */ 299 | public JSONObject(Object object, String names[]) { 300 | this(); 301 | Class c = object.getClass(); 302 | for (int i = 0; i < names.length; i += 1) { 303 | String name = names[i]; 304 | try { 305 | this.putOpt(name, c.getField(name).get(object)); 306 | } catch (Exception ignore) { 307 | } 308 | } 309 | } 310 | 311 | /** 312 | * Construct a JSONObject from a source JSON text string. This is the most 313 | * commonly used JSONObject constructor. 314 | * 315 | * @param source 316 | * A string beginning with { (left 317 | * brace) and ending with } 318 | *  (right brace). 319 | * @exception JSONException 320 | * If there is a syntax error in the source string or a 321 | * duplicated key. 322 | */ 323 | public JSONObject(String source) throws JSONException { 324 | this(new JSONTokener(source)); 325 | } 326 | 327 | /** 328 | * Construct a JSONObject from a ResourceBundle. 329 | * 330 | * @param baseName 331 | * The ResourceBundle base name. 332 | * @param locale 333 | * The Locale to load the ResourceBundle for. 334 | * @throws JSONException 335 | * If any JSONExceptions are detected. 336 | */ 337 | public JSONObject(String baseName, Locale locale) throws JSONException { 338 | this(); 339 | ResourceBundle bundle = ResourceBundle.getBundle(baseName, locale, 340 | Thread.currentThread().getContextClassLoader()); 341 | 342 | // Iterate through the keys in the bundle. 343 | 344 | Enumeration keys = bundle.getKeys(); 345 | while (keys.hasMoreElements()) { 346 | Object key = keys.nextElement(); 347 | if (key != null) { 348 | 349 | // Go through the path, ensuring that there is a nested JSONObject for each 350 | // segment except the last. Add the value using the last segment's name into 351 | // the deepest nested JSONObject. 352 | 353 | String[] path = ((String) key).split("\\."); 354 | int last = path.length - 1; 355 | JSONObject target = this; 356 | for (int i = 0; i < last; i += 1) { 357 | String segment = path[i]; 358 | JSONObject nextTarget = target.optJSONObject(segment); 359 | if (nextTarget == null) { 360 | nextTarget = new JSONObject(); 361 | target.put(segment, nextTarget); 362 | } 363 | target = nextTarget; 364 | } 365 | target.put(path[last], bundle.getString((String) key)); 366 | } 367 | } 368 | } 369 | 370 | /** 371 | * Accumulate values under a key. It is similar to the put method except 372 | * that if there is already an object stored under the key then a JSONArray 373 | * is stored under the key to hold all of the accumulated values. If there 374 | * is already a JSONArray, then the new value is appended to it. In 375 | * contrast, the put method replaces the previous value. 376 | * 377 | * If only one value is accumulated that is not a JSONArray, then the result 378 | * will be the same as using put. But if multiple values are accumulated, 379 | * then the result will be like append. 380 | * 381 | * @param key 382 | * A key string. 383 | * @param value 384 | * An object to be accumulated under the key. 385 | * @return this. 386 | * @throws JSONException 387 | * If the value is an invalid number or if the key is null. 388 | */ 389 | public JSONObject accumulate(String key, Object value) throws JSONException { 390 | testValidity(value); 391 | Object object = this.opt(key); 392 | if (object == null) { 393 | this.put(key, 394 | value instanceof JSONArray ? new JSONArray().put(value) 395 | : value); 396 | } else if (object instanceof JSONArray) { 397 | ((JSONArray) object).put(value); 398 | } else { 399 | this.put(key, new JSONArray().put(object).put(value)); 400 | } 401 | return this; 402 | } 403 | 404 | /** 405 | * Append values to the array under a key. If the key does not exist in the 406 | * JSONObject, then the key is put in the JSONObject with its value being a 407 | * JSONArray containing the value parameter. If the key was already 408 | * associated with a JSONArray, then the value parameter is appended to it. 409 | * 410 | * @param key 411 | * A key string. 412 | * @param value 413 | * An object to be accumulated under the key. 414 | * @return this. 415 | * @throws JSONException 416 | * If the key is null or if the current value associated with 417 | * the key is not a JSONArray. 418 | */ 419 | public JSONObject append(String key, Object value) throws JSONException { 420 | testValidity(value); 421 | Object object = this.opt(key); 422 | if (object == null) { 423 | this.put(key, new JSONArray().put(value)); 424 | } else if (object instanceof JSONArray) { 425 | this.put(key, ((JSONArray) object).put(value)); 426 | } else { 427 | throw new JSONException("JSONObject[" + key 428 | + "] is not a JSONArray."); 429 | } 430 | return this; 431 | } 432 | 433 | /** 434 | * Produce a string from a double. The string "null" will be returned if the 435 | * number is not finite. 436 | * 437 | * @param d 438 | * A double. 439 | * @return A String. 440 | */ 441 | public static String doubleToString(double d) { 442 | if (Double.isInfinite(d) || Double.isNaN(d)) { 443 | return "null"; 444 | } 445 | 446 | // Shave off trailing zeros and decimal point, if possible. 447 | 448 | String string = Double.toString(d); 449 | if (string.indexOf('.') > 0 && string.indexOf('e') < 0 450 | && string.indexOf('E') < 0) { 451 | while (string.endsWith("0")) { 452 | string = string.substring(0, string.length() - 1); 453 | } 454 | if (string.endsWith(".")) { 455 | string = string.substring(0, string.length() - 1); 456 | } 457 | } 458 | return string; 459 | } 460 | 461 | /** 462 | * Get the value object associated with a key. 463 | * 464 | * @param key 465 | * A key string. 466 | * @return The object associated with the key. 467 | * @throws JSONException 468 | * if the key is not found. 469 | */ 470 | public Object get(String key) throws JSONException { 471 | if (key == null) { 472 | throw new JSONException("Null key."); 473 | } 474 | Object object = this.opt(key); 475 | if (object == null) { 476 | throw new JSONException("JSONObject[" + quote(key) + "] not found."); 477 | } 478 | return object; 479 | } 480 | 481 | /** 482 | * Get the boolean value associated with a key. 483 | * 484 | * @param key 485 | * A key string. 486 | * @return The truth. 487 | * @throws JSONException 488 | * if the value is not a Boolean or the String "true" or 489 | * "false". 490 | */ 491 | public boolean getBoolean(String key) throws JSONException { 492 | Object object = this.get(key); 493 | if (object.equals(Boolean.FALSE) 494 | || (object instanceof String && ((String) object) 495 | .equalsIgnoreCase("false"))) { 496 | return false; 497 | } else if (object.equals(Boolean.TRUE) 498 | || (object instanceof String && ((String) object) 499 | .equalsIgnoreCase("true"))) { 500 | return true; 501 | } 502 | throw new JSONException("JSONObject[" + quote(key) 503 | + "] is not a Boolean."); 504 | } 505 | 506 | /** 507 | * Get the double value associated with a key. 508 | * 509 | * @param key 510 | * A key string. 511 | * @return The numeric value. 512 | * @throws JSONException 513 | * if the key is not found or if the value is not a Number 514 | * object and cannot be converted to a number. 515 | */ 516 | public double getDouble(String key) throws JSONException { 517 | Object object = this.get(key); 518 | try { 519 | return object instanceof Number ? ((Number) object).doubleValue() 520 | : Double.parseDouble((String) object); 521 | } catch (Exception e) { 522 | throw new JSONException("JSONObject[" + quote(key) 523 | + "] is not a number."); 524 | } 525 | } 526 | 527 | /** 528 | * Get the int value associated with a key. 529 | * 530 | * @param key 531 | * A key string. 532 | * @return The integer value. 533 | * @throws JSONException 534 | * if the key is not found or if the value cannot be converted 535 | * to an integer. 536 | */ 537 | public int getInt(String key) throws JSONException { 538 | Object object = this.get(key); 539 | try { 540 | return object instanceof Number ? ((Number) object).intValue() 541 | : Integer.parseInt((String) object); 542 | } catch (Exception e) { 543 | throw new JSONException("JSONObject[" + quote(key) 544 | + "] is not an int."); 545 | } 546 | } 547 | 548 | /** 549 | * Get the JSONArray value associated with a key. 550 | * 551 | * @param key 552 | * A key string. 553 | * @return A JSONArray which is the value. 554 | * @throws JSONException 555 | * if the key is not found or if the value is not a JSONArray. 556 | */ 557 | public JSONArray getJSONArray(String key) throws JSONException { 558 | Object object = this.get(key); 559 | if (object instanceof JSONArray) { 560 | return (JSONArray) object; 561 | } 562 | throw new JSONException("JSONObject[" + quote(key) 563 | + "] is not a JSONArray."); 564 | } 565 | 566 | /** 567 | * Get the JSONObject value associated with a key. 568 | * 569 | * @param key 570 | * A key string. 571 | * @return A JSONObject which is the value. 572 | * @throws JSONException 573 | * if the key is not found or if the value is not a JSONObject. 574 | */ 575 | public JSONObject getJSONObject(String key) throws JSONException { 576 | Object object = this.get(key); 577 | if (object instanceof JSONObject) { 578 | return (JSONObject) object; 579 | } 580 | throw new JSONException("JSONObject[" + quote(key) 581 | + "] is not a JSONObject."); 582 | } 583 | 584 | /** 585 | * Get the long value associated with a key. 586 | * 587 | * @param key 588 | * A key string. 589 | * @return The long value. 590 | * @throws JSONException 591 | * if the key is not found or if the value cannot be converted 592 | * to a long. 593 | */ 594 | public long getLong(String key) throws JSONException { 595 | Object object = this.get(key); 596 | try { 597 | return object instanceof Number ? ((Number) object).longValue() 598 | : Long.parseLong((String) object); 599 | } catch (Exception e) { 600 | throw new JSONException("JSONObject[" + quote(key) 601 | + "] is not a long."); 602 | } 603 | } 604 | 605 | /** 606 | * Get an array of field names from a JSONObject. 607 | * 608 | * @return An array of field names, or null if there are no names. 609 | */ 610 | public static String[] getNames(JSONObject jo) { 611 | int length = jo.length(); 612 | if (length == 0) { 613 | return null; 614 | } 615 | Iterator iterator = jo.keys(); 616 | String[] names = new String[length]; 617 | int i = 0; 618 | while (iterator.hasNext()) { 619 | names[i] = iterator.next(); 620 | i += 1; 621 | } 622 | return names; 623 | } 624 | 625 | /** 626 | * Get an array of field names from an Object. 627 | * 628 | * @return An array of field names, or null if there are no names. 629 | */ 630 | public static String[] getNames(Object object) { 631 | if (object == null) { 632 | return null; 633 | } 634 | Class klass = object.getClass(); 635 | Field[] fields = klass.getFields(); 636 | int length = fields.length; 637 | if (length == 0) { 638 | return null; 639 | } 640 | String[] names = new String[length]; 641 | for (int i = 0; i < length; i += 1) { 642 | names[i] = fields[i].getName(); 643 | } 644 | return names; 645 | } 646 | 647 | /** 648 | * Get the string associated with a key. 649 | * 650 | * @param key 651 | * A key string. 652 | * @return A string which is the value. 653 | * @throws JSONException 654 | * if there is no string value for the key. 655 | */ 656 | public String getString(String key) throws JSONException { 657 | Object object = this.get(key); 658 | if (object instanceof String) { 659 | return (String) object; 660 | } 661 | throw new JSONException("JSONObject[" + quote(key) + "] not a string."); 662 | } 663 | 664 | /** 665 | * Determine if the JSONObject contains a specific key. 666 | * 667 | * @param key 668 | * A key string. 669 | * @return true if the key exists in the JSONObject. 670 | */ 671 | public boolean has(String key) { 672 | return this.map.containsKey(key); 673 | } 674 | 675 | /** 676 | * Increment a property of a JSONObject. If there is no such property, 677 | * create one with a value of 1. If there is such a property, and if it is 678 | * an Integer, Long, Double, or Float, then add one to it. 679 | * 680 | * @param key 681 | * A key string. 682 | * @return this. 683 | * @throws JSONException 684 | * If there is already a property with this name that is not an 685 | * Integer, Long, Double, or Float. 686 | */ 687 | public JSONObject increment(String key) throws JSONException { 688 | Object value = this.opt(key); 689 | if (value == null) { 690 | this.put(key, 1); 691 | } else if (value instanceof Integer) { 692 | this.put(key, (Integer) value + 1); 693 | } else if (value instanceof Long) { 694 | this.put(key, (Long) value + 1); 695 | } else if (value instanceof Double) { 696 | this.put(key, (Double) value + 1); 697 | } else if (value instanceof Float) { 698 | this.put(key, (Float) value + 1); 699 | } else { 700 | throw new JSONException("Unable to increment [" + quote(key) + "]."); 701 | } 702 | return this; 703 | } 704 | 705 | /** 706 | * Determine if the value associated with the key is null or if there is no 707 | * value. 708 | * 709 | * @param key 710 | * A key string. 711 | * @return true if there is no value associated with the key or if the value 712 | * is the JSONObject.NULL object. 713 | */ 714 | public boolean isNull(String key) { 715 | return JSONObject.NULL.equals(this.opt(key)); 716 | } 717 | 718 | /** 719 | * Get an enumeration of the keys of the JSONObject. 720 | * 721 | * @return An iterator of the keys. 722 | */ 723 | public Iterator keys() { 724 | return this.keySet().iterator(); 725 | } 726 | 727 | /** 728 | * Get a set of keys of the JSONObject. 729 | * 730 | * @return A keySet. 731 | */ 732 | public Set keySet() { 733 | return this.map.keySet(); 734 | } 735 | 736 | /** 737 | * Get the number of keys stored in the JSONObject. 738 | * 739 | * @return The number of keys in the JSONObject. 740 | */ 741 | public int length() { 742 | return this.map.size(); 743 | } 744 | 745 | /** 746 | * Produce a JSONArray containing the names of the elements of this 747 | * JSONObject. 748 | * 749 | * @return A JSONArray containing the key strings, or null if the JSONObject 750 | * is empty. 751 | */ 752 | public JSONArray names() { 753 | JSONArray ja = new JSONArray(); 754 | Iterator keys = this.keys(); 755 | while (keys.hasNext()) { 756 | ja.put(keys.next()); 757 | } 758 | return ja.length() == 0 ? null : ja; 759 | } 760 | 761 | /** 762 | * Produce a string from a Number. 763 | * 764 | * @param number 765 | * A Number 766 | * @return A String. 767 | * @throws JSONException 768 | * If n is a non-finite number. 769 | */ 770 | public static String numberToString(Number number) throws JSONException { 771 | if (number == null) { 772 | throw new JSONException("Null pointer"); 773 | } 774 | testValidity(number); 775 | 776 | // Shave off trailing zeros and decimal point, if possible. 777 | 778 | String string = number.toString(); 779 | if (string.indexOf('.') > 0 && string.indexOf('e') < 0 780 | && string.indexOf('E') < 0) { 781 | while (string.endsWith("0")) { 782 | string = string.substring(0, string.length() - 1); 783 | } 784 | if (string.endsWith(".")) { 785 | string = string.substring(0, string.length() - 1); 786 | } 787 | } 788 | return string; 789 | } 790 | 791 | /** 792 | * Get an optional value associated with a key. 793 | * 794 | * @param key 795 | * A key string. 796 | * @return An object which is the value, or null if there is no value. 797 | */ 798 | public Object opt(String key) { 799 | return key == null ? null : this.map.get(key); 800 | } 801 | 802 | /** 803 | * Get an optional boolean associated with a key. It returns false if there 804 | * is no such key, or if the value is not Boolean.TRUE or the String "true". 805 | * 806 | * @param key 807 | * A key string. 808 | * @return The truth. 809 | */ 810 | public boolean optBoolean(String key) { 811 | return this.optBoolean(key, false); 812 | } 813 | 814 | /** 815 | * Get an optional boolean associated with a key. It returns the 816 | * defaultValue if there is no such key, or if it is not a Boolean or the 817 | * String "true" or "false" (case insensitive). 818 | * 819 | * @param key 820 | * A key string. 821 | * @param defaultValue 822 | * The default. 823 | * @return The truth. 824 | */ 825 | public boolean optBoolean(String key, boolean defaultValue) { 826 | try { 827 | return this.getBoolean(key); 828 | } catch (Exception e) { 829 | return defaultValue; 830 | } 831 | } 832 | 833 | /** 834 | * Get an optional double associated with a key, or NaN if there is no such 835 | * key or if its value is not a number. If the value is a string, an attempt 836 | * will be made to evaluate it as a number. 837 | * 838 | * @param key 839 | * A string which is the key. 840 | * @return An object which is the value. 841 | */ 842 | public double optDouble(String key) { 843 | return this.optDouble(key, Double.NaN); 844 | } 845 | 846 | /** 847 | * Get an optional double associated with a key, or the defaultValue if 848 | * there is no such key or if its value is not a number. If the value is a 849 | * string, an attempt will be made to evaluate it as a number. 850 | * 851 | * @param key 852 | * A key string. 853 | * @param defaultValue 854 | * The default. 855 | * @return An object which is the value. 856 | */ 857 | public double optDouble(String key, double defaultValue) { 858 | try { 859 | return this.getDouble(key); 860 | } catch (Exception e) { 861 | return defaultValue; 862 | } 863 | } 864 | 865 | /** 866 | * Get an optional int value associated with a key, or zero if there is no 867 | * such key or if the value is not a number. If the value is a string, an 868 | * attempt will be made to evaluate it as a number. 869 | * 870 | * @param key 871 | * A key string. 872 | * @return An object which is the value. 873 | */ 874 | public int optInt(String key) { 875 | return this.optInt(key, 0); 876 | } 877 | 878 | /** 879 | * Get an optional int value associated with a key, or the default if there 880 | * is no such key or if the value is not a number. If the value is a string, 881 | * an attempt will be made to evaluate it as a number. 882 | * 883 | * @param key 884 | * A key string. 885 | * @param defaultValue 886 | * The default. 887 | * @return An object which is the value. 888 | */ 889 | public int optInt(String key, int defaultValue) { 890 | try { 891 | return this.getInt(key); 892 | } catch (Exception e) { 893 | return defaultValue; 894 | } 895 | } 896 | 897 | /** 898 | * Get an optional JSONArray associated with a key. It returns null if there 899 | * is no such key, or if its value is not a JSONArray. 900 | * 901 | * @param key 902 | * A key string. 903 | * @return A JSONArray which is the value. 904 | */ 905 | public JSONArray optJSONArray(String key) { 906 | Object o = this.opt(key); 907 | return o instanceof JSONArray ? (JSONArray) o : null; 908 | } 909 | 910 | /** 911 | * Get an optional JSONObject associated with a key. It returns null if 912 | * there is no such key, or if its value is not a JSONObject. 913 | * 914 | * @param key 915 | * A key string. 916 | * @return A JSONObject which is the value. 917 | */ 918 | public JSONObject optJSONObject(String key) { 919 | Object object = this.opt(key); 920 | return object instanceof JSONObject ? (JSONObject) object : null; 921 | } 922 | 923 | /** 924 | * Get an optional long value associated with a key, or zero if there is no 925 | * such key or if the value is not a number. If the value is a string, an 926 | * attempt will be made to evaluate it as a number. 927 | * 928 | * @param key 929 | * A key string. 930 | * @return An object which is the value. 931 | */ 932 | public long optLong(String key) { 933 | return this.optLong(key, 0); 934 | } 935 | 936 | /** 937 | * Get an optional long value associated with a key, or the default if there 938 | * is no such key or if the value is not a number. If the value is a string, 939 | * an attempt will be made to evaluate it as a number. 940 | * 941 | * @param key 942 | * A key string. 943 | * @param defaultValue 944 | * The default. 945 | * @return An object which is the value. 946 | */ 947 | public long optLong(String key, long defaultValue) { 948 | try { 949 | return this.getLong(key); 950 | } catch (Exception e) { 951 | return defaultValue; 952 | } 953 | } 954 | 955 | /** 956 | * Get an optional string associated with a key. It returns an empty string 957 | * if there is no such key. If the value is not a string and is not null, 958 | * then it is converted to a string. 959 | * 960 | * @param key 961 | * A key string. 962 | * @return A string which is the value. 963 | */ 964 | public String optString(String key) { 965 | return this.optString(key, ""); 966 | } 967 | 968 | /** 969 | * Get an optional string associated with a key. It returns the defaultValue 970 | * if there is no such key. 971 | * 972 | * @param key 973 | * A key string. 974 | * @param defaultValue 975 | * The default. 976 | * @return A string which is the value. 977 | */ 978 | public String optString(String key, String defaultValue) { 979 | Object object = this.opt(key); 980 | return NULL.equals(object) ? defaultValue : object.toString(); 981 | } 982 | 983 | private void populateMap(Object bean) { 984 | Class klass = bean.getClass(); 985 | 986 | // If klass is a System class then set includeSuperClass to false. 987 | 988 | boolean includeSuperClass = klass.getClassLoader() != null; 989 | 990 | Method[] methods = includeSuperClass ? klass.getMethods() : klass 991 | .getDeclaredMethods(); 992 | for (int i = 0; i < methods.length; i += 1) { 993 | try { 994 | Method method = methods[i]; 995 | if (Modifier.isPublic(method.getModifiers())) { 996 | String name = method.getName(); 997 | String key = ""; 998 | if (name.startsWith("get")) { 999 | if ("getClass".equals(name) 1000 | || "getDeclaringClass".equals(name)) { 1001 | key = ""; 1002 | } else { 1003 | key = name.substring(3); 1004 | } 1005 | } else if (name.startsWith("is")) { 1006 | key = name.substring(2); 1007 | } 1008 | if (key.length() > 0 1009 | && Character.isUpperCase(key.charAt(0)) 1010 | && method.getParameterTypes().length == 0) { 1011 | if (key.length() == 1) { 1012 | key = key.toLowerCase(); 1013 | } else if (!Character.isUpperCase(key.charAt(1))) { 1014 | key = key.substring(0, 1).toLowerCase() 1015 | + key.substring(1); 1016 | } 1017 | 1018 | Object result = method.invoke(bean, (Object[]) null); 1019 | if (result != null) { 1020 | this.map.put(key, wrap(result)); 1021 | } 1022 | } 1023 | } 1024 | } catch (Exception ignore) { 1025 | } 1026 | } 1027 | } 1028 | 1029 | /** 1030 | * Put a key/boolean pair in the JSONObject. 1031 | * 1032 | * @param key 1033 | * A key string. 1034 | * @param value 1035 | * A boolean which is the value. 1036 | * @return this. 1037 | * @throws JSONException 1038 | * If the key is null. 1039 | */ 1040 | public JSONObject put(String key, boolean value) throws JSONException { 1041 | this.put(key, value ? Boolean.TRUE : Boolean.FALSE); 1042 | return this; 1043 | } 1044 | 1045 | /** 1046 | * Put a key/value pair in the JSONObject, where the value will be a 1047 | * JSONArray which is produced from a Collection. 1048 | * 1049 | * @param key 1050 | * A key string. 1051 | * @param value 1052 | * A Collection value. 1053 | * @return this. 1054 | * @throws JSONException 1055 | */ 1056 | public JSONObject put(String key, Collection value) throws JSONException { 1057 | this.put(key, new JSONArray(value)); 1058 | return this; 1059 | } 1060 | 1061 | /** 1062 | * Put a key/double pair in the JSONObject. 1063 | * 1064 | * @param key 1065 | * A key string. 1066 | * @param value 1067 | * A double which is the value. 1068 | * @return this. 1069 | * @throws JSONException 1070 | * If the key is null or if the number is invalid. 1071 | */ 1072 | public JSONObject put(String key, double value) throws JSONException { 1073 | this.put(key, new Double(value)); 1074 | return this; 1075 | } 1076 | 1077 | /** 1078 | * Put a key/int pair in the JSONObject. 1079 | * 1080 | * @param key 1081 | * A key string. 1082 | * @param value 1083 | * An int which is the value. 1084 | * @return this. 1085 | * @throws JSONException 1086 | * If the key is null. 1087 | */ 1088 | public JSONObject put(String key, int value) throws JSONException { 1089 | this.put(key, new Integer(value)); 1090 | return this; 1091 | } 1092 | 1093 | /** 1094 | * Put a key/long pair in the JSONObject. 1095 | * 1096 | * @param key 1097 | * A key string. 1098 | * @param value 1099 | * A long which is the value. 1100 | * @return this. 1101 | * @throws JSONException 1102 | * If the key is null. 1103 | */ 1104 | public JSONObject put(String key, long value) throws JSONException { 1105 | this.put(key, new Long(value)); 1106 | return this; 1107 | } 1108 | 1109 | /** 1110 | * Put a key/value pair in the JSONObject, where the value will be a 1111 | * JSONObject which is produced from a Map. 1112 | * 1113 | * @param key 1114 | * A key string. 1115 | * @param value 1116 | * A Map value. 1117 | * @return this. 1118 | * @throws JSONException 1119 | */ 1120 | public JSONObject put(String key, Map value) throws JSONException { 1121 | this.put(key, new JSONObject(value)); 1122 | return this; 1123 | } 1124 | 1125 | /** 1126 | * Put a key/value pair in the JSONObject. If the value is null, then the 1127 | * key will be removed from the JSONObject if it is present. 1128 | * 1129 | * @param key 1130 | * A key string. 1131 | * @param value 1132 | * An object which is the value. It should be of one of these 1133 | * types: Boolean, Double, Integer, JSONArray, JSONObject, Long, 1134 | * String, or the JSONObject.NULL object. 1135 | * @return this. 1136 | * @throws JSONException 1137 | * If the value is non-finite number or if the key is null. 1138 | */ 1139 | public JSONObject put(String key, Object value) throws JSONException { 1140 | if (key == null) { 1141 | throw new NullPointerException("Null key."); 1142 | } 1143 | if (value != null) { 1144 | testValidity(value); 1145 | this.map.put(key, value); 1146 | } else { 1147 | this.remove(key); 1148 | } 1149 | return this; 1150 | } 1151 | 1152 | /** 1153 | * Put a key/value pair in the JSONObject, but only if the key and the value 1154 | * are both non-null, and only if there is not already a member with that 1155 | * name. 1156 | * 1157 | * @param key string 1158 | * @param value object 1159 | * @return this. 1160 | * @throws JSONException 1161 | * if the key is a duplicate 1162 | */ 1163 | public JSONObject putOnce(String key, Object value) throws JSONException { 1164 | if (key != null && value != null) { 1165 | if (this.opt(key) != null) { 1166 | throw new JSONException("Duplicate key \"" + key + "\""); 1167 | } 1168 | this.put(key, value); 1169 | } 1170 | return this; 1171 | } 1172 | 1173 | /** 1174 | * Put a key/value pair in the JSONObject, but only if the key and the value 1175 | * are both non-null. 1176 | * 1177 | * @param key 1178 | * A key string. 1179 | * @param value 1180 | * An object which is the value. It should be of one of these 1181 | * types: Boolean, Double, Integer, JSONArray, JSONObject, Long, 1182 | * String, or the JSONObject.NULL object. 1183 | * @return this. 1184 | * @throws JSONException 1185 | * If the value is a non-finite number. 1186 | */ 1187 | public JSONObject putOpt(String key, Object value) throws JSONException { 1188 | if (key != null && value != null) { 1189 | this.put(key, value); 1190 | } 1191 | return this; 1192 | } 1193 | 1194 | /** 1195 | * Produce a string in double quotes with backslash sequences in all the 1196 | * right places. A backslash will be inserted within = '\u0080' && c < '\u00a0') 1261 | || (c >= '\u2000' && c < '\u2100')) { 1262 | w.write("\\u"); 1263 | hhhh = Integer.toHexString(c); 1264 | w.write("0000", 0, 4 - hhhh.length()); 1265 | w.write(hhhh); 1266 | } else { 1267 | w.write(c); 1268 | } 1269 | } 1270 | } 1271 | w.write('"'); 1272 | return w; 1273 | } 1274 | 1275 | /** 1276 | * Remove a name and its value, if present. 1277 | * 1278 | * @param key 1279 | * The name to be removed. 1280 | * @return The value that was associated with the name, or null if there was 1281 | * no value. 1282 | */ 1283 | public Object remove(String key) { 1284 | return this.map.remove(key); 1285 | } 1286 | 1287 | /** 1288 | * Determine if two JSONObjects are similar. 1289 | * They must contain the same set of names which must be associated with 1290 | * similar values. 1291 | * 1292 | * @param other The other JSONObject 1293 | * @return true if they are equal 1294 | */ 1295 | public boolean similar(Object other) { 1296 | try { 1297 | if (!(other instanceof JSONObject)) { 1298 | return false; 1299 | } 1300 | Set set = this.keySet(); 1301 | if (!set.equals(((JSONObject)other).keySet())) { 1302 | return false; 1303 | } 1304 | Iterator iterator = set.iterator(); 1305 | while (iterator.hasNext()) { 1306 | String name = iterator.next(); 1307 | Object valueThis = this.get(name); 1308 | Object valueOther = ((JSONObject)other).get(name); 1309 | if (valueThis instanceof JSONObject) { 1310 | if (!((JSONObject)valueThis).similar(valueOther)) { 1311 | return false; 1312 | } 1313 | } else if (valueThis instanceof JSONArray) { 1314 | if (!((JSONArray)valueThis).similar(valueOther)) { 1315 | return false; 1316 | } 1317 | } else if (!valueThis.equals(valueOther)) { 1318 | return false; 1319 | } 1320 | } 1321 | return true; 1322 | } catch (Throwable exception) { 1323 | return false; 1324 | } 1325 | } 1326 | 1327 | /** 1328 | * Try to convert a string into a number, boolean, or null. If the string 1329 | * can't be converted, return the string. 1330 | * 1331 | * @param string 1332 | * A String. 1333 | * @return A simple JSON value. 1334 | */ 1335 | public static Object stringToValue(String string) { 1336 | Double d; 1337 | if (string.equals("")) { 1338 | return string; 1339 | } 1340 | if (string.equalsIgnoreCase("true")) { 1341 | return Boolean.TRUE; 1342 | } 1343 | if (string.equalsIgnoreCase("false")) { 1344 | return Boolean.FALSE; 1345 | } 1346 | if (string.equalsIgnoreCase("null")) { 1347 | return JSONObject.NULL; 1348 | } 1349 | 1350 | /* 1351 | * If it might be a number, try converting it. If a number cannot be 1352 | * produced, then the value will just be a string. 1353 | */ 1354 | 1355 | char b = string.charAt(0); 1356 | if ((b >= '0' && b <= '9') || b == '-') { 1357 | try { 1358 | if (string.indexOf('.') > -1 || string.indexOf('e') > -1 1359 | || string.indexOf('E') > -1) { 1360 | d = Double.valueOf(string); 1361 | if (!d.isInfinite() && !d.isNaN()) { 1362 | return d; 1363 | } 1364 | } else { 1365 | Long myLong = new Long(string); 1366 | if (string.equals(myLong.toString())) { 1367 | if (myLong == myLong.intValue()) { 1368 | return myLong.intValue(); 1369 | } else { 1370 | return myLong; 1371 | } 1372 | } 1373 | } 1374 | } catch (Exception ignore) { 1375 | } 1376 | } 1377 | return string; 1378 | } 1379 | 1380 | /** 1381 | * Throw an exception if the object is a NaN or infinite number. 1382 | * 1383 | * @param o 1384 | * The object to test. 1385 | * @throws JSONException 1386 | * If o is a non-finite number. 1387 | */ 1388 | public static void testValidity(Object o) throws JSONException { 1389 | if (o != null) { 1390 | if (o instanceof Double) { 1391 | if (((Double) o).isInfinite() || ((Double) o).isNaN()) { 1392 | throw new JSONException( 1393 | "JSON does not allow non-finite numbers."); 1394 | } 1395 | } else if (o instanceof Float) { 1396 | if (((Float) o).isInfinite() || ((Float) o).isNaN()) { 1397 | throw new JSONException( 1398 | "JSON does not allow non-finite numbers."); 1399 | } 1400 | } 1401 | } 1402 | } 1403 | 1404 | /** 1405 | * Produce a JSONArray containing the values of the members of this 1406 | * JSONObject. 1407 | * 1408 | * @param names 1409 | * A JSONArray containing a list of key strings. This determines 1410 | * the sequence of the values in the result. 1411 | * @return A JSONArray of values. 1412 | * @throws JSONException 1413 | * If any of the values are non-finite numbers. 1414 | */ 1415 | public JSONArray toJSONArray(JSONArray names) throws JSONException { 1416 | if (names == null || names.length() == 0) { 1417 | return null; 1418 | } 1419 | JSONArray ja = new JSONArray(); 1420 | for (int i = 0; i < names.length(); i += 1) { 1421 | ja.put(this.opt(names.getString(i))); 1422 | } 1423 | return ja; 1424 | } 1425 | 1426 | /** 1427 | * Make a JSON text of this JSONObject. For compactness, no whitespace is 1428 | * added. If this would not result in a syntactically correct JSON text, 1429 | * then null will be returned instead. 1430 | *

1431 | * Warning: This method assumes that the data structure is acyclical. 1432 | * 1433 | * @return a printable, displayable, portable, transmittable representation 1434 | * of the object, beginning with { (left 1435 | * brace) and ending with } (right 1436 | * brace). 1437 | */ 1438 | public String toString() { 1439 | try { 1440 | return this.toString(0); 1441 | } catch (Exception e) { 1442 | return null; 1443 | } 1444 | } 1445 | 1446 | /** 1447 | * Make a prettyprinted JSON text of this JSONObject. 1448 | *

1449 | * Warning: This method assumes that the data structure is acyclical. 1450 | * 1451 | * @param indentFactor 1452 | * The number of spaces to add to each level of indentation. 1453 | * @return a printable, displayable, portable, transmittable representation 1454 | * of the object, beginning with { (left 1455 | * brace) and ending with } (right 1456 | * brace). 1457 | * @throws JSONException 1458 | * If the object contains an invalid number. 1459 | */ 1460 | public String toString(int indentFactor) throws JSONException { 1461 | StringWriter w = new StringWriter(); 1462 | synchronized (w.getBuffer()) { 1463 | return this.write(w, indentFactor, 0).toString(); 1464 | } 1465 | } 1466 | 1467 | /** 1468 | * Make a JSON text of an Object value. If the object has an 1469 | * value.toJSONString() method, then that method will be used to produce the 1470 | * JSON text. The method is required to produce a strictly conforming text. 1471 | * If the object does not contain a toJSONString method (which is the most 1472 | * common case), then a text will be produced by other means. If the value 1473 | * is an array or Collection, then a JSONArray will be made from it and its 1474 | * toJSONString method will be called. If the value is a MAP, then a 1475 | * JSONObject will be made from it and its toJSONString method will be 1476 | * called. Otherwise, the value's toString method will be called, and the 1477 | * result will be quoted. 1478 | * 1479 | *

1480 | * Warning: This method assumes that the data structure is acyclical. 1481 | * 1482 | * @param value 1483 | * The value to be serialized. 1484 | * @return a printable, displayable, transmittable representation of the 1485 | * object, beginning with { (left 1486 | * brace) and ending with } (right 1487 | * brace). 1488 | * @throws JSONException 1489 | * If the value is or contains an invalid number. 1490 | */ 1491 | public static String valueToString(Object value) throws JSONException { 1492 | if (value == null || value.equals(null)) { 1493 | return "null"; 1494 | } 1495 | if (value instanceof JSONString) { 1496 | Object object; 1497 | try { 1498 | object = ((JSONString) value).toJSONString(); 1499 | } catch (Exception e) { 1500 | throw new JSONException(e); 1501 | } 1502 | if (object instanceof String) { 1503 | return (String) object; 1504 | } 1505 | throw new JSONException("Bad value from toJSONString: " + object); 1506 | } 1507 | if (value instanceof Number) { 1508 | return numberToString((Number) value); 1509 | } 1510 | if (value instanceof Boolean || value instanceof JSONObject 1511 | || value instanceof JSONArray) { 1512 | return value.toString(); 1513 | } 1514 | if (value instanceof Map) { 1515 | @SuppressWarnings("unchecked") 1516 | Map map = (Map) value; 1517 | return new JSONObject(map).toString(); 1518 | } 1519 | if (value instanceof Collection) { 1520 | @SuppressWarnings("unchecked") 1521 | Collection coll = (Collection) value; 1522 | return new JSONArray(coll).toString(); 1523 | } 1524 | if (value.getClass().isArray()) { 1525 | return new JSONArray(value).toString(); 1526 | } 1527 | return quote(value.toString()); 1528 | } 1529 | 1530 | /** 1531 | * Wrap an object, if necessary. If the object is null, return the NULL 1532 | * object. If it is an array or collection, wrap it in a JSONArray. If it is 1533 | * a map, wrap it in a JSONObject. If it is a standard property (Double, 1534 | * String, et al) then it is already wrapped. Otherwise, if it comes from 1535 | * one of the java packages, turn it into a string. And if it doesn't, try 1536 | * to wrap it in a JSONObject. If the wrapping fails, then null is returned. 1537 | * 1538 | * @param object 1539 | * The object to wrap 1540 | * @return The wrapped value 1541 | */ 1542 | public static Object wrap(Object object) { 1543 | try { 1544 | if (object == null) { 1545 | return NULL; 1546 | } 1547 | if (object instanceof JSONObject || object instanceof JSONArray 1548 | || NULL.equals(object) || object instanceof JSONString 1549 | || object instanceof Byte || object instanceof Character 1550 | || object instanceof Short || object instanceof Integer 1551 | || object instanceof Long || object instanceof Boolean 1552 | || object instanceof Float || object instanceof Double 1553 | || object instanceof String) { 1554 | return object; 1555 | } 1556 | 1557 | if (object instanceof Collection) { 1558 | @SuppressWarnings("unchecked") 1559 | Collection coll = (Collection) object; 1560 | return new JSONArray(coll); 1561 | } 1562 | if (object.getClass().isArray()) { 1563 | return new JSONArray(object); 1564 | } 1565 | if (object instanceof Map) { 1566 | @SuppressWarnings("unchecked") 1567 | Map map = (Map) object; 1568 | return new JSONObject(map); 1569 | } 1570 | Package objectPackage = object.getClass().getPackage(); 1571 | String objectPackageName = objectPackage != null ? objectPackage 1572 | .getName() : ""; 1573 | if (objectPackageName.startsWith("java.") 1574 | || objectPackageName.startsWith("javax.") 1575 | || object.getClass().getClassLoader() == null) { 1576 | return object.toString(); 1577 | } 1578 | return new JSONObject(object); 1579 | } catch (Exception exception) { 1580 | return null; 1581 | } 1582 | } 1583 | 1584 | /** 1585 | * Write the contents of the JSONObject as JSON text to a writer. For 1586 | * compactness, no whitespace is added. 1587 | *

1588 | * Warning: This method assumes that the data structure is acyclical. 1589 | * 1590 | * @return The writer. 1591 | * @throws JSONException 1592 | */ 1593 | public Writer write(Writer writer) throws JSONException { 1594 | return this.write(writer, 0, 0); 1595 | } 1596 | 1597 | static final Writer writeValue(Writer writer, Object value, 1598 | int indentFactor, int indent) throws JSONException, IOException { 1599 | if (value == null || value.equals(null)) { 1600 | writer.write("null"); 1601 | } else if (value instanceof JSONObject) { 1602 | ((JSONObject) value).write(writer, indentFactor, indent); 1603 | } else if (value instanceof JSONArray) { 1604 | ((JSONArray) value).write(writer, indentFactor, indent); 1605 | } else if (value instanceof Map) { 1606 | @SuppressWarnings("unchecked") 1607 | Map map = (Map) value; 1608 | new JSONObject(map).write(writer, indentFactor, indent); 1609 | } else if (value instanceof Collection) { 1610 | @SuppressWarnings("unchecked") 1611 | Collection coll = (Collection) value; 1612 | new JSONArray(coll).write(writer, indentFactor, 1613 | indent); 1614 | } else if (value.getClass().isArray()) { 1615 | new JSONArray(value).write(writer, indentFactor, indent); 1616 | } else if (value instanceof Number) { 1617 | writer.write(numberToString((Number) value)); 1618 | } else if (value instanceof Boolean) { 1619 | writer.write(value.toString()); 1620 | } else if (value instanceof JSONString) { 1621 | Object o; 1622 | try { 1623 | o = ((JSONString) value).toJSONString(); 1624 | } catch (Exception e) { 1625 | throw new JSONException(e); 1626 | } 1627 | writer.write(o != null ? o.toString() : quote(value.toString())); 1628 | } else { 1629 | quote(value.toString(), writer); 1630 | } 1631 | return writer; 1632 | } 1633 | 1634 | static final void indent(Writer writer, int indent) throws IOException { 1635 | for (int i = 0; i < indent; i += 1) { 1636 | writer.write(' '); 1637 | } 1638 | } 1639 | 1640 | /** 1641 | * Write the contents of the JSONObject as JSON text to a writer. For 1642 | * compactness, no whitespace is added. 1643 | *

1644 | * Warning: This method assumes that the data structure is acyclical. 1645 | * 1646 | * @return The writer. 1647 | * @throws JSONException 1648 | */ 1649 | Writer write(Writer writer, int indentFactor, int indent) 1650 | throws JSONException { 1651 | try { 1652 | boolean commanate = false; 1653 | final int length = this.length(); 1654 | Iterator keys = this.keys(); 1655 | writer.write('{'); 1656 | 1657 | if (length == 1) { 1658 | Object key = keys.next(); 1659 | writer.write(quote(key.toString())); 1660 | writer.write(':'); 1661 | if (indentFactor > 0) { 1662 | writer.write(' '); 1663 | } 1664 | writeValue(writer, this.map.get(key), indentFactor, indent); 1665 | } else if (length != 0) { 1666 | final int newindent = indent + indentFactor; 1667 | while (keys.hasNext()) { 1668 | Object key = keys.next(); 1669 | if (commanate) { 1670 | writer.write(','); 1671 | } 1672 | if (indentFactor > 0) { 1673 | writer.write('\n'); 1674 | } 1675 | indent(writer, newindent); 1676 | writer.write(quote(key.toString())); 1677 | writer.write(':'); 1678 | if (indentFactor > 0) { 1679 | writer.write(' '); 1680 | } 1681 | writeValue(writer, this.map.get(key), indentFactor, newindent); 1682 | commanate = true; 1683 | } 1684 | if (indentFactor > 0) { 1685 | writer.write('\n'); 1686 | } 1687 | indent(writer, indent); 1688 | } 1689 | writer.write('}'); 1690 | return writer; 1691 | } catch (IOException exception) { 1692 | throw new JSONException(exception); 1693 | } 1694 | } 1695 | } 1696 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Utilities/Json/JSONString.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Utilities.Json; 2 | /** 3 | * The JSONString interface allows a toJSONString() 4 | * method so that a class can change the behavior of 5 | * JSONObject.toString(), JSONArray.toString(), 6 | * and JSONWriter.value(Object). The 7 | * toJSONString method will be used instead of the default behavior 8 | * of using the Object's toString() method and quoting the result. 9 | */ 10 | public interface JSONString { 11 | /** 12 | * The toJSONString method allows a class to produce its own JSON 13 | * serialization. 14 | * 15 | * @return A strictly syntactically correct JSON text. 16 | */ 17 | public String toJSONString(); 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Utilities/Json/JSONStringer.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Utilities.Json; 2 | 3 | /* 4 | Copyright (c) 2006 JSON.org 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | The Software shall be used for Good, not Evil. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | */ 26 | 27 | import java.io.StringWriter; 28 | 29 | /** 30 | * JSONStringer provides a quick and convenient way of producing JSON text. 31 | * The texts produced strictly conform to JSON syntax rules. No whitespace is 32 | * added, so the results are ready for transmission or storage. Each instance of 33 | * JSONStringer can produce one JSON text. 34 | *

35 | * A JSONStringer instance provides a value method for appending 36 | * values to the 37 | * text, and a key 38 | * method for adding keys before values in objects. There are array 39 | * and endArray methods that make and bound array values, and 40 | * object and endObject methods which make and bound 41 | * object values. All of these methods return the JSONWriter instance, 42 | * permitting cascade style. For example,

43 |  * myString = new JSONStringer()
44 |  *     .object()
45 |  *         .key("JSON")
46 |  *         .value("Hello, World!")
47 |  *     .endObject()
48 |  *     .toString();
which produces the string
49 |  * {"JSON":"Hello, World!"}
50 | *

51 | * The first method called must be array or object. 52 | * There are no methods for adding commas or colons. JSONStringer adds them for 53 | * you. Objects and arrays can be nested up to 20 levels deep. 54 | *

55 | * This can sometimes be easier than using a JSONObject to build a string. 56 | * @author JSON.org 57 | * @version 2008-09-18 58 | */ 59 | public class JSONStringer extends JSONWriter { 60 | /** 61 | * Make a fresh JSONStringer. It can be used to build one JSON text. 62 | */ 63 | public JSONStringer() { 64 | super(new StringWriter()); 65 | } 66 | 67 | /** 68 | * Return the JSON text. This method is used to obtain the product of the 69 | * JSONStringer instance. It will return null if there was a 70 | * problem in the construction of the JSON text (such as the calls to 71 | * array were not properly balanced with calls to 72 | * endArray). 73 | * @return The JSON text. 74 | */ 75 | public String toString() { 76 | return this.mode == 'd' ? this.writer.toString() : null; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Utilities/Json/JSONTokener.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Utilities.Json; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.io.InputStreamReader; 7 | import java.io.Reader; 8 | import java.io.StringReader; 9 | 10 | /* 11 | Copyright (c) 2002 JSON.org 12 | 13 | Permission is hereby granted, free of charge, to any person obtaining a copy 14 | of this software and associated documentation files (the "Software"), to deal 15 | in the Software without restriction, including without limitation the rights 16 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 | copies of the Software, and to permit persons to whom the Software is 18 | furnished to do so, subject to the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be included in all 21 | copies or substantial portions of the Software. 22 | 23 | The Software shall be used for Good, not Evil. 24 | 25 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31 | SOFTWARE. 32 | */ 33 | 34 | /** 35 | * A JSONTokener takes a source string and extracts characters and tokens from 36 | * it. It is used by the JSONObject and JSONArray constructors to parse 37 | * JSON source strings. 38 | * @author JSON.org 39 | * @version 2014-05-03 40 | */ 41 | public class JSONTokener { 42 | 43 | private long character; 44 | private boolean eof; 45 | private long index; 46 | private long line; 47 | private char previous; 48 | private Reader reader; 49 | private boolean usePrevious; 50 | 51 | 52 | /** 53 | * Construct a JSONTokener from a Reader. 54 | * 55 | * @param reader A reader. 56 | */ 57 | public JSONTokener(Reader reader) { 58 | this.reader = reader.markSupported() 59 | ? reader 60 | : new BufferedReader(reader); 61 | this.eof = false; 62 | this.usePrevious = false; 63 | this.previous = 0; 64 | this.index = 0; 65 | this.character = 1; 66 | this.line = 1; 67 | } 68 | 69 | 70 | /** 71 | * Construct a JSONTokener from an InputStream. 72 | * @param inputStream The source. 73 | */ 74 | public JSONTokener(InputStream inputStream) throws JSONException { 75 | this(new InputStreamReader(inputStream)); 76 | } 77 | 78 | 79 | /** 80 | * Construct a JSONTokener from a string. 81 | * 82 | * @param s A source string. 83 | */ 84 | public JSONTokener(String s) { 85 | this(new StringReader(s)); 86 | } 87 | 88 | 89 | /** 90 | * Back up one character. This provides a sort of lookahead capability, 91 | * so that you can test for a digit or letter before attempting to parse 92 | * the next number or identifier. 93 | */ 94 | public void back() throws JSONException { 95 | if (this.usePrevious || this.index <= 0) { 96 | throw new JSONException("Stepping back two steps is not supported"); 97 | } 98 | this.index -= 1; 99 | this.character -= 1; 100 | this.usePrevious = true; 101 | this.eof = false; 102 | } 103 | 104 | 105 | /** 106 | * Get the hex value of a character (base16). 107 | * @param c A character between '0' and '9' or between 'A' and 'F' or 108 | * between 'a' and 'f'. 109 | * @return An int between 0 and 15, or -1 if c was not a hex digit. 110 | */ 111 | public static int dehexchar(char c) { 112 | if (c >= '0' && c <= '9') { 113 | return c - '0'; 114 | } 115 | if (c >= 'A' && c <= 'F') { 116 | return c - ('A' - 10); 117 | } 118 | if (c >= 'a' && c <= 'f') { 119 | return c - ('a' - 10); 120 | } 121 | return -1; 122 | } 123 | 124 | public boolean end() { 125 | return this.eof && !this.usePrevious; 126 | } 127 | 128 | 129 | /** 130 | * Determine if the source string still contains characters that next() 131 | * can consume. 132 | * @return true if not yet at the end of the source. 133 | */ 134 | public boolean more() throws JSONException { 135 | this.next(); 136 | if (this.end()) { 137 | return false; 138 | } 139 | this.back(); 140 | return true; 141 | } 142 | 143 | 144 | /** 145 | * Get the next character in the source string. 146 | * 147 | * @return The next character, or 0 if past the end of the source string. 148 | */ 149 | public char next() throws JSONException { 150 | int c; 151 | if (this.usePrevious) { 152 | this.usePrevious = false; 153 | c = this.previous; 154 | } else { 155 | try { 156 | c = this.reader.read(); 157 | } catch (IOException exception) { 158 | throw new JSONException(exception); 159 | } 160 | 161 | if (c <= 0) { // End of stream 162 | this.eof = true; 163 | c = 0; 164 | } 165 | } 166 | this.index += 1; 167 | if (this.previous == '\r') { 168 | this.line += 1; 169 | this.character = c == '\n' ? 0 : 1; 170 | } else if (c == '\n') { 171 | this.line += 1; 172 | this.character = 0; 173 | } else { 174 | this.character += 1; 175 | } 176 | this.previous = (char) c; 177 | return this.previous; 178 | } 179 | 180 | 181 | /** 182 | * Consume the next character, and check that it matches a specified 183 | * character. 184 | * @param c The character to match. 185 | * @return The character. 186 | * @throws JSONException if the character does not match. 187 | */ 188 | public char next(char c) throws JSONException { 189 | char n = this.next(); 190 | if (n != c) { 191 | throw this.syntaxError("Expected '" + c + "' and instead saw '" + 192 | n + "'"); 193 | } 194 | return n; 195 | } 196 | 197 | 198 | /** 199 | * Get the next n characters. 200 | * 201 | * @param n The number of characters to take. 202 | * @return A string of n characters. 203 | * @throws JSONException 204 | * Substring bounds error if there are not 205 | * n characters remaining in the source string. 206 | */ 207 | public String next(int n) throws JSONException { 208 | if (n == 0) { 209 | return ""; 210 | } 211 | 212 | char[] chars = new char[n]; 213 | int pos = 0; 214 | 215 | while (pos < n) { 216 | chars[pos] = this.next(); 217 | if (this.end()) { 218 | throw this.syntaxError("Substring bounds error"); 219 | } 220 | pos += 1; 221 | } 222 | return new String(chars); 223 | } 224 | 225 | 226 | /** 227 | * Get the next char in the string, skipping whitespace. 228 | * @throws JSONException 229 | * @return A character, or 0 if there are no more characters. 230 | */ 231 | public char nextClean() throws JSONException { 232 | for (;;) { 233 | char c = this.next(); 234 | if (c == 0 || c > ' ') { 235 | return c; 236 | } 237 | } 238 | } 239 | 240 | 241 | /** 242 | * Return the characters up to the next close quote character. 243 | * Backslash processing is done. The formal JSON format does not 244 | * allow strings in single quotes, but an implementation is allowed to 245 | * accept them. 246 | * @param quote The quoting character, either 247 | * " (double quote) or 248 | * ' (single quote). 249 | * @return A String. 250 | * @throws JSONException Unterminated string. 251 | */ 252 | public String nextString(char quote) throws JSONException { 253 | char c; 254 | StringBuilder sb = new StringBuilder(); 255 | for (;;) { 256 | c = this.next(); 257 | switch (c) { 258 | case 0: 259 | case '\n': 260 | case '\r': 261 | throw this.syntaxError("Unterminated string"); 262 | case '\\': 263 | c = this.next(); 264 | switch (c) { 265 | case 'b': 266 | sb.append('\b'); 267 | break; 268 | case 't': 269 | sb.append('\t'); 270 | break; 271 | case 'n': 272 | sb.append('\n'); 273 | break; 274 | case 'f': 275 | sb.append('\f'); 276 | break; 277 | case 'r': 278 | sb.append('\r'); 279 | break; 280 | case 'u': 281 | sb.append((char)Integer.parseInt(this.next(4), 16)); 282 | break; 283 | case '"': 284 | case '\'': 285 | case '\\': 286 | case '/': 287 | sb.append(c); 288 | break; 289 | default: 290 | throw this.syntaxError("Illegal escape."); 291 | } 292 | break; 293 | default: 294 | if (c == quote) { 295 | return sb.toString(); 296 | } 297 | sb.append(c); 298 | } 299 | } 300 | } 301 | 302 | 303 | /** 304 | * Get the text up but not including the specified character or the 305 | * end of line, whichever comes first. 306 | * @param delimiter A delimiter character. 307 | * @return A string. 308 | */ 309 | public String nextTo(char delimiter) throws JSONException { 310 | StringBuilder sb = new StringBuilder(); 311 | for (;;) { 312 | char c = this.next(); 313 | if (c == delimiter || c == 0 || c == '\n' || c == '\r') { 314 | if (c != 0) { 315 | this.back(); 316 | } 317 | return sb.toString().trim(); 318 | } 319 | sb.append(c); 320 | } 321 | } 322 | 323 | 324 | /** 325 | * Get the text up but not including one of the specified delimiter 326 | * characters or the end of line, whichever comes first. 327 | * @param delimiters A set of delimiter characters. 328 | * @return A string, trimmed. 329 | */ 330 | public String nextTo(String delimiters) throws JSONException { 331 | char c; 332 | StringBuilder sb = new StringBuilder(); 333 | for (;;) { 334 | c = this.next(); 335 | if (delimiters.indexOf(c) >= 0 || c == 0 || 336 | c == '\n' || c == '\r') { 337 | if (c != 0) { 338 | this.back(); 339 | } 340 | return sb.toString().trim(); 341 | } 342 | sb.append(c); 343 | } 344 | } 345 | 346 | 347 | /** 348 | * Get the next value. The value can be a Boolean, Double, Integer, 349 | * JSONArray, JSONObject, Long, or String, or the JSONObject.NULL object. 350 | * @throws JSONException If syntax error. 351 | * 352 | * @return An object. 353 | */ 354 | public Object nextValue() throws JSONException { 355 | char c = this.nextClean(); 356 | String string; 357 | 358 | switch (c) { 359 | case '"': 360 | case '\'': 361 | return this.nextString(c); 362 | case '{': 363 | this.back(); 364 | return new JSONObject(this); 365 | case '[': 366 | this.back(); 367 | return new JSONArray(this); 368 | } 369 | 370 | /* 371 | * Handle unquoted text. This could be the values true, false, or 372 | * null, or it can be a number. An implementation (such as this one) 373 | * is allowed to also accept non-standard forms. 374 | * 375 | * Accumulate characters until we reach the end of the text or a 376 | * formatting character. 377 | */ 378 | 379 | StringBuilder sb = new StringBuilder(); 380 | while (c >= ' ' && ",:]}/\\\"[{;=#".indexOf(c) < 0) { 381 | sb.append(c); 382 | c = this.next(); 383 | } 384 | this.back(); 385 | 386 | string = sb.toString().trim(); 387 | if ("".equals(string)) { 388 | throw this.syntaxError("Missing value"); 389 | } 390 | return JSONObject.stringToValue(string); 391 | } 392 | 393 | 394 | /** 395 | * Skip characters until the next character is the requested character. 396 | * If the requested character is not found, no characters are skipped. 397 | * @param to A character to skip to. 398 | * @return The requested character, or zero if the requested character 399 | * is not found. 400 | */ 401 | public char skipTo(char to) throws JSONException { 402 | char c; 403 | try { 404 | long startIndex = this.index; 405 | long startCharacter = this.character; 406 | long startLine = this.line; 407 | this.reader.mark(1000000); 408 | do { 409 | c = this.next(); 410 | if (c == 0) { 411 | this.reader.reset(); 412 | this.index = startIndex; 413 | this.character = startCharacter; 414 | this.line = startLine; 415 | return c; 416 | } 417 | } while (c != to); 418 | } catch (IOException exception) { 419 | throw new JSONException(exception); 420 | } 421 | this.back(); 422 | return c; 423 | } 424 | 425 | 426 | /** 427 | * Make a JSONException to signal a syntax error. 428 | * 429 | * @param message The error message. 430 | * @return A JSONException object, suitable for throwing 431 | */ 432 | public JSONException syntaxError(String message) { 433 | return new JSONException(message + this.toString()); 434 | } 435 | 436 | 437 | /** 438 | * Make a printable string of this JSONTokener. 439 | * 440 | * @return " at {index} [character {character} line {line}]" 441 | */ 442 | public String toString() { 443 | return " at " + this.index + " [character " + this.character + " line " + 444 | this.line + "]"; 445 | } 446 | } 447 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Utilities/Json/JSONWriter.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Utilities.Json; 2 | 3 | import java.io.IOException; 4 | import java.io.Writer; 5 | 6 | /* 7 | Copyright (c) 2006 JSON.org 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining a copy 10 | of this software and associated documentation files (the "Software"), to deal 11 | in the Software without restriction, including without limitation the rights 12 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | copies of the Software, and to permit persons to whom the Software is 14 | furnished to do so, subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included in all 17 | copies or substantial portions of the Software. 18 | 19 | The Software shall be used for Good, not Evil. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | SOFTWARE. 28 | */ 29 | 30 | /** 31 | * JSONWriter provides a quick and convenient way of producing JSON text. 32 | * The texts produced strictly conform to JSON syntax rules. No whitespace is 33 | * added, so the results are ready for transmission or storage. Each instance of 34 | * JSONWriter can produce one JSON text. 35 | *

36 | * A JSONWriter instance provides a value method for appending 37 | * values to the 38 | * text, and a key 39 | * method for adding keys before values in objects. There are array 40 | * and endArray methods that make and bound array values, and 41 | * object and endObject methods which make and bound 42 | * object values. All of these methods return the JSONWriter instance, 43 | * permitting a cascade style. For example,

 44 |  * new JSONWriter(myWriter)
 45 |  *     .object()
 46 |  *         .key("JSON")
 47 |  *         .value("Hello, World!")
 48 |  *     .endObject();
which writes
 49 |  * {"JSON":"Hello, World!"}
50 | *

51 | * The first method called must be array or object. 52 | * There are no methods for adding commas or colons. JSONWriter adds them for 53 | * you. Objects and arrays can be nested up to 20 levels deep. 54 | *

55 | * This can sometimes be easier than using a JSONObject to build a string. 56 | * @author JSON.org 57 | * @version 2011-11-24 58 | */ 59 | public class JSONWriter { 60 | private static final int maxdepth = 200; 61 | 62 | /** 63 | * The comma flag determines if a comma should be output before the next 64 | * value. 65 | */ 66 | private boolean comma; 67 | 68 | /** 69 | * The current mode. Values: 70 | * 'a' (array), 71 | * 'd' (done), 72 | * 'i' (initial), 73 | * 'k' (key), 74 | * 'o' (object). 75 | */ 76 | protected char mode; 77 | 78 | /** 79 | * The object/array stack. 80 | */ 81 | private final JSONObject stack[]; 82 | 83 | /** 84 | * The stack top index. A value of 0 indicates that the stack is empty. 85 | */ 86 | private int top; 87 | 88 | /** 89 | * The writer that will receive the output. 90 | */ 91 | protected Writer writer; 92 | 93 | /** 94 | * Make a fresh JSONWriter. It can be used to build one JSON text. 95 | */ 96 | public JSONWriter(Writer w) { 97 | this.comma = false; 98 | this.mode = 'i'; 99 | this.stack = new JSONObject[maxdepth]; 100 | this.top = 0; 101 | this.writer = w; 102 | } 103 | 104 | /** 105 | * Append a value. 106 | * @param string A string value. 107 | * @return this 108 | * @throws JSONException If the value is out of sequence. 109 | */ 110 | private JSONWriter append(String string) throws JSONException { 111 | if (string == null) { 112 | throw new JSONException("Null pointer"); 113 | } 114 | if (this.mode == 'o' || this.mode == 'a') { 115 | try { 116 | if (this.comma && this.mode == 'a') { 117 | this.writer.write(','); 118 | } 119 | this.writer.write(string); 120 | } catch (IOException e) { 121 | throw new JSONException(e); 122 | } 123 | if (this.mode == 'o') { 124 | this.mode = 'k'; 125 | } 126 | this.comma = true; 127 | return this; 128 | } 129 | throw new JSONException("Value out of sequence."); 130 | } 131 | 132 | /** 133 | * Begin appending a new array. All values until the balancing 134 | * endArray will be appended to this array. The 135 | * endArray method must be called to mark the array's end. 136 | * @return this 137 | * @throws JSONException If the nesting is too deep, or if the object is 138 | * started in the wrong place (for example as a key or after the end of the 139 | * outermost array or object). 140 | */ 141 | public JSONWriter array() throws JSONException { 142 | if (this.mode == 'i' || this.mode == 'o' || this.mode == 'a') { 143 | this.push(null); 144 | this.append("["); 145 | this.comma = false; 146 | return this; 147 | } 148 | throw new JSONException("Misplaced array."); 149 | } 150 | 151 | /** 152 | * End something. 153 | * @param mode Mode 154 | * @param c Closing character 155 | * @return this 156 | * @throws JSONException If unbalanced. 157 | */ 158 | private JSONWriter end(char mode, char c) throws JSONException { 159 | if (this.mode != mode) { 160 | throw new JSONException(mode == 'a' 161 | ? "Misplaced endArray." 162 | : "Misplaced endObject."); 163 | } 164 | this.pop(mode); 165 | try { 166 | this.writer.write(c); 167 | } catch (IOException e) { 168 | throw new JSONException(e); 169 | } 170 | this.comma = true; 171 | return this; 172 | } 173 | 174 | /** 175 | * End an array. This method most be called to balance calls to 176 | * array. 177 | * @return this 178 | * @throws JSONException If incorrectly nested. 179 | */ 180 | public JSONWriter endArray() throws JSONException { 181 | return this.end('a', ']'); 182 | } 183 | 184 | /** 185 | * End an object. This method most be called to balance calls to 186 | * object. 187 | * @return this 188 | * @throws JSONException If incorrectly nested. 189 | */ 190 | public JSONWriter endObject() throws JSONException { 191 | return this.end('k', '}'); 192 | } 193 | 194 | /** 195 | * Append a key. The key will be associated with the next value. In an 196 | * object, every value must be preceded by a key. 197 | * @param string A key string. 198 | * @return this 199 | * @throws JSONException If the key is out of place. For example, keys 200 | * do not belong in arrays or if the key is null. 201 | */ 202 | public JSONWriter key(String string) throws JSONException { 203 | if (string == null) { 204 | throw new JSONException("Null key."); 205 | } 206 | if (this.mode == 'k') { 207 | try { 208 | this.stack[this.top - 1].putOnce(string, Boolean.TRUE); 209 | if (this.comma) { 210 | this.writer.write(','); 211 | } 212 | this.writer.write(JSONObject.quote(string)); 213 | this.writer.write(':'); 214 | this.comma = false; 215 | this.mode = 'o'; 216 | return this; 217 | } catch (IOException e) { 218 | throw new JSONException(e); 219 | } 220 | } 221 | throw new JSONException("Misplaced key."); 222 | } 223 | 224 | 225 | /** 226 | * Begin appending a new object. All keys and values until the balancing 227 | * endObject will be appended to this object. The 228 | * endObject method must be called to mark the object's end. 229 | * @return this 230 | * @throws JSONException If the nesting is too deep, or if the object is 231 | * started in the wrong place (for example as a key or after the end of the 232 | * outermost array or object). 233 | */ 234 | public JSONWriter object() throws JSONException { 235 | if (this.mode == 'i') { 236 | this.mode = 'o'; 237 | } 238 | if (this.mode == 'o' || this.mode == 'a') { 239 | this.append("{"); 240 | this.push(new JSONObject()); 241 | this.comma = false; 242 | return this; 243 | } 244 | throw new JSONException("Misplaced object."); 245 | 246 | } 247 | 248 | 249 | /** 250 | * Pop an array or object scope. 251 | * @param c The scope to close. 252 | * @throws JSONException If nesting is wrong. 253 | */ 254 | private void pop(char c) throws JSONException { 255 | if (this.top <= 0) { 256 | throw new JSONException("Nesting error."); 257 | } 258 | char m = this.stack[this.top - 1] == null ? 'a' : 'k'; 259 | if (m != c) { 260 | throw new JSONException("Nesting error."); 261 | } 262 | this.top -= 1; 263 | this.mode = this.top == 0 264 | ? 'd' 265 | : this.stack[this.top - 1] == null 266 | ? 'a' 267 | : 'k'; 268 | } 269 | 270 | /** 271 | * Push an array or object scope. 272 | * @param jo The scope to open. 273 | * @throws JSONException If nesting is too deep. 274 | */ 275 | private void push(JSONObject jo) throws JSONException { 276 | if (this.top >= maxdepth) { 277 | throw new JSONException("Nesting too deep."); 278 | } 279 | this.stack[this.top] = jo; 280 | this.mode = jo == null ? 'a' : 'k'; 281 | this.top += 1; 282 | } 283 | 284 | 285 | /** 286 | * Append either the value true or the value 287 | * false. 288 | * @param b A boolean. 289 | * @return this 290 | * @throws JSONException 291 | */ 292 | public JSONWriter value(boolean b) throws JSONException { 293 | return this.append(b ? "true" : "false"); 294 | } 295 | 296 | /** 297 | * Append a double value. 298 | * @param d A double. 299 | * @return this 300 | * @throws JSONException If the number is not finite. 301 | */ 302 | public JSONWriter value(double d) throws JSONException { 303 | return this.value(new Double(d)); 304 | } 305 | 306 | /** 307 | * Append a long value. 308 | * @param l A long. 309 | * @return this 310 | * @throws JSONException 311 | */ 312 | public JSONWriter value(long l) throws JSONException { 313 | return this.append(Long.toString(l)); 314 | } 315 | 316 | 317 | /** 318 | * Append an object value. 319 | * @param object The object to append. It can be null, or a Boolean, Number, 320 | * String, JSONObject, or JSONArray, or an object that implements JSONString. 321 | * @return this 322 | * @throws JSONException If the value is out of sequence. 323 | */ 324 | public JSONWriter value(Object object) throws JSONException { 325 | return this.append(JSONObject.valueToString(object)); 326 | } 327 | } 328 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Utilities/MD5.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Utilities; 2 | 3 | import java.io.FileInputStream; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.security.MessageDigest; 7 | 8 | public class MD5 { 9 | 10 | public static String stringToMD5(String str) { 11 | 12 | try { 13 | byte[] strTemp = str.getBytes(); 14 | MessageDigest mdTemp = MessageDigest.getInstance("MD5"); 15 | mdTemp.update(strTemp); 16 | return toHexString(mdTemp.digest()); 17 | } catch (Exception e) { 18 | return null; 19 | } 20 | } 21 | 22 | public static String fileNameToMD5(String fileName) { 23 | InputStream inputStream = null; 24 | try { 25 | inputStream = new FileInputStream(fileName); 26 | return streamToMD5(inputStream); 27 | } catch (Exception e) { 28 | return null; 29 | } finally { 30 | if (inputStream != null) { 31 | try { 32 | inputStream.close(); 33 | } catch (IOException e) { 34 | e.printStackTrace(); 35 | } 36 | } 37 | } 38 | } 39 | 40 | public static String streamToMD5(InputStream inputStream) { 41 | try { 42 | MessageDigest mdTemp = MessageDigest.getInstance("MD5"); 43 | byte[] buffer = new byte[1024]; 44 | int numRead = 0; 45 | while ((numRead = inputStream.read(buffer)) > 0) { 46 | mdTemp.update(buffer, 0, numRead); 47 | } 48 | return toHexString(mdTemp.digest()); 49 | } catch (Exception e) { 50 | return null; 51 | } 52 | } 53 | 54 | private static String toHexString(byte[] md) { 55 | char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 56 | 'a', 'b', 'c', 'd', 'e', 'f' }; 57 | int j = md.length; 58 | char str[] = new char[j * 2]; 59 | for (int i = 0; i < j; i++) { 60 | byte byte0 = md[i]; 61 | str[2 * i] = hexDigits[byte0 >>> 4 & 0xf]; 62 | str[i * 2 + 1] = hexDigits[byte0 & 0xf]; 63 | } 64 | return new String(str); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/com/qcloud/Utilities/SHA1.java: -------------------------------------------------------------------------------- 1 | package com.qcloud.Utilities; 2 | 3 | import java.io.FileInputStream; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.security.MessageDigest; 7 | 8 | public class SHA1 { 9 | 10 | public static String stringToSHA(String str) { 11 | 12 | try { 13 | byte[] strTemp = str.getBytes(); 14 | MessageDigest mdTemp = MessageDigest.getInstance("SHA-1"); //SHA-256 15 | mdTemp.update(strTemp); 16 | return toHexString(mdTemp.digest()); 17 | } catch (Exception e) { 18 | return null; 19 | } 20 | } 21 | 22 | public static String fileNameToSHA(String fileName) { 23 | InputStream inputStream = null; 24 | try { 25 | inputStream = new FileInputStream(fileName); 26 | return streamToSHA(inputStream); 27 | } catch (Exception e) { 28 | return null; 29 | } finally { 30 | if (inputStream != null) { 31 | try { 32 | inputStream.close(); 33 | } catch (IOException e) { 34 | e.printStackTrace(); 35 | } 36 | } 37 | } 38 | } 39 | 40 | public static String streamToSHA(InputStream inputStream) { 41 | try { 42 | MessageDigest mdTemp = MessageDigest.getInstance("SHA-1"); //SHA-256 43 | byte[] buffer = new byte[1024]; 44 | int numRead = 0; 45 | while ((numRead = inputStream.read(buffer)) > 0) { 46 | mdTemp.update(buffer, 0, numRead); 47 | } 48 | return toHexString(mdTemp.digest()); 49 | } catch (Exception e) { 50 | return null; 51 | } 52 | } 53 | 54 | private static String toHexString(byte[] md) { 55 | char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 56 | 'a', 'b', 'c', 'd', 'e', 'f' }; 57 | int j = md.length; 58 | char str[] = new char[j * 2]; 59 | for (int i = 0; i < j; i++) { 60 | byte byte0 = md[i]; 61 | str[2 * i] = hexDigits[byte0 >>> 4 & 0xf]; 62 | str[i * 2 + 1] = hexDigits[byte0 & 0xf]; 63 | } 64 | return new String(str); 65 | } 66 | 67 | public static void main(String[]args) { 68 | System.out.println("start..."); 69 | System.out.println(SHA1.fileNameToSHA("d:\\test.rmvb")); 70 | System.out.println("end..."); 71 | } 72 | } 73 | --------------------------------------------------------------------------------