source: icXML/icXML-devel/tests/src/XSerializerTest/XSerializerTest.cpp @ 2733

Last change on this file since 2733 was 2733, checked in by cameron, 6 years ago

More path fixes.

File size: 16.0 KB
Line 
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements.  See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License.  You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18/*
19* $Id: XSerializerTest.cpp 833057 2009-11-05 15:25:10Z borisk $
20*/
21#if HAVE_CONFIG_H
22#       include <config.h>
23#endif
24// ---------------------------------------------------------------------------
25//  Includes
26// ---------------------------------------------------------------------------
27#include <icxercesc/framework/XMLGrammarPoolImpl.hpp>
28#include <xercesc/internal/MemoryManagerImpl.hpp>
29#include <xercesc/internal/XSerializationException.hpp>
30#include <xercesc/internal/BinMemOutputStream.hpp>
31#include <xercesc/util/BinMemInputStream.hpp>
32
33#include "XSerializerTest.hpp"
34
35#if defined(XERCES_NEW_IOSTREAMS)
36#include <fstream>
37#else
38#include <fstream.h>
39#endif
40
41// ---------------------------------------------------------------------------
42//  command line option variables
43// ---------------------------------------------------------------------------
44static const char*                  xmlFile            = 0;
45static SAX2XMLReader::ValSchemes    valScheme          = SAX2XMLReader::Val_Auto;
46static bool                         doNamespaces       = true;
47static bool                         doSchema           = true;
48static bool                         schemaFullChecking = false;
49static bool                         doList             = false;
50static bool                         namespacePrefixes  = false;
51static bool                         errorOccurred      = false;
52static bool                         recognizeNEL       = false;
53
54static char                         localeStr[64];
55
56// ---------------------------------------------------------------------------
57//  parsing components
58// ---------------------------------------------------------------------------
59static XSerializerHandlers*     handler     = 0;
60
61/***
62*
63*   This program is a variation of SAX2Count.
64*
65*   Whenever a file is served, it does the following:
66*
67*   . parses the file
68*   . caches the grammar without issuing any error message with regards to the parsing
69*   . serializes(store) the grammar cached to a BinOutputStream
70*   . deserialize(load) the grammar from the BinInputStream
71*   . parses the instance document a second time
72*   . validates the instance against the deserialized grammar if validation is on.
73*
74***/
75
76#include <stdio.h>
77
78static
79void parseCase(const char* const xmlFile);
80
81static
82bool parseOne(BinOutputStream*    outStream
83            , const char* const  xmlFile);
84
85static
86void parseTwo(BinInputStream*     inStream
87            , const char* const  xmlFile);
88
89static
90void parseFile(SAX2XMLReader* const parser
91             , const char* const xmlFile);
92
93static
94SAX2XMLReader* getParser(XMLGrammarPool* const theGramPool
95                       , bool                  setHandler);
96
97// ---------------------------------------------------------------------------
98//  Local helper methods
99// ---------------------------------------------------------------------------
100void usage()
101{
102    XERCES_STD_QUALIFIER cout << "\nUsage:\n"
103            "    XSerializerTest [options] <XML file | List file>\n\n"
104            "This program invokes the SAX2XMLReader, and then prints the\n"
105            "number of elements, attributes, spaces and characters found\n"
106            "in each XML file, using SAX2 API.\n\n"
107            "Options:\n"
108            "    -l          Indicate the input file is a List File that has a list of xml files.\n"
109            "                Default to off (Input file is an XML file).\n"
110            "    -v=xxx      Validation scheme [always | never | auto*].\n"
111            "    -f          Enable full schema constraint checking processing. Defaults to off.\n"
112            "    -p          Enable namespace-prefixes feature. Defaults to off.\n"
113            "    -n          Disable namespace processing. Defaults to on.\n"
114            "                NOTE: THIS IS OPPOSITE FROM OTHER SAMPLES.\n"
115            "    -s          Disable schema processing. Defaults to on.\n"
116            "                NOTE: THIS IS OPPOSITE FROM OTHER SAMPLES.\n"
117            "    -locale=ll_CC specify the locale, default: en_US.\n"
118            "    -?          Show this help.\n\n"
119            "  * = Default if not provided explicitly.\n"
120         << XERCES_STD_QUALIFIER endl;
121}
122
123// ---------------------------------------------------------------------------
124//  Program entry point
125// ---------------------------------------------------------------------------
126int main(int argC, char* argV[])
127{
128
129    // Check command line and extract arguments.
130    if (argC < 2)
131    {
132        usage();
133        return 1;
134    }
135
136    memset(localeStr, 0, sizeof localeStr);
137
138    int argInd;
139    for (argInd = 1; argInd < argC; argInd++)
140    {
141        // Break out on first parm not starting with a dash
142        if (argV[argInd][0] != '-')
143            break;
144
145        // Watch for special case help request
146        if (!strcmp(argV[argInd], "-?"))
147        {
148            usage();
149            return 2;
150        }
151         else if (!strncmp(argV[argInd], "-v=", 3)
152              ||  !strncmp(argV[argInd], "-V=", 3))
153        {
154            const char* const parm = &argV[argInd][3];
155
156            if (!strcmp(parm, "never"))
157                valScheme = SAX2XMLReader::Val_Never;
158            else if (!strcmp(parm, "auto"))
159                valScheme = SAX2XMLReader::Val_Auto;
160            else if (!strcmp(parm, "always"))
161                valScheme = SAX2XMLReader::Val_Always;
162            else
163            {
164                XERCES_STD_QUALIFIER cerr << "Unknown -v= value: " << parm << XERCES_STD_QUALIFIER endl;
165                return 2;
166            }
167        }
168         else if (!strcmp(argV[argInd], "-n")
169              ||  !strcmp(argV[argInd], "-N"))
170        {
171            doNamespaces = false;
172        }
173         else if (!strcmp(argV[argInd], "-s")
174              ||  !strcmp(argV[argInd], "-S"))
175        {
176            doSchema = false;
177        }
178         else if (!strcmp(argV[argInd], "-f")
179              ||  !strcmp(argV[argInd], "-F"))
180        {
181            schemaFullChecking = true;
182        }
183         else if (!strcmp(argV[argInd], "-l")
184              ||  !strcmp(argV[argInd], "-L"))
185        {
186            doList = true;
187        }
188         else if (!strcmp(argV[argInd], "-p")
189              ||  !strcmp(argV[argInd], "-P"))
190        {
191            namespacePrefixes = true;
192        }
193         else if (!strcmp(argV[argInd], "-special:nel"))
194        {
195            // turning this on will lead to non-standard compliance behaviour
196            // it will recognize the unicode character 0x85 as new line character
197            // instead of regular character as specified in XML 1.0
198            // do not turn this on unless really necessary
199             recognizeNEL = true;
200        }
201         else if (!strncmp(argV[argInd], "-locale=", 8))
202        {
203             // Get out the end of line
204             strcpy(localeStr, &(argV[argInd][8]));
205        }
206        else
207        {
208            XERCES_STD_QUALIFIER cerr << "Unknown option '" << argV[argInd]
209                << "', ignoring it\n" << XERCES_STD_QUALIFIER endl;
210        }
211    }
212
213    //
214    //  There should at least one parameter left, and that
215    //  should be the file name(s).
216    //
217    if (argInd == argC)
218    {
219        usage();
220        return 1;
221    }
222
223    // Initialize the XML4C2 system
224    try
225    {
226        if (strlen(localeStr))
227        {
228            XMLPlatformUtils::Initialize(localeStr);
229        }
230        else
231        {
232            XMLPlatformUtils::Initialize();
233        }
234
235        if (recognizeNEL)
236        {
237            XMLPlatformUtils::recognizeNEL(recognizeNEL);
238        }
239
240    }
241
242    catch (const XMLException& toCatch)
243    {
244        XERCES_STD_QUALIFIER cerr << "Error during initialization! Message:\n"
245            << StrX(toCatch.getMessage()) << XERCES_STD_QUALIFIER endl;
246        return 1;
247    }
248
249    XERCES_STD_QUALIFIER ifstream fin;
250
251    // the input is a list file
252    if (doList)
253        fin.open(argV[argInd]);
254
255    if (fin.fail()) {
256        XERCES_STD_QUALIFIER cerr <<"Cannot open the list file: " << argV[argInd] << XERCES_STD_QUALIFIER endl;
257        return 2;
258    }
259
260    while (true)
261    {
262        char fURI[1000];
263        //initialize the array to zeros
264        memset(fURI,0,sizeof(fURI));
265
266        if (doList) {
267            if (! fin.eof() ) {
268                fin.getline (fURI, sizeof(fURI));
269                if (!*fURI)
270                    continue;
271                else {
272                    xmlFile = fURI;
273                    XERCES_STD_QUALIFIER cerr << "==Parsing== " << xmlFile << XERCES_STD_QUALIFIER endl;
274                }
275            }
276            else
277                break;
278        }
279        else {
280            if (argInd < argC)
281            {
282                 xmlFile = argV[argInd];
283                 argInd++;
284            }
285            else
286                break;
287        }
288
289        parseCase(xmlFile);
290    }
291
292    if (doList)
293        fin.close();
294
295    // And call the termination method
296    XMLPlatformUtils::Terminate();
297
298    if (errorOccurred)
299        return 4;
300    else
301        return 0;
302
303}
304
305// ---------------------------------------------------------------------------
306//  Serialization/Deserialization
307// ---------------------------------------------------------------------------
308static const int BufSize = 1024;
309
310static void parseCase(const char* const xmlFile)
311{
312    //
313    //  Create our SAX handler object and install it on the parser, as the
314    //  document and error handler.
315    //
316    if (!handler)
317        handler = new XSerializerHandlers();
318
319    BinOutputStream* myOut = new BinMemOutputStream(BufSize);
320    Janitor<BinOutputStream> janOut(myOut);
321
322    if (!parseOne(myOut, xmlFile))
323        return;
324
325    BinInputStream*  myIn  = new BinMemInputStream(
326                                                   ((BinMemOutputStream*)myOut)->getRawBuffer()
327                                                 , (XMLSize_t)((BinMemOutputStream*)myOut)->getSize()
328                                                 , BinMemInputStream::BufOpt_Reference
329                                                  );
330    Janitor<BinInputStream> janIn(myIn);
331
332    parseTwo(myIn, xmlFile);
333
334}
335
336static
337bool parseOne(BinOutputStream*    outStream
338            , const char* const   xmlFile)
339{
340    //we don't use janitor here
341    MemoryManager*  theMemMgr   = new MemoryManagerImpl();
342    XMLGrammarPool* theGramPool = new XMLGrammarPoolImpl(theMemMgr);
343    SAX2XMLReader*  theParser   = getParser(theGramPool, false);  //don't emit error
344    bool            retVal      = true;
345
346    theParser->setFeature(XMLUni::fgXercesCacheGrammarFromParse, true);
347
348    //scan instance document and cache grammar
349    try
350    {
351        theParser->parse(xmlFile);
352    }
353    catch (...)
354    {
355        //do nothing, it could be an invalid instance document, but the grammar is fine
356    }
357
358    //serialize the grammar pool
359    try
360    {
361        theGramPool->serializeGrammars(outStream);
362    }
363    catch (const XSerializationException& e)
364    {
365        //do emit error here so that we know serialization failure
366        XERCES_STD_QUALIFIER cerr << "An error occurred during serialization\n   Message: "
367            << StrX(e.getMessage()) << XERCES_STD_QUALIFIER endl;
368
369        retVal = false;
370    }
371
372    catch (...)
373    {
374        //do emit error here so that we know serialization failure
375        XERCES_STD_QUALIFIER cerr << "An error occurred during serialization\n" << XERCES_STD_QUALIFIER endl;
376
377        retVal = false;
378    }
379
380    //the order is important
381    delete theParser;
382    delete theGramPool;
383    delete theMemMgr;
384
385    return retVal;
386}
387
388static
389void parseTwo(BinInputStream*     inStream
390            , const char* const   xmlFile)
391{
392    //we don't use janitor here
393    MemoryManager*  theMemMgr   = new MemoryManagerImpl();
394    XMLGrammarPool* theGramPool = new XMLGrammarPoolImpl(theMemMgr);
395    bool            errorSeen   = false;
396
397    //de-serialize grammar pool
398    try
399    {
400        theGramPool->deserializeGrammars(inStream);
401    }
402
403    catch(const XSerializationException& e)
404    {
405        XERCES_STD_QUALIFIER cerr << "An error occurred during de-serialization\n   Message: "
406            << StrX(e.getMessage()) << XERCES_STD_QUALIFIER endl;
407
408        errorSeen = true;
409    }
410
411    catch (...)
412    {
413        //do emit error here so that we know serialization failure
414        XERCES_STD_QUALIFIER cerr << "An error occurred during de-serialization\n" << XERCES_STD_QUALIFIER endl;
415
416        errorSeen = true;
417    }
418
419    if (!errorSeen)
420    {
421        SAX2XMLReader*  theParser   = getParser(theGramPool, true); //set the handler
422
423        theParser->setFeature(XMLUni::fgXercesUseCachedGrammarInParse, true);
424        parseFile(theParser, xmlFile);
425        delete theParser;
426    }
427
428    //the order is important
429    delete theGramPool;
430    delete theMemMgr;
431
432    return;
433}
434
435static SAX2XMLReader* getParser(XMLGrammarPool* const theGramPool
436                              , bool                  setHandler)
437{
438    SAX2XMLReader* parser = XMLReaderFactory::createXMLReader(theGramPool->getMemoryManager(), theGramPool);
439
440    parser->setFeature(XMLUni::fgSAX2CoreNameSpaces, doNamespaces);
441    parser->setFeature(XMLUni::fgXercesSchema, doSchema);
442    parser->setFeature(XMLUni::fgXercesHandleMultipleImports, true);
443    parser->setFeature(XMLUni::fgXercesSchemaFullChecking, schemaFullChecking);
444    parser->setFeature(XMLUni::fgSAX2CoreNameSpacePrefixes, namespacePrefixes);
445
446    if (valScheme == SAX2XMLReader::Val_Auto)
447    {
448        parser->setFeature(XMLUni::fgSAX2CoreValidation, true);
449        parser->setFeature(XMLUni::fgXercesDynamic, true);
450    }
451    if (valScheme == SAX2XMLReader::Val_Never)
452    {
453        parser->setFeature(XMLUni::fgSAX2CoreValidation, false);
454    }
455    if (valScheme == SAX2XMLReader::Val_Always)
456    {
457        parser->setFeature(XMLUni::fgSAX2CoreValidation, true);
458        parser->setFeature(XMLUni::fgXercesDynamic, false);
459    }
460
461    if (setHandler)
462    {
463        parser->setContentHandler(handler);
464        parser->setErrorHandler(handler);
465    }
466    else
467    {
468        parser->setContentHandler(0);
469        parser->setErrorHandler(0);
470    }
471
472    return parser;
473}
474
475static void parseFile(SAX2XMLReader* const parser
476                    , const char* const xmlFile)
477{
478    //
479    //  Get the starting time and kick off the parse of the indicated
480    //  file. Catch any exceptions that might propogate out of it.
481    //
482    unsigned long duration;
483
484    //reset error count first
485    handler->resetErrors();
486
487    try
488    {
489        const unsigned long startMillis = XMLPlatformUtils::getCurrentMillis();
490        parser->parse(xmlFile);
491        const unsigned long endMillis = XMLPlatformUtils::getCurrentMillis();
492        duration = endMillis - startMillis;
493    }
494    catch (const XMLException& e)
495    {
496        XERCES_STD_QUALIFIER cerr << "\nError during parsing: '" << xmlFile << "'\n"
497            << "Exception message is:  \n"
498            << StrX(e.getMessage()) << "\n" << XERCES_STD_QUALIFIER endl;
499        errorOccurred = true;
500    }
501    catch (...)
502    {
503        XERCES_STD_QUALIFIER cerr << "\nUnexpected exception during parsing: '" << xmlFile << "'\n";
504        errorOccurred = true;
505    }
506
507    // Print out the stats that we collected and time taken
508    if (!handler->getSawErrors())
509    {
510        XERCES_STD_QUALIFIER cout << xmlFile << ": " << duration << " ms ("
511            << handler->getElementCount() << " elems, "
512            << handler->getAttrCount() << " attrs, "
513            << handler->getSpaceCount() << " spaces, "
514            << handler->getCharacterCount() << " chars)" << XERCES_STD_QUALIFIER endl;
515    }
516    else
517        errorOccurred = true;
518
519}
Note: See TracBrowser for help on using the repository browser.