1/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package tests.api.javax.xml.parsers;
18
19import java.io.File;
20import java.io.FileInputStream;
21import java.io.IOException;
22import java.io.InputStream;
23import java.util.HashMap;
24
25import org.xml.sax.Attributes;
26import org.xml.sax.HandlerBase;
27import org.xml.sax.InputSource;
28import org.xml.sax.Locator;
29import org.xml.sax.SAXParseException;
30import org.xml.sax.helpers.DefaultHandler;
31
32/**
33 * Support for SAXParserTest. Shares the element keys used in the golden files.
34 * Compares the result of the parser with golden data.
35 * Contains the handler classes used to track the output of the parser.
36 */
37class SAXParserTestSupport {
38
39    public static final char SEPARATOR_ELEMENT = '^';
40    public static final char SEPARATOR_STRING = '$';
41    public static final char SEPARATOR_DATA = '#';
42
43    public static final String XML_WF = "/wf/";
44    public static final String XML_NWF = "/nwf/";
45
46    public static final String XML_WF_OUT_DH = "/out_dh/";
47    public static final String XML_WF_OUT_HB = "/out_hb/";
48
49    public static final String XML_SYSTEM_ID = "." + "/systemid/";
50
51    public static final String KEY_IS_START_DOC = "isEndDocument";
52    public static final String KEY_IS_END_DOC = "isStartDocument";
53    public static final String KEY_TEXT = "text";
54    public static final String KEY_ERROR = "error";
55    public static final String KEY_FATAL_ERROR = "fatalError";
56    public static final String KEY_WARNING = "warning";
57    public static final String KEY_END_ELEMENT = "endElement";
58    public static final String KEY_END_PREFIX_MAPPING = "endPrefixMapping";
59    public static final String KEY_IGNORABLE_WHITE_SPACE =
60        "ignorableWhitespace";
61    public static final String KEY_NOTATION_DECL = "notationDecl";
62    public static final String KEY_PROCESSING_INSTRUCTION =
63        "processingInstruction";
64    public static final String KEY_RESOLVE_ENTITY = "resolveEntity";
65    public static final String KEY_DOCUMENT_LOCATORS = "documentLocators";
66    public static final String KEY_SKIPPED_ENTITY = "skippedEntity";
67    public static final String KEY_START_ELEMENT = "startElement";
68    public static final String KEY_START_PREFIX_MAPPING = "startPrefixMapping";
69    public static final String KEY_UNPARSED_ENTITY_DECL = "unparsedEntityDecl";
70
71    static String [] KEYS = {KEY_IS_START_DOC, KEY_IS_END_DOC, KEY_TEXT,
72            KEY_ERROR, KEY_FATAL_ERROR, KEY_WARNING, KEY_END_ELEMENT,
73            KEY_END_PREFIX_MAPPING, KEY_PROCESSING_INSTRUCTION,
74            KEY_SKIPPED_ENTITY, KEY_START_ELEMENT,
75            KEY_START_PREFIX_MAPPING};
76
77    static {
78        String tmp = System.getProperty("java.io.tmpdir", ".");
79
80        new File(tmp).mkdirs();
81        new File(tmp, XML_WF).mkdirs();
82        new File(tmp, XML_NWF).mkdirs();
83        new File(tmp, XML_WF_OUT_DH).mkdirs();
84        new File(tmp, XML_WF_OUT_HB).mkdirs();
85    }
86
87    /**
88     * Initialize the SAXParserTest reference by filling in the data from the
89     * file passed to the method. This will be the reference to compare
90     * against with the output of the parser.
91     */
92    public HashMap<String, String> readFile(String fileName) {
93        HashMap<String, String> storage = new HashMap<String, String>();
94        try {
95
96            InputStream is = new FileInputStream(fileName);
97
98            int c = is.read();
99
100            StringBuffer str = new StringBuffer();
101            int i = 0;
102            while(c != -1) {
103                if((char)c == SEPARATOR_DATA) {
104                  //  if(str.length() > 0) {
105                        if(i < KEYS.length) {
106                            storage.put(KEYS[i], str.toString());
107                        //    System.out.println(str.toString());
108                            str.setLength(0);
109                            i++;
110                        }
111                  //  }
112                } else {
113                    str.append((char)c);
114                }
115                try {
116                    c = is.read();
117                } catch (Exception e) {
118                    c = -1;
119                }
120            }
121            try {
122                is.close();
123            } catch (IOException e) {
124            }
125
126        } catch(IOException ioe) {
127            System.out.println("IOException during processing the file: "
128                    + fileName);
129        }
130        return storage;
131    }
132
133    /**
134     * Compares the content of two HashMaps. One map should be the reference
135     * containing the correct string for each xml document element and the other
136     * should contain the elements filled with output from the parser.
137     *
138     * @param original the reference
139     * @param result the result of the parser
140     * @return true if they're equal.
141     */
142    public static boolean equalsMaps(HashMap<String, String> original,
143            HashMap<String, String> result) {
144
145        if(original == null && result == null) {
146            return true;
147        } else {
148            if(original.size() != result.size()) return false;
149
150            for(int i = 0; i < KEYS.length; i++) {
151                if(!original.get(KEYS[i]).equals(result.get(KEYS[i]))) {
152                    System.out.println("for "+KEYS[i]+": original:" +
153                            original.get(KEYS[i]));
154                    System.out.println();
155                    System.out.println("  result:" + result.get(KEYS[i]));
156                    System.out.println();
157                    return false;
158                }
159            }
160            return true;
161        }
162    }
163
164    static class MyDefaultHandler extends DefaultHandler {
165
166        public StringBuffer data_isEndDocument = new StringBuffer();
167        public StringBuffer data_isStartDocument = new StringBuffer();
168        public StringBuffer data_text = new StringBuffer();
169        public StringBuffer data_error = new StringBuffer();
170        public StringBuffer data_fatalError = new StringBuffer();
171        public StringBuffer data_warning = new StringBuffer();
172        public StringBuffer data_endElement = new StringBuffer();
173        public StringBuffer data_endPrefixMapping = new StringBuffer();
174        public StringBuffer data_processingInstruction = new StringBuffer();
175        public StringBuffer data_skippedEntity = new StringBuffer();
176        public StringBuffer data_startElement = new StringBuffer();
177        public StringBuffer data_startPrefixMapping = new StringBuffer();
178
179        public HashMap<String, String> createData() {
180            HashMap<String, String> hm = new HashMap<String, String>();
181            hm.put(KEY_IS_END_DOC, data_isEndDocument.toString());
182            hm.put(KEY_IS_START_DOC, data_isStartDocument.toString());
183            hm.put(KEY_TEXT, data_text.toString());
184            hm.put(KEY_ERROR, data_error.toString());
185            hm.put(KEY_FATAL_ERROR, data_fatalError.toString());
186            hm.put(KEY_WARNING, data_warning.toString());
187            hm.put(KEY_END_ELEMENT, data_endElement.toString());
188            hm.put(KEY_END_PREFIX_MAPPING, data_endPrefixMapping.toString());
189
190            hm.put(KEY_PROCESSING_INSTRUCTION,
191                    data_processingInstruction.toString());
192            hm.put(KEY_SKIPPED_ENTITY, data_skippedEntity.toString());
193            hm.put(KEY_START_ELEMENT, data_startElement.toString());
194            hm.put(KEY_START_PREFIX_MAPPING,
195                    data_startPrefixMapping.toString());
196            return hm;
197        }
198
199        public void printMap() {
200            System.out.print(data_isStartDocument.toString() + SEPARATOR_DATA +
201                    data_isEndDocument.toString() + SEPARATOR_DATA +
202                    data_text.toString() + SEPARATOR_DATA +
203                    data_error.toString()+ SEPARATOR_DATA +
204                    data_fatalError.toString()+ SEPARATOR_DATA +
205                    data_warning.toString()+ SEPARATOR_DATA +
206                    data_endElement.toString() + SEPARATOR_DATA+
207                    data_endPrefixMapping.toString()+ SEPARATOR_DATA +
208                    data_processingInstruction.toString() + SEPARATOR_DATA +
209                    data_skippedEntity.toString() +  SEPARATOR_DATA +
210                    data_startElement.toString() + SEPARATOR_DATA +
211                    data_startPrefixMapping.toString()+ SEPARATOR_DATA);
212        }
213
214        @Override
215        public void characters(char[] ch, int start, int length) {
216            String str = new String(ch, start, length);
217            data_text.append(str);
218            // different sax parsers are allowed to handle chunking differently,
219            // therefore we cannot rely on identical chunks being delivered.
220            //data_text.append(ParsingSupport.SEPARATOR_ELEMENT);
221        }
222
223        @Override
224        public void endDocument() {
225            data_isEndDocument.append(true);
226            data_isEndDocument.append(SEPARATOR_ELEMENT);
227        }
228
229        @Override
230        public void endElement(String uri, String localName, String qName) {
231            StringBuffer sb = new StringBuffer();
232            sb.append(uri);
233            sb.append(SEPARATOR_STRING);
234            sb.append(localName);
235            sb.append(SEPARATOR_STRING);
236            sb.append(qName);
237            data_endElement.append(sb);
238            data_endElement.append(SEPARATOR_ELEMENT);
239        }
240
241        @Override
242        public void endPrefixMapping(String prefix) {
243            data_endPrefixMapping.append(prefix);
244            data_endPrefixMapping.append(SEPARATOR_ELEMENT);
245        }
246
247        @Override
248        public void error(SAXParseException e) {
249            data_error.append(e);
250            data_error.append(SEPARATOR_ELEMENT);
251        }
252
253        @Override
254        public void fatalError(SAXParseException e) {
255            data_fatalError.append(e);
256            data_fatalError.append(SEPARATOR_ELEMENT);
257        }
258
259        @Override
260        public void ignorableWhitespace(char[] ch, int start, int length) {
261            /*    String s = new String(ch, start, length);
262            ignorableWhitespace.append(s);
263            ignorableWhitespace.append(ParsingSupport.SEPARATOR_ELEMENT);*/
264        }
265
266        @Override
267        public void notationDecl(String name, String publicId,
268                String systemId) {
269            /* data_notationDecl.append(name + ParsingSupport.SEPARATOR_STRING +
270                              publicId + ParsingSupport.SEPARATOR_STRING +
271                              systemId + ParsingSupport.SEPARATOR_STRING);
272            data_notationDecl.append(ParsingSupport.SEPARATOR_ELEMENT);*/
273        }
274
275        @Override
276        public void processingInstruction(String target, String data) {
277            data_processingInstruction.append(target + SEPARATOR_STRING + data);
278            data_processingInstruction.append(SEPARATOR_ELEMENT);
279        }
280
281        @Override
282        public InputSource    resolveEntity(String publicId, String systemId) {
283            // data_resolveEntity.append(publicId +
284            //            ParsingSupport.SEPARATOR_STRING + systemId);
285            // data_resolveEntity.append(ParsingSupport.SEPARATOR_ELEMENT);
286            return null;
287        }
288
289        @Override
290        public void setDocumentLocator(Locator locator) {
291            //       data_documentLocators.append(locator);
292            // data_documentLocators.append(ParsingSupport.SEPARATOR_ELEMENT);
293        }
294
295        @Override
296        public void skippedEntity(String name) {
297            data_skippedEntity.append(name);
298            data_skippedEntity.append(SEPARATOR_ELEMENT);
299        }
300
301        @Override
302        public void startDocument() {
303            data_isStartDocument.append(true);
304            data_isStartDocument.append(SEPARATOR_ELEMENT);
305        }
306
307        @Override
308        public void startElement(String uri, String localName, String qName,
309                Attributes attributes) {
310            data_startElement.append(uri);
311            data_startElement.append(SEPARATOR_STRING);
312            data_startElement.append(localName);
313            data_startElement.append(SEPARATOR_STRING);
314            data_startElement.append(qName);
315
316            for(int i = 0; i < attributes.getLength(); i ++)
317                data_startElement.append(
318                        SEPARATOR_STRING +attributes.getQName(i) +
319                        SEPARATOR_STRING + attributes.getValue(i));
320
321            data_isStartDocument.append(SEPARATOR_ELEMENT);
322        }
323
324        @Override
325        public void startPrefixMapping(String prefix, String uri) {
326            data_startPrefixMapping.append(prefix + SEPARATOR_STRING + uri);
327        }
328
329        @Override
330        public void unparsedEntityDecl(String name, String publicId,
331                String systemId, String notationName) {
332            // data_unparsedEntityDecl.append(name
333            //     + ParsingSupport.SEPARATOR_STRING + publicId
334            //     + ParsingSupport.SEPARATOR_STRING
335            //     + systemId + ParsingSupport.SEPARATOR_STRING + notationName);
336        }
337
338        @Override
339        public void warning(SAXParseException e) {
340            data_warning.append(e);
341        }
342    }
343
344    @SuppressWarnings("deprecation")
345    static class MyHandler extends HandlerBase {
346
347        public StringBuffer data_isEndDocument = new StringBuffer();
348        public StringBuffer data_isStartDocument = new StringBuffer();
349        public StringBuffer data_text = new StringBuffer();
350        public StringBuffer data_error = new StringBuffer();
351        public StringBuffer data_fatalError = new StringBuffer();
352        public StringBuffer data_warning = new StringBuffer();
353        public StringBuffer data_endElement = new StringBuffer();
354        public StringBuffer data_endPrefixMapping = new StringBuffer();
355        public StringBuffer data_processingInstruction = new StringBuffer();
356        public StringBuffer data_skippedEntity = new StringBuffer();
357        public StringBuffer data_startElement = new StringBuffer();
358        public StringBuffer data_startPrefixMapping = new StringBuffer();
359
360        public void printMap() {
361            System.out.print(data_isStartDocument.toString() + SEPARATOR_DATA +
362                    data_isEndDocument.toString() + SEPARATOR_DATA +
363                    data_text.toString() + SEPARATOR_DATA +
364                    data_error.toString()+ SEPARATOR_DATA +
365                    data_fatalError.toString()+ SEPARATOR_DATA +
366                    data_warning.toString()+ SEPARATOR_DATA +
367                    data_endElement.toString() + SEPARATOR_DATA+
368                    data_endPrefixMapping.toString()+ SEPARATOR_DATA +
369                    data_processingInstruction.toString() + SEPARATOR_DATA +
370                    data_skippedEntity.toString() +  SEPARATOR_DATA +
371                    data_startElement.toString() + SEPARATOR_DATA +
372                    data_startPrefixMapping.toString()+ SEPARATOR_DATA);
373        }
374
375        public HashMap<String, String> createData() {
376            HashMap<String, String> hm = new HashMap<String, String>();
377            hm.put(KEY_IS_END_DOC, data_isEndDocument.toString());
378            hm.put(KEY_IS_START_DOC, data_isStartDocument.toString());
379            hm.put(KEY_TEXT, data_text.toString());
380            hm.put(KEY_ERROR, data_error.toString());
381            hm.put(KEY_FATAL_ERROR, data_fatalError.toString());
382            hm.put(KEY_WARNING, data_warning.toString());
383            hm.put(KEY_END_ELEMENT, data_endElement.toString());
384            hm.put(KEY_END_PREFIX_MAPPING, data_endPrefixMapping.toString());
385            hm.put(KEY_PROCESSING_INSTRUCTION,
386                    data_processingInstruction.toString());
387            hm.put(KEY_SKIPPED_ENTITY, data_skippedEntity.toString());
388            hm.put(KEY_START_ELEMENT, data_startElement.toString());
389            hm.put(KEY_START_PREFIX_MAPPING,
390                    data_startPrefixMapping.toString());
391            return hm;
392        }
393
394        @Override
395        public void characters(char[] ch, int start, int length) {
396            String str = new String(ch, start, length);
397            data_text.append(str);
398            // different sax parsers are allowed to handle chunking differently,
399            // therefore we cannot rely on identical chunks being delivered.
400            //data_text.append(ParsingSupport.SEPARATOR_ELEMENT);
401        }
402
403        @Override
404        public void    endDocument() {
405            data_isEndDocument.append(true);
406            data_isEndDocument.append(SEPARATOR_ELEMENT);
407        }
408
409        public void endElement(String uri, String localName, String qName) {
410            StringBuffer sb = new StringBuffer();
411            sb.append(uri);
412            sb.append(SEPARATOR_STRING);
413            sb.append(localName);
414            sb.append(SEPARATOR_STRING);
415            sb.append(qName);
416            data_endElement.append(sb);
417            data_endElement.append(SEPARATOR_ELEMENT);
418        }
419
420        @Override
421        public void error(SAXParseException e) {
422            data_error.append(e);
423            data_error.append(SEPARATOR_ELEMENT);
424        }
425
426        @Override
427        public void fatalError(SAXParseException e) {
428            data_fatalError.append(e);
429            data_fatalError.append(SEPARATOR_ELEMENT);
430        }
431
432        @Override
433        public void ignorableWhitespace(char[] ch, int start, int length) {
434
435        }
436
437        @Override
438        public void notationDecl(String name, String publicId,
439                String systemId) {
440
441        }
442
443        @Override
444        public void processingInstruction(String target, String data) {
445            data_processingInstruction.append(target + SEPARATOR_STRING + data);
446            data_processingInstruction.append(SEPARATOR_ELEMENT);
447        }
448
449        @Override
450        public InputSource    resolveEntity(String publicId, String systemId) {
451            return null;
452        }
453
454        @Override
455        public void setDocumentLocator(Locator locator) {
456
457        }
458
459        @Override
460        public void startDocument() {
461            data_isStartDocument.append(true);
462            data_isStartDocument.append(SEPARATOR_ELEMENT);
463        }
464
465        public void startElement(String uri, String localName, String qName,
466                Attributes attributes) {
467            data_startElement.append(uri);
468            data_startElement.append(SEPARATOR_STRING);
469            data_startElement.append(localName);
470            data_startElement.append(SEPARATOR_STRING);
471            data_startElement.append(qName);
472
473            for(int i = 0; i < attributes.getLength(); i ++)
474                data_startElement.append(SEPARATOR_STRING
475                        + attributes.getQName(i) +
476                        SEPARATOR_STRING + attributes.getValue(i));
477
478            data_isStartDocument.append(SEPARATOR_ELEMENT);
479        }
480
481        @Override
482        public void unparsedEntityDecl(String name, String publicId,
483                String systemId, String notationName) {
484
485        }
486
487        @Override
488        public void warning(SAXParseException e) {
489            data_warning.append(e);
490        }
491    }
492}
493