Fix license issues in dmaap dr
[dmaap/datarouter.git] / datarouter-prov / src / main / java / org / json / XMLTokener.java
1 /*******************************************************************************\r
2  * ============LICENSE_START==================================================\r
3  * * org.onap.dmaap\r
4  * * ===========================================================================\r
5  * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.\r
6  * * ===========================================================================\r
7  * * Licensed under the Apache License, Version 2.0 (the "License");\r
8  * * you may not use this file except in compliance with the License.\r
9  * * You may obtain a copy of the License at\r
10  * * \r
11  *  *      http://www.apache.org/licenses/LICENSE-2.0\r
12  * * \r
13  *  * Unless required by applicable law or agreed to in writing, software\r
14  * * distributed under the License is distributed on an "AS IS" BASIS,\r
15  * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
16  * * See the License for the specific language governing permissions and\r
17  * * limitations under the License.\r
18  * * ============LICENSE_END====================================================\r
19  * *\r
20  * * ECOMP is a trademark and service mark of AT&T Intellectual Property.\r
21  * *\r
22  ******************************************************************************/\r
23 package org.json;\r
24 \r
25 import java.util.HashMap;\r
26 import java.util.Map;\r
27 \r
28 \r
29 \r
30 \r
31 public class XMLTokener extends JSONTokener {\r
32 \r
33 \r
34    /** The table of entity values. It initially contains Character values for\r
35     * amp, apos, gt, lt, quot.\r
36     */\r
37    public static final Map<String,Character> entity;\r
38 \r
39    static {\r
40        entity = new HashMap<String,Character>(8);\r
41        entity.put("amp",  XML.AMP);\r
42        entity.put("apos", XML.APOS);\r
43        entity.put("gt",   XML.GT);\r
44        entity.put("lt",   XML.LT);\r
45        entity.put("quot", XML.QUOT);\r
46    }\r
47 \r
48     /**\r
49      * Construct an XMLTokener from a string.\r
50      * @param s A source string.\r
51      */\r
52     public XMLTokener(String s) {\r
53         super(s);\r
54     }\r
55 \r
56     /**\r
57      * Get the text in the CDATA block.\r
58      * @return The string up to the <code>]]&gt;</code>.\r
59      * @throws JSONException If the <code>]]&gt;</code> is not found.\r
60      */\r
61     public String nextCDATA() throws JSONException {\r
62         char         c;\r
63         int          i;\r
64         StringBuffer sb = new StringBuffer();\r
65         for (;;) {\r
66             c = next();\r
67             if (end()) {\r
68                 throw syntaxError("Unclosed CDATA");\r
69             }\r
70             sb.append(c);\r
71             i = sb.length() - 3;\r
72             if (i >= 0 && sb.charAt(i) == ']' &&\r
73                           sb.charAt(i + 1) == ']' && sb.charAt(i + 2) == '>') {\r
74                 sb.setLength(i);\r
75                 return sb.toString();\r
76             }\r
77         }\r
78     }\r
79 \r
80 \r
81     /**\r
82      * Get the next XML outer token, trimming whitespace. There are two kinds\r
83      * of tokens: the '<' character which begins a markup tag, and the content\r
84      * text between markup tags.\r
85      *\r
86      * @return  A string, or a '<' Character, or null if there is no more\r
87      * source text.\r
88      * @throws JSONException\r
89      */\r
90     public Object nextContent() throws JSONException {\r
91         char         c;\r
92         StringBuffer sb;\r
93         do {\r
94             c = next();\r
95         } while (Character.isWhitespace(c));\r
96         if (c == 0) {\r
97             return null;\r
98         }\r
99         if (c == '<') {\r
100             return XML.LT;\r
101         }\r
102         sb = new StringBuffer();\r
103         for (;;) {\r
104             if (c == '<' || c == 0) {\r
105                 back();\r
106                 return sb.toString().trim();\r
107             }\r
108             if (c == '&') {\r
109                 sb.append(nextEntity(c));\r
110             } else {\r
111                 sb.append(c);\r
112             }\r
113             c = next();\r
114         }\r
115     }\r
116 \r
117 \r
118     /**\r
119      * Return the next entity. These entities are translated to Characters:\r
120      *     <code>&amp;  &apos;  &gt;  &lt;  &quot;</code>.\r
121      * @param ampersand An ampersand character.\r
122      * @return  A Character or an entity String if the entity is not recognized.\r
123      * @throws JSONException If missing ';' in XML entity.\r
124      */\r
125     public Object nextEntity(char ampersand) throws JSONException {\r
126         StringBuffer sb = new StringBuffer();\r
127         for (;;) {\r
128             char c = next();\r
129             if (Character.isLetterOrDigit(c) || c == '#') {\r
130                 sb.append(Character.toLowerCase(c));\r
131             } else if (c == ';') {\r
132                 break;\r
133             } else {\r
134                 throw syntaxError("Missing ';' in XML entity: &" + sb);\r
135             }\r
136         }\r
137         String string = sb.toString();\r
138         Object object = entity.get(string);\r
139         return object != null ? object : ampersand + string + ";";\r
140     }\r
141 \r
142 \r
143     /**\r
144      * Returns the next XML meta token. This is used for skipping over <!...>\r
145      * and <?...?> structures.\r
146      * @return Syntax characters (<code>< > / = ! ?</code>) are returned as\r
147      *  Character, and strings and names are returned as Boolean. We don't care\r
148      *  what the values actually are.\r
149      * @throws JSONException If a string is not properly closed or if the XML\r
150      *  is badly structured.\r
151      */\r
152     public Object nextMeta() throws JSONException {\r
153         char c;\r
154         char q;\r
155         do {\r
156             c = next();\r
157         } while (Character.isWhitespace(c));\r
158         switch (c) {\r
159         case 0:\r
160             throw syntaxError("Misshaped meta tag");\r
161         case '<':\r
162             return XML.LT;\r
163         case '>':\r
164             return XML.GT;\r
165         case '/':\r
166             return XML.SLASH;\r
167         case '=':\r
168             return XML.EQ;\r
169         case '!':\r
170             return XML.BANG;\r
171         case '?':\r
172             return XML.QUEST;\r
173         case '"':\r
174         case '\'':\r
175             q = c;\r
176             for (;;) {\r
177                 c = next();\r
178                 if (c == 0) {\r
179                     throw syntaxError("Unterminated string");\r
180                 }\r
181                 if (c == q) {\r
182                     return Boolean.TRUE;\r
183                 }\r
184             }\r
185         default:\r
186             for (;;) {\r
187                 c = next();\r
188                 if (Character.isWhitespace(c)) {\r
189                     return Boolean.TRUE;\r
190                 }\r
191                 switch (c) {\r
192                 case 0:\r
193                 case '<':\r
194                 case '>':\r
195                 case '/':\r
196                 case '=':\r
197                 case '!':\r
198                 case '?':\r
199                 case '"':\r
200                 case '\'':\r
201                     back();\r
202                     return Boolean.TRUE;\r
203                 }\r
204             }\r
205         }\r
206     }\r
207 \r
208 \r
209     /**\r
210      * Get the next XML Token. These tokens are found inside of angle\r
211      * brackets. It may be one of these characters: <code>/ > = ! ?</code> or it\r
212      * may be a string wrapped in single quotes or double quotes, or it may be a\r
213      * name.\r
214      * @return a String or a Character.\r
215      * @throws JSONException If the XML is not well formed.\r
216      */\r
217     public Object nextToken() throws JSONException {\r
218         char c;\r
219         char q;\r
220         StringBuffer sb;\r
221         do {\r
222             c = next();\r
223         } while (Character.isWhitespace(c));\r
224         switch (c) {\r
225         case 0:\r
226             throw syntaxError("Misshaped element");\r
227         case '<':\r
228             throw syntaxError("Misplaced '<'");\r
229         case '>':\r
230             return XML.GT;\r
231         case '/':\r
232             return XML.SLASH;\r
233         case '=':\r
234             return XML.EQ;\r
235         case '!':\r
236             return XML.BANG;\r
237         case '?':\r
238             return XML.QUEST;\r
239 \r
240 // Quoted string\r
241 \r
242         case '"':\r
243         case '\'':\r
244             q = c;\r
245             sb = new StringBuffer();\r
246             for (;;) {\r
247                 c = next();\r
248                 if (c == 0) {\r
249                     throw syntaxError("Unterminated string");\r
250                 }\r
251                 if (c == q) {\r
252                     return sb.toString();\r
253                 }\r
254                 if (c == '&') {\r
255                     sb.append(nextEntity(c));\r
256                 } else {\r
257                     sb.append(c);\r
258                 }\r
259             }\r
260         default:\r
261 \r
262 // Name\r
263 \r
264             sb = new StringBuffer();\r
265             for (;;) {\r
266                 sb.append(c);\r
267                 c = next();\r
268                 if (Character.isWhitespace(c)) {\r
269                     return sb.toString();\r
270                 }\r
271                 switch (c) {\r
272                 case 0:\r
273                     return sb.toString();\r
274                 case '>':\r
275                 case '/':\r
276                 case '=':\r
277                 case '!':\r
278                 case '?':\r
279                 case '[':\r
280                 case ']':\r
281                     back();\r
282                     return sb.toString();\r
283                 case '<':\r
284                 case '"':\r
285                 case '\'':\r
286                     throw syntaxError("Bad character in a name");\r
287                 }\r
288             }\r
289         }\r
290     }\r
291 \r
292 \r
293     /**\r
294      * Skip characters until past the requested string.\r
295      * If it is not found, we are left at the end of the source with a result of false.\r
296      * @param to A string to skip past.\r
297      * @throws JSONException\r
298      */\r
299     public boolean skipPast(String to) throws JSONException {\r
300         boolean b;\r
301         char c;\r
302         int i;\r
303         int j;\r
304         int offset = 0;\r
305         int length = to.length();\r
306         char[] circle = new char[length];\r
307 \r
308         /*\r
309          * First fill the circle buffer with as many characters as are in the\r
310          * to string. If we reach an early end, bail.\r
311          */\r
312 \r
313         for (i = 0; i < length; i += 1) {\r
314             c = next();\r
315             if (c == 0) {\r
316                 return false;\r
317             }\r
318             circle[i] = c;\r
319         }\r
320 \r
321         /* We will loop, possibly for all of the remaining characters. */\r
322 \r
323         for (;;) {\r
324             j = offset;\r
325             b = true;\r
326 \r
327             /* Compare the circle buffer with the to string. */\r
328 \r
329             for (i = 0; i < length; i += 1) {\r
330                 if (circle[j] != to.charAt(i)) {\r
331                     b = false;\r
332                     break;\r
333                 }\r
334                 j += 1;\r
335                 if (j >= length) {\r
336                     j -= length;\r
337                 }\r
338             }\r
339 \r
340             /* If we exit the loop with b intact, then victory is ours. */\r
341 \r
342             if (b) {\r
343                 return true;\r
344             }\r
345 \r
346             /* Get the next character. If there isn't one, then defeat is ours. */\r
347 \r
348             c = next();\r
349             if (c == 0) {\r
350                 return false;\r
351             }\r
352             /*\r
353              * Shove the character in the circle buffer and advance the\r
354              * circle offset. The offset is mod n.\r
355              */\r
356             circle[offset] = c;\r
357             offset += 1;\r
358             if (offset >= length) {\r
359                 offset -= length;\r
360             }\r
361         }\r
362     }\r
363 }\r