1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_i18npool.hxx"
30 
31 #include <stdio.h>
32 #include <string.h>
33 #include <stack>
34 
35 #include "sal/main.h"
36 
37 #include <com/sun/star/lang/XComponent.hpp>
38 
39 #include <com/sun/star/xml/sax/SAXParseException.hpp>
40 #include <com/sun/star/xml/sax/XParser.hpp>
41 #include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp>
42 
43 #include <com/sun/star/io/XOutputStream.hpp>
44 #include <com/sun/star/io/XActiveDataSource.hpp>
45 
46 #include <cppuhelper/servicefactory.hxx>
47 #include <cppuhelper/implbase1.hxx>
48 #include <cppuhelper/implbase3.hxx>
49 
50 #include <vos/diagnose.hxx>
51 
52 #include "LocaleNode.hxx"
53 
54 using namespace ::rtl;
55 using namespace ::std;
56 using namespace ::cppu;
57 using namespace ::com::sun::star::uno;
58 using namespace ::com::sun::star::lang;
59 using namespace ::com::sun::star::registry;
60 using namespace ::com::sun::star::xml::sax;
61 using namespace ::com::sun::star::io;
62 
63 
64 
65 
66 
67 
68 /************
69  * Sequence of bytes -> InputStream
70  ************/
71 class OInputStream : public WeakImplHelper1 < XInputStream >
72 {
73 public:
74 	OInputStream( const Sequence< sal_Int8 >&seq ) :
75 		nPos( 0 ),
76 		m_seq( seq )
77 		{}
78 
79 public:
80     virtual sal_Int32 SAL_CALL readBytes( Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead )
81 		throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
82 		{
83 			nBytesToRead = (nBytesToRead > m_seq.getLength() - nPos ) ?
84 				m_seq.getLength() - nPos :
85 				nBytesToRead;
86 			aData = Sequence< sal_Int8 > ( &(m_seq.getConstArray()[nPos]) , nBytesToRead );
87 			nPos += nBytesToRead;
88 			return nBytesToRead;
89 		}
90     virtual sal_Int32 SAL_CALL readSomeBytes(
91 		::com::sun::star::uno::Sequence< sal_Int8 >& aData,
92 		sal_Int32 nMaxBytesToRead )
93 		throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
94 		{
95 			return readBytes( aData, nMaxBytesToRead );
96 		}
97     virtual void SAL_CALL skipBytes( sal_Int32 /*nBytesToSkip*/ )
98 		throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
99 		{
100 			// not implemented
101 		}
102     virtual sal_Int32 SAL_CALL available(  )
103 		throw(NotConnectedException, IOException, RuntimeException)
104 		{
105 			return m_seq.getLength() - nPos;
106 		}
107     virtual void SAL_CALL closeInput(  )
108 		throw(NotConnectedException, IOException, RuntimeException)
109 		{
110 			// not needed
111 		}
112 	sal_Int32 nPos;
113 	Sequence< sal_Int8> m_seq;
114 };
115 
116 //-------------------------------
117 // Helper : create an input stream from a file
118 //------------------------------
119 Reference< XInputStream > createStreamFromFile(
120 	const char *pcFile )
121 {
122 	FILE *f = fopen( pcFile , "rb" );
123 	Reference<  XInputStream >  r;
124 
125 	if( f ) {
126 		fseek( f , 0 , SEEK_END );
127 		size_t nLength = ftell( f );
128 		fseek( f , 0 , SEEK_SET );
129 
130 		Sequence<sal_Int8> seqIn(nLength);
131 		if (fread( seqIn.getArray() , nLength , 1 , f ) == 1)
132 			r = Reference< XInputStream > ( new OInputStream( seqIn ) );
133 		else
134 			fprintf(stderr, "failure reading %s\n", pcFile);
135 		fclose( f );
136 	}
137 	return r;
138 }
139 
140 
141 class TestDocumentHandler :
142 	public WeakImplHelper3< XExtendedDocumentHandler , XEntityResolver , XErrorHandler >
143 {
144 public:
145 	TestDocumentHandler(const char* locale, const char* outFile ) :
146       rootNode(0), nError(0), nbOfCurrencies(0), nbOfCalendars(0), nbOfFormatElements(0),
147       nbOfTransliterations(0), nbOfCollations(0), nbOfDays(50), nbOfMonths(50), nbOfEras(10),
148       flag(-1), of(outFile, locale), isStartDayOfWeek(false), foundDefaultName(false),
149       foundVariant(false), openElement(false)
150 	{
151         strncpy( theLocale, locale, sizeof(theLocale) );
152         theLocale[sizeof(theLocale)-1] = 0;
153 	}
154 
155 	~TestDocumentHandler(  )
156 	{
157 		of.closeOutput();
158 	}
159 
160 
161 public: // Error handler
162     virtual void SAL_CALL error(const Any& aSAXParseException) throw (SAXException, RuntimeException)
163     {
164         ++nError;
165     	printf( "Error !\n" );
166     	throw  SAXException(
167 			OUString( RTL_CONSTASCII_USTRINGPARAM("error from error handler")) ,
168 			Reference < XInterface >() ,
169 			aSAXParseException );
170     }
171     virtual void SAL_CALL fatalError(const Any& /*aSAXParseException*/) throw (SAXException, RuntimeException)
172     {
173         ++nError;
174     	printf( "Fatal Error !\n" );
175     }
176     virtual void SAL_CALL warning(const Any& /*aSAXParseException*/) throw (SAXException, RuntimeException)
177     {
178     	printf( "Warning !\n" );
179     }
180 
181 
182 public: // ExtendedDocumentHandler
183 
184 
185 
186 	stack<LocaleNode *> currentNode ;
187 	sal_Bool  fElement ;
188 	LocaleNode * rootNode;
189 
190 	virtual void SAL_CALL startDocument(void) throw (SAXException, RuntimeException)
191     {
192 	printf( "parsing document %s started\n", theLocale);
193 	of.writeAsciiString("#include <sal/types.h>\n\n\n");
194 	of.writeAsciiString("#include <stdio.h> // debug printfs\n\n");
195 	of.writeAsciiString("extern \"C\" {\n\n");
196 	}
197 
198     virtual void SAL_CALL endDocument(void) throw (SAXException, RuntimeException)
199     {
200 		if (rootNode)
201         {
202 			rootNode->generateCode(of);
203             int err = rootNode->getError();
204             if (err)
205             {
206                 printf( "Error: in data for %s: %d\n", theLocale, err);
207                 nError += err;
208             }
209         }
210         else
211         {
212             ++nError;
213             printf( "Error: no data for %s\n", theLocale);
214         }
215 		printf( "parsing document %s finished\n", theLocale);
216 
217 		of.writeAsciiString("} // extern \"C\"\n\n");
218 		of.closeOutput();
219     }
220 
221     virtual void SAL_CALL startElement(const OUString& aName,
222 							  const Reference< XAttributeList > & xAttribs)
223 		throw (SAXException,RuntimeException)
224 	{
225 
226 		LocaleNode * l =  LocaleNode::createNode (aName, xAttribs);
227 		if (!currentNode.empty() ) {
228 			LocaleNode * ln = (LocaleNode *) currentNode . top();
229 			ln->addChild(l);
230 		} else {
231 			rootNode = l;
232 		}
233 		currentNode . push (l);
234 	}
235 
236 
237 	virtual void SAL_CALL endElement(const OUString& /*aName*/) throw (SAXException,RuntimeException)
238     {
239     	currentNode . pop();
240     }
241 
242 	virtual void SAL_CALL characters(const OUString& aChars) throw (SAXException,RuntimeException)
243     {
244 
245     	LocaleNode * l = currentNode . top();
246     	l->setValue (aChars);
247 		::rtl::OUString str(aChars);
248 		sal_Unicode nonBreakSPace[2]= {0xa, 0x0};
249 		if(!openElement || str.equals(nonBreakSPace))
250 		  return;
251     }
252 
253 	virtual void SAL_CALL ignorableWhitespace(const OUString& /*aWhitespaces*/) throw (SAXException,RuntimeException)
254     {
255     }
256 
257     virtual void SAL_CALL processingInstruction(const OUString& /*aTarget*/, const OUString& /*aData*/) throw (SAXException,RuntimeException)
258     {
259 		// ignored
260     }
261 
262     virtual void SAL_CALL setDocumentLocator(const Reference< XLocator> & /*xLocator*/)
263 		throw (SAXException,RuntimeException)
264     {
265 		// ignored
266     }
267 
268     virtual InputSource SAL_CALL resolveEntity(
269 		const OUString& sPublicId,
270 		const OUString& sSystemId)
271 		throw (RuntimeException)
272 	{
273 		InputSource source;
274 		source.sSystemId = sSystemId;
275 		source.sPublicId = sPublicId;
276 
277 		source.aInputStream = createStreamFromFile(
278 			OUStringToOString( sSystemId , RTL_TEXTENCODING_ASCII_US) );
279 
280 		return source;
281 	}
282 
283     virtual void SAL_CALL startCDATA(void) throw (SAXException,RuntimeException)
284     {
285     }
286     virtual void SAL_CALL endCDATA(void) throw (RuntimeException)
287     {
288     }
289     virtual void SAL_CALL comment(const OUString& /*sComment*/) throw (SAXException,RuntimeException)
290     {
291     }
292     virtual void SAL_CALL unknown(const OUString& /*sString*/) throw (SAXException,RuntimeException)
293     {
294     }
295 
296 	virtual void SAL_CALL allowLineBreak( void) throw (SAXException, RuntimeException )
297 	{
298 
299 	}
300 
301 public:
302     int nError;
303 	::rtl::OUString currentElement;
304 	sal_Int16 nbOfCurrencies;
305 	sal_Int16 nbOfCalendars;
306 	sal_Int16 nbOfFormatElements;
307 	sal_Int16 nbOfTransliterations;
308 	sal_Int16 nbOfCollations;
309 	Sequence<sal_Int16> nbOfDays;
310 	Sequence<sal_Int16> nbOfMonths;
311 	Sequence<sal_Int16> nbOfEras;
312 	sal_Char *elementTag;
313 	sal_Char theLocale[50];
314 	sal_Int16 flag;
315 	OFileWriter of;
316 	sal_Bool isStartDayOfWeek;
317 	sal_Bool foundDefaultName;
318 	sal_Bool foundVariant;
319         sal_Bool openElement;
320 };
321 
322 
323 
324 
325 
326 SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv)
327 {
328 
329 
330 	if( argc < 6) {
331 		printf( "usage : %s <locaLe> <XML inputfile> <destination file> <services.rdb location> <types.rdb location>\n", argv[0] );
332 		exit( 1 );
333 	}
334 
335 	// create service manager
336 	Reference< XMultiServiceFactory > xSMgr;
337 	try
338 	{
339 		xSMgr = createRegistryServiceFactory(
340 			::rtl::OUString::createFromAscii(argv[4]),
341 			::rtl::OUString::createFromAscii(argv[5]), true );
342 	}
343 	catch ( Exception& )
344 	{
345 		printf( "Exception on createRegistryServiceFactory\n" );
346 		exit(1);
347 	}
348 
349 	//--------------------------------
350 	// parser demo
351 	// read xml from a file and count elements
352 	//--------------------------------
353 	Reference< XInterface > x = xSMgr->createInstance(
354 		OUString::createFromAscii( "com.sun.star.xml.sax.Parser" ) );
355     int nError = 0;
356 	if( x.is() )
357 	{
358 		Reference< XParser > rParser( x , UNO_QUERY );
359 
360 		// create and connect the document handler to the parser
361 		TestDocumentHandler *pDocHandler = new TestDocumentHandler( argv[1], argv[3]);
362 
363 		Reference < XDocumentHandler >	rDocHandler( (XDocumentHandler *) pDocHandler );
364 		Reference< XEntityResolver > rEntityResolver( (XEntityResolver *) pDocHandler );
365 
366 		rParser->setDocumentHandler( rDocHandler );
367 		rParser->setEntityResolver( rEntityResolver );
368 
369 		// create the input stream
370 		InputSource source;
371 		source.aInputStream = createStreamFromFile( argv[2] );
372 		source.sSystemId 	= OUString::createFromAscii( argv[2] );
373 
374 		try
375 		{
376 			// start parsing
377 			rParser->parseStream( source );
378 		}
379 
380 		catch( Exception & e )
381 		{
382 			OString o1 = OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8 );
383 			printf( "Exception during parsing : %s\n" ,  o1.getStr() );
384 			exit(1);
385 		}
386         nError = pDocHandler->nError;
387 	}
388 	else
389 	{
390 		printf( "couln't create sax-parser component\n" );
391 		exit(1);
392 	}
393 
394 	return nError;
395 }
396