New upstream version 2.12.0
Mechtilde
3 years ago
11 | 11 | before_install: "git clone -b travis `git config --get remote.origin.url` target/travis" |
12 | 12 | script: "[ ${TRAVIS_PULL_REQUEST} = 'false' ] && mvn clean deploy --settings target/travis/settings.xml || mvn clean verify --settings target/travis/settings.xml" |
13 | 13 | |
14 | # whitelist | |
15 | branches: | |
16 | only: | |
17 | - "2.11" | |
18 | ||
19 | 14 | env: |
20 | 15 | global: |
21 | 16 | - secure: "YW0hrdsHvH41pb5uPJ2DGzXrBgOVT7nEyag/bAQoDcSlOQ/g55tnY6rIGkqE/aYD47IroTEhW4yLyM3tZpbrqwagX4dUX90ukjcUwUvFE1ePTSEfdBtuHVwl8f6HmLIIw2yK0dQ1gOJ21T+3g+wddvK+6sWBJJ+s3O1FePDh6X0=" |
0 | This copy of Jackson JSON processor annotations is licensed under the | |
1 | Apache (Software) License, version 2.0 ("the License"). | |
2 | See the License for details about distribution rights, and the | |
3 | specific rights regarding derivate works. | |
4 | ||
5 | You may obtain a copy of the License at: | |
6 | ||
7 | http://www.apache.org/licenses/LICENSE-2.0 | |
0 | ||
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. |
0 | 0 | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
1 | <!-- This module was also published with a richer model, Gradle metadata, --> | |
2 | <!-- which should be used instead. Do not delete the following line which --> | |
3 | <!-- is to indicate to Gradle or any Gradle module metadata file consumer --> | |
4 | <!-- that they should prefer consuming it instead. --> | |
5 | <!-- do_not_remove: published-with-gradle-metadata --> | |
1 | 6 | <modelVersion>4.0.0</modelVersion> |
2 | 7 | <parent> |
3 | 8 | <groupId>com.fasterxml.jackson</groupId> |
4 | 9 | <artifactId>jackson-base</artifactId> |
5 | <version>2.11.3</version> | |
10 | <version>2.12.0</version> | |
6 | 11 | </parent> |
7 | 12 | |
8 | 13 | <groupId>com.fasterxml.jackson.core</groupId> |
9 | 14 | <artifactId>jackson-core</artifactId> |
10 | 15 | <name>Jackson-core</name> |
11 | <version>2.11.3</version> | |
16 | <version>2.12.0</version> | |
12 | 17 | <packaging>bundle</packaging> |
13 | 18 | <description>Core Jackson processing abstractions (aka Streaming API), implementation for JSON</description> |
14 | 19 | <licenses> |
25 | 30 | <connection>scm:git:git@github.com:FasterXML/jackson-core.git</connection> |
26 | 31 | <developerConnection>scm:git:git@github.com:FasterXML/jackson-core.git</developerConnection> |
27 | 32 | <url>http://github.com/FasterXML/jackson-core</url> |
28 | <tag>jackson-core-2.11.3</tag> | |
33 | <tag>jackson-core-2.12.0</tag> | |
29 | 34 | </scm> |
30 | 35 | |
31 | 36 | <properties> |
66 | 71 | <plugin> |
67 | 72 | <groupId>org.jacoco</groupId> |
68 | 73 | <artifactId>jacoco-maven-plugin</artifactId> |
69 | <version>0.8.4</version> | |
70 | 74 | <executions> |
71 | 75 | <execution> |
72 | 76 | <goals> |
121 | 125 | <artifactId>replacer</artifactId> |
122 | 126 | </plugin> |
123 | 127 | |
124 | <!-- 04-Mar-2019, tatu: Add rudimentary JDK9+ module info. To build with JDK 8 | |
128 | <!-- 04-Mar-2019, tatu: Add rudimentary JDK9+ module info. To build with JDK 8 | |
125 | 129 | will have to use `moduleInfoFile` as anything else requires JDK 9+ |
126 | 130 | --> |
127 | 131 | <plugin> |
128 | 132 | <groupId>org.moditect</groupId> |
129 | 133 | <artifactId>moditect-maven-plugin</artifactId> |
130 | 134 | </plugin> |
135 | <!-- 03-Nov-2020, tatu: Add LICENSE from main level --> | |
136 | <plugin> | |
137 | <groupId>org.codehaus.mojo</groupId> | |
138 | <artifactId>build-helper-maven-plugin</artifactId> | |
139 | </plugin> | |
140 | ||
141 | <plugin> | |
142 | <groupId>de.jjohannes</groupId> | |
143 | <artifactId>gradle-module-metadata-maven-plugin</artifactId> | |
144 | </plugin> | |
131 | 145 | </plugins> |
132 | 146 | </build> |
133 | 147 |
239 | 239 | James Agnew (jamesagnew@github) |
240 | 240 | * Contributed implementation of #611: Optionally allow leading decimal in float tokens |
241 | 241 | (2.11.0) |
242 | ||
243 | Pavel Krutikhin (pakru@github) | |
244 | * Contributed fix for #647: Fix NPE in `writeNumber(String)` method of `UTF8JsonGenerator`, | |
245 | `WriterBasedJsonGenerator` | |
246 | (2.11.4) | |
247 | ||
248 | Pavan Kalyan (pavan-kalyan@github) | |
249 | * Contributed #500: Allow "optional-padding" for `Base64Variant` | |
250 | (2.12.0) | |
251 | ||
252 | Jendrik Johannes (jjohannes@github) | |
253 | * Contributed #618: Publish Gradle Module Metadata | |
254 | (2.12.0) | |
255 | ||
256 | Jonathan Haber (jhaber@github) | |
257 | * Contributed #573: More customizable TokenFilter inclusion (using `Tokenfilter.Inclusion`) | |
258 | (2.12.0) |
13 | 13 | === Releases === |
14 | 14 | ------------------------------------------------------------------------ |
15 | 15 | |
16 | 2.12.0 (not yet released) | |
16 | 2.12.0 (29-Nov-2020) | |
17 | ||
18 | #500: Allow "optional-padding" for `Base64Variant` | |
19 | (contributed by Pavan K) | |
20 | #573: More customizable TokenFilter inclusion (using `Tokenfilter.Inclusion`) | |
21 | (contributed by Jonathan H) | |
22 | #618: Publish Gradle Module Metadata | |
23 | (contributed by Jendrik J) | |
24 | #619: Add `StreamReadCapability` for further format-based/format-agnostic | |
25 | handling improvements | |
26 | #627: Add `JsonParser.isExpectedNumberIntToken()` convenience method | |
27 | #630: Add `StreamWriteCapability` for further format-based/format-agnostic | |
28 | handling improvements | |
29 | #631: Add `JsonParser.getNumberValueExact()` to allow precision-retaining buffering | |
30 | #639: Limit initial allocated block size by `ByteArrayBuilder` to max block size | |
31 | #640: Add `JacksonException` as parent class of `JsonProcessingException` | |
32 | #653: Make `JsonWriteContext.reset()` and `JsonReadContext.reset()` methods public | |
33 | - Deprecate `JsonParser.getCurrentTokenId()` (use `#currentTokenId()` instead) | |
34 | - Full "LICENSE" included in jar for easier access by compliancy tools | |
35 | ||
36 | 2.11.4 (not yet released) | |
37 | ||
38 | #647: Fix NPE in `writeNumber(String)` method of `UTF8JsonGenerator`, | |
39 | `WriterBasedJsonGenerator` | |
40 | (contributed by Pavel K) | |
17 | 41 | |
18 | 42 | 2.11.3 (02-Oct-2020) |
19 | 43 | 2.11.2 (02-Aug-2020) |
18 | 18 | public final class Base64Variant |
19 | 19 | implements java.io.Serializable |
20 | 20 | { |
21 | /** | |
22 | * Defines how the Base64Variant deals with Padding while reading | |
23 | * | |
24 | * @since 2.12 | |
25 | */ | |
26 | public enum PaddingReadBehaviour { | |
27 | /** | |
28 | * Padding is not allowed in Base64 content being read (finding something | |
29 | * that looks like padding at the end of content results in an exception) | |
30 | */ | |
31 | PADDING_FORBIDDEN, | |
32 | ||
33 | /** | |
34 | * Padding is required in Base64 content being read | |
35 | * (missing padding for incomplete ending quartet results in an exception) | |
36 | */ | |
37 | PADDING_REQUIRED, | |
38 | ||
39 | /** | |
40 | * Padding is allowed but not required in Base64 content being read: no | |
41 | * exception thrown based on existence or absence, as long as proper | |
42 | * padding characters are used. | |
43 | */ | |
44 | PADDING_ALLOWED | |
45 | ; | |
46 | } | |
47 | ||
21 | 48 | private final static int INT_SPACE = 0x20; |
22 | 49 | |
23 | 50 | // We'll only serialize name |
27 | 54 | * Placeholder used by "no padding" variant, to be used when a character |
28 | 55 | * value is needed. |
29 | 56 | */ |
30 | final static char PADDING_CHAR_NONE = '\0'; | |
57 | protected final static char PADDING_CHAR_NONE = '\0'; | |
31 | 58 | |
32 | 59 | /** |
33 | 60 | * Marker used to denote ascii characters that do not correspond |
82 | 109 | final String _name; |
83 | 110 | |
84 | 111 | /** |
85 | * Whether this variant uses padding or not. | |
86 | */ | |
87 | private final transient boolean _usesPadding; | |
88 | ||
89 | /** | |
90 | 112 | * Character used for padding, if any ({@link #PADDING_CHAR_NONE} if not). |
91 | 113 | */ |
92 | private final transient char _paddingChar; | |
93 | ||
114 | private final char _paddingChar; | |
115 | ||
94 | 116 | /** |
95 | 117 | * Maximum number of encoded base64 characters to output during encoding |
96 | 118 | * before adding a linefeed, if line length is to be limited |
99 | 121 | * Note: for some output modes (when writing attributes) linefeeds may |
100 | 122 | * need to be avoided, and this value ignored. |
101 | 123 | */ |
102 | private final transient int _maxLineLength; | |
124 | private final int _maxLineLength; | |
125 | ||
126 | /** | |
127 | * Whether this variant uses padding when writing out content or not. | |
128 | * | |
129 | * @since 2.12 | |
130 | */ | |
131 | private final boolean _writePadding; | |
132 | ||
133 | /** | |
134 | * Whether padding characters should be required or not while decoding | |
135 | * | |
136 | * @since 2.12 | |
137 | */ | |
138 | private final PaddingReadBehaviour _paddingReadBehaviour; | |
103 | 139 | |
104 | 140 | /* |
105 | 141 | /********************************************************** |
107 | 143 | /********************************************************** |
108 | 144 | */ |
109 | 145 | |
110 | public Base64Variant(String name, String base64Alphabet, boolean usesPadding, char paddingChar, int maxLineLength) | |
146 | public Base64Variant(String name, String base64Alphabet, boolean writePadding, char paddingChar, int maxLineLength) | |
111 | 147 | { |
112 | 148 | _name = name; |
113 | _usesPadding = usesPadding; | |
149 | _writePadding = writePadding; | |
114 | 150 | _paddingChar = paddingChar; |
115 | 151 | _maxLineLength = maxLineLength; |
116 | 152 | |
132 | 168 | } |
133 | 169 | |
134 | 170 | // Plus if we use padding, add that in too |
135 | if (usesPadding) { | |
171 | if (writePadding) { | |
136 | 172 | _asciiToBase64[(int) paddingChar] = BASE64_VALUE_PADDING; |
137 | 173 | } |
174 | ||
175 | // By default, require padding on input if written on output; do not | |
176 | // accept if padding not written | |
177 | _paddingReadBehaviour = writePadding | |
178 | ? PaddingReadBehaviour.PADDING_REQUIRED | |
179 | : PaddingReadBehaviour.PADDING_FORBIDDEN; | |
138 | 180 | } |
139 | 181 | |
140 | 182 | /** |
142 | 184 | * to one used by another variant except for the maximum line length |
143 | 185 | * (and obviously, name). |
144 | 186 | */ |
145 | public Base64Variant(Base64Variant base, String name, int maxLineLength) | |
146 | { | |
147 | this(base, name, base._usesPadding, base._paddingChar, maxLineLength); | |
187 | public Base64Variant(Base64Variant base, | |
188 | String name, int maxLineLength) | |
189 | { | |
190 | this(base, name, base._writePadding, base._paddingChar, maxLineLength); | |
148 | 191 | } |
149 | 192 | |
150 | 193 | /** |
152 | 195 | * to one used by another variant, but other details (padding, maximum |
153 | 196 | * line length) differ |
154 | 197 | */ |
155 | public Base64Variant(Base64Variant base, String name, boolean usesPadding, char paddingChar, int maxLineLength) | |
198 | public Base64Variant(Base64Variant base, | |
199 | String name, boolean writePadding, char paddingChar, int maxLineLength) | |
200 | { | |
201 | this(base, name, writePadding, paddingChar, base._paddingReadBehaviour, maxLineLength); | |
202 | } | |
203 | ||
204 | private Base64Variant(Base64Variant base, | |
205 | String name, boolean writePadding, char paddingChar, PaddingReadBehaviour paddingReadBehaviour, int maxLineLength) | |
156 | 206 | { |
157 | 207 | _name = name; |
158 | 208 | byte[] srcB = base._base64ToAsciiB; |
162 | 212 | int[] srcV = base._asciiToBase64; |
163 | 213 | System.arraycopy(srcV, 0, this._asciiToBase64, 0, srcV.length); |
164 | 214 | |
165 | _usesPadding = usesPadding; | |
215 | _writePadding = writePadding; | |
166 | 216 | _paddingChar = paddingChar; |
167 | 217 | _maxLineLength = maxLineLength; |
218 | _paddingReadBehaviour = paddingReadBehaviour; | |
219 | } | |
220 | ||
221 | private Base64Variant(Base64Variant base, PaddingReadBehaviour paddingReadBehaviour) { | |
222 | this(base, base._name, base._writePadding, base._paddingChar, paddingReadBehaviour, base._maxLineLength); | |
223 | } | |
224 | ||
225 | /** | |
226 | * @return Base64Variant which does not require padding on read | |
227 | * | |
228 | * @since 2.12 | |
229 | */ | |
230 | public Base64Variant withPaddingAllowed() { | |
231 | return withReadPadding(PaddingReadBehaviour.PADDING_ALLOWED); | |
232 | } | |
233 | ||
234 | /** | |
235 | * @return Base64Variant which requires padding on read | |
236 | * @since 2.12 | |
237 | */ | |
238 | public Base64Variant withPaddingRequired() { | |
239 | return withReadPadding(PaddingReadBehaviour.PADDING_REQUIRED); | |
240 | } | |
241 | ||
242 | /** | |
243 | * @return Base64Variant which does not accept padding on read | |
244 | * @since 2.12 | |
245 | */ | |
246 | public Base64Variant withPaddingForbidden() { | |
247 | return withReadPadding(PaddingReadBehaviour.PADDING_FORBIDDEN); | |
248 | } | |
249 | ||
250 | /** | |
251 | * @param readPadding Padding read behavior desired | |
252 | * | |
253 | * @return Instance with desired padding read behavior setting (this | |
254 | * if already has setting; new instance otherwise) | |
255 | * | |
256 | * @since 2.12 | |
257 | */ | |
258 | public Base64Variant withReadPadding(PaddingReadBehaviour readPadding) { | |
259 | return (readPadding == _paddingReadBehaviour) ? this | |
260 | : new Base64Variant(this, readPadding); | |
261 | } | |
262 | ||
263 | /** | |
264 | * @param writePadding Determines if padding is output on write or not | |
265 | * | |
266 | * @return Base64Variant which writes padding or not depending on writePadding | |
267 | * | |
268 | * @since 2.12 | |
269 | */ | |
270 | public Base64Variant withWritePadding(boolean writePadding) { | |
271 | return (writePadding == _writePadding) ? this | |
272 | : new Base64Variant(this, _name, writePadding, _paddingChar, _maxLineLength); | |
168 | 273 | } |
169 | 274 | |
170 | 275 | /* |
173 | 278 | /********************************************************** |
174 | 279 | */ |
175 | 280 | |
176 | /** | |
177 | * Method used to "demote" deserialized instances back to | |
178 | * canonical ones | |
179 | */ | |
281 | // 26-Oct-2020, tatu: Much more complicated with 2.12 as it is | |
282 | // possible to create differently configured instances. | |
283 | // Need to start with name to regenerate tables etc but then | |
284 | // handle overrides | |
180 | 285 | protected Object readResolve() { |
181 | return Base64Variants.valueOf(_name); | |
182 | } | |
183 | ||
286 | Base64Variant base = Base64Variants.valueOf(_name); | |
287 | if ((_writePadding != base._writePadding) | |
288 | || (_paddingChar != base._paddingChar) | |
289 | || (_paddingReadBehaviour != base._paddingReadBehaviour) | |
290 | || (_maxLineLength != base._maxLineLength) | |
291 | || (_writePadding != base._writePadding) | |
292 | ) { | |
293 | return new Base64Variant(base, | |
294 | _name, _writePadding, _paddingChar, _paddingReadBehaviour, _maxLineLength); | |
295 | } | |
296 | return base; | |
297 | } | |
298 | ||
184 | 299 | /* |
185 | 300 | /********************************************************** |
186 | 301 | /* Public accessors |
189 | 304 | |
190 | 305 | public String getName() { return _name; } |
191 | 306 | |
192 | public boolean usesPadding() { return _usesPadding; } | |
307 | /** | |
308 | * @return True if this Base64 encoding will <b>write</b> padding on output | |
309 | * (note: before Jackson 2.12 also dictated whether padding was accepted on read) | |
310 | */ | |
311 | public boolean usesPadding() { return _writePadding; } | |
312 | ||
313 | /** | |
314 | * @since 2.12 | |
315 | */ | |
316 | public boolean requiresPaddingOnRead() { | |
317 | return _paddingReadBehaviour == PaddingReadBehaviour.PADDING_REQUIRED; | |
318 | } | |
319 | ||
320 | /** | |
321 | * @since 2.12 | |
322 | */ | |
323 | public boolean acceptsPaddingOnRead() { | |
324 | return _paddingReadBehaviour != PaddingReadBehaviour.PADDING_FORBIDDEN; | |
325 | } | |
326 | ||
193 | 327 | public boolean usesPaddingChar(char c) { return c == _paddingChar; } |
194 | 328 | public boolean usesPaddingChar(int ch) { return ch == (int) _paddingChar; } |
329 | ||
330 | /** | |
331 | * @return Indicator on how this Base64 encoding will handle possible padding | |
332 | * in content when reading. | |
333 | */ | |
334 | public PaddingReadBehaviour paddingReadBehaviour() { return _paddingReadBehaviour; } | |
335 | ||
195 | 336 | public char getPaddingChar() { return _paddingChar; } |
196 | 337 | public byte getPaddingByte() { return (byte)_paddingChar; } |
197 | 338 | |
235 | 376 | |
236 | 377 | public char encodeBase64BitsAsChar(int value) |
237 | 378 | { |
238 | /* Let's assume caller has done necessary checks; this | |
239 | * method must be fast and inlinable | |
240 | */ | |
379 | // Let's assume caller has done necessary checks; this | |
380 | // method must be fast and inlinable | |
241 | 381 | return _base64ToAsciiC[value]; |
242 | 382 | } |
243 | 383 | |
274 | 414 | { |
275 | 415 | buffer[outPtr++] = _base64ToAsciiC[(bits >> 18) & 0x3F]; |
276 | 416 | buffer[outPtr++] = _base64ToAsciiC[(bits >> 12) & 0x3F]; |
277 | if (_usesPadding) { | |
417 | if (usesPadding()) { | |
278 | 418 | buffer[outPtr++] = (outputBytes == 2) ? |
279 | 419 | _base64ToAsciiC[(bits >> 6) & 0x3F] : _paddingChar; |
280 | 420 | buffer[outPtr++] = _paddingChar; |
290 | 430 | { |
291 | 431 | sb.append(_base64ToAsciiC[(bits >> 18) & 0x3F]); |
292 | 432 | sb.append(_base64ToAsciiC[(bits >> 12) & 0x3F]); |
293 | if (_usesPadding) { | |
433 | if (usesPadding()) { | |
294 | 434 | sb.append((outputBytes == 2) ? |
295 | 435 | _base64ToAsciiC[(bits >> 6) & 0x3F] : _paddingChar); |
296 | 436 | sb.append(_paddingChar); |
332 | 472 | { |
333 | 473 | buffer[outPtr++] = _base64ToAsciiB[(bits >> 18) & 0x3F]; |
334 | 474 | buffer[outPtr++] = _base64ToAsciiB[(bits >> 12) & 0x3F]; |
335 | if (_usesPadding) { | |
475 | if (usesPadding()) { | |
336 | 476 | byte pb = (byte) _paddingChar; |
337 | 477 | buffer[outPtr++] = (outputBytes == 2) ? |
338 | 478 | _base64ToAsciiB[(bits >> 6) & 0x3F] : pb; |
528 | 668 | decodedData = (decodedData << 6) | bits; |
529 | 669 | // third base64 char; can be padding, but not ws |
530 | 670 | if (ptr >= len) { |
531 | // but as per [JACKSON-631] can be end-of-input, iff not using padding | |
532 | if (!usesPadding()) { | |
671 | // but as per [JACKSON-631] can be end-of-input, iff padding is not required | |
672 | if (!requiresPaddingOnRead()) { | |
533 | 673 | decodedData >>= 4; |
534 | 674 | builder.append(decodedData); |
535 | 675 | break; |
543 | 683 | if (bits < 0) { |
544 | 684 | if (bits != Base64Variant.BASE64_VALUE_PADDING) { |
545 | 685 | _reportInvalidBase64(ch, 2, null); |
686 | } | |
687 | if (!acceptsPaddingOnRead()) { | |
688 | _reportBase64UnexpectedPadding(); | |
546 | 689 | } |
547 | 690 | // Ok, must get padding |
548 | 691 | if (ptr >= len) { |
561 | 704 | decodedData = (decodedData << 6) | bits; |
562 | 705 | // fourth and last base64 char; can be padding, but not ws |
563 | 706 | if (ptr >= len) { |
564 | // but as per [JACKSON-631] can be end-of-input, iff not using padding | |
565 | if (!usesPadding()) { | |
707 | // but as per [JACKSON-631] can be end-of-input, iff padding on read is not required | |
708 | if (!requiresPaddingOnRead()) { | |
566 | 709 | decodedData >>= 2; |
567 | 710 | builder.appendTwoBytes(decodedData); |
568 | 711 | break; |
574 | 717 | if (bits < 0) { |
575 | 718 | if (bits != Base64Variant.BASE64_VALUE_PADDING) { |
576 | 719 | _reportInvalidBase64(ch, 3, null); |
720 | } | |
721 | if (!acceptsPaddingOnRead()) { | |
722 | _reportBase64UnexpectedPadding(); | |
577 | 723 | } |
578 | 724 | decodedData >>= 2; |
579 | 725 | builder.appendTwoBytes(decodedData); |
593 | 739 | |
594 | 740 | @Override |
595 | 741 | public String toString() { return _name; } |
596 | ||
742 | ||
597 | 743 | @Override |
598 | 744 | public boolean equals(Object o) { |
599 | // identity comparison should be dine | |
600 | return (o == this); | |
745 | // identity comparison should be fine | |
746 | // 26-Oct-2020, tatu: ... not any more with 2.12 | |
747 | if (o == this) return true; | |
748 | if (o == null || o.getClass() != getClass()) return false; | |
749 | ||
750 | Base64Variant other = (Base64Variant) o; | |
751 | return (other._paddingChar == _paddingChar) | |
752 | && (other._maxLineLength == _maxLineLength) | |
753 | && (other._writePadding == _writePadding) | |
754 | && (other._paddingReadBehaviour == _paddingReadBehaviour) | |
755 | && (_name.equals(other._name)) | |
756 | ; | |
601 | 757 | } |
602 | 758 | |
603 | 759 | @Override |
604 | 760 | public int hashCode() { |
605 | 761 | return _name.hashCode(); |
606 | 762 | } |
607 | ||
763 | ||
608 | 764 | /* |
609 | 765 | /********************************************************** |
610 | 766 | /* Internal helper methods |
611 | 767 | /********************************************************** |
612 | 768 | */ |
613 | ||
769 | ||
614 | 770 | /** |
615 | 771 | * @param bindex Relative index within base64 character unit; between 0 |
616 | 772 | * and 3 (as unit has exactly 4 characters) |
639 | 795 | throw new IllegalArgumentException(missingPaddingMessage()); |
640 | 796 | } |
641 | 797 | |
798 | protected void _reportBase64UnexpectedPadding() throws IllegalArgumentException { | |
799 | throw new IllegalArgumentException(unexpectedPaddingMessage()); | |
800 | } | |
801 | ||
802 | /** | |
803 | * Helper method that will construct a message to use in exceptions for cases where input ends | |
804 | * prematurely in place where padding is not expected. | |
805 | * | |
806 | * @since 2.12 | |
807 | */ | |
808 | protected String unexpectedPaddingMessage() { | |
809 | return String.format("Unexpected end of base64-encoded String: base64 variant '%s' expects no padding at the end while decoding. This Base64Variant might have been incorrectly configured", | |
810 | getName()); | |
811 | } | |
812 | ||
642 | 813 | /** |
643 | 814 | * Helper method that will construct a message to use in exceptions for cases where input ends |
644 | 815 | * prematurely in place where padding would be expected. |
645 | 816 | * |
646 | 817 | * @since 2.10 |
647 | 818 | */ |
648 | public String missingPaddingMessage() { | |
649 | return String.format("Unexpected end of base64-encoded String: base64 variant '%s' expects padding (one or more '%c' characters) at the end", | |
819 | public String missingPaddingMessage() { // !!! TODO: why is this 'public'? | |
820 | return String.format("Unexpected end of base64-encoded String: base64 variant '%s' expects padding (one or more '%c' characters) at the end. This Base64Variant might have been incorrectly configured", | |
650 | 821 | getName(), getPaddingChar()); |
651 | 822 | } |
652 | ||
653 | 823 | } |
654 |
11 | 11 | * <li> {@link #PEM} |
12 | 12 | * <li> {@link #MODIFIED_FOR_URL} |
13 | 13 | * </ul> |
14 | * | |
14 | * See entries for full description of differences. | |
15 | *<p> | |
16 | * Note that for default {@link Base64Variant} instances listed above, configuration | |
17 | * is such that if padding is written on output, it will also be required on | |
18 | * reading. This behavior may be changed by using methods: | |
19 | *<ul> | |
20 | * <li>{@link Base64Variant#withPaddingAllowed()} | |
21 | * </li> | |
22 | * <li>{@link Base64Variant#withPaddingForbidden()} | |
23 | * </li> | |
24 | * <li>{@link Base64Variant#withPaddingRequired()} | |
25 | * </li> | |
26 | * <li>{@link Base64Variant#withWritePadding(boolean)} | |
27 | * </li> | |
28 | *</ul> | |
29 | * | |
15 | 30 | * @author Tatu Saloranta |
16 | 31 | */ |
17 | 32 | public final class Base64Variants |
26 | 41 | *<p> |
27 | 42 | * Note that although this can be thought of as the standard variant, |
28 | 43 | * it is <b>not</b> the default for Jackson: no-linefeeds alternative |
29 | * is because of JSON requirement of escaping all linefeeds. | |
44 | * is instead used because of JSON requirement of escaping all linefeeds. | |
45 | *<p> | |
46 | * Writes padding on output; requires padding when reading (may change later with a call to {@link Base64Variant#withWritePadding}) | |
30 | 47 | */ |
31 | 48 | public final static Base64Variant MIME; |
32 | 49 | static { |
38 | 55 | * use linefeeds (max line length set to infinite). Useful when linefeeds |
39 | 56 | * wouldn't work well (possibly in attributes), or for minor space savings |
40 | 57 | * (save 1 linefeed per 76 data chars, ie. ~1.4% savings). |
58 | *<p> | |
59 | * Writes padding on output; requires padding when reading (may change later with a call to {@link Base64Variant#withWritePadding}) | |
41 | 60 | */ |
42 | 61 | public final static Base64Variant MIME_NO_LINEFEEDS; |
43 | 62 | static { |
47 | 66 | /** |
48 | 67 | * This variant is the one that predates {@link #MIME}: it is otherwise |
49 | 68 | * identical, except that it mandates shorter line length. |
69 | *<p> | |
70 | * Writes padding on output; requires padding when reading (may change later with a call to {@link Base64Variant#withWritePadding}) | |
50 | 71 | */ |
51 | 72 | public final static Base64Variant PEM = new Base64Variant(MIME, "PEM", true, '=', 64); |
52 | 73 | |
60 | 81 | * line length set to infinite). And finally, two characters (plus and |
61 | 82 | * slash) that would need quoting in URLs are replaced with more |
62 | 83 | * optimal alternatives (hyphen and underscore, respectively). |
84 | *<p> | |
85 | * Does not write padding on output; does not accept padding when reading (may change later with a call to {@link Base64Variant#withWritePadding}) | |
63 | 86 | */ |
64 | 87 | public final static Base64Variant MODIFIED_FOR_URL; |
65 | 88 | static { |
72 | 95 | } |
73 | 96 | |
74 | 97 | /** |
75 | * Method used to get the default variant ("MIME_NO_LINEFEEDS") for cases | |
98 | * Method used to get the default variant -- {@link #MIME_NO_LINEFEEDS} -- for cases | |
76 | 99 | * where caller does not explicitly specify the variant. |
77 | 100 | * We will prefer no-linefeed version because linefeeds in JSON values |
78 | 101 | * must be escaped, making linefeed-containing variants sub-optimal. |
82 | 105 | } |
83 | 106 | |
84 | 107 | /** |
108 | * Lookup method for finding one of standard variants by name. | |
109 | * If name does not match any of standard variant names, | |
110 | * a {@link IllegalArgumentException} is thrown. | |
111 | * | |
85 | 112 | * @since 2.1 |
86 | 113 | */ |
87 | 114 | public static Base64Variant valueOf(String name) throws IllegalArgumentException |
0 | 0 | package com.fasterxml.jackson.core; |
1 | ||
2 | import com.fasterxml.jackson.core.util.JacksonFeature; | |
1 | 3 | |
2 | 4 | /** |
3 | 5 | * Marker interface that is to be implemented by data format - specific features. |
5 | 7 | * they can implement interfaces; and as such we may be able to use limited |
6 | 8 | * amount of generic functionality. |
7 | 9 | *<p> |
8 | * Note that this type is only implemented by non-JSON formats: | |
9 | * types {@link JsonParser.Feature} and {@link JsonGenerator.Feature} do NOT | |
10 | * implement it. This is to make it easier to avoid ambiguity with method | |
11 | * calls. | |
10 | * Since 2.12 this is more of an extra marker feature, as its core API is now | |
11 | * defined in more general {@link JacksonFeature}. | |
12 | 12 | * |
13 | * @since 2.6 (to be fully used in 2.7 and beyond) | |
13 | * @since 2.6 | |
14 | 14 | */ |
15 | 15 | public interface FormatFeature |
16 | extends JacksonFeature // since 2.12 | |
16 | 17 | { |
17 | 18 | /** |
18 | 19 | * Accessor for checking whether this feature is enabled by default. |
19 | 20 | */ |
21 | @Override | |
20 | 22 | public boolean enabledByDefault(); |
21 | 23 | |
22 | 24 | /** |
23 | 25 | * Returns bit mask for this feature instance; must be a single bit, |
24 | 26 | * that is of form <code>(1 << N)</code> |
25 | 27 | */ |
28 | @Override | |
26 | 29 | public int getMask(); |
27 | 30 | |
28 | 31 | /** |
29 | 32 | * Convenience method for checking whether feature is enabled in given bitmask |
30 | 33 | */ |
34 | @Override | |
31 | 35 | public boolean enabledIn(int flags); |
32 | 36 | } |
0 | package com.fasterxml.jackson.core; | |
1 | ||
2 | /** | |
3 | * Base class for all Jackson-produced checked exceptions. | |
4 | *<p> | |
5 | * For Jackson 2.x this base type is not widely used (instead, its main subtype | |
6 | * {@link JsonProcessingException} is): it is provided more for forwards-compatibility | |
7 | * purposes as 3.x will base all other types directly on it and deprecate | |
8 | * {@link JsonProcessingException} (as well as chance its type to unchecked). | |
9 | * | |
10 | * @since 2.12 | |
11 | */ | |
12 | public abstract class JacksonException extends java.io.IOException | |
13 | { | |
14 | private final static long serialVersionUID = 123; // eclipse complains otherwise | |
15 | ||
16 | protected JacksonException(String msg) { | |
17 | super(msg); | |
18 | } | |
19 | ||
20 | protected JacksonException(Throwable t) { | |
21 | super(t); | |
22 | } | |
23 | ||
24 | protected JacksonException(String msg, Throwable rootCause) { | |
25 | super(msg, rootCause); | |
26 | // 23-Sep-2020, tatu: before 2.12, had null checks for some reason... | |
27 | // But I don't think that is actually required; Javadocs for | |
28 | // `java.lang.Throwable` constructor claim {@code null} is fine. | |
29 | /* if (rootCause != null) { | |
30 | initCause(rootCause); | |
31 | }*/ | |
32 | } | |
33 | ||
34 | /* | |
35 | /********************************************************** | |
36 | /* Extended API | |
37 | /********************************************************** | |
38 | */ | |
39 | ||
40 | /** | |
41 | * Accessor for location information related to position within input | |
42 | * or output (depending on operation), if available; if not available | |
43 | * may return {@code null}. | |
44 | *<p> | |
45 | * Accuracy of location information depends on backend (format) as well | |
46 | * as (in some cases) operation being performed. | |
47 | */ | |
48 | public abstract JsonLocation getLocation(); | |
49 | ||
50 | /** | |
51 | * Method that allows accessing the original "message" argument, | |
52 | * without additional decorations (like location information) | |
53 | * that overridden {@link #getMessage} adds. | |
54 | */ | |
55 | public abstract String getOriginalMessage(); | |
56 | ||
57 | /** | |
58 | * Method that allows accessing underlying processor that triggered | |
59 | * this exception; typically either {@link JsonParser} or {@link JsonGenerator} | |
60 | * for exceptions that originate from streaming API, but other abstractions | |
61 | * when thrown by databinding. | |
62 | *<p> | |
63 | * Note that it is possible that `null` may be returned if code throwing | |
64 | * exception either has no access to processor; or has not been retrofitted | |
65 | * to set it; this means that caller needs to take care to check for nulls. | |
66 | * Subtypes override this method with co-variant return type, for more | |
67 | * type-safe access. | |
68 | * | |
69 | * @return Originating processor, if available; null if not. | |
70 | */ | |
71 | public abstract Object getProcessor(); | |
72 | } |
17 | 17 | import com.fasterxml.jackson.core.util.BufferRecycler; |
18 | 18 | import com.fasterxml.jackson.core.util.BufferRecyclers; |
19 | 19 | import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; |
20 | import com.fasterxml.jackson.core.util.JacksonFeature; | |
20 | 21 | |
21 | 22 | /** |
22 | 23 | * The main factory class of Jackson package, used to configure and |
56 | 57 | * Enumeration that defines all on/off features that can only be |
57 | 58 | * changed for {@link JsonFactory}. |
58 | 59 | */ |
59 | public enum Feature { | |
60 | ||
60 | public enum Feature | |
61 | implements JacksonFeature // since 2.12 | |
62 | { | |
61 | 63 | // // // Symbol handling (interning etc) |
62 | 64 | |
63 | 65 | /** |
111 | 113 | * but may not make sense on platforms where {@link SoftReference} handling |
112 | 114 | * is broken (like Android), or if there are retention issues due to |
113 | 115 | * {@link ThreadLocal} (see |
114 | * <a href="https://github.com/FasterXML/jackson-core/issues/189">Issue #189</a> | |
116 | * <a href="https://github.com/FasterXML/jackson-core/issues/189">jackson-core#189</a> | |
115 | 117 | * for a possible case) |
116 | 118 | *<p> |
117 | 119 | * This setting is enabled by default. |
140 | 142 | } |
141 | 143 | |
142 | 144 | private Feature(boolean defaultState) { _defaultState = defaultState; } |
143 | ||
145 | ||
146 | @Override | |
144 | 147 | public boolean enabledByDefault() { return _defaultState; } |
148 | @Override | |
145 | 149 | public boolean enabledIn(int flags) { return (flags & getMask()) != 0; } |
150 | @Override | |
146 | 151 | public int getMask() { return (1 << ordinal()); } |
147 | 152 | } |
148 | 153 |
12 | 12 | public class JsonGenerationException |
13 | 13 | extends JsonProcessingException |
14 | 14 | { |
15 | private final static long serialVersionUID = 123; // Stupid eclipse... | |
15 | private final static long serialVersionUID = 123; // eclipse complains otherwise | |
16 | 16 | |
17 | 17 | // transient since 2.7.4 |
18 | 18 | protected transient JsonGenerator _processor; |
14 | 14 | import com.fasterxml.jackson.core.io.CharacterEscapes; |
15 | 15 | import com.fasterxml.jackson.core.type.WritableTypeId; |
16 | 16 | import com.fasterxml.jackson.core.type.WritableTypeId.Inclusion; |
17 | import com.fasterxml.jackson.core.util.JacksonFeatureSet; | |
17 | 18 | import com.fasterxml.jackson.core.util.VersionUtil; |
18 | 19 | |
19 | 20 | import static com.fasterxml.jackson.core.JsonTokenId.*; |
28 | 29 | public abstract class JsonGenerator |
29 | 30 | implements Closeable, Flushable, Versioned |
30 | 31 | { |
32 | /** | |
33 | * Default set of {@link StreamReadCapability}ies that may be used as | |
34 | * basis for format-specific readers (or as bogus instance if non-null | |
35 | * set needs to be passed). | |
36 | * | |
37 | * @since 2.12 | |
38 | */ | |
39 | protected final static JacksonFeatureSet<StreamWriteCapability> DEFAULT_WRITE_CAPABILITIES | |
40 | = JacksonFeatureSet.fromDefaults(StreamWriteCapability.values()); | |
41 | ||
42 | /** | |
43 | * Default set of {@link StreamReadCapability}ies for typical textual formats, | |
44 | * to use either as-is, or as a base with possible differences. | |
45 | * | |
46 | * @since 2.12 | |
47 | */ | |
48 | protected final static JacksonFeatureSet<StreamWriteCapability> DEFAULT_TEXTUAL_WRITE_CAPABILITIES | |
49 | = DEFAULT_WRITE_CAPABILITIES.with(StreamWriteCapability.CAN_WRITE_FORMATTED_NUMBERS); | |
50 | ||
51 | /** | |
52 | * Default set of {@link StreamReadCapability}ies for typical binary formats, | |
53 | * to use either as-is, or as a base with possible differences. | |
54 | * | |
55 | * @since 2.12 | |
56 | */ | |
57 | protected final static JacksonFeatureSet<StreamWriteCapability> DEFAULT_BINARY_WRITE_CAPABILITIES | |
58 | = DEFAULT_WRITE_CAPABILITIES.with(StreamWriteCapability.CAN_WRITE_BINARY_NATIVELY); | |
59 | ||
31 | 60 | /** |
32 | 61 | * Enumeration that defines all togglable features for generators. |
33 | 62 | */ |
633 | 662 | ctxt.setCurrentValue(v); |
634 | 663 | } |
635 | 664 | } |
636 | ||
665 | ||
637 | 666 | /* |
638 | 667 | /********************************************************** |
639 | 668 | /* Public API, capability introspection methods |
718 | 747 | */ |
719 | 748 | public boolean canWriteFormattedNumbers() { return false; } |
720 | 749 | |
750 | /** | |
751 | * Accessor for getting metadata on capabilities of this parser, based on | |
752 | * underlying data format being read (directly or indirectly). | |
753 | * | |
754 | * @return Set of read capabilities for content to read via this parser | |
755 | * | |
756 | * @since 2.12 | |
757 | */ | |
758 | public JacksonFeatureSet<StreamWriteCapability> getWriteCapabilities() { | |
759 | return DEFAULT_WRITE_CAPABILITIES; | |
760 | } | |
761 | ||
721 | 762 | /* |
722 | 763 | /********************************************************** |
723 | 764 | /* Public API, write methods, structural |
735 | 776 | */ |
736 | 777 | public abstract void writeStartArray() throws IOException; |
737 | 778 | |
738 | // TODO: deprecate in 2.11 (remove from 3.0) | |
739 | 779 | /** |
740 | 780 | * Method for writing start marker of an Array value, similar |
741 | 781 | * to {@link #writeStartArray()}, but also specifying how many |
750 | 790 | * this is the case. |
751 | 791 | * |
752 | 792 | * @since 2.4 |
753 | */ | |
793 | * | |
794 | * @deprecated Since 2.12 Use {@link #writeStartArray(Object, int)} instead | |
795 | */ | |
796 | @Deprecated | |
754 | 797 | public void writeStartArray(int size) throws IOException { |
755 | 798 | writeStartArray(); |
756 | 799 | } |
12 | 12 | import com.fasterxml.jackson.core.async.NonBlockingInputFeeder; |
13 | 13 | import com.fasterxml.jackson.core.exc.InputCoercionException; |
14 | 14 | import com.fasterxml.jackson.core.type.TypeReference; |
15 | import com.fasterxml.jackson.core.util.JacksonFeatureSet; | |
15 | 16 | import com.fasterxml.jackson.core.util.RequestPayload; |
16 | 17 | |
17 | 18 | /** |
38 | 39 | public enum NumberType { |
39 | 40 | INT, LONG, BIG_INTEGER, FLOAT, DOUBLE, BIG_DECIMAL |
40 | 41 | }; |
42 | ||
43 | /** | |
44 | * Default set of {@link StreamReadCapability}ies that may be used as | |
45 | * basis for format-specific readers (or as bogus instance if non-null | |
46 | * set needs to be passed). | |
47 | * | |
48 | * @since 2.12 | |
49 | */ | |
50 | protected final static JacksonFeatureSet<StreamReadCapability> DEFAULT_READ_CAPABILITIES | |
51 | = JacksonFeatureSet.fromDefaults(StreamReadCapability.values()); | |
41 | 52 | |
42 | 53 | /** |
43 | 54 | * Enumeration that defines all on/off features for parsers. |
542 | 553 | * Access mode is determined by earlier calls via {@link JsonFactory}; |
543 | 554 | * it may not be changed after construction. |
544 | 555 | *<p> |
545 | * If non-blocking decoding is u (@code true}, it is possible to call | |
556 | * If non-blocking decoding is (@code true}, it is possible to call | |
546 | 557 | * {@link #getNonBlockingInputFeeder()} to obtain object to use |
547 | 558 | * for feeding input; otherwise (<code>false</code> returned) |
548 | 559 | * input is read by blocking |
560 | 571 | */ |
561 | 572 | public NonBlockingInputFeeder getNonBlockingInputFeeder() { |
562 | 573 | return null; |
574 | } | |
575 | ||
576 | /** | |
577 | * Accessor for getting metadata on capabilities of this parser, based on | |
578 | * underlying data format being read (directly or indirectly). | |
579 | * | |
580 | * @return Set of read capabilities for content to read via this parser | |
581 | * | |
582 | * @since 2.12 | |
583 | */ | |
584 | public JacksonFeatureSet<StreamReadCapability> getReadCapabilities() { | |
585 | return DEFAULT_READ_CAPABILITIES; | |
563 | 586 | } |
564 | 587 | |
565 | 588 | /* |
1008 | 1031 | } |
1009 | 1032 | |
1010 | 1033 | /** |
1011 | * Alias for {@link #currentToken()}, will be deprecated in Jackson 2.9 | |
1034 | * Alias for {@link #currentToken()}, may be deprecated sometime after | |
1035 | * Jackson 2.12 (will be removed from 3.0). | |
1012 | 1036 | */ |
1013 | 1037 | public abstract JsonToken getCurrentToken(); |
1014 | 1038 | |
1015 | 1039 | /** |
1016 | * Alias for {@link #currentTokenId()}, will be deprecated in Jackson 2.9 | |
1017 | */ | |
1040 | * Alias for {@link #currentTokenId()}. | |
1041 | * | |
1042 | * @deprecated Since 2.12 use {@link #currentTokenId} instead | |
1043 | */ | |
1044 | @Deprecated | |
1018 | 1045 | public abstract int getCurrentTokenId(); |
1019 | ||
1046 | ||
1020 | 1047 | /** |
1021 | 1048 | * Method for checking whether parser currently points to |
1022 | 1049 | * a token (and data for that token is available). |
1089 | 1116 | */ |
1090 | 1117 | public boolean isExpectedStartObjectToken() { return currentToken() == JsonToken.START_OBJECT; } |
1091 | 1118 | |
1119 | /** | |
1120 | * Similar to {@link #isExpectedStartArrayToken()}, but checks whether stream | |
1121 | * currently points to {@link JsonToken#VALUE_NUMBER_INT}. | |
1122 | *<p> | |
1123 | * The initial use case is for XML backend to efficiently (attempt to) coerce | |
1124 | * textual content into numbers. | |
1125 | * | |
1126 | * @since 2.12 | |
1127 | */ | |
1128 | public boolean isExpectedNumberIntToken() { return currentToken() == JsonToken.VALUE_NUMBER_INT; } | |
1129 | ||
1092 | 1130 | /** |
1093 | 1131 | * Access for checking whether current token is a numeric value token, but |
1094 | 1132 | * one that is of "not-a-number" (NaN) variety (including both "NaN" AND |
1276 | 1314 | * all kinds of numeric values. It will return the optimal |
1277 | 1315 | * (simplest/smallest possible) wrapper object that can |
1278 | 1316 | * express the numeric value just parsed. |
1317 | * | |
1318 | * @return Numeric value of the current token in its most optimal | |
1319 | * representation | |
1320 | * | |
1321 | * @throws IOException Problem with access: {@link JsonParseException} if | |
1322 | * the current token is not numeric, or if decoding of the value fails | |
1323 | * (invalid format for numbers); plain {@link IOException} if underlying | |
1324 | * content read fails (possible if values are extracted lazily) | |
1279 | 1325 | */ |
1280 | 1326 | public abstract Number getNumberValue() throws IOException; |
1327 | ||
1328 | /** | |
1329 | * Method similar to {@link #getNumberValue} with the difference that | |
1330 | * for floating-point numbers value returned may be {@link BigDecimal} | |
1331 | * if the underlying format does not store floating-point numbers using | |
1332 | * native representation: for example, textual formats represent numbers | |
1333 | * as Strings (which are 10-based), and conversion to {@link java.lang.Double} | |
1334 | * is potentially lossy operation. | |
1335 | *<p> | |
1336 | * Default implementation simply returns {@link #getNumberValue()} | |
1337 | * | |
1338 | * @return Numeric value of the current token using most accurate representation | |
1339 | * | |
1340 | * @throws IOException Problem with access: {@link JsonParseException} if | |
1341 | * the current token is not numeric, or if decoding of the value fails | |
1342 | * (invalid format for numbers); plain {@link IOException} if underlying | |
1343 | * content read fails (possible if values are extracted lazily) | |
1344 | * | |
1345 | * @since 2.12 | |
1346 | */ | |
1347 | public Number getNumberValueExact() throws IOException { | |
1348 | return getNumberValue(); | |
1349 | } | |
1281 | 1350 | |
1282 | 1351 | /** |
1283 | 1352 | * If current token is of type |
1297 | 1366 | * exception. |
1298 | 1367 | *<p> |
1299 | 1368 | * Note: if the resulting integer value falls outside range of |
1300 | * Java byte, a {@link JsonParseException} | |
1369 | * Java byte, a {@link InputCoercionException} | |
1301 | 1370 | * will be thrown to indicate numeric overflow/underflow. |
1302 | 1371 | */ |
1303 | 1372 | public byte getByteValue() throws IOException { |
1323 | 1392 | * exception. |
1324 | 1393 | *<p> |
1325 | 1394 | * Note: if the resulting integer value falls outside range of |
1326 | * Java short, a {@link JsonParseException} | |
1395 | * Java short, a {@link InputCoercionException} | |
1327 | 1396 | * will be thrown to indicate numeric overflow/underflow. |
1328 | 1397 | */ |
1329 | 1398 | public short getShortValue() throws IOException |
1347 | 1416 | * exception. |
1348 | 1417 | *<p> |
1349 | 1418 | * Note: if the resulting integer value falls outside range of |
1350 | * Java int, a {@link JsonParseException} | |
1419 | * Java int, a {@link InputCoercionException} | |
1351 | 1420 | * may be thrown to indicate numeric overflow/underflow. |
1352 | 1421 | */ |
1353 | 1422 | public abstract int getIntValue() throws IOException; |
1362 | 1431 | * exception. |
1363 | 1432 | *<p> |
1364 | 1433 | * Note: if the token is an integer, but its value falls |
1365 | * outside of range of Java long, a {@link JsonParseException} | |
1434 | * outside of range of Java long, a {@link InputCoercionException} | |
1366 | 1435 | * may be thrown to indicate numeric overflow/underflow. |
1367 | 1436 | */ |
1368 | 1437 | public abstract long getLongValue() throws IOException; |
1388 | 1457 | * exception. |
1389 | 1458 | *<p> |
1390 | 1459 | * Note: if the value falls |
1391 | * outside of range of Java float, a {@link JsonParseException} | |
1460 | * outside of range of Java float, a {@link InputCoercionException} | |
1392 | 1461 | * will be thrown to indicate numeric overflow/underflow. |
1393 | 1462 | */ |
1394 | 1463 | public abstract float getFloatValue() throws IOException; |
1403 | 1472 | * exception. |
1404 | 1473 | *<p> |
1405 | 1474 | * Note: if the value falls |
1406 | * outside of range of Java double, a {@link JsonParseException} | |
1475 | * outside of range of Java double, a {@link InputCoercionException} | |
1407 | 1476 | * will be thrown to indicate numeric overflow/underflow. |
1408 | 1477 | */ |
1409 | 1478 | public abstract double getDoubleValue() throws IOException; |
1489 | 1558 | * Convenience alternative to {@link #getBinaryValue(Base64Variant)} |
1490 | 1559 | * that defaults to using |
1491 | 1560 | * {@link Base64Variants#getDefaultVariant} as the default encoding. |
1561 | * | |
1562 | * @return Decoded binary data | |
1492 | 1563 | */ |
1493 | 1564 | public byte[] getBinaryValue() throws IOException { |
1494 | 1565 | return getBinaryValue(Base64Variants.getDefaultVariant()); |
10 | 10 | * that are not pure I/O problems. |
11 | 11 | * Regular {@link java.io.IOException}s will be passed through as is. |
12 | 12 | * Sub-class of {@link java.io.IOException} for convenience. |
13 | *<p> | |
14 | * Since Jackson 2.12 extends intermediate {@link JacksonException} type | |
15 | * instead of directly extending {@link java.io.IOException} | |
13 | 16 | */ |
14 | public class JsonProcessingException extends java.io.IOException | |
17 | public class JsonProcessingException extends JacksonException | |
15 | 18 | { |
16 | final static long serialVersionUID = 123; // Stupid eclipse... | |
17 | ||
19 | private final static long serialVersionUID = 123; // eclipse complains otherwise | |
20 | ||
18 | 21 | protected JsonLocation _location; |
19 | 22 | |
20 | 23 | protected JsonProcessingException(String msg, JsonLocation loc, Throwable rootCause) { |
21 | super(msg); | |
22 | if (rootCause != null) { | |
23 | initCause(rootCause); | |
24 | } | |
24 | super(msg, rootCause); | |
25 | 25 | _location = loc; |
26 | 26 | } |
27 | 27 | |
47 | 47 | /********************************************************** |
48 | 48 | */ |
49 | 49 | |
50 | @Override | |
50 | 51 | public JsonLocation getLocation() { return _location; } |
51 | ||
52 | ||
52 | 53 | /** |
53 | 54 | * Method that allows to remove context information from this exception's message. |
54 | 55 | * Useful when you are parsing security-sensitive data and don't want original data excerpts |
65 | 66 | * |
66 | 67 | * @since 2.1 |
67 | 68 | */ |
69 | @Override | |
68 | 70 | public String getOriginalMessage() { return super.getMessage(); } |
69 | 71 | |
70 | 72 | /** |
81 | 83 | * |
82 | 84 | * @since 2.7 |
83 | 85 | */ |
86 | @Override | |
84 | 87 | public Object getProcessor() { return null; } |
85 | 88 | |
86 | 89 | /* |
19 | 19 | public abstract class JsonStreamContext |
20 | 20 | { |
21 | 21 | // // // Type constants used internally |
22 | ||
23 | protected final static int TYPE_ROOT = 0; | |
24 | protected final static int TYPE_ARRAY = 1; | |
25 | protected final static int TYPE_OBJECT = 2; | |
26 | ||
22 | // // // (but exposed publicly as of 2.12 as possibly needed) | |
23 | ||
24 | /** | |
25 | * Indicator for "Root Value" context (has not parent) | |
26 | */ | |
27 | public final static int TYPE_ROOT = 0; | |
28 | ||
29 | /** | |
30 | * Indicator for "Array" context. | |
31 | */ | |
32 | public final static int TYPE_ARRAY = 1; | |
33 | ||
34 | /** | |
35 | * Indicator for "Object" context. | |
36 | */ | |
37 | public final static int TYPE_OBJECT = 2; | |
38 | ||
39 | /** | |
40 | * Indicates logical type of context as one of {@code TYPE_xxx} consants. | |
41 | */ | |
27 | 42 | protected int _type; |
28 | 43 | |
29 | 44 | /** |
0 | package com.fasterxml.jackson.core; | |
1 | ||
2 | import com.fasterxml.jackson.core.util.JacksonFeature; | |
3 | ||
4 | /** | |
5 | * Set of on/off capabilities that a {@link JsonParser} for given format | |
6 | * (or in case of buffering, original format) has. | |
7 | * Used in some cases to adjust aspects of things like content conversions, | |
8 | * coercions and validation by format-agnostic functionality. | |
9 | * Specific or expected usage documented by individual capability entry | |
10 | * Javadocs. | |
11 | * | |
12 | * @since 2.12 | |
13 | */ | |
14 | public enum StreamReadCapability | |
15 | implements JacksonFeature | |
16 | { | |
17 | /** | |
18 | * Capability that indicates that data format can expose multiple properties | |
19 | * with same name ("duplicates") within one Object context. | |
20 | * This is usually not enabled, except for formats like {@code xml} that | |
21 | * have content model that does not map cleanly to JSON-based token stream. | |
22 | *<p> | |
23 | * Capability may be used for allowing secondary mapping of such duplicates | |
24 | * in case of using Tree Model (see {@link TreeNode}), or "untyped" databinding | |
25 | * (mapping content as generic {@link java.lang.Object}). | |
26 | *<p> | |
27 | * Capability is currently only enabled for XML format backend. | |
28 | */ | |
29 | DUPLICATE_PROPERTIES(false), | |
30 | ||
31 | /** | |
32 | * Capability that indicates that data format may in some cases expose Scalar values | |
33 | * (whether typed or untyped) as Object values. There are additional access methods | |
34 | * at databind level: this capability may be used to decide whether to attempt to | |
35 | * use such methods especially in potentially ambiguous cases. | |
36 | *<p> | |
37 | * Capability is currently only enabled for XML format backend. | |
38 | */ | |
39 | SCALARS_AS_OBJECTS(false), | |
40 | ||
41 | /** | |
42 | * Capability that indicates that data format only exposed "untyped" scalars: that is, | |
43 | * instead of Number, Boolean and String types all scalar values are reported as | |
44 | * text ({@link JsonToken#VALUE_STRING}) | |
45 | * unless some sort of coercion is implied by caller. | |
46 | *<p> | |
47 | * This capability is true for many textual formats like CSV, Properties and XML. | |
48 | */ | |
49 | UNTYPED_SCALARS(false), | |
50 | ; | |
51 | ||
52 | /** | |
53 | * Whether feature is enabled or disabled by default. | |
54 | */ | |
55 | private final boolean _defaultState; | |
56 | ||
57 | private final int _mask; | |
58 | ||
59 | private StreamReadCapability(boolean defaultState) { | |
60 | _defaultState = defaultState; | |
61 | _mask = (1 << ordinal()); | |
62 | } | |
63 | ||
64 | @Override | |
65 | public boolean enabledByDefault() { return _defaultState; } | |
66 | @Override | |
67 | public boolean enabledIn(int flags) { return (flags & _mask) != 0; } | |
68 | @Override | |
69 | public int getMask() { return _mask; } | |
70 | } |
1 | 1 | |
2 | 2 | import java.io.InputStream; |
3 | 3 | import java.io.Reader; |
4 | ||
5 | import com.fasterxml.jackson.core.util.JacksonFeature; | |
4 | 6 | |
5 | 7 | /** |
6 | 8 | * Token reader (parser) features not-specific to any particular format backend. |
9 | 11 | * @since 2.10 |
10 | 12 | */ |
11 | 13 | public enum StreamReadFeature |
14 | implements JacksonFeature // since 2.12 | |
12 | 15 | { |
13 | 16 | // // // Low-level I/O handling features: |
14 | 17 | |
124 | 127 | return flags; |
125 | 128 | } |
126 | 129 | |
130 | @Override | |
127 | 131 | public boolean enabledByDefault() { return _defaultState; } |
132 | @Override | |
128 | 133 | public boolean enabledIn(int flags) { return (flags & _mask) != 0; } |
134 | @Override | |
129 | 135 | public int getMask() { return _mask; } |
130 | 136 | |
131 | 137 | public JsonParser.Feature mappedFeature() { return _mappedFeature; } |
0 | package com.fasterxml.jackson.core; | |
1 | ||
2 | import com.fasterxml.jackson.core.util.JacksonFeature; | |
3 | ||
4 | /** | |
5 | * Set of on/off capabilities that a {@link JsonGenerator} for given format | |
6 | * (or in case of buffering, original format) has. | |
7 | * Used in some cases to adjust aspects of things like content conversions and | |
8 | * coercions by format-agnostic functionality. | |
9 | * Specific or expected usage documented by individual capability entry Javadocs. | |
10 | * | |
11 | * @since 2.12 | |
12 | */ | |
13 | public enum StreamWriteCapability | |
14 | implements JacksonFeature | |
15 | { | |
16 | /** | |
17 | * Capability that indicates that the data format is able to express binary | |
18 | * data natively, without using textual encoding like Base64. | |
19 | *<p> | |
20 | * Capability is currently enabled for all binary formats and none of textual | |
21 | * formats. | |
22 | */ | |
23 | CAN_WRITE_BINARY_NATIVELY(false), | |
24 | ||
25 | /** | |
26 | * Capability that indicates that the data format is able to write | |
27 | * "formatted numbers": that is, output of numbers is done as Strings | |
28 | * and caller is allowed to pass in logical number values as Strings. | |
29 | *<p> | |
30 | * Capability is currently enabled for most textual formats and none of binary | |
31 | * formats. | |
32 | */ | |
33 | CAN_WRITE_FORMATTED_NUMBERS(false) | |
34 | ; | |
35 | ||
36 | /** | |
37 | * Whether feature is enabled or disabled by default. | |
38 | */ | |
39 | private final boolean _defaultState; | |
40 | ||
41 | private final int _mask; | |
42 | ||
43 | private StreamWriteCapability(boolean defaultState) { | |
44 | _defaultState = defaultState; | |
45 | _mask = (1 << ordinal()); | |
46 | } | |
47 | ||
48 | @Override | |
49 | public boolean enabledByDefault() { return _defaultState; } | |
50 | @Override | |
51 | public boolean enabledIn(int flags) { return (flags & _mask) != 0; } | |
52 | @Override | |
53 | public int getMask() { return _mask; } | |
54 | } |
2 | 2 | import java.io.OutputStream; |
3 | 3 | import java.io.Writer; |
4 | 4 | import java.math.BigDecimal; |
5 | ||
6 | import com.fasterxml.jackson.core.util.JacksonFeature; | |
5 | 7 | |
6 | 8 | /** |
7 | 9 | * Token writer (generator) features not-specific to any particular format backend. |
10 | 12 | * @since 2.10 |
11 | 13 | */ |
12 | 14 | public enum StreamWriteFeature |
15 | implements JacksonFeature // since 2.12 | |
13 | 16 | { |
14 | 17 | // // Low-level I/O / content features |
15 | 18 | |
143 | 146 | return flags; |
144 | 147 | } |
145 | 148 | |
149 | @Override | |
146 | 150 | public boolean enabledByDefault() { return _defaultState; } |
151 | @Override | |
147 | 152 | public boolean enabledIn(int flags) { return (flags & _mask) != 0; } |
153 | @Override | |
148 | 154 | public int getMask() { return _mask; } |
149 | 155 | |
150 | 156 | public JsonGenerator.Feature mappedFeature() { return _mappedFeature; } |
71 | 71 | /** |
72 | 72 | * Flag set to indicate that implicit conversion from number |
73 | 73 | * to JSON String is needed (as per |
74 | * {@link com.fasterxml.jackson.core.JsonGenerator.Feature#WRITE_NUMBERS_AS_STRINGS}). | |
74 | * {@link com.fasterxml.jackson.core.json.JsonWriteFeature#WRITE_NUMBERS_AS_STRINGS}). | |
75 | 75 | */ |
76 | 76 | protected boolean _cfgNumbersAsStrings; |
77 | 77 |
5 | 5 | import java.util.Arrays; |
6 | 6 | |
7 | 7 | import com.fasterxml.jackson.core.*; |
8 | import com.fasterxml.jackson.core.JsonParser.Feature; | |
9 | 8 | import com.fasterxml.jackson.core.io.IOContext; |
10 | 9 | import com.fasterxml.jackson.core.io.NumberInput; |
11 | 10 | import com.fasterxml.jackson.core.json.DupDetector; |
12 | 11 | import com.fasterxml.jackson.core.json.JsonReadContext; |
13 | 12 | import com.fasterxml.jackson.core.json.PackageVersion; |
14 | 13 | import com.fasterxml.jackson.core.util.ByteArrayBuilder; |
14 | import com.fasterxml.jackson.core.util.JacksonFeatureSet; | |
15 | 15 | import com.fasterxml.jackson.core.util.TextBuffer; |
16 | 16 | |
17 | 17 | /** |
21 | 21 | */ |
22 | 22 | public abstract class ParserBase extends ParserMinimalBase |
23 | 23 | { |
24 | // JSON capabilities are the same as defaults | |
25 | // @since 2.12 | |
26 | protected final static JacksonFeatureSet<StreamReadCapability> JSON_READ_CAPABILITIES | |
27 | = DEFAULT_READ_CAPABILITIES; | |
28 | ||
24 | 29 | /* |
25 | 30 | /********************************************************** |
26 | 31 | /* Generic I/O state |
349 | 354 | if (_currToken == JsonToken.START_OBJECT || _currToken == JsonToken.START_ARRAY) { |
350 | 355 | ctxt = ctxt.getParent(); |
351 | 356 | } |
352 | /* 24-Sep-2013, tatu: Unfortunate, but since we did not expose exceptions, | |
353 | * need to wrap this here | |
354 | */ | |
357 | // 24-Sep-2013, tatu: Unfortunate, but since we did not expose exceptions, | |
358 | // need to wrap this here | |
355 | 359 | try { |
356 | 360 | ctxt.setCurrentName(name); |
357 | 361 | } catch (IOException e) { |
575 | 579 | /* Numeric accessors of public API |
576 | 580 | /********************************************************** |
577 | 581 | */ |
578 | ||
582 | ||
579 | 583 | @Override |
580 | 584 | public Number getNumberValue() throws IOException |
581 | 585 | { |
593 | 597 | if ((_numTypesValid & NR_BIGINT) != 0) { |
594 | 598 | return _numberBigInt; |
595 | 599 | } |
596 | // Shouldn't get this far but if we do | |
597 | return _numberBigDecimal; | |
598 | } | |
599 | ||
600 | /* And then floating point types. But here optimal type | |
601 | * needs to be big decimal, to avoid losing any data? | |
602 | */ | |
600 | _throwInternal(); | |
601 | } | |
602 | ||
603 | // And then floating point types. But here optimal type | |
604 | // needs to be big decimal, to avoid losing any data? | |
603 | 605 | if ((_numTypesValid & NR_BIGDECIMAL) != 0) { |
604 | 606 | return _numberBigDecimal; |
605 | 607 | } |
608 | 610 | } |
609 | 611 | return _numberDouble; |
610 | 612 | } |
611 | ||
613 | ||
614 | // NOTE: mostly copied from above | |
615 | @Override | |
616 | public Number getNumberValueExact() throws IOException | |
617 | { | |
618 | if (_currToken == JsonToken.VALUE_NUMBER_INT) { | |
619 | if (_numTypesValid == NR_UNKNOWN) { | |
620 | _parseNumericValue(NR_UNKNOWN); | |
621 | } | |
622 | if ((_numTypesValid & NR_INT) != 0) { | |
623 | return _numberInt; | |
624 | } | |
625 | if ((_numTypesValid & NR_LONG) != 0) { | |
626 | return _numberLong; | |
627 | } | |
628 | if ((_numTypesValid & NR_BIGINT) != 0) { | |
629 | return _numberBigInt; | |
630 | } | |
631 | _throwInternal(); | |
632 | } | |
633 | // 09-Jul-2020, tatu: [databind#2644] requires we will retain accuracy, so: | |
634 | if (_numTypesValid == NR_UNKNOWN) { | |
635 | _parseNumericValue(NR_BIGDECIMAL); | |
636 | } | |
637 | if ((_numTypesValid & NR_BIGDECIMAL) != 0) { | |
638 | return _numberBigDecimal; | |
639 | } | |
640 | if ((_numTypesValid & NR_DOUBLE) == 0) { // sanity check | |
641 | _throwInternal(); | |
642 | } | |
643 | return _numberDouble; | |
644 | } | |
645 | ||
612 | 646 | @Override |
613 | 647 | public NumberType getNumberType() throws IOException |
614 | 648 | { |
727 | 761 | /* Conversion from textual to numeric representation |
728 | 762 | /********************************************************** |
729 | 763 | */ |
730 | ||
764 | ||
731 | 765 | /** |
732 | 766 | * Method that will parse actual numeric value out of a syntactically |
733 | 767 | * valid number value. Type it will parse into depends on whether |
739 | 773 | */ |
740 | 774 | protected void _parseNumericValue(int expType) throws IOException |
741 | 775 | { |
776 | // 12-Jun-2020, tatu: Sanity check to prevent more cryptic error for this case. | |
777 | // (note: could alternatively see if TextBuffer has aggregated contents, avoid | |
778 | // exception -- but that might be more confusing) | |
779 | if (_closed) { | |
780 | _reportError("Internal error: _parseNumericValue called when parser instance closed"); | |
781 | } | |
782 | ||
742 | 783 | // Int or float? |
743 | 784 | if (_currToken == JsonToken.VALUE_NUMBER_INT) { |
744 | int len = _intLength; | |
785 | final int len = _intLength; | |
745 | 786 | // First: optimization for simple int |
746 | if (len <= 9) { | |
787 | if (len <= 9) { | |
747 | 788 | int i = _textBuffer.contentsAsInt(_numberNegative); |
748 | 789 | _numberInt = i; |
749 | 790 | _numTypesValid = NR_INT; |
786 | 827 | */ |
787 | 828 | protected int _parseIntValue() throws IOException |
788 | 829 | { |
830 | // 12-Jun-2020, tatu: Sanity check to prevent more cryptic error for this case. | |
831 | // (note: could alternatively see if TextBuffer has aggregated contents, avoid | |
832 | // exception -- but that might be more confusing) | |
833 | if (_closed) { | |
834 | _reportError("Internal error: _parseNumericValue called when parser instance closed"); | |
835 | } | |
789 | 836 | // Inlined variant of: _parseNumericValue(NR_INT) |
790 | 837 | if (_currToken == JsonToken.VALUE_NUMBER_INT) { |
791 | 838 | if (_intLength <= 9) { |
1034 | 1081 | /** |
1035 | 1082 | * Method called to report a problem with unquoted control character. |
1036 | 1083 | * Note: it is possible to suppress some instances of |
1037 | * exception by enabling {@link Feature#ALLOW_UNQUOTED_CONTROL_CHARS}. | |
1084 | * exception by enabling | |
1085 | * {@link com.fasterxml.jackson.core.json.JsonReadFeature#ALLOW_UNESCAPED_CONTROL_CHARS}. | |
1038 | 1086 | */ |
1039 | 1087 | @SuppressWarnings("deprecation") |
1040 | 1088 | protected void _throwUnquotedSpace(int i, String ctxtDesc) throws JsonParseException { |
187 | 187 | final JsonToken t = _currToken; |
188 | 188 | return (t == null) ? JsonTokenId.ID_NO_TOKEN : t.id(); |
189 | 189 | } |
190 | ||
190 | ||
191 | 191 | @Override public JsonToken getCurrentToken() { return _currToken; } |
192 | ||
193 | @Deprecated | |
192 | 194 | @Override public int getCurrentTokenId() { |
193 | 195 | final JsonToken t = _currToken; |
194 | 196 | return (t == null) ? JsonTokenId.ID_NO_TOKEN : t.id(); |
209 | 211 | |
210 | 212 | @Override public boolean isExpectedStartArrayToken() { return _currToken == JsonToken.START_ARRAY; } |
211 | 213 | @Override public boolean isExpectedStartObjectToken() { return _currToken == JsonToken.START_OBJECT; } |
212 | ||
214 | @Override public boolean isExpectedNumberIntToken() { return _currToken == JsonToken.VALUE_NUMBER_INT; } | |
215 | ||
213 | 216 | @Override |
214 | 217 | public JsonToken nextValue() throws IOException { |
215 | 218 | // Implementation should be as trivial as follows; only needs to change if |
547 | 550 | |
548 | 551 | /** |
549 | 552 | * Method called to throw an exception for integral (not floating point) input |
550 | * token with value outside of Java signed 32-bit range when requested as {@link int}. | |
553 | * token with value outside of Java signed 32-bit range when requested as {@code int}. | |
551 | 554 | * Result will be {@link InputCoercionException} being thrown. |
552 | 555 | */ |
553 | 556 | protected void reportOverflowInt() throws IOException { |
568 | 571 | |
569 | 572 | /** |
570 | 573 | * Method called to throw an exception for integral (not floating point) input |
571 | * token with value outside of Java signed 64-bit range when requested as {@link long}. | |
574 | * token with value outside of Java signed 64-bit range when requested as {@code long}. | |
572 | 575 | * Result will be {@link InputCoercionException} being thrown. |
573 | 576 | */ |
574 | 577 | protected void reportOverflowLong() throws IOException { |
6 | 6 | import java.math.BigInteger; |
7 | 7 | |
8 | 8 | import com.fasterxml.jackson.core.*; |
9 | import com.fasterxml.jackson.core.filter.TokenFilter.Inclusion; | |
9 | 10 | import com.fasterxml.jackson.core.util.JsonGeneratorDelegate; |
10 | 11 | |
11 | 12 | /** |
17 | 18 | */ |
18 | 19 | public class FilteringGeneratorDelegate extends JsonGeneratorDelegate |
19 | 20 | { |
21 | ||
20 | 22 | /* |
21 | 23 | /********************************************************** |
22 | 24 | /* Configuration |
44 | 46 | * done and only explicitly included entries are output; if `true` then |
45 | 47 | * path from main level down to match is also included as necessary. |
46 | 48 | */ |
47 | protected boolean _includePath; | |
48 | ||
49 | /* NOTE: this feature is included in the first version (2.6), but | |
50 | * there is no public API to enable it, yet, since there isn't an | |
51 | * actual use case. But it seemed possible need could arise, which | |
52 | * is feature has not yet been removed. If no use is found within | |
53 | * first version or two, just remove. | |
54 | * | |
55 | * Marked as deprecated since its status is uncertain. | |
56 | */ | |
57 | @Deprecated | |
58 | protected boolean _includeImmediateParent; | |
49 | protected TokenFilter.Inclusion _inclusion; | |
59 | 50 | |
60 | 51 | /* |
61 | 52 | /********************************************************** |
89 | 80 | /********************************************************** |
90 | 81 | */ |
91 | 82 | |
83 | /** | |
84 | * @deprecated since 2.12 Use the constructor that takes {@link TokenFilter.Inclusion} | |
85 | * argument instead. | |
86 | */ | |
87 | @Deprecated | |
92 | 88 | public FilteringGeneratorDelegate(JsonGenerator d, TokenFilter f, |
93 | 89 | boolean includePath, boolean allowMultipleMatches) |
90 | { | |
91 | this(d, f, includePath ? Inclusion.INCLUDE_ALL_AND_PATH : Inclusion.ONLY_INCLUDE_ALL, allowMultipleMatches); | |
92 | } | |
93 | ||
94 | /** | |
95 | * @since 2.12 | |
96 | */ | |
97 | public FilteringGeneratorDelegate(JsonGenerator d, TokenFilter f, | |
98 | TokenFilter.Inclusion inclusion, boolean allowMultipleMatches) | |
94 | 99 | { |
95 | 100 | // By default, do NOT delegate copy methods |
96 | 101 | super(d, false); |
98 | 103 | // and this is the currently active filter for root values |
99 | 104 | _itemFilter = f; |
100 | 105 | _filterContext = TokenFilterContext.createRootContext(f); |
101 | _includePath = includePath; | |
106 | _inclusion = inclusion; | |
102 | 107 | _allowMultipleMatches = allowMultipleMatches; |
103 | 108 | } |
104 | 109 | |
169 | 174 | _checkParentPath(); |
170 | 175 | _filterContext = _filterContext.createChildArrayContext(_itemFilter, true); |
171 | 176 | delegate.writeStartArray(); |
177 | } else if (_itemFilter != null && _inclusion == Inclusion.INCLUDE_NON_NULL) { | |
178 | _checkParentPath(false /* isMatch */); | |
179 | _filterContext = _filterContext.createChildArrayContext(_itemFilter, true); | |
180 | delegate.writeStartArray(); | |
172 | 181 | } else { |
173 | 182 | _filterContext = _filterContext.createChildArrayContext(_itemFilter, false); |
174 | 183 | } |
175 | 184 | } |
176 | 185 | |
186 | @SuppressWarnings("deprecation") | |
177 | 187 | @Override |
178 | 188 | public void writeStartArray(int size) throws IOException |
179 | 189 | { |
196 | 206 | } |
197 | 207 | if (_itemFilter == TokenFilter.INCLUDE_ALL) { |
198 | 208 | _checkParentPath(); |
209 | _filterContext = _filterContext.createChildArrayContext(_itemFilter, true); | |
210 | delegate.writeStartArray(size); | |
211 | } else if (_itemFilter != null && _inclusion == Inclusion.INCLUDE_NON_NULL) { | |
212 | _checkParentPath(false /* isMatch */); | |
199 | 213 | _filterContext = _filterContext.createChildArrayContext(_itemFilter, true); |
200 | 214 | delegate.writeStartArray(size); |
201 | 215 | } else { |
296 | 310 | _checkParentPath(); |
297 | 311 | _filterContext = _filterContext.createChildObjectContext(f, true); |
298 | 312 | delegate.writeStartObject(); |
313 | } else if (f != null && _inclusion == Inclusion.INCLUDE_NON_NULL) { | |
314 | _checkParentPath(false /* isMatch */); | |
315 | _filterContext = _filterContext.createChildObjectContext(f, true); | |
316 | delegate.writeStartObject(); | |
299 | 317 | } else { // filter out |
300 | 318 | _filterContext = _filterContext.createChildObjectContext(f, false); |
301 | 319 | } |
324 | 342 | } |
325 | 343 | if (f == TokenFilter.INCLUDE_ALL) { |
326 | 344 | _checkParentPath(); |
345 | _filterContext = _filterContext.createChildObjectContext(f, true); | |
346 | delegate.writeStartObject(forValue); | |
347 | } else if (f != null && _inclusion == Inclusion.INCLUDE_NON_NULL) { | |
348 | _checkParentPath(false /* isMatch */); | |
327 | 349 | _filterContext = _filterContext.createChildObjectContext(f, true); |
328 | 350 | delegate.writeStartObject(forValue); |
329 | 351 | } else { // filter out |
439 | 461 | } |
440 | 462 | } |
441 | 463 | _checkParentPath(); |
442 | } | |
464 | } | |
443 | 465 | delegate.writeString(value); |
444 | 466 | } |
445 | 467 | |
461 | 483 | } |
462 | 484 | } |
463 | 485 | _checkParentPath(); |
464 | } | |
486 | } | |
465 | 487 | delegate.writeString(text, offset, len); |
466 | 488 | } |
467 | 489 | |
482 | 504 | } |
483 | 505 | } |
484 | 506 | _checkParentPath(); |
485 | } | |
507 | } | |
486 | 508 | delegate.writeString(value); |
487 | 509 | } |
488 | 510 | |
635 | 657 | } |
636 | 658 | } |
637 | 659 | _checkParentPath(); |
638 | } | |
660 | } | |
639 | 661 | delegate.writeNumber(v); |
640 | 662 | } |
641 | 663 | |
656 | 678 | } |
657 | 679 | } |
658 | 680 | _checkParentPath(); |
659 | } | |
681 | } | |
660 | 682 | delegate.writeNumber(v); |
661 | 683 | } |
662 | 684 | |
677 | 699 | } |
678 | 700 | } |
679 | 701 | _checkParentPath(); |
680 | } | |
702 | } | |
681 | 703 | delegate.writeNumber(v); |
682 | 704 | } |
683 | 705 | |
698 | 720 | } |
699 | 721 | } |
700 | 722 | _checkParentPath(); |
701 | } | |
723 | } | |
702 | 724 | delegate.writeNumber(v); |
703 | 725 | } |
704 | 726 | |
719 | 741 | } |
720 | 742 | } |
721 | 743 | _checkParentPath(); |
722 | } | |
744 | } | |
723 | 745 | delegate.writeNumber(v); |
724 | 746 | } |
725 | 747 | |
740 | 762 | } |
741 | 763 | } |
742 | 764 | _checkParentPath(); |
743 | } | |
765 | } | |
744 | 766 | delegate.writeNumber(v); |
745 | 767 | } |
746 | 768 | |
761 | 783 | } |
762 | 784 | } |
763 | 785 | _checkParentPath(); |
764 | } | |
786 | } | |
765 | 787 | delegate.writeNumber(v); |
766 | 788 | } |
767 | 789 | |
824 | 846 | } |
825 | 847 | } |
826 | 848 | _checkParentPath(); |
827 | } | |
849 | } | |
828 | 850 | delegate.writeBoolean(v); |
829 | 851 | } |
830 | 852 | |
845 | 867 | } |
846 | 868 | } |
847 | 869 | _checkParentPath(); |
848 | } | |
870 | } | |
849 | 871 | delegate.writeNull(); |
850 | 872 | } |
851 | 873 | |
968 | 990 | |
969 | 991 | protected void _checkParentPath() throws IOException |
970 | 992 | { |
993 | _checkParentPath(true); | |
994 | } | |
995 | ||
996 | protected void _checkParentPath(boolean isMatch) throws IOException | |
997 | { | |
998 | if (isMatch) { | |
999 | ++_matchCount; | |
1000 | } | |
1001 | // only need to construct path if parent wasn't written | |
1002 | if (_inclusion == Inclusion.INCLUDE_ALL_AND_PATH) { | |
1003 | _filterContext.writePath(delegate); | |
1004 | } else if (_inclusion == Inclusion.INCLUDE_NON_NULL) { | |
1005 | // path has already been written, except for maybe field name | |
1006 | _filterContext.ensureFieldNameWritten(delegate); | |
1007 | } | |
1008 | // also: if no multiple matches desired, short-cut checks | |
1009 | if (isMatch && !_allowMultipleMatches) { | |
1010 | // Mark parents as "skip" so that further check calls are not made | |
1011 | _filterContext.skipParentChecks(); | |
1012 | } | |
1013 | } | |
1014 | ||
1015 | /** | |
1016 | * Specialized variant of {@link #_checkParentPath} used when checking | |
1017 | * parent for a property name to be included with value: rules are slightly | |
1018 | * different. | |
1019 | */ | |
1020 | protected void _checkPropertyParentPath() throws IOException | |
1021 | { | |
971 | 1022 | ++_matchCount; |
972 | // only need to construct path if parent wasn't written | |
973 | if (_includePath) { | |
1023 | if (_inclusion == Inclusion.INCLUDE_ALL_AND_PATH) { | |
974 | 1024 | _filterContext.writePath(delegate); |
975 | } | |
1025 | } else if (_inclusion == Inclusion.INCLUDE_NON_NULL) { | |
1026 | // path has already been written, except for maybe field name | |
1027 | _filterContext.ensureFieldNameWritten(delegate); | |
1028 | } | |
1029 | ||
976 | 1030 | // also: if no multiple matches desired, short-cut checks |
977 | 1031 | if (!_allowMultipleMatches) { |
978 | 1032 | // Mark parents as "skip" so that further check calls are not made |
979 | 1033 | _filterContext.skipParentChecks(); |
980 | 1034 | } |
981 | 1035 | } |
982 | ||
983 | /** | |
984 | * Specialized variant of {@link #_checkParentPath} used when checking | |
985 | * parent for a property name to be included with value: rules are slightly | |
986 | * different. | |
987 | */ | |
988 | protected void _checkPropertyParentPath() throws IOException | |
989 | { | |
990 | ++_matchCount; | |
991 | if (_includePath) { | |
992 | _filterContext.writePath(delegate); | |
993 | } else if (_includeImmediateParent) { | |
994 | // 21-Apr-2015, tatu: Note that there is no API to enable this currently... | |
995 | // retained for speculative future use | |
996 | _filterContext.writeImmediatePath(delegate); | |
997 | } | |
998 | ||
999 | // also: if no multiple matches desired, short-cut checks | |
1000 | if (!_allowMultipleMatches) { | |
1001 | // Mark parents as "skip" so that further check calls are not made | |
1002 | _filterContext.skipParentChecks(); | |
1003 | } | |
1004 | } | |
1005 | 1036 | |
1006 | 1037 | protected boolean _checkBinaryWrite() throws IOException |
1007 | 1038 | { |
5 | 5 | import java.math.BigInteger; |
6 | 6 | |
7 | 7 | import com.fasterxml.jackson.core.*; |
8 | import com.fasterxml.jackson.core.filter.TokenFilter.Inclusion; | |
8 | 9 | import com.fasterxml.jackson.core.util.JsonParserDelegate; |
9 | 10 | |
10 | 11 | import static com.fasterxml.jackson.core.JsonTokenId.*; |
45 | 46 | * done and only explicitly included entries are output; if `true` then |
46 | 47 | * path from main level down to match is also included as necessary. |
47 | 48 | */ |
48 | protected boolean _includePath; | |
49 | ||
50 | /* NOTE: this feature is included in the first version (2.6), but | |
51 | * there is no public API to enable it, yet, since there isn't an | |
52 | * actual use case. But it seemed possible need could arise, which | |
53 | * is feature has not yet been removed. If no use is found within | |
54 | * first version or two, just remove. | |
55 | * | |
56 | * Marked as deprecated since its status is uncertain. | |
57 | */ | |
58 | @Deprecated | |
59 | protected boolean _includeImmediateParent; | |
60 | ||
49 | protected TokenFilter.Inclusion _inclusion; | |
50 | ||
61 | 51 | /* |
62 | 52 | /********************************************************** |
63 | 53 | /* State |
110 | 100 | /********************************************************** |
111 | 101 | */ |
112 | 102 | |
103 | @Deprecated | |
113 | 104 | public FilteringParserDelegate(JsonParser p, TokenFilter f, |
114 | 105 | boolean includePath, boolean allowMultipleMatches) |
106 | { | |
107 | this(p, f, includePath ? Inclusion.INCLUDE_ALL_AND_PATH : Inclusion.ONLY_INCLUDE_ALL, allowMultipleMatches); | |
108 | } | |
109 | ||
110 | public FilteringParserDelegate(JsonParser p, TokenFilter f, | |
111 | TokenFilter.Inclusion inclusion, boolean allowMultipleMatches) | |
115 | 112 | { |
116 | 113 | super(p); |
117 | 114 | rootFilter = f; |
118 | 115 | // and this is the currently active filter for root values |
119 | 116 | _itemFilter = f; |
120 | 117 | _headContext = TokenFilterContext.createRootContext(f); |
121 | _includePath = includePath; | |
118 | _inclusion = inclusion; | |
122 | 119 | _allowMultipleMatches = allowMultipleMatches; |
123 | 120 | } |
124 | 121 | |
147 | 144 | @Override public JsonToken getCurrentToken() { return _currToken; } |
148 | 145 | @Override public JsonToken currentToken() { return _currToken; } |
149 | 146 | |
147 | @Deprecated // since 2.12 | |
150 | 148 | @Override public final int getCurrentTokenId() { |
151 | final JsonToken t = _currToken; | |
152 | return (t == null) ? JsonTokenId.ID_NO_TOKEN : t.id(); | |
149 | return currentTokenId(); | |
153 | 150 | } |
154 | 151 | @Override public final int currentTokenId() { |
155 | 152 | final JsonToken t = _currToken; |
234 | 231 | // If all the conditions matches then check for scalar / non-scalar property |
235 | 232 | |
236 | 233 | if (!_allowMultipleMatches && (_currToken != null) && (_exposedContext == null)) { |
237 | // if scalar, and scalar not present in obj/array and !includePath and INCLUDE_ALL | |
238 | // matched once, return null | |
239 | if (_currToken.isScalarValue() && !_headContext.isStartHandled() && !_includePath | |
234 | // if scalar, and scalar not present in obj/array and _inclusion == ONLY_INCLUDE_ALL | |
235 | // and INCLUDE_ALL matched once, return null | |
236 | if (_currToken.isScalarValue() && !_headContext.isStartHandled() | |
237 | && _inclusion == Inclusion.ONLY_INCLUDE_ALL | |
240 | 238 | && (_itemFilter == TokenFilter.INCLUDE_ALL)) { |
241 | 239 | return (_currToken = null); |
242 | 240 | } |
317 | 315 | if (f == TokenFilter.INCLUDE_ALL) { |
318 | 316 | _headContext = _headContext.createChildArrayContext(f, true); |
319 | 317 | return (_currToken = t); |
318 | } else if (f != null && _inclusion == Inclusion.INCLUDE_NON_NULL) { | |
319 | // TODO don't count as match? | |
320 | _headContext = _headContext.createChildArrayContext(f, true); | |
321 | return (_currToken = t); | |
320 | 322 | } |
321 | 323 | _headContext = _headContext.createChildArrayContext(f, false); |
322 | ||
324 | ||
323 | 325 | // Also: only need buffering if parent path to be included |
324 | if (_includePath) { | |
326 | if (_inclusion == Inclusion.INCLUDE_ALL_AND_PATH) { | |
325 | 327 | t = _nextTokenWithBuffering(_headContext); |
326 | 328 | if (t != null) { |
327 | 329 | _currToken = t; |
353 | 355 | if (f == TokenFilter.INCLUDE_ALL) { |
354 | 356 | _headContext = _headContext.createChildObjectContext(f, true); |
355 | 357 | return (_currToken = t); |
358 | } else if (f != null && _inclusion == Inclusion.INCLUDE_NON_NULL) { | |
359 | // TODO don't count as match? | |
360 | _headContext = _headContext.createChildObjectContext(f, true); | |
361 | return (_currToken = t); | |
356 | 362 | } |
357 | 363 | _headContext = _headContext.createChildObjectContext(f, false); |
358 | 364 | // Also: only need buffering if parent path to be included |
359 | if (_includePath) { | |
365 | if (_inclusion == Inclusion.INCLUDE_ALL_AND_PATH) { | |
360 | 366 | t = _nextTokenWithBuffering(_headContext); |
361 | 367 | if (t != null) { |
362 | 368 | _currToken = t; |
390 | 396 | f = _headContext.setFieldName(name); |
391 | 397 | if (f == TokenFilter.INCLUDE_ALL) { |
392 | 398 | _itemFilter = f; |
393 | if (!_includePath) { | |
394 | // Minor twist here: if parent NOT included, may need to induce output of | |
395 | // surrounding START_OBJECT/END_OBJECT | |
396 | if (_includeImmediateParent && !_headContext.isStartHandled()) { | |
397 | t = _headContext.nextTokenToRead(); // returns START_OBJECT but also marks it handled | |
398 | _exposedContext = _headContext; | |
399 | } | |
400 | } | |
401 | 399 | return (_currToken = t); |
402 | 400 | } |
403 | 401 | if (f == null) { |
414 | 412 | _itemFilter = f; |
415 | 413 | if (f == TokenFilter.INCLUDE_ALL) { |
416 | 414 | if (_verifyAllowedMatches()) { |
417 | if (_includePath) { | |
415 | if (_inclusion == Inclusion.INCLUDE_ALL_AND_PATH) { | |
418 | 416 | return (_currToken = t); |
419 | 417 | } |
420 | 418 | } else { |
422 | 420 | delegate.skipChildren(); |
423 | 421 | } |
424 | 422 | } |
425 | if (_includePath) { | |
423 | if (_inclusion != Inclusion.ONLY_INCLUDE_ALL) { | |
426 | 424 | t = _nextTokenWithBuffering(_headContext); |
427 | 425 | if (t != null) { |
428 | 426 | _currToken = t; |
495 | 493 | if (f == TokenFilter.INCLUDE_ALL) { |
496 | 494 | _headContext = _headContext.createChildArrayContext(f, true); |
497 | 495 | return (_currToken = t); |
496 | } else if (f != null && _inclusion == Inclusion.INCLUDE_NON_NULL) { | |
497 | _headContext = _headContext.createChildArrayContext(f, true); | |
498 | return (_currToken = t); | |
498 | 499 | } |
499 | 500 | _headContext = _headContext.createChildArrayContext(f, false); |
500 | 501 | // but if we didn't figure it out yet, need to buffer possible events |
501 | if (_includePath) { | |
502 | if (_inclusion == Inclusion.INCLUDE_ALL_AND_PATH) { | |
502 | 503 | t = _nextTokenWithBuffering(_headContext); |
503 | 504 | if (t != null) { |
504 | 505 | _currToken = t; |
530 | 531 | if (f == TokenFilter.INCLUDE_ALL) { |
531 | 532 | _headContext = _headContext.createChildObjectContext(f, true); |
532 | 533 | return (_currToken = t); |
534 | } else if (f != null && _inclusion == Inclusion.INCLUDE_NON_NULL) { | |
535 | _headContext = _headContext.createChildObjectContext(f, true); | |
536 | return (_currToken = t); | |
533 | 537 | } |
534 | 538 | _headContext = _headContext.createChildObjectContext(f, false); |
535 | if (_includePath) { | |
539 | if (_inclusion == Inclusion.INCLUDE_ALL_AND_PATH) { | |
536 | 540 | t = _nextTokenWithBuffering(_headContext); |
537 | 541 | if (t != null) { |
538 | 542 | _currToken = t; |
578 | 582 | } |
579 | 583 | _itemFilter = f; |
580 | 584 | if (f == TokenFilter.INCLUDE_ALL) { |
581 | if (_verifyAllowedMatches() && _includePath) { | |
585 | if (_verifyAllowedMatches() && _inclusion == Inclusion.INCLUDE_ALL_AND_PATH) { | |
582 | 586 | return (_currToken = t); |
583 | 587 | } |
584 | // if (_includeImmediateParent) { ... | |
585 | 588 | continue main_loop; |
586 | 589 | } |
587 | if (_includePath) { | |
590 | if (_inclusion != Inclusion.ONLY_INCLUDE_ALL) { | |
588 | 591 | t = _nextTokenWithBuffering(_headContext); |
589 | 592 | if (t != null) { |
590 | 593 | _currToken = t; |
646 | 649 | if (f == TokenFilter.INCLUDE_ALL) { |
647 | 650 | _headContext = _headContext.createChildArrayContext(f, true); |
648 | 651 | return _nextBuffered(buffRoot); |
652 | } else if (f != null && _inclusion == Inclusion.INCLUDE_NON_NULL) { | |
653 | // TODO don't count as match? | |
654 | _headContext = _headContext.createChildArrayContext(f, true); | |
655 | return _nextBuffered(buffRoot); | |
649 | 656 | } |
650 | 657 | _headContext = _headContext.createChildArrayContext(f, false); |
651 | 658 | continue main_loop; |
672 | 679 | _itemFilter = f; |
673 | 680 | if (f == TokenFilter.INCLUDE_ALL) { |
674 | 681 | _headContext = _headContext.createChildObjectContext(f, true); |
682 | return _nextBuffered(buffRoot); | |
683 | } else if (f != null && _inclusion == Inclusion.INCLUDE_NON_NULL) { | |
684 | // TODO don't count as match? | |
685 | _headContext = _headContext.createChildArrayContext(f, true); | |
675 | 686 | return _nextBuffered(buffRoot); |
676 | 687 | } |
677 | 688 | _headContext = _headContext.createChildObjectContext(f, false); |
15 | 15 | public class TokenFilter |
16 | 16 | { |
17 | 17 | |
18 | /** | |
19 | * Enumeration that controls how TokenFilter return values are interpreted. | |
20 | * | |
21 | * @since 2.12 | |
22 | */ | |
23 | public enum Inclusion { | |
24 | /** | |
25 | * Tokens will only be included if the filter returns TokenFilter.INCLUDE_ALL | |
26 | */ | |
27 | ONLY_INCLUDE_ALL, | |
28 | /** | |
29 | * When TokenFilter.INCLUDE_ALL is returned, the corresponding token will | |
30 | * be included as well as enclosing tokens up to the root | |
31 | */ | |
32 | INCLUDE_ALL_AND_PATH, | |
33 | /** | |
34 | * Tokens will be included if any non-null filter is returned. | |
35 | * The exception is if a field name returns a non-null filter, | |
36 | * but the field value returns a null filter. In this case the | |
37 | * field name and value will both be omitted. | |
38 | */ | |
39 | INCLUDE_NON_NULL | |
40 | } | |
41 | ||
18 | 42 | // // Marker values |
19 | 43 | |
20 | 44 | /** |
147 | 147 | } |
148 | 148 | |
149 | 149 | /** |
150 | * Method called to ensure that field name, if present, has been written | |
151 | */ | |
152 | public void ensureFieldNameWritten(JsonGenerator gen) throws IOException | |
153 | { | |
154 | if (_needToHandleName) { | |
155 | _needToHandleName = false; | |
156 | gen.writeFieldName(_currentName); | |
157 | } | |
158 | } | |
159 | ||
160 | /** | |
150 | 161 | * Method called to ensure that parent path from root is written up to |
151 | 162 | * and including this node. |
152 | 163 | */ |
168 | 179 | if (_type == TYPE_OBJECT) { |
169 | 180 | gen.writeStartObject(); |
170 | 181 | gen.writeFieldName(_currentName); // we know name must be written |
171 | } else if (_type == TYPE_ARRAY) { | |
172 | gen.writeStartArray(); | |
173 | } | |
174 | } | |
175 | } | |
176 | ||
177 | /** | |
178 | * Variant of {@link #writePath(JsonGenerator)} called when all we | |
179 | * need is immediately surrounding Object. Method typically called | |
180 | * when including a single property but not including full path | |
181 | * to root. | |
182 | */ | |
183 | public void writeImmediatePath(JsonGenerator gen) throws IOException | |
184 | { | |
185 | if ((_filter == null) || (_filter == TokenFilter.INCLUDE_ALL)) { | |
186 | return; | |
187 | } | |
188 | if (_startHandled) { | |
189 | // even if Object started, need to start leaf-level name | |
190 | if (_needToHandleName) { | |
191 | gen.writeFieldName(_currentName); | |
192 | } | |
193 | } else { | |
194 | _startHandled = true; | |
195 | if (_type == TYPE_OBJECT) { | |
196 | gen.writeStartObject(); | |
197 | if (_needToHandleName) { | |
198 | gen.writeFieldName(_currentName); | |
199 | } | |
200 | 182 | } else if (_type == TYPE_ARRAY) { |
201 | 183 | gen.writeStartArray(); |
202 | 184 | } |
3 | 3 | |
4 | 4 | public final class CharTypes |
5 | 5 | { |
6 | private final static char[] HC = "0123456789ABCDEF".toCharArray(); | |
7 | private final static byte[] HB; | |
6 | protected final static char[] HC = "0123456789ABCDEF".toCharArray(); | |
7 | protected final static byte[] HB; | |
8 | 8 | static { |
9 | 9 | int len = HC.length; |
10 | 10 | HB = new byte[len]; |
17 | 17 | * Lookup table used for determining which input characters |
18 | 18 | * need special handling when contained in text segment. |
19 | 19 | */ |
20 | private final static int[] sInputCodes; | |
20 | protected final static int[] sInputCodes; | |
21 | 21 | static { |
22 | 22 | /* 96 would do for most cases (backslash is ASCII 94) |
23 | 23 | * but if we want to do lookups by raw bytes it's better |
38 | 38 | * Additionally we can combine UTF-8 decoding info into similar |
39 | 39 | * data table. |
40 | 40 | */ |
41 | private final static int[] sInputCodesUTF8; | |
41 | protected final static int[] sInputCodesUTF8; | |
42 | 42 | static { |
43 | 43 | final int[] table = new int[sInputCodes.length]; |
44 | 44 | System.arraycopy(sInputCodes, 0, table, 0, table.length); |
68 | 68 | * Basically this is list of 8-bit ASCII characters that are legal |
69 | 69 | * as part of Javascript identifier |
70 | 70 | */ |
71 | private final static int[] sInputCodesJsNames; | |
71 | protected final static int[] sInputCodesJsNames; | |
72 | 72 | static { |
73 | 73 | final int[] table = new int[256]; |
74 | 74 | // Default is "not a name char", mark ones that are |
95 | 95 | * code as ok. They will be validated at a later point, when decoding |
96 | 96 | * name |
97 | 97 | */ |
98 | private final static int[] sInputCodesUtf8JsNames; | |
98 | protected final static int[] sInputCodesUtf8JsNames; | |
99 | 99 | static { |
100 | 100 | final int[] table = new int[256]; |
101 | 101 | // start with 8-bit JS names |
108 | 108 | * Decoding table used to quickly determine characters that are |
109 | 109 | * relevant within comment content. |
110 | 110 | */ |
111 | private final static int[] sInputCodesComment; | |
111 | protected final static int[] sInputCodesComment; | |
112 | 112 | static { |
113 | 113 | final int[] buf = new int[256]; |
114 | 114 | // but first: let's start with UTF-8 multi-byte markers: |
128 | 128 | * |
129 | 129 | * @since 2.3 |
130 | 130 | */ |
131 | private final static int[] sInputCodesWS; | |
131 | protected final static int[] sInputCodesWS; | |
132 | 132 | static { |
133 | 133 | // but first: let's start with UTF-8 multi-byte markers: |
134 | 134 | final int[] buf = new int[256]; |
151 | 151 | * Lookup table used for determining which output characters in |
152 | 152 | * 7-bit ASCII range need to be quoted. |
153 | 153 | */ |
154 | private final static int[] sOutputEscapes128; | |
154 | protected final static int[] sOutputEscapes128; | |
155 | 155 | static { |
156 | 156 | int[] table = new int[128]; |
157 | 157 | // Control chars need generic escape sequence |
178 | 178 | *<p> |
179 | 179 | * NOTE: before 2.10.1, was of size 128, extended for simpler handling |
180 | 180 | */ |
181 | private final static int[] sHexValues = new int[256]; | |
181 | protected final static int[] sHexValues = new int[256]; | |
182 | 182 | static { |
183 | 183 | Arrays.fill(sHexValues, -1); |
184 | 184 | for (int i = 0; i < 10; ++i) { |
7 | 7 | import com.fasterxml.jackson.core.io.CharacterEscapes; |
8 | 8 | import com.fasterxml.jackson.core.io.IOContext; |
9 | 9 | import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; |
10 | import com.fasterxml.jackson.core.util.JacksonFeatureSet; | |
10 | 11 | import com.fasterxml.jackson.core.util.VersionUtil; |
11 | 12 | |
12 | 13 | /** |
29 | 30 | */ |
30 | 31 | protected final static int[] sOutputEscapes = CharTypes.get7BitOutputEscapes(); |
31 | 32 | |
33 | /** | |
34 | * Default capabilities for JSON generator implementations which do not | |
35 | * different from "general textual" defaults | |
36 | * | |
37 | * @since 2.12 | |
38 | */ | |
39 | protected final static JacksonFeatureSet<StreamWriteCapability> JSON_WRITE_CAPABILITIES | |
40 | = DEFAULT_TEXTUAL_WRITE_CAPABILITIES; | |
41 | ||
32 | 42 | /* |
33 | 43 | /********************************************************** |
34 | 44 | /* Configuration, basic I/O |
191 | 201 | return this; |
192 | 202 | } |
193 | 203 | |
204 | @Override | |
205 | public JacksonFeatureSet<StreamWriteCapability> getWriteCapabilities() { | |
206 | return JSON_WRITE_CAPABILITIES; | |
207 | } | |
208 | ||
194 | 209 | /* |
195 | 210 | /********************************************************** |
196 | 211 | /* Shared helper methods |
14 | 14 | * Parent context for this context; null for root context. |
15 | 15 | */ |
16 | 16 | protected final JsonReadContext _parent; |
17 | ||
17 | ||
18 | 18 | // // // Optional duplicate detection |
19 | 19 | |
20 | 20 | protected DupDetector _dups; |
21 | 21 | |
22 | 22 | /* |
23 | 23 | /********************************************************** |
24 | /* Simple instance reuse slots; speeds up things | |
25 | /* a bit (10-15%) for docs with lots of small | |
26 | /* arrays/objects (for which allocation was | |
27 | /* visible in profile stack frames) | |
24 | /* Simple instance reuse slots; speeds up things a bit (10-15%) | |
25 | /* for docs with lots of small arrays/objects (for which | |
26 | /* allocation was visible in profile stack frames) | |
28 | 27 | /********************************************************** |
29 | 28 | */ |
30 | 29 | |
62 | 61 | _index = -1; |
63 | 62 | } |
64 | 63 | |
65 | protected void reset(int type, int lineNr, int colNr) { | |
64 | /** | |
65 | * Internal method to allow instance reuse: DO NOT USE unless you absolutely | |
66 | * know what you are doing. | |
67 | * Clears up state (including "current value"), changes type to one specified; | |
68 | * resets current duplicate-detection state (if any). | |
69 | * Parent link left as-is since it is {@code final}. | |
70 | *<p> | |
71 | * NOTE: Public since 2.12. | |
72 | */ | |
73 | public void reset(int type, int lineNr, int colNr) { | |
66 | 74 | _type = type; |
67 | 75 | _index = -1; |
68 | 76 | _lineNr = lineNr; |
83 | 83 | _currentValue = currValue; |
84 | 84 | } |
85 | 85 | |
86 | protected JsonWriteContext reset(int type) { | |
86 | /** | |
87 | * Internal method to allow instance reuse: DO NOT USE unless you absolutely | |
88 | * know what you are doing. | |
89 | * Clears up state (including "current value"), changes type to one specified; | |
90 | * resets current duplicate-detection state (if any). | |
91 | * Parent link left as-is since it is {@code final}. | |
92 | *<p> | |
93 | * NOTE: Public since 2.12. | |
94 | */ | |
95 | public JsonWriteContext reset(int type) { | |
87 | 96 | _type = type; |
88 | 97 | _index = -1; |
89 | 98 | _currentName = null; |
93 | 102 | return this; |
94 | 103 | } |
95 | 104 | |
96 | /* @since 2.10 */ | |
97 | protected JsonWriteContext reset(int type, Object currValue) { | |
105 | /** | |
106 | * Internal method to allow instance reuse: DO NOT USE unless you absolutely | |
107 | * know what you are doing. | |
108 | * Clears up state, changes type to one specified, assigns "current value"; | |
109 | * resets current duplicate-detection state (if any). | |
110 | * Parent link left as-is since it is {@code final}. | |
111 | *<p> | |
112 | * NOTE: Public since 2.12. | |
113 | * | |
114 | * @since 2.10 | |
115 | */ | |
116 | public JsonWriteContext reset(int type, Object currValue) { | |
98 | 117 | _type = type; |
99 | 118 | _index = -1; |
100 | 119 | _currentName = null; |
15 | 15 | * based on a {@link java.io.Reader} to handle low-level character |
16 | 16 | * conversion tasks. |
17 | 17 | */ |
18 | public class ReaderBasedJsonParser // final in 2.3, earlier | |
18 | public class ReaderBasedJsonParser | |
19 | 19 | extends ParserBase |
20 | 20 | { |
21 | 21 | @SuppressWarnings("deprecation") |
166 | 166 | |
167 | 167 | @Override public ObjectCodec getCodec() { return _objectCodec; } |
168 | 168 | @Override public void setCodec(ObjectCodec c) { _objectCodec = c; } |
169 | ||
170 | @Override // @since 2.12 | |
171 | public JacksonFeatureSet<StreamReadCapability> getReadCapabilities() { | |
172 | return JSON_READ_CAPABILITIES; | |
173 | } | |
169 | 174 | |
170 | 175 | @Override |
171 | 176 | public int releaseBuffered(Writer w) throws IOException { |
139 | 139 | @Override |
140 | 140 | public void setCodec(ObjectCodec c) { |
141 | 141 | _objectCodec = c; |
142 | } | |
143 | ||
144 | @Override // @since 2.12 | |
145 | public JacksonFeatureSet<StreamReadCapability> getReadCapabilities() { | |
146 | return JSON_READ_CAPABILITIES; | |
142 | 147 | } |
143 | 148 | |
144 | 149 | /* |
324 | 324 | } |
325 | 325 | } |
326 | 326 | |
327 | @Override // since 2.10 | |
328 | public void writeStartArray(int size) throws IOException | |
327 | @Override // since 2.12 | |
328 | public final void writeStartArray(Object currentValue) throws IOException | |
329 | 329 | { |
330 | 330 | _verifyValueWrite("start an array"); |
331 | _writeContext = _writeContext.createChildArrayContext(); | |
331 | _writeContext = _writeContext.createChildArrayContext(currentValue); | |
332 | if (_cfgPrettyPrinter != null) { | |
333 | _cfgPrettyPrinter.writeStartArray(this); | |
334 | } else { | |
335 | if (_outputTail >= _outputEnd) { | |
336 | _flushBuffer(); | |
337 | } | |
338 | _outputBuffer[_outputTail++] = BYTE_LBRACKET; | |
339 | } | |
340 | } | |
341 | ||
342 | @Override // since 2.12 | |
343 | public void writeStartArray(Object currentValue, int size) throws IOException | |
344 | { | |
345 | _verifyValueWrite("start an array"); | |
346 | _writeContext = _writeContext.createChildArrayContext(currentValue); | |
332 | 347 | if (_cfgPrettyPrinter != null) { |
333 | 348 | _cfgPrettyPrinter.writeStartArray(this); |
334 | 349 | } else { |
1053 | 1068 | public void writeNumber(String encodedValue) throws IOException |
1054 | 1069 | { |
1055 | 1070 | _verifyValueWrite(WRITE_NUMBER); |
1056 | if (_cfgNumbersAsStrings) { | |
1071 | if (encodedValue == null) { | |
1072 | _writeNull(); | |
1073 | } else if (_cfgNumbersAsStrings) { | |
1057 | 1074 | _writeQuotedRaw(encodedValue); |
1058 | 1075 | } else { |
1059 | 1076 | writeRaw(encodedValue); |
175 | 175 | @Override |
176 | 176 | public void setCodec(ObjectCodec c) { |
177 | 177 | _objectCodec = c; |
178 | } | |
179 | ||
180 | @Override // @since 2.12 | |
181 | public JacksonFeatureSet<StreamReadCapability> getReadCapabilities() { | |
182 | return JSON_READ_CAPABILITIES; | |
178 | 183 | } |
179 | 184 | |
180 | 185 | /* |
257 | 257 | } |
258 | 258 | } |
259 | 259 | |
260 | @Override // since 2.10 | |
261 | public void writeStartArray(int size) throws IOException | |
260 | @Override // since 2.12 | |
261 | public void writeStartArray(Object currentValue) throws IOException | |
262 | 262 | { |
263 | 263 | _verifyValueWrite("start an array"); |
264 | _writeContext = _writeContext.createChildArrayContext(); | |
264 | _writeContext = _writeContext.createChildArrayContext(currentValue); | |
265 | 265 | if (_cfgPrettyPrinter != null) { |
266 | 266 | _cfgPrettyPrinter.writeStartArray(this); |
267 | 267 | } else { |
271 | 271 | _outputBuffer[_outputTail++] = '['; |
272 | 272 | } |
273 | 273 | } |
274 | ||
274 | ||
275 | @Override // since 2.12 | |
276 | public void writeStartArray(Object currentValue, int size) throws IOException | |
277 | { | |
278 | _verifyValueWrite("start an array"); | |
279 | _writeContext = _writeContext.createChildArrayContext(currentValue); | |
280 | if (_cfgPrettyPrinter != null) { | |
281 | _cfgPrettyPrinter.writeStartArray(this); | |
282 | } else { | |
283 | if (_outputTail >= _outputEnd) { | |
284 | _flushBuffer(); | |
285 | } | |
286 | _outputBuffer[_outputTail++] = '['; | |
287 | } | |
288 | } | |
289 | ||
275 | 290 | @Override |
276 | 291 | public void writeEndArray() throws IOException |
277 | 292 | { |
828 | 843 | public void writeNumber(String encodedValue) throws IOException |
829 | 844 | { |
830 | 845 | _verifyValueWrite(WRITE_NUMBER); |
831 | if (_cfgNumbersAsStrings) { | |
846 | if (encodedValue == null) { | |
847 | _writeNull(); | |
848 | } else if (_cfgNumbersAsStrings) { | |
832 | 849 | _writeQuotedRaw(encodedValue); |
833 | 850 | } else { |
834 | 851 | writeRaw(encodedValue); |
7 | 7 | import com.fasterxml.jackson.core.json.JsonReadContext; |
8 | 8 | import com.fasterxml.jackson.core.sym.ByteQuadsCanonicalizer; |
9 | 9 | import com.fasterxml.jackson.core.util.ByteArrayBuilder; |
10 | import com.fasterxml.jackson.core.util.JacksonFeatureSet; | |
10 | 11 | |
11 | 12 | import static com.fasterxml.jackson.core.JsonTokenId.*; |
12 | 13 | |
265 | 266 | throw new UnsupportedOperationException("Can not use ObjectMapper with non-blocking parser"); |
266 | 267 | } |
267 | 268 | |
268 | /** | |
269 | * @since 2.9 | |
270 | */ | |
271 | @Override | |
269 | @Override // since 2.9 | |
272 | 270 | public boolean canParseAsync() { return true; } |
271 | ||
272 | @Override // @since 2.12 | |
273 | public JacksonFeatureSet<StreamReadCapability> getReadCapabilities() { | |
274 | return JSON_READ_CAPABILITIES; | |
275 | } | |
273 | 276 | |
274 | 277 | /* |
275 | 278 | /********************************************************** |
66 | 66 | * Reference to the root symbol table, for child tables, so |
67 | 67 | * that they can merge table information back as necessary. |
68 | 68 | */ |
69 | final private ByteQuadsCanonicalizer _parent; | |
69 | final protected ByteQuadsCanonicalizer _parent; | |
70 | 70 | |
71 | 71 | /** |
72 | 72 | * Member that is only used by the root table instance: root |
74 | 74 | * may return new state if they add entries to the table. |
75 | 75 | * Child tables do NOT use the reference. |
76 | 76 | */ |
77 | final private AtomicReference<TableInfo> _tableInfo; | |
77 | final protected AtomicReference<TableInfo> _tableInfo; | |
78 | 78 | |
79 | 79 | /** |
80 | 80 | * Seed value we use as the base to make hash codes non-static between |
83 | 83 | * This is done for security reasons, to avoid potential DoS attack via |
84 | 84 | * hash collisions. |
85 | 85 | */ |
86 | final private int _seed; | |
86 | final protected int _seed; | |
87 | 87 | |
88 | 88 | /* |
89 | 89 | /********************************************************** |
98 | 98 | * NOTE: non-final to allow disabling intern()ing in case of excessive |
99 | 99 | * collisions. |
100 | 100 | */ |
101 | private boolean _intern; | |
101 | protected boolean _intern; | |
102 | 102 | |
103 | 103 | /** |
104 | 104 | * Flag that indicates whether we should throw an exception if enough |
106 | 106 | * |
107 | 107 | * @since 2.4 |
108 | 108 | */ |
109 | private final boolean _failOnDoS; | |
109 | protected final boolean _failOnDoS; | |
110 | 110 | |
111 | 111 | /* |
112 | 112 | /********************************************************** |
120 | 120 | * structure (details of which may be tweaked depending on expected rates |
121 | 121 | * of collisions). |
122 | 122 | */ |
123 | private int[] _hashArea; | |
123 | protected int[] _hashArea; | |
124 | 124 | |
125 | 125 | /** |
126 | 126 | * Number of slots for primary entries within {@link #_hashArea}; which is |
128 | 128 | * primary covers only half of the area; plus, additional area for longer |
129 | 129 | * symbols after hash area). |
130 | 130 | */ |
131 | private int _hashSize; | |
131 | protected int _hashSize; | |
132 | 132 | |
133 | 133 | /** |
134 | 134 | * Offset within {@link #_hashArea} where secondary entries start |
135 | 135 | */ |
136 | private int _secondaryStart; | |
136 | protected int _secondaryStart; | |
137 | 137 | |
138 | 138 | /** |
139 | 139 | * Offset within {@link #_hashArea} where tertiary entries start |
140 | 140 | */ |
141 | private int _tertiaryStart; | |
141 | protected int _tertiaryStart; | |
142 | 142 | |
143 | 143 | /** |
144 | 144 | * Constant that determines size of buckets for tertiary entries: |
149 | 149 | * Default value is 2, for buckets of 4 slots; grows bigger with |
150 | 150 | * bigger table sizes. |
151 | 151 | */ |
152 | private int _tertiaryShift; | |
152 | protected int _tertiaryShift; | |
153 | 153 | |
154 | 154 | /** |
155 | 155 | * Total number of Strings in the symbol table; only used for child tables. |
156 | 156 | */ |
157 | private int _count; | |
157 | protected int _count; | |
158 | 158 | |
159 | 159 | /** |
160 | 160 | * Array that contains <code>String</code> instances matching |
162 | 162 | * Contains nulls for unused entries. Note that this size is twice |
163 | 163 | * that of {@link #_hashArea} |
164 | 164 | */ |
165 | private String[] _names; | |
165 | protected String[] _names; | |
166 | 166 | |
167 | 167 | /* |
168 | 168 | /********************************************************** |
175 | 175 | * for more spilled over entries (if any). |
176 | 176 | * Spill over area is within fixed-size portion of {@link #_hashArea}. |
177 | 177 | */ |
178 | private int _spilloverEnd; | |
178 | protected int _spilloverEnd; | |
179 | 179 | |
180 | 180 | /** |
181 | 181 | * Offset within {@link #_hashArea} that follows main slots and contains |
185 | 185 | * Note that long name area follows immediately after the fixed-size |
186 | 186 | * main hash area ({@link #_hashArea}). |
187 | 187 | */ |
188 | private int _longNameOffset; | |
188 | protected int _longNameOffset; | |
189 | 189 | |
190 | 190 | /* |
191 | 191 | /********************************************************** |
206 | 206 | * and when adding new collision list queues (i.e. creating a new |
207 | 207 | * collision list head entry) |
208 | 208 | */ |
209 | private boolean _hashShared; | |
209 | protected boolean _hashShared; | |
210 | 210 | |
211 | 211 | /* |
212 | 212 | /********************************************************** |
100 | 100 | * defined, and child instance is released (call to <code>release</code>), |
101 | 101 | * parent's shared tables may be updated from the child instance. |
102 | 102 | */ |
103 | final private CharsToNameCanonicalizer _parent; | |
103 | final protected CharsToNameCanonicalizer _parent; | |
104 | 104 | |
105 | 105 | /** |
106 | 106 | * Member that is only used by the root table instance: root |
108 | 108 | * may return new state if they add entries to the table. |
109 | 109 | * Child tables do NOT use the reference. |
110 | 110 | */ |
111 | final private AtomicReference<TableInfo> _tableInfo; | |
111 | final protected AtomicReference<TableInfo> _tableInfo; | |
112 | 112 | |
113 | 113 | /** |
114 | 114 | * Seed value we use as the base to make hash codes non-static between |
119 | 119 | * |
120 | 120 | * @since 2.1 |
121 | 121 | */ |
122 | final private int _seed; | |
123 | ||
124 | final private int _flags; | |
122 | final protected int _seed; | |
123 | ||
124 | final protected int _flags; | |
125 | 125 | |
126 | 126 | /** |
127 | 127 | * Whether any canonicalization should be attempted (whether using |
129 | 129 | *<p> |
130 | 130 | * NOTE: non-final since we may need to disable this with overflow. |
131 | 131 | */ |
132 | private boolean _canonicalize; | |
132 | protected boolean _canonicalize; | |
133 | 133 | |
134 | 134 | /* |
135 | 135 | /********************************************************** |
141 | 141 | * Primary matching symbols; it's expected most match occur from |
142 | 142 | * here. |
143 | 143 | */ |
144 | private String[] _symbols; | |
144 | protected String[] _symbols; | |
145 | 145 | |
146 | 146 | /** |
147 | 147 | * Overflow buckets; if primary doesn't match, lookup is done |
150 | 150 | * Note: Number of buckets is half of number of symbol entries, on |
151 | 151 | * assumption there's less need for buckets. |
152 | 152 | */ |
153 | private Bucket[] _buckets; | |
153 | protected Bucket[] _buckets; | |
154 | 154 | |
155 | 155 | /** |
156 | 156 | * Current size (number of entries); needed to know if and when |
157 | 157 | * rehash. |
158 | 158 | */ |
159 | private int _size; | |
159 | protected int _size; | |
160 | 160 | |
161 | 161 | /** |
162 | 162 | * Limit that indicates maximum size this instance can hold before |
163 | 163 | * it needs to be expanded and rehashed. Calculated using fill |
164 | 164 | * factor passed in to constructor. |
165 | 165 | */ |
166 | private int _sizeThreshold; | |
166 | protected int _sizeThreshold; | |
167 | 167 | |
168 | 168 | /** |
169 | 169 | * Mask used to get index from hash values; equal to |
170 | 170 | * <code>_buckets.length - 1</code>, when _buckets.length is |
171 | 171 | * a power of two. |
172 | 172 | */ |
173 | private int _indexMask; | |
173 | protected int _indexMask; | |
174 | 174 | |
175 | 175 | /** |
176 | 176 | * We need to keep track of the longest collision list; this is needed |
179 | 179 | * |
180 | 180 | * @since 2.1 |
181 | 181 | */ |
182 | private int _longestCollisionList; | |
182 | protected int _longestCollisionList; | |
183 | 183 | |
184 | 184 | /* |
185 | 185 | /********************************************************** |
198 | 198 | * and when adding new collision list queues (i.e. creating a new |
199 | 199 | * collision list head entry) |
200 | 200 | */ |
201 | private boolean _hashShared; | |
201 | protected boolean _hashShared; | |
202 | 202 | |
203 | 203 | /* |
204 | 204 | /********************************************************** |
214 | 214 | * |
215 | 215 | * @since 2.4 |
216 | 216 | */ |
217 | private BitSet _overflows; | |
217 | protected BitSet _overflows; | |
218 | 218 | |
219 | 219 | /* |
220 | 220 | /********************************************************** |
53 | 53 | |
54 | 54 | public ByteArrayBuilder(BufferRecycler br, int firstBlockSize) { |
55 | 55 | _bufferRecycler = br; |
56 | // 04-Sep-2020, tatu: Let's make this bit more robust and refuse to allocate | |
57 | // humongous blocks even if requested | |
58 | if (firstBlockSize > MAX_BLOCK_SIZE) { | |
59 | firstBlockSize = MAX_BLOCK_SIZE; | |
60 | } | |
56 | 61 | _currBlock = (br == null) ? new byte[firstBlockSize] : br.allocByteBuffer(BufferRecycler.BYTE_WRITE_CONCAT_BUFFER); |
57 | 62 | } |
58 | 63 |
0 | package com.fasterxml.jackson.core.util; | |
1 | ||
2 | /** | |
3 | * Basic API implemented by Enums used for simple Jackson "features": on/off | |
4 | * settings and capabilities exposed as something that can be internally | |
5 | * represented as bit sets. | |
6 | * Designed to be used with {@link JacksonFeatureSet}. | |
7 | * | |
8 | * @since 2.12 | |
9 | */ | |
10 | public interface JacksonFeature | |
11 | { | |
12 | /** | |
13 | * Accessor for checking whether this feature is enabled by default. | |
14 | */ | |
15 | public boolean enabledByDefault(); | |
16 | ||
17 | /** | |
18 | * Returns bit mask for this feature instance; must be a single bit, | |
19 | * that is of form {@code 1 << N} | |
20 | */ | |
21 | public int getMask(); | |
22 | ||
23 | /** | |
24 | * Convenience method for checking whether feature is enabled in given bitmask | |
25 | */ | |
26 | public boolean enabledIn(int flags); | |
27 | } |
0 | package com.fasterxml.jackson.core.util; | |
1 | ||
2 | /** | |
3 | * Container similar to {@link java.util.EnumSet} meant for storing sets of | |
4 | * {@link JacksonFeature}s (usually {@link java.lang.Enum}s): main | |
5 | * difference being that these sets are immutable. Also only supports relatively | |
6 | * small sets of features: specifically, up to 31 features. | |
7 | * | |
8 | * @since 2.12 | |
9 | */ | |
10 | public final class JacksonFeatureSet<F extends JacksonFeature> | |
11 | { | |
12 | protected int _enabled; | |
13 | ||
14 | /** | |
15 | * Constructor for creating instance with specific bitmask, wherein | |
16 | * {@code 1} bit means matching {@link JacksonFeature} is enabled and | |
17 | * {@code 0} disabled. | |
18 | */ | |
19 | protected JacksonFeatureSet(int bitmask) { | |
20 | _enabled = bitmask; | |
21 | } | |
22 | ||
23 | /** | |
24 | * "Default" factory which will calculate settings based on default-enabled | |
25 | * status of all features. | |
26 | * | |
27 | * @param allFeatures Set of all features (enabled or disabled): usually from {@code Enum.values()} | |
28 | */ | |
29 | public static <F extends JacksonFeature> JacksonFeatureSet<F> fromDefaults(F[] allFeatures) { | |
30 | // first sanity check | |
31 | if (allFeatures.length > 31) { | |
32 | final String desc = allFeatures[0].getClass().getName(); | |
33 | throw new IllegalArgumentException(String.format( | |
34 | "Can not use type `%s` with JacksonFeatureSet: too many entries (%d > 31)", | |
35 | desc, allFeatures.length)); | |
36 | } | |
37 | ||
38 | int flags = 0; | |
39 | for (F f : allFeatures) { | |
40 | if (f.enabledByDefault()) { | |
41 | flags |= f.getMask(); | |
42 | } | |
43 | } | |
44 | return new JacksonFeatureSet<F>(flags); | |
45 | } | |
46 | ||
47 | public static <F extends JacksonFeature> JacksonFeatureSet<F> fromBitmask(int bitmask) { | |
48 | return new JacksonFeatureSet<F>(bitmask); | |
49 | } | |
50 | ||
51 | /** | |
52 | * Mutant factory for getting a set in which specified feature is enabled: | |
53 | * will either return this instance (if no change), or newly created set (if there | |
54 | * is change). | |
55 | * | |
56 | * @param feature Feature to enable in set returned | |
57 | * | |
58 | * @return Newly created set of state of feature changed; {@code this} if not | |
59 | */ | |
60 | public JacksonFeatureSet<F> with(F feature) { | |
61 | int newMask = _enabled | feature.getMask(); | |
62 | return (newMask == _enabled) ? this : new JacksonFeatureSet<F>(newMask); | |
63 | } | |
64 | ||
65 | /** | |
66 | * Mutant factory for getting a set in which specified feature is disabled: | |
67 | * will either return this instance (if no change), or newly created set (if there | |
68 | * is change). | |
69 | * | |
70 | * @param feature Feature to disable in set returned | |
71 | * | |
72 | * @return Newly created set of state of feature changed; {@code this} if not | |
73 | */ | |
74 | public JacksonFeatureSet<F> without(F feature) { | |
75 | int newMask = _enabled & ~feature.getMask(); | |
76 | return (newMask == _enabled) ? this : new JacksonFeatureSet<F>(newMask); | |
77 | } | |
78 | ||
79 | /** | |
80 | * Main accessor for checking whether given feature is enabled in this feature set. | |
81 | * | |
82 | * @param feature Feature to check | |
83 | * | |
84 | * @return True if feature is enabled in this set; false otherwise | |
85 | */ | |
86 | public boolean isEnabled(F feature) { | |
87 | return (feature.getMask() & _enabled) != 0; | |
88 | } | |
89 | ||
90 | /** | |
91 | * Accessor for underlying bitmask | |
92 | * | |
93 | * @return Bitmask of enabled features | |
94 | */ | |
95 | public int asBitmask() { | |
96 | return _enabled; | |
97 | } | |
98 | } |
95 | 95 | @Override |
96 | 96 | public boolean canWriteFormattedNumbers() { return delegate.canWriteFormattedNumbers(); } |
97 | 97 | |
98 | @Override | |
99 | public JacksonFeatureSet<StreamWriteCapability> getWriteCapabilities() { | |
100 | return delegate.getWriteCapabilities(); | |
101 | } | |
102 | ||
98 | 103 | /* |
99 | 104 | /********************************************************** |
100 | 105 | /* Public API, configuration |
187 | 192 | @Override |
188 | 193 | public void writeStartArray() throws IOException { delegate.writeStartArray(); } |
189 | 194 | |
195 | @SuppressWarnings("deprecation") | |
190 | 196 | @Override |
191 | 197 | public void writeStartArray(int size) throws IOException { delegate.writeStartArray(size); } |
192 | 198 |
92 | 92 | |
93 | 93 | @Override public boolean requiresCustomCodec() { return delegate.requiresCustomCodec(); } |
94 | 94 | |
95 | @Override public JacksonFeatureSet<StreamReadCapability> getReadCapabilities() { return delegate.getReadCapabilities(); } | |
96 | ||
95 | 97 | /* |
96 | 98 | /********************************************************** |
97 | 99 | /* Closeable impl |
111 | 113 | @Override public int currentTokenId() { return delegate.currentTokenId(); } |
112 | 114 | |
113 | 115 | @Override public JsonToken getCurrentToken() { return delegate.getCurrentToken(); } |
116 | ||
117 | @Deprecated // since 2.12 | |
114 | 118 | @Override public int getCurrentTokenId() { return delegate.getCurrentTokenId(); } |
119 | ||
115 | 120 | @Override public boolean hasCurrentToken() { return delegate.hasCurrentToken(); } |
116 | 121 | @Override public boolean hasTokenId(int id) { return delegate.hasTokenId(id); } |
117 | 122 | @Override public boolean hasToken(JsonToken t) { return delegate.hasToken(t); } |
121 | 126 | @Override public JsonStreamContext getParsingContext() { return delegate.getParsingContext(); } |
122 | 127 | @Override public boolean isExpectedStartArrayToken() { return delegate.isExpectedStartArrayToken(); } |
123 | 128 | @Override public boolean isExpectedStartObjectToken() { return delegate.isExpectedStartObjectToken(); } |
129 | @Override public boolean isExpectedNumberIntToken() { return delegate.isExpectedNumberIntToken(); } | |
130 | ||
124 | 131 | @Override public boolean isNaN() throws IOException { return delegate.isNaN(); } |
125 | 132 | |
126 | 133 | /* |
185 | 192 | @Override |
186 | 193 | public Number getNumberValue() throws IOException { return delegate.getNumberValue(); } |
187 | 194 | |
195 | @Override | |
196 | public Number getNumberValueExact() throws IOException { return delegate.getNumberValueExact(); } | |
197 | ||
188 | 198 | /* |
189 | 199 | /********************************************************** |
190 | 200 | /* Public API, access to token information, coercion/conversion |
191 | 201 | /********************************************************** |
192 | 202 | */ |
193 | ||
203 | ||
194 | 204 | @Override public int getValueAsInt() throws IOException { return delegate.getValueAsInt(); } |
195 | 205 | @Override public int getValueAsInt(int defaultValue) throws IOException { return delegate.getValueAsInt(defaultValue); } |
196 | 206 | @Override public long getValueAsLong() throws IOException { return delegate.getValueAsLong(); } |
201 | 211 | @Override public boolean getValueAsBoolean(boolean defaultValue) throws IOException { return delegate.getValueAsBoolean(defaultValue); } |
202 | 212 | @Override public String getValueAsString() throws IOException { return delegate.getValueAsString(); } |
203 | 213 | @Override public String getValueAsString(String defaultValue) throws IOException { return delegate.getValueAsString(defaultValue); } |
204 | ||
214 | ||
205 | 215 | /* |
206 | 216 | /********************************************************** |
207 | 217 | /* Public API, access to token values, other |
0 | This copy of Jackson JSON processor streaming parser/generator is licensed under the | |
1 | Apache (Software) License, version 2.0 ("the License"). | |
2 | See the License for details about distribution rights, and the | |
3 | specific rights regarding derivate works. | |
4 | ||
5 | You may obtain a copy of the License at: | |
6 | ||
7 | http://www.apache.org/licenses/LICENSE-2.0 |
2 | 2 | Jackson is a high-performance, Free/Open Source JSON processing library. |
3 | 3 | It was originally written by Tatu Saloranta (tatu.saloranta@iki.fi), and has |
4 | 4 | been in development since 2007. |
5 | It is currently developed by a community of developers, as well as supported | |
6 | commercially by FasterXML.com. | |
5 | It is currently developed by a community of developers. | |
7 | 6 | |
8 | 7 | ## Licensing |
9 | 8 | |
10 | Jackson core and extension components may licensed under different licenses. | |
9 | Jackson 2.x core and extension components are licensed under Apache License 2.0 | |
11 | 10 | To find the details that apply to this artifact see the accompanying LICENSE file. |
12 | For more information, including possible other licensing options, contact | |
13 | FasterXML.com (http://fasterxml.com). | |
14 | 11 | |
15 | 12 | ## Credits |
16 | 13 | |
17 | A list of contributors may be found from CREDITS file, which is included | |
14 | A list of contributors may be found from CREDITS(-2.x) file, which is included | |
18 | 15 | in some artifacts (usually source distributions); but is always available |
19 | 16 | from the source code management (SCM) system project uses. |
26 | 26 | |
27 | 27 | public void testBase64Variant() throws Exception |
28 | 28 | { |
29 | Base64Variant orig = Base64Variants.PEM; | |
30 | byte[] stuff = jdkSerialize(orig); | |
31 | Base64Variant back = jdkDeserialize(stuff); | |
32 | assertSame(orig, back); | |
29 | { | |
30 | Base64Variant orig = Base64Variants.PEM; | |
31 | final String exp = _encodeBase64(orig); | |
32 | byte[] stuff = jdkSerialize(orig); | |
33 | Base64Variant back = jdkDeserialize(stuff); | |
34 | assertSame(orig, back); | |
35 | assertEquals(exp, _encodeBase64(back)); | |
36 | } | |
37 | ||
38 | // and then with a twist | |
39 | { | |
40 | Base64Variant orig = Base64Variants.MODIFIED_FOR_URL; | |
41 | assertFalse(orig.usesPadding()); | |
42 | Base64Variant mod = orig.withWritePadding(true); | |
43 | assertTrue(mod.usesPadding()); | |
44 | assertNotSame(orig, mod); | |
45 | assertFalse(orig.equals(mod)); | |
46 | assertFalse(mod.equals(orig)); | |
47 | ||
48 | final String exp = _encodeBase64(mod); | |
49 | byte[] stuff = jdkSerialize(mod); | |
50 | Base64Variant back = jdkDeserialize(stuff); | |
51 | assertTrue(back.usesPadding()); | |
52 | assertNotSame(mod, back); | |
53 | assertEquals(mod, back); | |
54 | assertEquals(exp, _encodeBase64(back)); | |
55 | } | |
33 | 56 | } |
34 | 57 | |
35 | 58 | public void testPrettyPrinter() throws Exception |
146 | 169 | p.close(); |
147 | 170 | g.close(); |
148 | 171 | } |
172 | ||
173 | protected String _encodeBase64(Base64Variant b64) throws IOException | |
174 | { | |
175 | // something with padding... | |
176 | return b64.encode("abcde".getBytes("UTF-8")); | |
177 | } | |
149 | 178 | } |
14 | 14 | |
15 | 15 | protected final static String UNICODE_SEGMENT = "["+UNICODE_2BYTES+"/"+UNICODE_3BYTES+"]"; |
16 | 16 | |
17 | protected static AsyncReaderWrapper asyncForBytes(JsonFactory f, | |
17 | public static AsyncReaderWrapper asyncForBytes(JsonFactory f, | |
18 | 18 | int bytesPerRead, |
19 | 19 | byte[] bytes, int padding) throws IOException |
20 | 20 | { |
51 | 51 | |
52 | 52 | assertEquals(Base64Variant.BASE64_VALUE_INVALID, std.decodeBase64Byte((byte) '?')); |
53 | 53 | assertEquals(Base64Variant.BASE64_VALUE_INVALID, std.decodeBase64Byte((byte) 0xA0)); |
54 | ||
54 | ||
55 | 55 | assertEquals(0, std.decodeBase64Char('A')); |
56 | 56 | assertEquals(1, std.decodeBase64Char((int) 'B')); |
57 | 57 | assertEquals(2, std.decodeBase64Char((byte)'C')); |
59 | 59 | assertEquals(0, std.decodeBase64Byte((byte) 'A')); |
60 | 60 | assertEquals(1, std.decodeBase64Byte((byte) 'B')); |
61 | 61 | assertEquals(2, std.decodeBase64Byte((byte)'C')); |
62 | ||
62 | ||
63 | 63 | assertEquals('/', std.encodeBase64BitsAsChar(63)); |
64 | 64 | assertEquals((byte) 'b', std.encodeBase64BitsAsByte(27)); |
65 | 65 | |
81 | 81 | |
82 | 82 | byte[] input = new byte[] { 1, 2, 34, 127, -1 }; |
83 | 83 | String encoded = std.encode(input, false); |
84 | byte[] decoded = std.decode(encoded); | |
84 | byte[] decoded = std.decode(encoded); | |
85 | 85 | Assert.assertArrayEquals(input, decoded); |
86 | 86 | |
87 | 87 | assertEquals(quote(encoded), std.encode(input, true)); |
114 | 114 | } |
115 | 115 | sb.append("AQ=="); |
116 | 116 | final String exp = sb.toString(); |
117 | ||
117 | ||
118 | 118 | // first, JSON standard |
119 | 119 | assertEquals(exp.replace("##", "\\n"), std.encode(data, false)); |
120 | 120 | |
147 | 147 | verifyException(iae, "Illegal character"); |
148 | 148 | } |
149 | 149 | } |
150 | ||
151 | public void testPaddingReadBehaviour() throws Exception { | |
152 | ||
153 | for (Base64Variant variant: Arrays.asList(Base64Variants.MIME, Base64Variants.MIME_NO_LINEFEEDS, Base64Variants.PEM)) { | |
154 | ||
155 | final String BASE64_HELLO = "aGVsbG8="; | |
156 | try { | |
157 | variant.withPaddingForbidden().decode(BASE64_HELLO); | |
158 | fail("Should not pass"); | |
159 | } catch (IllegalArgumentException iae) { | |
160 | verifyException(iae, "no padding"); | |
161 | } | |
162 | ||
163 | variant.withPaddingAllowed().decode(BASE64_HELLO); | |
164 | variant.withPaddingRequired().decode(BASE64_HELLO); | |
165 | ||
166 | final String BASE64_HELLO_WITHOUT_PADDING = "aGVsbG8"; | |
167 | try { | |
168 | variant.withPaddingRequired().decode(BASE64_HELLO_WITHOUT_PADDING); | |
169 | fail("Should not pass"); | |
170 | } catch (IllegalArgumentException iae) { | |
171 | verifyException(iae, "expects padding"); | |
172 | } | |
173 | variant.withPaddingAllowed().decode(BASE64_HELLO_WITHOUT_PADDING); | |
174 | variant.withPaddingForbidden().decode(BASE64_HELLO_WITHOUT_PADDING); | |
175 | } | |
176 | ||
177 | //testing for MODIFIED_FOR_URL | |
178 | ||
179 | final String BASE64_HELLO = "aGVsbG8="; | |
180 | try { | |
181 | Base64Variants.MODIFIED_FOR_URL.withPaddingForbidden().decode(BASE64_HELLO); | |
182 | fail("Should not pass"); | |
183 | } catch (IllegalArgumentException iae) { | |
184 | verifyException(iae, "illegal character"); | |
185 | } | |
186 | ||
187 | try { | |
188 | Base64Variants.MODIFIED_FOR_URL.withPaddingAllowed().decode(BASE64_HELLO); | |
189 | fail("Should not pass"); | |
190 | } catch (IllegalArgumentException iae) { | |
191 | verifyException(iae, "illegal character"); | |
192 | } | |
193 | ||
194 | try { | |
195 | Base64Variants.MODIFIED_FOR_URL.withPaddingRequired().decode(BASE64_HELLO); | |
196 | fail("Should not pass"); | |
197 | } catch (IllegalArgumentException iae) { | |
198 | verifyException(iae, "illegal character"); | |
199 | } | |
200 | ||
201 | final String BASE64_HELLO_WITHOUT_PADDING = "aGVsbG8"; | |
202 | try { | |
203 | Base64Variants.MODIFIED_FOR_URL.withPaddingRequired().decode(BASE64_HELLO_WITHOUT_PADDING); | |
204 | fail("Should not pass"); | |
205 | } catch (IllegalArgumentException iae) { | |
206 | verifyException(iae, "expects padding"); | |
207 | } | |
208 | ||
209 | Base64Variants.MODIFIED_FOR_URL.withPaddingAllowed().decode(BASE64_HELLO_WITHOUT_PADDING); | |
210 | Base64Variants.MODIFIED_FOR_URL.withPaddingForbidden().decode(BASE64_HELLO_WITHOUT_PADDING); | |
211 | ||
212 | } | |
150 | 213 | } |
5 | 5 | import java.util.*; |
6 | 6 | |
7 | 7 | import com.fasterxml.jackson.core.*; |
8 | import com.fasterxml.jackson.core.filter.TokenFilter.Inclusion; | |
8 | 9 | import com.fasterxml.jackson.core.io.SerializedString; |
9 | 10 | |
10 | 11 | /** |
66 | 67 | } |
67 | 68 | } |
68 | 69 | |
70 | static class StrictNameMatchFilter extends TokenFilter | |
71 | { | |
72 | private final Set<String> _names; | |
73 | ||
74 | public StrictNameMatchFilter(String... names) { | |
75 | _names = new HashSet<String>(Arrays.asList(names)); | |
76 | } | |
77 | ||
78 | @Override | |
79 | public TokenFilter includeProperty(String name) { | |
80 | if (_names.contains(name)) { | |
81 | return TokenFilter.INCLUDE_ALL; | |
82 | } | |
83 | return null; | |
84 | } | |
85 | } | |
86 | ||
69 | 87 | static class IndexMatchFilter extends TokenFilter |
70 | 88 | { |
71 | 89 | private final BitSet _indices; |
94 | 112 | protected boolean _includeScalar() { return false; } |
95 | 113 | } |
96 | 114 | |
115 | static class NoArraysFilter extends TokenFilter | |
116 | { | |
117 | @Override | |
118 | public TokenFilter filterStartArray() { | |
119 | return null; | |
120 | } | |
121 | } | |
122 | ||
123 | static class NoObjectsFilter extends TokenFilter | |
124 | { | |
125 | @Override | |
126 | public TokenFilter filterStartObject() { | |
127 | return null; | |
128 | } | |
129 | } | |
130 | ||
97 | 131 | /* |
98 | 132 | /********************************************************** |
99 | 133 | /* Test methods |
119 | 153 | StringWriter w = new StringWriter(); |
120 | 154 | JsonGenerator gen = new FilteringGeneratorDelegate(_createGenerator(w), |
121 | 155 | new NameMatchFilter("value"), |
122 | false, // includePath | |
156 | Inclusion.ONLY_INCLUDE_ALL, | |
123 | 157 | false // multipleMatches |
124 | 158 | ); |
125 | 159 | final String JSON = "{'a':123,'array':[1,2],'ob':{'value0':2,'value':3,'value2':4},'b':true}"; |
140 | 174 | NameMatchFilter filter = new NameMatchFilter("value"); |
141 | 175 | FilteringGeneratorDelegate gen = new FilteringGeneratorDelegate(origGen, |
142 | 176 | filter, |
143 | true, // includePath | |
177 | Inclusion.INCLUDE_ALL_AND_PATH, | |
144 | 178 | false // multipleMatches |
145 | 179 | ); |
146 | 180 | |
162 | 196 | NameMatchFilter filter = new NameMatchFilter("value"); |
163 | 197 | FilteringGeneratorDelegate gen = new FilteringGeneratorDelegate(origGen, |
164 | 198 | filter, |
165 | true, // includePath | |
199 | Inclusion.INCLUDE_ALL_AND_PATH, | |
166 | 200 | false // multipleMatches |
167 | 201 | ); |
168 | 202 | |
191 | 225 | : new NameMatchFilter("value"); |
192 | 226 | FilteringGeneratorDelegate gen = new FilteringGeneratorDelegate(_createGenerator(w), |
193 | 227 | tf, |
194 | true, // includePath | |
228 | Inclusion.INCLUDE_ALL_AND_PATH, | |
195 | 229 | true // multipleMatches |
196 | 230 | ); |
197 | 231 | //final String JSON = "{'a':123,'array':[1,2],'ob':{'value0':2,'value':[3],'value2':'foo'},'b':true}"; |
238 | 272 | StringWriter w = new StringWriter(); |
239 | 273 | FilteringGeneratorDelegate gen = new FilteringGeneratorDelegate(_createGenerator(w), |
240 | 274 | new NameMatchFilter("array"), |
241 | true, // includePath | |
275 | Inclusion.INCLUDE_ALL_AND_PATH, | |
242 | 276 | false // multipleMatches |
243 | 277 | ); |
244 | 278 | //final String JSON = "{'header':['ENCODED',raw],'array':['base64stuff',1,2,3,4,5,6.25,7.5],'extra':[1,2,3,4,5,6.25,7.5]}"; |
289 | 323 | StringWriter w = new StringWriter(); |
290 | 324 | FilteringGeneratorDelegate gen = new FilteringGeneratorDelegate(_createGenerator(w), |
291 | 325 | new NameMatchFilter("value0", "value2"), |
292 | true, /* includePath */ true /* multipleMatches */ ); | |
326 | Inclusion.INCLUDE_ALL_AND_PATH, true /* multipleMatches */ ); | |
293 | 327 | final String JSON = "{'a':123,'array':[1,2],'ob':{'value0':2,'value':3,'value2':4},'b':true}"; |
294 | 328 | writeJsonDoc(JSON_F, JSON, gen); |
295 | 329 | assertEquals(aposToQuotes("{'ob':{'value0':2,'value2':4}}"), w.toString()); |
299 | 333 | |
300 | 334 | w = new StringWriter(); |
301 | 335 | gen = new FilteringGeneratorDelegate(_createGenerator(w), |
302 | new NameExcludeFilter(true, "ob"), true, true); | |
336 | new NameExcludeFilter(true, "ob"), Inclusion.INCLUDE_ALL_AND_PATH, true); | |
303 | 337 | writeJsonDoc(JSON_F, JSON, gen); |
304 | 338 | assertEquals(aposToQuotes("{'a':123,'array':[1,2],'b':true}"), w.toString()); |
305 | 339 | |
306 | 340 | // then excluding them |
307 | 341 | w = new StringWriter(); |
308 | 342 | gen = new FilteringGeneratorDelegate(_createGenerator(w), |
309 | new NameExcludeFilter(false, "ob"), true, true); | |
343 | new NameExcludeFilter(false, "ob"), Inclusion.INCLUDE_ALL_AND_PATH, true); | |
310 | 344 | writeJsonDoc(JSON_F, JSON, gen); |
311 | 345 | assertEquals(aposToQuotes("{'a':123,'b':true}"), w.toString()); |
312 | 346 | } |
317 | 351 | |
318 | 352 | FilteringGeneratorDelegate gen = new FilteringGeneratorDelegate(_createGenerator(w), |
319 | 353 | new NameMatchFilter("array", "b", "value"), |
320 | true, true); | |
354 | Inclusion.INCLUDE_ALL_AND_PATH, true); | |
321 | 355 | final String JSON = "{'a':123,'array':[1,2],'ob':{'value0':2,'value':3,'value2':4},'b':true}"; |
322 | 356 | writeJsonDoc(JSON_F, JSON, gen); |
323 | 357 | assertEquals(aposToQuotes("{'array':[1,2],'ob':{'value':3},'b':true}"), w.toString()); |
330 | 364 | |
331 | 365 | FilteringGeneratorDelegate gen = new FilteringGeneratorDelegate(_createGenerator(w), |
332 | 366 | new NameMatchFilter("value"), |
333 | true, true); | |
367 | Inclusion.INCLUDE_ALL_AND_PATH, true); | |
334 | 368 | final String JSON = "{'root':{'a0':true,'a':{'value':3},'b':{'value':'abc'}},'b0':false}"; |
335 | 369 | writeJsonDoc(JSON_F, JSON, gen); |
336 | 370 | assertEquals(aposToQuotes("{'root':{'a':{'value':3},'b':{'value':'abc'}}}"), w.toString()); |
337 | 371 | assertEquals(2, gen.getMatchCount()); |
338 | 372 | } |
339 | 373 | |
374 | public void testNoMatchFiltering1() throws Exception | |
375 | { | |
376 | StringWriter w = new StringWriter(); | |
377 | ||
378 | FilteringGeneratorDelegate gen = new FilteringGeneratorDelegate(JSON_F.createGenerator(w), | |
379 | new NameMatchFilter("invalid"), | |
380 | Inclusion.INCLUDE_NON_NULL, true); | |
381 | final String JSON = "{'root':{'a0':true,'b':{'value':4}},'b0':false}"; | |
382 | writeJsonDoc(JSON_F, JSON, gen); | |
383 | assertEquals(aposToQuotes("{'root':{'b':{}}}"), w.toString()); | |
384 | assertEquals(0, gen.getMatchCount()); | |
385 | } | |
386 | ||
387 | public void testNoMatchFiltering2() throws Exception | |
388 | { | |
389 | StringWriter w = new StringWriter(); | |
390 | ||
391 | FilteringGeneratorDelegate gen = new FilteringGeneratorDelegate(JSON_F.createGenerator(w), | |
392 | new NameMatchFilter("invalid"), | |
393 | Inclusion.INCLUDE_NON_NULL, true); | |
394 | final String object = "{'root':{'a0':true,'b':{'value':4}},'b0':false}"; | |
395 | final String JSON = String.format("[%s,%s,%s]", object, object, object); | |
396 | writeJsonDoc(JSON_F, JSON, gen); | |
397 | assertEquals(aposToQuotes("[{'root':{'b':{}}},{'root':{'b':{}}},{'root':{'b':{}}}]"), w.toString()); | |
398 | assertEquals(0, gen.getMatchCount()); | |
399 | } | |
400 | ||
401 | public void testNoMatchFiltering3() throws Exception | |
402 | { | |
403 | StringWriter w = new StringWriter(); | |
404 | ||
405 | FilteringGeneratorDelegate gen = new FilteringGeneratorDelegate(JSON_F.createGenerator(w), | |
406 | new NameMatchFilter("invalid"), | |
407 | Inclusion.INCLUDE_NON_NULL, true); | |
408 | final String object = "{'root':{'a0':true,'b':{'value':4}},'b0':false}"; | |
409 | final String JSON = String.format("[[%s],[%s],[%s]]", object, object, object); | |
410 | writeJsonDoc(JSON_F, JSON, gen); | |
411 | assertEquals(aposToQuotes("[[{'root':{'b':{}}}],[{'root':{'b':{}}}],[{'root':{'b':{}}}]]"), w.toString()); | |
412 | assertEquals(0, gen.getMatchCount()); | |
413 | } | |
414 | ||
415 | public void testNoMatchFiltering4() throws Exception | |
416 | { | |
417 | StringWriter w = new StringWriter(); | |
418 | ||
419 | FilteringGeneratorDelegate gen = new FilteringGeneratorDelegate(JSON_F.createGenerator(w), | |
420 | new StrictNameMatchFilter("invalid"), | |
421 | Inclusion.INCLUDE_NON_NULL, true); | |
422 | final String JSON = "{'root':{'a0':true,'a':{'value':3},'b':{'value':4}},'b0':false}"; | |
423 | writeJsonDoc(JSON_F, JSON, gen); | |
424 | assertEquals(aposToQuotes("{}"), w.toString()); | |
425 | assertEquals(0, gen.getMatchCount()); | |
426 | } | |
427 | ||
428 | public void testNoMatchFiltering5() throws Exception | |
429 | { | |
430 | StringWriter w = new StringWriter(); | |
431 | ||
432 | FilteringGeneratorDelegate gen = new FilteringGeneratorDelegate(JSON_F.createGenerator(w), | |
433 | new StrictNameMatchFilter("invalid"), | |
434 | Inclusion.INCLUDE_NON_NULL, true); | |
435 | final String object = "{'root':{'a0':true,'b':{'value':4}},'b0':false}"; | |
436 | final String JSON = String.format("[%s,%s,%s]", object, object, object); | |
437 | writeJsonDoc(JSON_F, JSON, gen); | |
438 | assertEquals(aposToQuotes("[{},{},{}]"), w.toString()); | |
439 | assertEquals(0, gen.getMatchCount()); | |
440 | } | |
441 | ||
442 | public void testNoMatchFiltering6() throws Exception | |
443 | { | |
444 | StringWriter w = new StringWriter(); | |
445 | ||
446 | FilteringGeneratorDelegate gen = new FilteringGeneratorDelegate(JSON_F.createGenerator(w), | |
447 | new StrictNameMatchFilter("invalid"), | |
448 | Inclusion.INCLUDE_NON_NULL, true); | |
449 | final String object = "{'root':{'a0':true,'b':{'value':4}},'b0':false}"; | |
450 | final String JSON = String.format("[[%s],[%s],[%s]]", object, object, object); | |
451 | writeJsonDoc(JSON_F, JSON, gen); | |
452 | assertEquals(aposToQuotes("[[{}],[{}],[{}]]"), w.toString()); | |
453 | assertEquals(0, gen.getMatchCount()); | |
454 | } | |
455 | ||
456 | public void testValueOmitsFieldName1() throws Exception | |
457 | { | |
458 | StringWriter w = new StringWriter(); | |
459 | ||
460 | FilteringGeneratorDelegate gen = new FilteringGeneratorDelegate(JSON_F.createGenerator(w), | |
461 | new NoArraysFilter(), | |
462 | Inclusion.INCLUDE_NON_NULL, true); | |
463 | final String JSON = "{'root':['a'],'b0':false}"; | |
464 | writeJsonDoc(JSON_F, JSON, gen); | |
465 | assertEquals(aposToQuotes("{'b0':false}"), w.toString()); | |
466 | assertEquals(1, gen.getMatchCount()); | |
467 | } | |
468 | ||
340 | 469 | public void testMultipleMatchFilteringWithPath4() throws Exception |
341 | 470 | { |
342 | 471 | StringWriter w = new StringWriter(); |
343 | 472 | FilteringGeneratorDelegate gen = new FilteringGeneratorDelegate(_createGenerator(w), |
344 | 473 | new NameMatchFilter("b0"), |
345 | true, true); | |
474 | Inclusion.INCLUDE_ALL_AND_PATH, true); | |
346 | 475 | final String JSON = "{'root':{'a0':true,'a':{'value':3},'b':{'value':'abc'}},'b0':false}"; |
347 | 476 | writeJsonDoc(JSON_F, JSON, gen); |
348 | 477 | assertEquals(aposToQuotes("{'b0':false}"), w.toString()); |
349 | 478 | assertEquals(1, gen.getMatchCount()); |
350 | 479 | } |
351 | 480 | |
481 | public void testValueOmitsFieldName2() throws Exception | |
482 | { | |
483 | StringWriter w = new StringWriter(); | |
484 | ||
485 | FilteringGeneratorDelegate gen = new FilteringGeneratorDelegate(JSON_F.createGenerator(w), | |
486 | new NoObjectsFilter(), | |
487 | Inclusion.INCLUDE_NON_NULL, true); | |
488 | final String JSON = "['a',{'root':{'b':{'value':4}},'b0':false}]"; | |
489 | writeJsonDoc(JSON_F, JSON, gen); | |
490 | assertEquals(aposToQuotes("['a']"), w.toString()); | |
491 | assertEquals(1, gen.getMatchCount()); | |
492 | } | |
493 | ||
352 | 494 | public void testIndexMatchWithPath1() throws Exception |
353 | 495 | { |
354 | 496 | StringWriter w = new StringWriter(); |
355 | 497 | FilteringGeneratorDelegate gen = new FilteringGeneratorDelegate(_createGenerator(w), |
356 | 498 | new IndexMatchFilter(1), |
357 | true, true); | |
499 | Inclusion.INCLUDE_ALL_AND_PATH, true); | |
358 | 500 | final String JSON = "{'a':123,'array':[1,2],'ob':{'value0':2,'value':3,'value2':'abc'},'b':true}"; |
359 | 501 | writeJsonDoc(JSON_F, JSON, gen); |
360 | 502 | assertEquals(aposToQuotes("{'array':[2]}"), w.toString()); |
362 | 504 | w = new StringWriter(); |
363 | 505 | gen = new FilteringGeneratorDelegate(_createGenerator(w), |
364 | 506 | new IndexMatchFilter(0), |
365 | true, true); | |
507 | Inclusion.INCLUDE_ALL_AND_PATH, true); | |
366 | 508 | writeJsonDoc(JSON_F, JSON, gen); |
367 | 509 | assertEquals(aposToQuotes("{'array':[1]}"), w.toString()); |
368 | 510 | assertEquals(1, gen.getMatchCount()); |
373 | 515 | StringWriter w = new StringWriter(); |
374 | 516 | FilteringGeneratorDelegate gen = new FilteringGeneratorDelegate(_createGenerator(w), |
375 | 517 | new IndexMatchFilter(0,1), |
376 | true, true); | |
518 | Inclusion.INCLUDE_ALL_AND_PATH, true); | |
377 | 519 | String JSON = "{'a':123,'array':[1,2],'ob':{'value0':2,'value':3,'value2':4},'b':true}"; |
378 | 520 | writeJsonDoc(JSON_F, JSON, gen); |
379 | 521 | assertEquals(aposToQuotes("{'array':[1,2]}"), w.toString()); |
383 | 525 | w = new StringWriter(); |
384 | 526 | gen = new FilteringGeneratorDelegate(_createGenerator(w), |
385 | 527 | new IndexMatchFilter(1, 3, 5), |
386 | true, true); | |
528 | Inclusion.INCLUDE_ALL_AND_PATH, true); | |
387 | 529 | JSON = "{'a':123,'misc':[1,2, null, true, false, 'abc', 123],'ob':null,'b':true}"; |
388 | 530 | writeJsonDoc(JSON_F, JSON, gen); |
389 | 531 | assertEquals(aposToQuotes("{'misc':[2,true,'abc']}"), w.toString()); |
392 | 534 | w = new StringWriter(); |
393 | 535 | gen = new FilteringGeneratorDelegate(_createGenerator(w), |
394 | 536 | new IndexMatchFilter(2,6), |
395 | true, true); | |
537 | Inclusion.INCLUDE_ALL_AND_PATH, true); | |
396 | 538 | JSON = "{'misc':[1,2, null, 0.25, false, 'abc', 11234567890]}"; |
397 | 539 | writeJsonDoc(JSON_F, JSON, gen); |
398 | 540 | assertEquals(aposToQuotes("{'misc':[null,11234567890]}"), w.toString()); |
401 | 543 | w = new StringWriter(); |
402 | 544 | gen = new FilteringGeneratorDelegate(_createGenerator(w), |
403 | 545 | new IndexMatchFilter(1), |
404 | true, true); | |
546 | Inclusion.INCLUDE_ALL_AND_PATH, true); | |
405 | 547 | JSON = "{'misc':[1,0.25,11234567890]}"; |
406 | 548 | writeJsonDoc(JSON_F, JSON, gen); |
407 | 549 | assertEquals(aposToQuotes("{'misc':[0.25]}"), w.toString()); |
414 | 556 | |
415 | 557 | FilteringGeneratorDelegate gen = new FilteringGeneratorDelegate(_createGenerator(w), |
416 | 558 | TokenFilter.INCLUDE_ALL, |
417 | true, true); | |
559 | Inclusion.INCLUDE_ALL_AND_PATH, true); | |
418 | 560 | |
419 | 561 | String value = "val"; |
420 | 562 | |
438 | 580 | { |
439 | 581 | StringWriter w = new StringWriter(); |
440 | 582 | FilteringGeneratorDelegate gen = new FilteringGeneratorDelegate(_createGenerator(w), |
441 | TokenFilter.INCLUDE_ALL, true, true); | |
583 | TokenFilter.INCLUDE_ALL, Inclusion.INCLUDE_ALL_AND_PATH, true); | |
442 | 584 | |
443 | 585 | gen.writeStartArray(); |
444 | 586 | gen.writeRawValue(new char[] { '1'}, 0, 1); |
458 | 600 | { |
459 | 601 | StringWriter w = new StringWriter(); |
460 | 602 | FilteringGeneratorDelegate gen = new FilteringGeneratorDelegate(_createGenerator(w), |
461 | TokenFilter.INCLUDE_ALL, true, true); | |
603 | TokenFilter.INCLUDE_ALL, Inclusion.INCLUDE_ALL_AND_PATH, true); | |
462 | 604 | |
463 | 605 | gen.writeStartObject(); |
464 | 606 | gen.writeNumberField("f1", 1); |
3 | 3 | import java.util.*; |
4 | 4 | |
5 | 5 | import com.fasterxml.jackson.core.*; |
6 | import com.fasterxml.jackson.core.filter.TokenFilter.Inclusion; | |
6 | 7 | |
7 | 8 | @SuppressWarnings("resource") |
8 | 9 | public class BasicParserFilteringTest extends BaseTest |
30 | 31 | |
31 | 32 | @Override |
32 | 33 | protected boolean _includeScalar() { return false; } |
34 | } | |
35 | ||
36 | static class StrictNameMatchFilter extends TokenFilter | |
37 | { | |
38 | private final Set<String> _names; | |
39 | ||
40 | public StrictNameMatchFilter(String... names) { | |
41 | _names = new HashSet<String>(Arrays.asList(names)); | |
42 | } | |
43 | ||
44 | @Override | |
45 | public TokenFilter includeProperty(String name) { | |
46 | if (_names.contains(name)) { | |
47 | return TokenFilter.INCLUDE_ALL; | |
48 | } | |
49 | return null; | |
50 | } | |
33 | 51 | } |
34 | 52 | |
35 | 53 | static class IndexMatchFilter extends TokenFilter |
60 | 78 | protected boolean _includeScalar() { return false; } |
61 | 79 | } |
62 | 80 | |
81 | static class NoObjectsFilter extends TokenFilter | |
82 | { | |
83 | @Override | |
84 | public TokenFilter filterStartObject() { | |
85 | return null; | |
86 | } | |
87 | } | |
88 | ||
63 | 89 | /* |
64 | 90 | /********************************************************** |
65 | 91 | /* Test methods |
83 | 109 | JsonParser p0 = JSON_F.createParser(SIMPLE); |
84 | 110 | FilteringParserDelegate p = new FilteringParserDelegate(p0, |
85 | 111 | new NameMatchFilter("value"), |
86 | false, // includePath | |
112 | Inclusion.ONLY_INCLUDE_ALL, | |
87 | 113 | false // multipleMatches |
88 | 114 | ); |
89 | 115 | String result = readAndWrite(JSON_F, p); |
97 | 123 | JsonParser p0 = JSON_F.createParser(jsonString); |
98 | 124 | FilteringParserDelegate p = new FilteringParserDelegate(p0, |
99 | 125 | new NameMatchFilter("a"), |
100 | true, // includePath | |
126 | Inclusion.INCLUDE_ALL_AND_PATH, | |
101 | 127 | false // multipleMatches |
102 | 128 | ); |
103 | 129 | String result = readAndWrite(JSON_F, p); |
111 | 137 | JsonParser p0 = JSON_F.createParser(jsonString); |
112 | 138 | FilteringParserDelegate p = new FilteringParserDelegate(p0, |
113 | 139 | new NameMatchFilter("value"), |
114 | true, // includePath | |
140 | Inclusion.INCLUDE_ALL_AND_PATH, | |
115 | 141 | false // multipleMatches |
116 | 142 | ); |
117 | 143 | String result = readAndWrite(JSON_F, p); |
125 | 151 | JsonParser p0 = JSON_F.createParser(jsonString); |
126 | 152 | FilteringParserDelegate p = new FilteringParserDelegate(p0, |
127 | 153 | new NameMatchFilter("ob"), |
128 | true, // includePath | |
154 | Inclusion.INCLUDE_ALL_AND_PATH, | |
129 | 155 | false // multipleMatches |
130 | 156 | ); |
131 | 157 | String result = readAndWrite(JSON_F, p); |
139 | 165 | JsonParser p0 = JSON_F.createParser(jsonString); |
140 | 166 | FilteringParserDelegate p = new FilteringParserDelegate(p0, |
141 | 167 | new NameMatchFilter("value"), |
142 | false, // includePath | |
168 | Inclusion.ONLY_INCLUDE_ALL, | |
143 | 169 | false // multipleMatches -false |
144 | 170 | ); |
145 | 171 | String result = readAndWrite(JSON_F, p); |
153 | 179 | JsonParser p0 = JSON_F.createParser(jsonString); |
154 | 180 | FilteringParserDelegate p = new FilteringParserDelegate(p0, |
155 | 181 | new IndexMatchFilter(1), |
156 | false, // includePath | |
182 | Inclusion.ONLY_INCLUDE_ALL, | |
157 | 183 | false // multipleMatches -false |
158 | 184 | ); |
159 | 185 | String result = readAndWrite(JSON_F, p); |
167 | 193 | JsonParser p0 = JSON_F.createParser(jsonString); |
168 | 194 | FilteringParserDelegate p = new FilteringParserDelegate(p0, |
169 | 195 | new IndexMatchFilter(1), |
170 | true, // includePath | |
196 | Inclusion.INCLUDE_ALL_AND_PATH, | |
171 | 197 | false // multipleMatches -false |
172 | 198 | ); |
173 | 199 | String result = readAndWrite(JSON_F, p); |
182 | 208 | JsonParser p0 = JSON_F.createParser(jsonString); |
183 | 209 | FilteringParserDelegate p = new FilteringParserDelegate(p0, |
184 | 210 | new IndexMatchFilter(1), |
185 | true, // includePath | |
211 | Inclusion.INCLUDE_ALL_AND_PATH, | |
186 | 212 | false // multipleMatches -false |
187 | 213 | ); |
188 | 214 | String result = readAndWrite(JSON_F, p); |
196 | 222 | JsonParser p0 = JSON_F.createParser(jsonString); |
197 | 223 | FilteringParserDelegate p = new FilteringParserDelegate(p0, |
198 | 224 | new NameMatchFilter("value"), |
199 | true, // includePath | |
225 | Inclusion.INCLUDE_ALL_AND_PATH, | |
200 | 226 | false // multipleMatches -false |
201 | 227 | ); |
202 | 228 | String result = readAndWrite(JSON_F, p); |
210 | 236 | JsonParser p0 = JSON_F.createParser(jsonString); |
211 | 237 | FilteringParserDelegate p = new FilteringParserDelegate(p0, |
212 | 238 | new NameMatchFilter("ob"), |
213 | true, // includePath | |
239 | Inclusion.INCLUDE_ALL_AND_PATH, | |
214 | 240 | false // multipleMatches -false |
215 | 241 | ); |
216 | 242 | String result = readAndWrite(JSON_F, p); |
224 | 250 | JsonParser p0 = JSON_F.createParser(jsonString); |
225 | 251 | FilteringParserDelegate p = new FilteringParserDelegate(p0, |
226 | 252 | new NameMatchFilter("value"), |
227 | false, // includePath | |
253 | Inclusion.ONLY_INCLUDE_ALL, | |
228 | 254 | true // multipleMatches - true |
229 | 255 | ); |
230 | 256 | String result = readAndWrite(JSON_F, p); |
238 | 264 | JsonParser p0 = JSON_F.createParser(jsonString); |
239 | 265 | FilteringParserDelegate p = new FilteringParserDelegate(p0, |
240 | 266 | new NameMatchFilter("value"), |
241 | true, // includePath | |
267 | Inclusion.INCLUDE_ALL_AND_PATH, | |
242 | 268 | true // multipleMatches - true |
243 | 269 | ); |
244 | 270 | String result = readAndWrite(JSON_F, p); |
252 | 278 | JsonParser p0 = JSON_F.createParser(jsonString); |
253 | 279 | FilteringParserDelegate p = new FilteringParserDelegate(p0, |
254 | 280 | new IndexMatchFilter(1), |
255 | true, // includePath | |
281 | Inclusion.INCLUDE_ALL_AND_PATH, | |
256 | 282 | true // multipleMatches - true |
257 | 283 | ); |
258 | 284 | String result = readAndWrite(JSON_F, p); |
265 | 291 | JsonParser p0 = JSON_F.createParser(SIMPLE); |
266 | 292 | FilteringParserDelegate p = new FilteringParserDelegate(p0, |
267 | 293 | new NameMatchFilter("value0", "value2"), |
268 | true, /* includePath */ true /* multipleMatches */ ); | |
294 | Inclusion.INCLUDE_ALL_AND_PATH, true /* multipleMatches */ ); | |
269 | 295 | String result = readAndWrite(JSON_F, p); |
270 | 296 | assertEquals(aposToQuotes("{'ob':{'value0':2,'value2':0.25}}"), result); |
271 | 297 | assertEquals(2, p.getMatchCount()); |
278 | 304 | JsonParser p0 = JSON_F.createParser(INPUT); |
279 | 305 | FilteringParserDelegate p = new FilteringParserDelegate(p0, |
280 | 306 | new NameMatchFilter("b", "value"), |
281 | true, true); | |
307 | Inclusion.INCLUDE_ALL_AND_PATH, true); | |
282 | 308 | |
283 | 309 | String result = readAndWrite(JSON_F, p); |
284 | 310 | assertEquals(aposToQuotes("{'ob':{'value':3},'b':true}"), result); |
291 | 317 | JsonParser p0 = JSON_F.createParser(JSON); |
292 | 318 | FilteringParserDelegate p = new FilteringParserDelegate(p0, |
293 | 319 | new NameMatchFilter("value"), |
294 | true, true); | |
320 | Inclusion.INCLUDE_ALL_AND_PATH, true); | |
295 | 321 | String result = readAndWrite(JSON_F, p); |
296 | 322 | assertEquals(aposToQuotes("{'root':{'a':{'value':3},'b':{'value':\"foo\"}}}"), result); |
297 | 323 | assertEquals(2, p.getMatchCount()); |
298 | 324 | } |
299 | 325 | |
326 | public void testNoMatchFiltering1() throws Exception | |
327 | { | |
328 | String jsonString = aposToQuotes("{'a':123,'array':[1,2],'ob':{'value0':2,'value':3,'value2':4},'b':true}"); | |
329 | JsonParser p0 = JSON_F.createParser(jsonString); | |
330 | FilteringParserDelegate p = new FilteringParserDelegate(p0, | |
331 | new NameMatchFilter("invalid"), | |
332 | Inclusion.INCLUDE_NON_NULL, | |
333 | true // multipleMatches | |
334 | ); | |
335 | String result = readAndWrite(JSON_F, p); | |
336 | assertEquals(aposToQuotes("{'array':[],'ob':{}}"), result); | |
337 | assertEquals(0, p.getMatchCount()); | |
338 | } | |
339 | ||
340 | public void testNoMatchFiltering2() throws Exception | |
341 | { | |
342 | String object = aposToQuotes("{'a':123,'array':[1,2],'ob':{'value0':2,'value':3,'value2':4},'b':true}"); | |
343 | String jsonString = String.format("[%s,%s,%s]", object, object, object); | |
344 | JsonParser p0 = JSON_F.createParser(jsonString); | |
345 | FilteringParserDelegate p = new FilteringParserDelegate(p0, | |
346 | new NameMatchFilter("invalid"), | |
347 | Inclusion.INCLUDE_NON_NULL, | |
348 | true // multipleMatches | |
349 | ); | |
350 | String result = readAndWrite(JSON_F, p); | |
351 | assertEquals(aposToQuotes("[{'array':[],'ob':{}},{'array':[],'ob':{}},{'array':[],'ob':{}}]"), result); | |
352 | assertEquals(0, p.getMatchCount()); | |
353 | } | |
354 | ||
355 | public void testNoMatchFiltering3() throws Exception | |
356 | { | |
357 | String object = aposToQuotes("{'a':123,'array':[1,2],'ob':{'value0':2,'value':3,'value2':4},'b':true}"); | |
358 | String jsonString = String.format("[[%s],[%s],[%s]]", object, object, object); | |
359 | JsonParser p0 = JSON_F.createParser(jsonString); | |
360 | FilteringParserDelegate p = new FilteringParserDelegate(p0, | |
361 | new NameMatchFilter("invalid"), | |
362 | Inclusion.INCLUDE_NON_NULL, | |
363 | true // multipleMatches | |
364 | ); | |
365 | String result = readAndWrite(JSON_F, p); | |
366 | assertEquals(aposToQuotes("[[{'array':[],'ob':{}}],[{'array':[],'ob':{}}],[{'array':[],'ob':{}}]]"), result); | |
367 | assertEquals(0, p.getMatchCount()); | |
368 | } | |
369 | ||
370 | public void testNoMatchFiltering4() throws Exception | |
371 | { | |
372 | String jsonString = aposToQuotes("{'a':123,'array':[1,2],'ob':{'value0':2,'value':3,'value2':4},'b':true}"); | |
373 | JsonParser p0 = JSON_F.createParser(jsonString); | |
374 | FilteringParserDelegate p = new FilteringParserDelegate(p0, | |
375 | new StrictNameMatchFilter("invalid"), | |
376 | Inclusion.INCLUDE_NON_NULL, | |
377 | true // multipleMatches | |
378 | ); | |
379 | String result = readAndWrite(JSON_F, p); | |
380 | assertEquals(aposToQuotes("{}"), result); | |
381 | assertEquals(0, p.getMatchCount()); | |
382 | } | |
383 | ||
384 | public void testNoMatchFiltering5() throws Exception | |
385 | { | |
386 | String object = aposToQuotes("{'a':123,'array':[1,2],'ob':{'value0':2,'value':3,'value2':4},'b':true}"); | |
387 | String jsonString = String.format("[%s,%s,%s]", object, object, object); | |
388 | JsonParser p0 = JSON_F.createParser(jsonString); | |
389 | FilteringParserDelegate p = new FilteringParserDelegate(p0, | |
390 | new StrictNameMatchFilter("invalid"), | |
391 | Inclusion.INCLUDE_NON_NULL, | |
392 | true // multipleMatches | |
393 | ); | |
394 | String result = readAndWrite(JSON_F, p); | |
395 | assertEquals(aposToQuotes("[{},{},{}]"), result); | |
396 | assertEquals(0, p.getMatchCount()); | |
397 | } | |
398 | ||
399 | public void testNoMatchFiltering6() throws Exception | |
400 | { | |
401 | String object = aposToQuotes("{'a':123,'array':[1,2],'ob':{'value0':2,'value':3,'value2':4},'b':true}"); | |
402 | String jsonString = String.format("[[%s],[%s],[%s]]", object, object, object); | |
403 | JsonParser p0 = JSON_F.createParser(jsonString); | |
404 | FilteringParserDelegate p = new FilteringParserDelegate(p0, | |
405 | new StrictNameMatchFilter("invalid"), | |
406 | Inclusion.INCLUDE_NON_NULL, | |
407 | true // multipleMatches | |
408 | ); | |
409 | String result = readAndWrite(JSON_F, p); | |
410 | assertEquals(aposToQuotes("[[{}],[{}],[{}]]"), result); | |
411 | assertEquals(0, p.getMatchCount()); | |
412 | } | |
413 | ||
414 | public void testValueOmitsFieldName2() throws Exception | |
415 | { | |
416 | String jsonString = aposToQuotes("['a',{'value0':3,'b':{'value':4}},123]"); | |
417 | JsonParser p0 = JSON_F.createParser(jsonString); | |
418 | FilteringParserDelegate p = new FilteringParserDelegate(p0, | |
419 | new NoObjectsFilter(), | |
420 | Inclusion.INCLUDE_NON_NULL, | |
421 | true // multipleMatches | |
422 | ); | |
423 | String result = readAndWrite(JSON_F, p); | |
424 | assertEquals(aposToQuotes("['a',123]"), result); | |
425 | assertEquals(2, p.getMatchCount()); | |
426 | } | |
427 | ||
300 | 428 | public void testIndexMatchWithPath1() throws Exception |
301 | 429 | { |
302 | 430 | FilteringParserDelegate p = new FilteringParserDelegate(JSON_F.createParser(SIMPLE), |
303 | new IndexMatchFilter(1), true, true); | |
431 | new IndexMatchFilter(1), Inclusion.INCLUDE_ALL_AND_PATH, true); | |
304 | 432 | String result = readAndWrite(JSON_F, p); |
305 | 433 | assertEquals(aposToQuotes("{'array':[2]}"), result); |
306 | 434 | assertEquals(1, p.getMatchCount()); |
307 | 435 | |
308 | 436 | p = new FilteringParserDelegate(JSON_F.createParser(SIMPLE), |
309 | new IndexMatchFilter(0), true, true); | |
437 | new IndexMatchFilter(0), Inclusion.INCLUDE_ALL_AND_PATH, true); | |
310 | 438 | result = readAndWrite(JSON_F, p); |
311 | 439 | assertEquals(aposToQuotes("{'array':[1]}"), result); |
312 | 440 | assertEquals(1, p.getMatchCount()); |
315 | 443 | public void testIndexMatchWithPath2() throws Exception |
316 | 444 | { |
317 | 445 | FilteringParserDelegate p = new FilteringParserDelegate(JSON_F.createParser(SIMPLE), |
318 | new IndexMatchFilter(0, 1), true, true); | |
446 | new IndexMatchFilter(0, 1), Inclusion.INCLUDE_ALL_AND_PATH, true); | |
319 | 447 | assertEquals(aposToQuotes("{'array':[1,2]}"), readAndWrite(JSON_F, p)); |
320 | 448 | assertEquals(2, p.getMatchCount()); |
321 | 449 | |
322 | 450 | String JSON = aposToQuotes("{'a':123,'array':[1,2,3,4,5],'b':[1,2,3]}"); |
323 | 451 | p = new FilteringParserDelegate(JSON_F.createParser(JSON), |
324 | new IndexMatchFilter(1, 3), true, true); | |
452 | new IndexMatchFilter(1, 3), Inclusion.INCLUDE_ALL_AND_PATH, true); | |
325 | 453 | assertEquals(aposToQuotes("{'array':[2,4],'b':[2]}"), readAndWrite(JSON_F, p)); |
326 | 454 | assertEquals(3, p.getMatchCount()); |
327 | 455 | } |
331 | 459 | JsonParser p0 = JSON_F.createParser(SIMPLE); |
332 | 460 | JsonParser p = new FilteringParserDelegate(p0, |
333 | 461 | new NameMatchFilter("value"), |
334 | true, // includePath | |
462 | Inclusion.INCLUDE_ALL_AND_PATH, | |
335 | 463 | false // multipleMatches |
336 | 464 | ); |
337 | 465 | |
345 | 473 | JsonParser p0 = JSON_F.createParser(SIMPLE); |
346 | 474 | JsonParser p = new FilteringParserDelegate(p0, |
347 | 475 | new NameMatchFilter("value"), |
348 | true, // includePath | |
476 | Inclusion.INCLUDE_ALL_AND_PATH, | |
349 | 477 | false // multipleMatches |
350 | 478 | ); |
351 | 479 | |
352 | 480 | assertFalse(p.hasCurrentToken()); |
353 | 481 | assertNull(p.getCurrentToken()); |
354 | assertEquals(JsonTokenId.ID_NO_TOKEN, p.getCurrentTokenId()); | |
482 | assertEquals(JsonTokenId.ID_NO_TOKEN, p.currentTokenId()); | |
355 | 483 | assertFalse(p.isExpectedStartObjectToken()); |
356 | 484 | assertFalse(p.isExpectedStartArrayToken()); |
357 | 485 | |
363 | 491 | assertEquals(JsonToken.START_OBJECT, p.getCurrentToken()); |
364 | 492 | assertEquals(JsonToken.START_OBJECT, p.currentToken()); |
365 | 493 | assertEquals(JsonTokenId.ID_START_OBJECT, p.currentTokenId()); |
366 | assertEquals(JsonTokenId.ID_START_OBJECT, p.getCurrentTokenId()); | |
494 | assertEquals(JsonTokenId.ID_START_OBJECT, p.currentTokenId()); | |
367 | 495 | assertTrue(p.isExpectedStartObjectToken()); |
368 | 496 | assertFalse(p.isExpectedStartArrayToken()); |
369 | 497 | |
422 | 550 | JsonParser p0 = JSON_F.createParser(SIMPLE); |
423 | 551 | JsonParser p = new FilteringParserDelegate(p0, |
424 | 552 | new NameMatchFilter("value"), |
425 | true, // includePath | |
553 | Inclusion.INCLUDE_ALL_AND_PATH, | |
426 | 554 | false // multipleMatches |
427 | 555 | ); |
428 | 556 |
2 | 2 | import java.io.*; |
3 | 3 | |
4 | 4 | import com.fasterxml.jackson.core.*; |
5 | import com.fasterxml.jackson.core.filter.TokenFilter.Inclusion; | |
5 | 6 | import com.fasterxml.jackson.core.util.JsonGeneratorDelegate; |
6 | 7 | |
7 | 8 | // for [core#609] |
56 | 57 | } |
57 | 58 | |
58 | 59 | // for [core#609]: will pass in 2.10 for some cases |
59 | @SuppressWarnings("resource") | |
60 | 60 | public void testIssue609() throws Exception |
61 | 61 | { |
62 | 62 | ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); |
63 | 63 | JsonGenerator g = createGenerator(outputStream); |
64 | 64 | g = new FilteringGeneratorDelegate( |
65 | g, NullExcludingTokenFilter.INSTANCE, true, true); | |
65 | g, NullExcludingTokenFilter.INSTANCE, Inclusion.INCLUDE_ALL_AND_PATH, true); | |
66 | 66 | int maxStringLength = 10; |
67 | 67 | g = new StringTruncatingGeneratorDelegate( |
68 | 68 | g, maxStringLength); |
71 | 71 | g.writeString("1234567890!"); |
72 | 72 | g.writeEndObject(); |
73 | 73 | g.close(); |
74 | outputStream.close(); | |
74 | 75 | |
75 | 76 | String json = outputStream.toString("US-ASCII"); |
76 | 77 | assertEquals("{\"message\":\"1234567890\"}", json); |
+40
-39
2 | 2 | import java.io.*; |
3 | 3 | |
4 | 4 | import com.fasterxml.jackson.core.*; |
5 | import com.fasterxml.jackson.core.filter.TokenFilter.Inclusion; | |
5 | 6 | |
6 | 7 | @SuppressWarnings("resource") |
7 | 8 | public class JsonPointerGeneratorFilteringTest extends com.fasterxml.jackson.core.BaseTest |
12 | 13 | |
13 | 14 | public void testSimplePropertyWithPath() throws Exception |
14 | 15 | { |
15 | _assert(SIMPLE_INPUT, "/c", true, "{'c':{'d':{'a':true}}}"); | |
16 | _assert(SIMPLE_INPUT, "/c/d", true, "{'c':{'d':{'a':true}}}"); | |
17 | _assert(SIMPLE_INPUT, "/c/d/a", true, "{'c':{'d':{'a':true}}}"); | |
16 | _assert(SIMPLE_INPUT, "/c", Inclusion.INCLUDE_ALL_AND_PATH, "{'c':{'d':{'a':true}}}"); | |
17 | _assert(SIMPLE_INPUT, "/c/d", Inclusion.INCLUDE_ALL_AND_PATH, "{'c':{'d':{'a':true}}}"); | |
18 | _assert(SIMPLE_INPUT, "/c/d/a", Inclusion.INCLUDE_ALL_AND_PATH, "{'c':{'d':{'a':true}}}"); | |
18 | 19 | |
19 | _assert(SIMPLE_INPUT, "/c/d/a", true, "{'c':{'d':{'a':true}}}"); | |
20 | _assert(SIMPLE_INPUT, "/c/d/a", Inclusion.INCLUDE_ALL_AND_PATH, "{'c':{'d':{'a':true}}}"); | |
20 | 21 | |
21 | _assert(SIMPLE_INPUT, "/a", true, "{'a':1}"); | |
22 | _assert(SIMPLE_INPUT, "/d", true, "{'d':null}"); | |
22 | _assert(SIMPLE_INPUT, "/a", Inclusion.INCLUDE_ALL_AND_PATH, "{'a':1}"); | |
23 | _assert(SIMPLE_INPUT, "/d", Inclusion.INCLUDE_ALL_AND_PATH, "{'d':null}"); | |
23 | 24 | |
24 | 25 | // and then non-match |
25 | _assert(SIMPLE_INPUT, "/x", true, ""); | |
26 | _assert(SIMPLE_INPUT, "/x", Inclusion.INCLUDE_ALL_AND_PATH, ""); | |
26 | 27 | } |
27 | 28 | |
28 | 29 | public void testSimplePropertyWithoutPath() throws Exception |
29 | 30 | { |
30 | _assert(SIMPLE_INPUT, "/c", false, "{'d':{'a':true}}"); | |
31 | _assert(SIMPLE_INPUT, "/c/d", false, "{'a':true}"); | |
32 | _assert(SIMPLE_INPUT, "/c/d/a", false, "true"); | |
31 | _assert(SIMPLE_INPUT, "/c", Inclusion.ONLY_INCLUDE_ALL, "{'d':{'a':true}}"); | |
32 | _assert(SIMPLE_INPUT, "/c/d", Inclusion.ONLY_INCLUDE_ALL, "{'a':true}"); | |
33 | _assert(SIMPLE_INPUT, "/c/d/a", Inclusion.ONLY_INCLUDE_ALL, "true"); | |
33 | 34 | |
34 | _assert(SIMPLE_INPUT, "/a", false, "1"); | |
35 | _assert(SIMPLE_INPUT, "/d", false, "null"); | |
35 | _assert(SIMPLE_INPUT, "/a", Inclusion.ONLY_INCLUDE_ALL, "1"); | |
36 | _assert(SIMPLE_INPUT, "/d", Inclusion.ONLY_INCLUDE_ALL, "null"); | |
36 | 37 | |
37 | 38 | // and then non-match |
38 | _assert(SIMPLE_INPUT, "/x", false, ""); | |
39 | _assert(SIMPLE_INPUT, "/x", Inclusion.ONLY_INCLUDE_ALL, ""); | |
39 | 40 | } |
40 | 41 | |
41 | 42 | public void testArrayElementWithPath() throws Exception |
42 | 43 | { |
43 | _assert(SIMPLE_INPUT, "/b", true, "{'b':[1,2,3]}"); | |
44 | _assert(SIMPLE_INPUT, "/b/1", true, "{'b':[2]}"); | |
45 | _assert(SIMPLE_INPUT, "/b/2", true, "{'b':[3]}"); | |
44 | _assert(SIMPLE_INPUT, "/b", Inclusion.INCLUDE_ALL_AND_PATH, "{'b':[1,2,3]}"); | |
45 | _assert(SIMPLE_INPUT, "/b/1", Inclusion.INCLUDE_ALL_AND_PATH, "{'b':[2]}"); | |
46 | _assert(SIMPLE_INPUT, "/b/2", Inclusion.INCLUDE_ALL_AND_PATH, "{'b':[3]}"); | |
46 | 47 | |
47 | 48 | // and then non-match |
48 | _assert(SIMPLE_INPUT, "/b/8", true, ""); | |
49 | _assert(SIMPLE_INPUT, "/b/8", Inclusion.INCLUDE_ALL_AND_PATH, ""); | |
49 | 50 | } |
50 | 51 | |
51 | 52 | public void testArrayNestedWithPath() throws Exception |
52 | 53 | { |
53 | _assert("{'a':[true,{'b':3,'d':2},false]}", "/a/1/b", true, "{'a':[{'b':3}]}"); | |
54 | _assert("[true,[1]]", "/0", true, "[true]"); | |
55 | _assert("[true,[1]]", "/1", true, "[[1]]"); | |
56 | _assert("[true,[1,2,[true],3],0]", "/0", true, "[true]"); | |
57 | _assert("[true,[1,2,[true],3],0]", "/1", true, "[[1,2,[true],3]]"); | |
54 | _assert("{'a':[true,{'b':3,'d':2},false]}", "/a/1/b", Inclusion.INCLUDE_ALL_AND_PATH, "{'a':[{'b':3}]}"); | |
55 | _assert("[true,[1]]", "/0", Inclusion.INCLUDE_ALL_AND_PATH, "[true]"); | |
56 | _assert("[true,[1]]", "/1", Inclusion.INCLUDE_ALL_AND_PATH, "[[1]]"); | |
57 | _assert("[true,[1,2,[true],3],0]", "/0", Inclusion.INCLUDE_ALL_AND_PATH, "[true]"); | |
58 | _assert("[true,[1,2,[true],3],0]", "/1", Inclusion.INCLUDE_ALL_AND_PATH, "[[1,2,[true],3]]"); | |
58 | 59 | |
59 | _assert("[true,[1,2,[true],3],0]", "/1/2", true, "[[[true]]]"); | |
60 | _assert("[true,[1,2,[true],3],0]", "/1/2/0", true, "[[[true]]]"); | |
61 | _assert("[true,[1,2,[true],3],0]", "/1/3/0", true, ""); | |
60 | _assert("[true,[1,2,[true],3],0]", "/1/2", Inclusion.INCLUDE_ALL_AND_PATH, "[[[true]]]"); | |
61 | _assert("[true,[1,2,[true],3],0]", "/1/2/0", Inclusion.INCLUDE_ALL_AND_PATH, "[[[true]]]"); | |
62 | _assert("[true,[1,2,[true],3],0]", "/1/3/0", Inclusion.INCLUDE_ALL_AND_PATH, ""); | |
62 | 63 | } |
63 | 64 | |
64 | 65 | public void testArrayNestedWithoutPath() throws Exception |
65 | 66 | { |
66 | _assert("{'a':[true,{'b':3,'d':2},false]}", "/a/1/b", false, "3"); | |
67 | _assert("[true,[1,2,[true],3],0]", "/0", false, "true"); | |
68 | _assert("[true,[1,2,[true],3],0]", "/1", false, | |
67 | _assert("{'a':[true,{'b':3,'d':2},false]}", "/a/1/b", Inclusion.ONLY_INCLUDE_ALL, "3"); | |
68 | _assert("[true,[1,2,[true],3],0]", "/0", Inclusion.ONLY_INCLUDE_ALL, "true"); | |
69 | _assert("[true,[1,2,[true],3],0]", "/1", Inclusion.ONLY_INCLUDE_ALL, | |
69 | 70 | "[1,2,[true],3]"); |
70 | 71 | |
71 | _assert("[true,[1,2,[true],3],0]", "/1/2", false, "[true]"); | |
72 | _assert("[true,[1,2,[true],3],0]", "/1/2/0", false, "true"); | |
73 | _assert("[true,[1,2,[true],3],0]", "/1/3/0", false, ""); | |
72 | _assert("[true,[1,2,[true],3],0]", "/1/2", Inclusion.ONLY_INCLUDE_ALL, "[true]"); | |
73 | _assert("[true,[1,2,[true],3],0]", "/1/2/0", Inclusion.ONLY_INCLUDE_ALL, "true"); | |
74 | _assert("[true,[1,2,[true],3],0]", "/1/3/0", Inclusion.ONLY_INCLUDE_ALL, ""); | |
74 | 75 | } |
75 | 76 | |
76 | 77 | // final String SIMPLE_INPUT = aposToQuotes("{'a':1,'b':[1,2,3],'c':{'d':{'a':true}},'d':null}"); |
77 | 78 | |
78 | 79 | public void testArrayElementWithoutPath() throws Exception |
79 | 80 | { |
80 | _assert(SIMPLE_INPUT, "/b", false, "[1,2,3]"); | |
81 | _assert(SIMPLE_INPUT, "/b/1", false, "2"); | |
82 | _assert(SIMPLE_INPUT, "/b/2", false, "3"); | |
81 | _assert(SIMPLE_INPUT, "/b", Inclusion.ONLY_INCLUDE_ALL, "[1,2,3]"); | |
82 | _assert(SIMPLE_INPUT, "/b/1", Inclusion.ONLY_INCLUDE_ALL, "2"); | |
83 | _assert(SIMPLE_INPUT, "/b/2", Inclusion.ONLY_INCLUDE_ALL, "3"); | |
83 | 84 | |
84 | _assert(SIMPLE_INPUT, "/b/8", false, ""); | |
85 | _assert(SIMPLE_INPUT, "/b/8", Inclusion.ONLY_INCLUDE_ALL, ""); | |
85 | 86 | |
86 | 87 | // and then non-match |
87 | _assert(SIMPLE_INPUT, "/x", false, ""); | |
88 | _assert(SIMPLE_INPUT, "/x", Inclusion.ONLY_INCLUDE_ALL, ""); | |
88 | 89 | } |
89 | 90 | |
90 | private void _assert(String input, String pathExpr, boolean includeParent, String exp) | |
91 | private void _assert(String input, String pathExpr, Inclusion tokenFilterInclusion, String exp) | |
91 | 92 | throws Exception |
92 | 93 | { |
93 | 94 | StringWriter w = new StringWriter(); |
95 | 96 | JsonGenerator g0 = JSON_F.createGenerator(w); |
96 | 97 | FilteringGeneratorDelegate g = new FilteringGeneratorDelegate(g0, |
97 | 98 | new JsonPointerBasedFilter(pathExpr), |
98 | includeParent, false); | |
99 | tokenFilterInclusion, false); | |
99 | 100 | |
100 | 101 | try { |
101 | 102 | writeJsonDoc(JSON_F, input, g); |
129 | 130 | JsonGenerator jg = JSON_F.createGenerator(output); |
130 | 131 | |
131 | 132 | FilteringGeneratorDelegate gen = new FilteringGeneratorDelegate(jg, |
132 | new JsonPointerBasedFilter("/noMatch"), true, true); | |
133 | new JsonPointerBasedFilter("/noMatch"), Inclusion.INCLUDE_ALL_AND_PATH, true); | |
133 | 134 | final String[] stuff = new String[] { "foo", "bar" }; |
134 | 135 | |
135 | 136 | switch (mode) { |
+29
-28
2 | 2 | import java.io.StringWriter; |
3 | 3 | |
4 | 4 | import com.fasterxml.jackson.core.*; |
5 | import com.fasterxml.jackson.core.filter.TokenFilter.Inclusion; | |
5 | 6 | |
6 | 7 | public class JsonPointerParserFilteringTest extends com.fasterxml.jackson.core.BaseTest |
7 | 8 | { |
13 | 14 | |
14 | 15 | public void testSimplestWithPath() throws Exception |
15 | 16 | { |
16 | _assert(SIMPLEST_INPUT, "/a", true, "{'a':1}"); | |
17 | _assert(SIMPLEST_INPUT, "/b", true, "{'b':2}"); | |
18 | _assert(SIMPLEST_INPUT, "/c", true, "{'c':3}"); | |
19 | _assert(SIMPLEST_INPUT, "/c/0", true, ""); | |
20 | _assert(SIMPLEST_INPUT, "/d", true, ""); | |
17 | _assert(SIMPLEST_INPUT, "/a", Inclusion.INCLUDE_ALL_AND_PATH, "{'a':1}"); | |
18 | _assert(SIMPLEST_INPUT, "/b", Inclusion.INCLUDE_ALL_AND_PATH, "{'b':2}"); | |
19 | _assert(SIMPLEST_INPUT, "/c", Inclusion.INCLUDE_ALL_AND_PATH, "{'c':3}"); | |
20 | _assert(SIMPLEST_INPUT, "/c/0", Inclusion.INCLUDE_ALL_AND_PATH, ""); | |
21 | _assert(SIMPLEST_INPUT, "/d", Inclusion.INCLUDE_ALL_AND_PATH, ""); | |
21 | 22 | } |
22 | 23 | |
23 | 24 | public void testSimplestNoPath() throws Exception |
24 | 25 | { |
25 | _assert(SIMPLEST_INPUT, "/a", false, "1"); | |
26 | _assert(SIMPLEST_INPUT, "/b", false, "2"); | |
27 | _assert(SIMPLEST_INPUT, "/b/2", false, ""); | |
28 | _assert(SIMPLEST_INPUT, "/c", false, "3"); | |
29 | _assert(SIMPLEST_INPUT, "/d", false, ""); | |
26 | _assert(SIMPLEST_INPUT, "/a", Inclusion.ONLY_INCLUDE_ALL, "1"); | |
27 | _assert(SIMPLEST_INPUT, "/b", Inclusion.ONLY_INCLUDE_ALL, "2"); | |
28 | _assert(SIMPLEST_INPUT, "/b/2", Inclusion.ONLY_INCLUDE_ALL, ""); | |
29 | _assert(SIMPLEST_INPUT, "/c", Inclusion.ONLY_INCLUDE_ALL, "3"); | |
30 | _assert(SIMPLEST_INPUT, "/d", Inclusion.ONLY_INCLUDE_ALL, ""); | |
30 | 31 | } |
31 | 32 | |
32 | 33 | public void testSimpleWithPath() throws Exception |
33 | 34 | { |
34 | _assert(SIMPLE_INPUT, "/c", true, "{'c':{'d':{'a':true}}}"); | |
35 | _assert(SIMPLE_INPUT, "/c/d", true, "{'c':{'d':{'a':true}}}"); | |
36 | _assert(SIMPLE_INPUT, "/a", true, "{'a':1}"); | |
37 | _assert(SIMPLE_INPUT, "/b", true, "{'b':[1,2,3]}"); | |
38 | _assert(SIMPLE_INPUT, "/b/0", true, "{'b':[1]}"); | |
39 | _assert(SIMPLE_INPUT, "/b/1", true, "{'b':[2]}"); | |
40 | _assert(SIMPLE_INPUT, "/b/2", true, "{'b':[3]}"); | |
41 | _assert(SIMPLE_INPUT, "/b/3", true, ""); | |
35 | _assert(SIMPLE_INPUT, "/c", Inclusion.INCLUDE_ALL_AND_PATH, "{'c':{'d':{'a':true}}}"); | |
36 | _assert(SIMPLE_INPUT, "/c/d", Inclusion.INCLUDE_ALL_AND_PATH, "{'c':{'d':{'a':true}}}"); | |
37 | _assert(SIMPLE_INPUT, "/a", Inclusion.INCLUDE_ALL_AND_PATH, "{'a':1}"); | |
38 | _assert(SIMPLE_INPUT, "/b", Inclusion.INCLUDE_ALL_AND_PATH, "{'b':[1,2,3]}"); | |
39 | _assert(SIMPLE_INPUT, "/b/0", Inclusion.INCLUDE_ALL_AND_PATH, "{'b':[1]}"); | |
40 | _assert(SIMPLE_INPUT, "/b/1", Inclusion.INCLUDE_ALL_AND_PATH, "{'b':[2]}"); | |
41 | _assert(SIMPLE_INPUT, "/b/2", Inclusion.INCLUDE_ALL_AND_PATH, "{'b':[3]}"); | |
42 | _assert(SIMPLE_INPUT, "/b/3", Inclusion.INCLUDE_ALL_AND_PATH, ""); | |
42 | 43 | } |
43 | 44 | |
44 | 45 | public void testSimpleNoPath() throws Exception |
45 | 46 | { |
46 | _assert(SIMPLE_INPUT, "/c", false, "{'d':{'a':true}}"); | |
47 | _assert(SIMPLE_INPUT, "/c", Inclusion.ONLY_INCLUDE_ALL, "{'d':{'a':true}}"); | |
47 | 48 | |
48 | _assert(SIMPLE_INPUT, "/c/d", false, "{'a':true}"); | |
49 | _assert(SIMPLE_INPUT, "/a", false, "1"); | |
50 | _assert(SIMPLE_INPUT, "/b", false, "[1,2,3]"); | |
51 | _assert(SIMPLE_INPUT, "/b/0", false, "1"); | |
52 | _assert(SIMPLE_INPUT, "/b/1", false, "2"); | |
53 | _assert(SIMPLE_INPUT, "/b/2", false, "3"); | |
54 | _assert(SIMPLE_INPUT, "/b/3", false, ""); | |
49 | _assert(SIMPLE_INPUT, "/c/d", Inclusion.ONLY_INCLUDE_ALL, "{'a':true}"); | |
50 | _assert(SIMPLE_INPUT, "/a", Inclusion.ONLY_INCLUDE_ALL, "1"); | |
51 | _assert(SIMPLE_INPUT, "/b", Inclusion.ONLY_INCLUDE_ALL, "[1,2,3]"); | |
52 | _assert(SIMPLE_INPUT, "/b/0", Inclusion.ONLY_INCLUDE_ALL, "1"); | |
53 | _assert(SIMPLE_INPUT, "/b/1", Inclusion.ONLY_INCLUDE_ALL, "2"); | |
54 | _assert(SIMPLE_INPUT, "/b/2", Inclusion.ONLY_INCLUDE_ALL, "3"); | |
55 | _assert(SIMPLE_INPUT, "/b/3", Inclusion.ONLY_INCLUDE_ALL, ""); | |
55 | 56 | } |
56 | 57 | |
57 | 58 | @SuppressWarnings("resource") |
58 | void _assert(String input, String pathExpr, boolean includeParent, String exp) | |
59 | void _assert(String input, String pathExpr, TokenFilter.Inclusion inclusion, String exp) | |
59 | 60 | throws Exception |
60 | 61 | { |
61 | 62 | JsonParser p0 = JSON_F.createParser(input); |
62 | 63 | FilteringParserDelegate p = new FilteringParserDelegate(p0, |
63 | 64 | new JsonPointerBasedFilter(pathExpr), |
64 | includeParent, false); | |
65 | inclusion, false); | |
65 | 66 | StringWriter w = new StringWriter(); |
66 | 67 | JsonGenerator g = JSON_F.createGenerator(w); |
67 | 68 |
94 | 94 | { |
95 | 95 | JsonFactory f = new JsonFactory(); |
96 | 96 | // by default should output numbers as-is: |
97 | assertEquals("[1,2,3,1.25,2.25,3001,0.5,-1,12.3]", _writeNumbers(f, false)); | |
98 | assertEquals("[1,2,3,1.25,2.25,3001,0.5,-1,12.3]", _writeNumbers(f, true)); | |
97 | assertEquals("[1,2,3,1.25,2.25,3001,0.5,-1,12.3,null,null,null]", _writeNumbers(f, false)); | |
98 | assertEquals("[1,2,3,1.25,2.25,3001,0.5,-1,12.3,null,null,null]", _writeNumbers(f, true)); | |
99 | 99 | |
100 | 100 | // but if overridden, quotes as Strings |
101 | 101 | f = JsonFactory.builder() |
102 | 102 | .enable(JsonWriteFeature.WRITE_NUMBERS_AS_STRINGS) |
103 | 103 | .build(); |
104 | assertEquals("[\"1\",\"2\",\"3\",\"1.25\",\"2.25\",\"3001\",\"0.5\",\"-1\",\"12.3\"]", | |
104 | assertEquals("[\"1\",\"2\",\"3\",\"1.25\",\"2.25\",\"3001\",\"0.5\",\"-1\",\"12.3\",null,null,null]", | |
105 | 105 | _writeNumbers(f, false)); |
106 | assertEquals("[\"1\",\"2\",\"3\",\"1.25\",\"2.25\",\"3001\",\"0.5\",\"-1\",\"12.3\"]", | |
106 | assertEquals("[\"1\",\"2\",\"3\",\"1.25\",\"2.25\",\"3001\",\"0.5\",\"-1\",\"12.3\",null,null,null]", | |
107 | 107 | _writeNumbers(f, true)); |
108 | 108 | |
109 | 109 | |
227 | 227 | g.writeNumber(BigDecimal.valueOf(0.5)); |
228 | 228 | g.writeNumber("-1"); |
229 | 229 | g.writeNumber(new char[]{'1', '2', '.', '3', '-'}, 0, 4); |
230 | g.writeNumber((String) null); | |
231 | g.writeNumber((BigDecimal) null); | |
232 | g.writeNumber((BigInteger) null); | |
230 | 233 | g.writeEndArray(); |
231 | 234 | g.close(); |
232 | 235 |
9 | 9 | public class JsonFactoryTest |
10 | 10 | extends com.fasterxml.jackson.core.BaseTest |
11 | 11 | { |
12 | private static class BogusCodec extends ObjectCodec { | |
12 | static class BogusCodec extends ObjectCodec { | |
13 | 13 | @Override |
14 | 14 | public Version version() { return null; } |
15 | 15 |
11 | 11 | |
12 | 12 | public class AsyncConcurrencyTest extends AsyncTestBase |
13 | 13 | { |
14 | private final static JsonFactory JSON_F = new JsonFactory(); | |
14 | final static JsonFactory JSON_F = new JsonFactory(); | |
15 | 15 | static { |
16 | 16 | // To make it pass, try: |
17 | 17 | // JSON_F.disable(JsonFactory.Feature.USE_THREAD_LOCAL_FOR_BUFFER_RECYCLING); |
21 | 21 | private final static String TEXT2 = "Some longer text"; |
22 | 22 | private final static String TEXT3 = "and yet more"; |
23 | 23 | private final static String TEXT4 = "... Longest yet although not superbly long still (see 'apos'?)"; |
24 | ||
25 | private final static byte[] JSON_DOC = utf8Bytes(String.format( | |
24 | ||
25 | final static byte[] JSON_DOC = utf8Bytes(String.format( | |
26 | 26 | "[\"%s\", \"%s\",\n\"%s\",\"%s\" ]", TEXT1, TEXT2, TEXT3, TEXT4)); |
27 | 27 | |
28 | 28 | static class WorkUnit { |
29 | ||
30 | 29 | private int stage = 0; |
31 | 30 | |
32 | 31 | private AsyncReaderWrapper parser; |
5 | 5 | import com.fasterxml.jackson.core.async.AsyncTestBase; |
6 | 6 | import com.fasterxml.jackson.core.filter.FilteringParserDelegate; |
7 | 7 | import com.fasterxml.jackson.core.filter.TokenFilter; |
8 | import com.fasterxml.jackson.core.filter.TokenFilter.Inclusion; | |
8 | 9 | |
9 | 10 | // [core#462], [core#463] |
10 | 11 | public class AsyncTokenFilterTest extends AsyncTestBase |
32 | 33 | { |
33 | 34 | NonBlockingJsonParser nonBlockingParser = (NonBlockingJsonParser) JSON_F.createNonBlockingByteArrayParser(); |
34 | 35 | FilteringParserDelegate filteredParser = new FilteringParserDelegate(nonBlockingParser, |
35 | TOKEN_FILTER, true, true); | |
36 | TOKEN_FILTER, Inclusion.INCLUDE_ALL_AND_PATH, true); | |
36 | 37 | nonBlockingParser.feedInput(INPUT_BYTES, 0, INPUT_BYTES.length); |
37 | 38 | int expectedIdx = 0; |
38 | 39 | while (expectedIdx < EXPECTED_TOKENS.length) { |
53 | 54 | NonBlockingJsonParser nbParser = (NonBlockingJsonParser) JSON_F.createNonBlockingByteArrayParser(); |
54 | 55 | @SuppressWarnings("resource") |
55 | 56 | FilteringParserDelegate filteredParser = new FilteringParserDelegate(nbParser, |
56 | TOKEN_FILTER, true, true); | |
57 | TOKEN_FILTER, Inclusion.INCLUDE_ALL_AND_PATH, true); | |
57 | 58 | nbParser.feedInput(INPUT_BYTES, 0, 5); |
58 | 59 | |
59 | 60 | assertToken(JsonToken.START_OBJECT, nbParser.nextToken()); |
86 | 86 | assertEquals(expected, actual); |
87 | 87 | } |
88 | 88 | |
89 | private static class LocData | |
89 | static class LocData | |
90 | 90 | { |
91 | 91 | long lineNumber; |
92 | 92 | long columnNumber; |
86 | 86 | assertEquals(expected, actual); |
87 | 87 | } |
88 | 88 | |
89 | private static class LocData | |
89 | static class LocData | |
90 | 90 | { |
91 | 91 | long lineNumber; |
92 | 92 | long columnNumber; |
68 | 68 | assertToken(JsonToken.START_ARRAY, p.nextToken()); |
69 | 69 | assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); |
70 | 70 | assertEquals(JsonParser.NumberType.INT, p.getNumberType()); |
71 | assertTrue(p.isExpectedNumberIntToken()); | |
71 | 72 | assertEquals(""+EXP_I, p.getText()); |
72 | 73 | |
73 | 74 | if (((short) EXP_I) == EXP_I) { |
107 | 108 | DOC = String.valueOf(EXP_I); |
108 | 109 | p = createParser(mode, DOC + " "); // DataInput requires separator |
109 | 110 | assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); |
111 | assertTrue(p.isExpectedNumberIntToken()); | |
110 | 112 | assertEquals(DOC, p.getText()); |
111 | 113 | |
112 | 114 | int i = p.getIntValue(); |
121 | 123 | DOC = String.valueOf(EXP_I)+".0"; |
122 | 124 | p = createParser(mode, DOC + " "); |
123 | 125 | assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken()); |
126 | assertFalse(p.isExpectedNumberIntToken()); | |
124 | 127 | assertEquals(EXP_I, p.getValueAsInt()); |
125 | 128 | p.close(); |
126 | 129 | |
264 | 267 | public void testLongBoundsChecks() throws Exception |
265 | 268 | { |
266 | 269 | String minLong = String.valueOf(Long.MIN_VALUE).substring(1); |
270 | String belowMinLong = BigInteger.valueOf(Long.MIN_VALUE).subtract(BigInteger.ONE) | |
271 | .toString().substring(1); | |
267 | 272 | String maxLong = String.valueOf(Long.MAX_VALUE); |
273 | String aboveMaxLong = BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.ONE).toString(); | |
268 | 274 | final String VALUE_491 = "1323372036854775807"; // is within range (JACKSON-491) |
269 | 275 | final String OVERFLOW = "9999999999999999999"; // and this one is clearly out |
270 | 276 | |
272 | 278 | assertTrue(NumberInput.inLongRange(maxLong, false)); |
273 | 279 | assertTrue(NumberInput.inLongRange(VALUE_491, true)); |
274 | 280 | assertTrue(NumberInput.inLongRange(VALUE_491, false)); |
281 | ||
275 | 282 | assertFalse(NumberInput.inLongRange(OVERFLOW, false)); |
276 | 283 | assertFalse(NumberInput.inLongRange(OVERFLOW, true)); |
284 | assertFalse(NumberInput.inLongRange(belowMinLong, true)); | |
285 | assertFalse(NumberInput.inLongRange(aboveMaxLong, false)); | |
277 | 286 | |
278 | 287 | char[] cbuf = minLong.toCharArray(); |
279 | 288 | assertTrue(NumberInput.inLongRange(cbuf, 0, cbuf.length, true)); |
282 | 291 | cbuf = VALUE_491.toCharArray(); |
283 | 292 | assertTrue(NumberInput.inLongRange(cbuf, 0, cbuf.length, true)); |
284 | 293 | assertTrue(NumberInput.inLongRange(cbuf, 0, cbuf.length, false)); |
294 | ||
285 | 295 | cbuf = OVERFLOW.toCharArray(); |
286 | 296 | assertFalse(NumberInput.inLongRange(cbuf, 0, cbuf.length, true)); |
297 | assertFalse(NumberInput.inLongRange(cbuf, 0, cbuf.length, false)); | |
298 | ||
299 | cbuf = aboveMaxLong.toCharArray(); | |
287 | 300 | assertFalse(NumberInput.inLongRange(cbuf, 0, cbuf.length, false)); |
288 | 301 | } |
289 | 302 |
0 | 0 | package com.fasterxml.jackson.core.read; |
1 | ||
2 | import java.io.*; | |
3 | 1 | |
4 | 2 | import com.fasterxml.jackson.core.*; |
5 | 3 | import com.fasterxml.jackson.core.json.JsonReadFeature; |
11 | 9 | public class ParserFeaturesTest |
12 | 10 | extends com.fasterxml.jackson.core.BaseTest |
13 | 11 | { |
12 | private final JsonFactory JSON_F = sharedStreamFactory(); | |
13 | ||
14 | 14 | public void testDefaultSettings() throws Exception |
15 | 15 | { |
16 | JsonFactory f = new JsonFactory(); | |
17 | assertTrue(f.isEnabled(StreamReadFeature.AUTO_CLOSE_SOURCE)); | |
16 | assertTrue(JSON_F.isEnabled(StreamReadFeature.AUTO_CLOSE_SOURCE)); | |
18 | 17 | |
19 | JsonParser p = f.createParser(new StringReader("{}")); | |
20 | _testDefaultSettings(p); | |
21 | p.close(); | |
22 | p = f.createParser(new ByteArrayInputStream("{}".getBytes("UTF-8"))); | |
23 | _testDefaultSettings(p); | |
24 | p.close(); | |
18 | _testDefaultSettings(createParser(JSON_F, MODE_INPUT_STREAM, "{}")); | |
19 | _testDefaultSettings(createParser(JSON_F, MODE_READER, "{}")); | |
20 | _testDefaultSettings(createParser(JSON_F, MODE_DATA_INPUT, "{}")); | |
25 | 21 | } |
26 | 22 | |
27 | 23 | @SuppressWarnings("deprecation") |
28 | 24 | public void testDeprecatedDefaultSettings() throws Exception |
29 | 25 | { |
30 | JsonFactory f = sharedStreamFactory(); | |
31 | assertFalse(f.isEnabled(JsonParser.Feature.ALLOW_COMMENTS)); | |
32 | assertFalse(f.isEnabled(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS)); | |
33 | assertFalse(f.isEnabled(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES)); | |
34 | assertFalse(f.isEnabled(JsonParser.Feature.ALLOW_SINGLE_QUOTES)); | |
26 | assertFalse(JSON_F.isEnabled(JsonParser.Feature.ALLOW_COMMENTS)); | |
27 | assertFalse(JSON_F.isEnabled(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS)); | |
28 | assertFalse(JSON_F.isEnabled(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES)); | |
29 | assertFalse(JSON_F.isEnabled(JsonParser.Feature.ALLOW_SINGLE_QUOTES)); | |
35 | 30 | } |
36 | 31 | |
37 | 32 | public void testQuotesRequired() throws Exception |
39 | 34 | _testQuotesRequired(false); |
40 | 35 | _testQuotesRequired(true); |
41 | 36 | } |
42 | ||
43 | // // Tests for [JACKSON-208], unquoted tabs: | |
44 | 37 | |
45 | 38 | public void testTabsDefault() throws Exception |
46 | 39 | { |
60 | 53 | /**************************************************************** |
61 | 54 | */ |
62 | 55 | |
63 | private void _testDefaultSettings(JsonParser p) { | |
56 | private void _testDefaultSettings(JsonParser p) throws Exception { | |
64 | 57 | assertFalse(p.canReadObjectId()); |
65 | 58 | assertFalse(p.canReadTypeId()); |
59 | ||
60 | // [core#619]: | |
61 | assertFalse(p.getReadCapabilities().isEnabled(StreamReadCapability.DUPLICATE_PROPERTIES)); | |
62 | assertFalse(p.getReadCapabilities().isEnabled(StreamReadCapability.SCALARS_AS_OBJECTS)); | |
63 | assertFalse(p.getReadCapabilities().isEnabled(StreamReadCapability.UNTYPED_SCALARS)); | |
64 | ||
65 | p.close(); | |
66 | 66 | } |
67 | ||
67 | ||
68 | 68 | private void _testQuotesRequired(boolean useStream) throws Exception |
69 | 69 | { |
70 | 70 | final String JSON = "{ test : 3 }"; |
28 | 28 | DefaultIndenter defaultIndenterTwo = defaultIndenter.withIndent("9Qh/6,~n"); |
29 | 29 | DefaultIndenter defaultIndenterThree = defaultIndenterTwo.withIndent("9Qh/6,~n"); |
30 | 30 | |
31 | assertEquals("\n", defaultIndenterThree.getEol()); | |
31 | assertEquals(System.lineSeparator(), defaultIndenterThree.getEol()); | |
32 | 32 | assertNotSame(defaultIndenterThree, defaultIndenter); |
33 | 33 | assertSame(defaultIndenterThree, defaultIndenterTwo); |
34 | 34 | } |
9 | 9 | * @see RequestPayload |
10 | 10 | **/ |
11 | 11 | public class RequestPayloadTest { |
12 | @SuppressWarnings("unused") | |
13 | 12 | @Test(expected = IllegalArgumentException.class) |
14 | 13 | public void testFailsToCreateTakingCharSequenceThrowsIllegalArgumentExceptionOne() { |
15 | 14 | new RequestPayload(null); |
16 | 15 | } |
17 | 16 | |
18 | @SuppressWarnings("unused") | |
19 | 17 | @Test(expected = IllegalArgumentException.class) |
20 | 18 | public void testFailsToCreateTakingCharSequenceThrowsIllegalArgumentExceptionTwo() { |
21 | 19 | new RequestPayload(null, "UTF-8"); |
230 | 230 | assertFalse(del.hasTokenId(JsonTokenId.ID_START_OBJECT)); |
231 | 231 | assertTrue(del.isExpectedStartArrayToken()); |
232 | 232 | assertFalse(del.isExpectedStartObjectToken()); |
233 | assertFalse(del.isExpectedNumberIntToken()); | |
233 | 234 | assertEquals("[", del.getText()); |
234 | 235 | assertNotNull(del.getParsingContext()); |
235 | 236 | assertSame(parser.getParsingContext(), del.getParsingContext()); |
250 | 251 | assertEquals((short)1, del.getShortValue()); |
251 | 252 | assertEquals(1f, del.getFloatValue()); |
252 | 253 | assertFalse(del.isNaN()); |
254 | assertTrue(del.isExpectedNumberIntToken()); | |
253 | 255 | assertEquals(NumberType.INT, del.getNumberType()); |
254 | 256 | assertEquals(Integer.valueOf(1), del.getNumberValue()); |
255 | 257 | assertNull(del.getEmbeddedObject()); |
2 | 2 | import com.fasterxml.jackson.core.*; |
3 | 3 | import com.fasterxml.jackson.core.filter.FilteringGeneratorDelegate; |
4 | 4 | import com.fasterxml.jackson.core.filter.JsonPointerBasedFilter; |
5 | import com.fasterxml.jackson.core.filter.TokenFilter.Inclusion; | |
5 | 6 | import com.fasterxml.jackson.core.io.IOContext; |
6 | 7 | import com.fasterxml.jackson.core.json.UTF8JsonGenerator; |
7 | 8 | import com.fasterxml.jackson.core.util.BufferRecycler; |
73 | 74 | |
74 | 75 | FilteringGeneratorDelegate gen = new FilteringGeneratorDelegate(g, |
75 | 76 | new JsonPointerBasedFilter("/escapes"), |
76 | true, // includePath | |
77 | Inclusion.INCLUDE_ALL_AND_PATH, | |
77 | 78 | false // multipleMatches |
78 | 79 | ); |
79 | 80 |
0 | package com.fasterxml.jackson.failing.filter; | |
1 | ||
2 | import com.fasterxml.jackson.core.BaseTest; | |
3 | import com.fasterxml.jackson.core.JsonFactory; | |
4 | import com.fasterxml.jackson.core.JsonParser; | |
5 | import com.fasterxml.jackson.core.filter.FilteringParserDelegate; | |
6 | import com.fasterxml.jackson.core.filter.TokenFilter; | |
7 | import com.fasterxml.jackson.core.filter.TokenFilter.Inclusion; | |
8 | ||
9 | public class BasicParserFilteringTest extends BaseTest { | |
10 | ||
11 | private final JsonFactory JSON_F = new JsonFactory(); | |
12 | ||
13 | static class NoArraysFilter extends TokenFilter | |
14 | { | |
15 | @Override | |
16 | public TokenFilter filterStartArray() { | |
17 | return null; | |
18 | } | |
19 | } | |
20 | ||
21 | // for [core#649] | |
22 | public void testValueOmitsFieldName1() throws Exception | |
23 | { | |
24 | String jsonString = aposToQuotes("{'a':123,'array':[1,2]}"); | |
25 | JsonParser p0 = JSON_F.createParser(jsonString); | |
26 | FilteringParserDelegate p = new FilteringParserDelegate(p0, | |
27 | new NoArraysFilter(), | |
28 | Inclusion.INCLUDE_NON_NULL, | |
29 | true // multipleMatches | |
30 | ); | |
31 | String result = readAndWrite(JSON_F, p); | |
32 | assertEquals(aposToQuotes("{'a':123}"), result); | |
33 | assertEquals(0, p.getMatchCount()); | |
34 | } | |
35 | } |