1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  **************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_filter.hxx"
26 
27 #include <stdio.h>
28 
29 #include <cppuhelper/factory.hxx>
30 #include <cppuhelper/servicefactory.hxx>
31 #include <cppuhelper/implbase4.hxx>
32 #include <cppuhelper/implbase.hxx>
33 
34 #include <osl/time.h>
35 #include <osl/conditn.h>
36 #include <tools/urlobj.hxx>
37 #include <osl/module.h>
38 #include <osl/file.hxx>
39 #include <osl/process.h>
40 
41 #include <com/sun/star/lang/XComponent.hpp>
42 
43 #include <com/sun/star/uno/Any.hxx>
44 #include <com/sun/star/uno/Type.hxx>
45 
46 #include <com/sun/star/beans/PropertyValue.hpp>
47 
48 #include <com/sun/star/xml/sax/XParser.hpp>
49 #include <com/sun/star/xml/sax/InputSource.hpp>
50 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
51 #include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp>
52 #include <com/sun/star/xml/sax/SAXException.hpp>
53 #include <com/sun/star/xml/XImportFilter.hpp>
54 #include <com/sun/star/xml/XExportFilter.hpp>
55 #include <com/sun/star/beans/XPropertySet.hpp>
56 #include <com/sun/star/util/XMacroExpander.hpp>
57 
58 #include <com/sun/star/io/XInputStream.hpp>
59 #include <com/sun/star/io/XOutputStream.hpp>
60 #include <com/sun/star/io/XActiveDataSource.hpp>
61 #include <com/sun/star/io/XActiveDataSink.hpp>
62 #include <com/sun/star/io/XActiveDataControl.hpp>
63 #include <com/sun/star/io/XStreamListener.hpp>
64 #include <com/sun/star/uno/Any.hxx>
65 #include <com/sun/star/lang/EventObject.hpp>
66 #include <com/sun/star/util/XStringSubstitution.hpp>
67 #include <com/sun/star/beans/NamedValue.hpp>
68 
69 
70 #include "uof2splitter.hxx"
71 #include "uof2storage.hxx"
72 #include "uof2merge.hxx"
73 
74 using namespace ::rtl;
75 using namespace ::cppu;
76 using namespace ::osl;
77 using namespace ::com::sun::star::beans;
78 using namespace ::com::sun::star::io;
79 using namespace ::com::sun::star::uno;
80 using namespace ::com::sun::star::lang;
81 using namespace ::com::sun::star::registry;
82 using namespace ::com::sun::star::xml;
83 using namespace ::com::sun::star::xml::sax;
84 using namespace ::com::sun::star::util;
85 
86 namespace XSLT {
87 
88 
89 class XSLTFilter : public WeakImplHelper4< XImportFilter, XExportFilter, XDocumentHandler, XStreamListener>
90 {
91 public:
92 
93     // ctor...
94     XSLTFilter( const Reference< XMultiServiceFactory > &r );
95 
96     // XStreamListener
97     virtual void SAL_CALL error(const Any& a) throw (RuntimeException);
98     virtual void SAL_CALL closed() throw (RuntimeException);
99     virtual void SAL_CALL terminated() throw (RuntimeException);
100     virtual void SAL_CALL started() throw (RuntimeException);
101     virtual void SAL_CALL disposing(const EventObject& e) throw (RuntimeException);
102 
103 
104     // XImportFilter
105     virtual sal_Bool SAL_CALL importer(
106             const Sequence<PropertyValue>& aSourceData,
107             const Reference<XDocumentHandler>& xHandler,
108             const Sequence<OUString>& msUserData)
109         throw(RuntimeException);
110 
111     // XExportFilter
112     virtual sal_Bool SAL_CALL exporter(
113             const Sequence<PropertyValue>& aSourceData,
114             const Sequence<OUString>& msUserData)
115         throw(RuntimeException);
116 
117     // XDocumentHandler
118     virtual void SAL_CALL startDocument()
119         throw (SAXException,RuntimeException);
120     virtual void SAL_CALL endDocument()
121         throw (SAXException, RuntimeException);
122     virtual void SAL_CALL startElement(const OUString& str, const Reference<XAttributeList>& attriblist)
123         throw (SAXException,RuntimeException);
124     virtual void SAL_CALL endElement(const OUString& str)
125         throw (SAXException, RuntimeException);
126     virtual void SAL_CALL characters(const OUString& str)
127         throw (SAXException, RuntimeException);
128     virtual void SAL_CALL ignorableWhitespace(const OUString& str)
129         throw (SAXException, RuntimeException);
130     virtual void SAL_CALL processingInstruction(const OUString& str, const OUString& str2)
131         throw (com::sun::star::xml::sax::SAXException,RuntimeException);
132     virtual void SAL_CALL setDocumentLocator(const Reference<XLocator>& doclocator)
133         throw (SAXException,RuntimeException);
134 
135 private:
136     // the UNO ServiceFactory
137     Reference< XMultiServiceFactory > m_rServiceFactory;
138 
139     // DocumentHandler interface of the css::xml::sax::Writer service
140     Reference < XExtendedDocumentHandler > m_rDocumentHandler;
141     Reference < XOutputStream > m_rOutputStream;
142 
143     // controls pretty-printing
144     sal_Bool m_bPrettyPrint;
145 
146     Reference< XActiveDataControl > m_tcontrol;
147     oslCondition m_cTransformed;
148 
149     sal_Bool m_bTerminated;
150     sal_Bool m_bError;
151 
152     OUString m_aExportBaseUrl;
153     OUString m_aOldBaseUrl;
154 
155     OUString rel2abs(const OUString&);
156     OUString expandUrl(const OUString&);
157 
158     // for support of UOF v2.0
159     Reference< XActiveDataControl > m_splitControl;
160     Reference< XStream > m_rStream;
161 
162     bool isUOF2ExportStyleSheet( const OUString& rExportStyleSheet );
163 
164 };
165 
XSLTFilter(const Reference<XMultiServiceFactory> & r)166 XSLTFilter::XSLTFilter( const Reference< XMultiServiceFactory > &r )
167     : m_rServiceFactory( r )
168     , m_rDocumentHandler()
169     , m_rOutputStream()
170     , m_bPrettyPrint( sal_True )
171     , m_tcontrol()
172     , m_cTransformed()
173     , m_bTerminated( sal_False )
174     , m_bError( sal_False )
175     , m_aExportBaseUrl()
176     , m_aOldBaseUrl()
177     , m_splitControl()
178     , m_rStream()
179 {
180     m_cTransformed = osl_createCondition();
181 }
182 
disposing(const EventObject &)183 void XSLTFilter::disposing(const EventObject& ) throw (RuntimeException)
184 {
185 }
186 
expandUrl(const::rtl::OUString & sUrl)187 ::rtl::OUString XSLTFilter::expandUrl( const ::rtl::OUString& sUrl )
188 {
189     ::rtl::OUString sExpandedUrl;
190     try
191     {
192         Reference< XComponentContext > xContext;
193         Reference< XPropertySet > xProps( m_rServiceFactory, UNO_QUERY_THROW );
194         xContext.set( xProps->getPropertyValue( ::rtl::OUString::createFromAscii( "DefaultContext" ) ), UNO_QUERY_THROW );
195         Reference< XMacroExpander > xMacroExpander( xContext->getValueByName( ::rtl::OUString::createFromAscii( "/singletons/com.sun.star.util.theMacroExpander" ) ), UNO_QUERY_THROW );
196         sExpandedUrl = xMacroExpander->expandMacros(sUrl);
197         sal_Int32 nPos = sExpandedUrl.indexOf(::rtl::OUString::createFromAscii("vnd.sun.star.expand:"));
198         if ( nPos != -1 )
199             sExpandedUrl = sExpandedUrl.copy(nPos+20);
200     }
201     catch (Exception&) {}
202     return sExpandedUrl;
203 }
204 
started()205 void XSLTFilter::started() throw (RuntimeException)
206 {
207     osl_resetCondition(m_cTransformed);
208 }
error(const Any & a)209 void XSLTFilter::error(const Any& a) throw (RuntimeException)
210 {
211     Exception e;
212     if ( a >>= e)
213     {
214         OString aMessage("XSLTFilter::error was called: ");
215         aMessage += OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US);
216         OSL_ENSURE(sal_False, aMessage);
217     }
218     m_bError = sal_True;
219     osl_setCondition(m_cTransformed);
220 }
closed()221 void XSLTFilter::closed() throw (RuntimeException)
222 {
223     osl_setCondition(m_cTransformed);
224 }
terminated()225 void XSLTFilter::terminated() throw (RuntimeException)
226 {
227     m_bTerminated = sal_True;
228     osl_setCondition(m_cTransformed);
229 }
230 
rel2abs(const OUString & s)231 OUString XSLTFilter::rel2abs(const OUString& s)
232 {
233 
234 	Reference< XStringSubstitution > subs(m_rServiceFactory->createInstance(
235         OUString::createFromAscii("com.sun.star.util.PathSubstitution")), UNO_QUERY);
236     OUString aWorkingDir = subs->getSubstituteVariableValue(OUString::createFromAscii("$(progurl)"));
237     INetURLObject aObj( aWorkingDir );
238     aObj.setFinalSlash();
239     bool bWasAbsolute;
240     INetURLObject aURL = aObj.smartRel2Abs(
241         s, bWasAbsolute, false, INetURLObject::WAS_ENCODED, RTL_TEXTENCODING_UTF8, true );
242     return aURL.GetMainURL(INetURLObject::NO_DECODE);
243 }
244 
245 
246 
importer(const Sequence<PropertyValue> & aSourceData,const Reference<XDocumentHandler> & xHandler,const Sequence<OUString> & msUserData)247 sal_Bool XSLTFilter::importer(
248         const Sequence<PropertyValue>& aSourceData,
249         const Reference<XDocumentHandler>& xHandler,
250         const Sequence<OUString>& msUserData)
251     throw (RuntimeException)
252 {
253     if ( msUserData.getLength() < 5 )
254         return sal_False;
255 
256     const OUString udStyleSheet = rel2abs( msUserData[4] );
257 
258     // get information from media descriptor
259     // the input stream that represents the imported file
260     // is most important here since we need to supply it to
261     // the sax parser that drives the supplied document handler
262     const sal_Int32 nLength = aSourceData.getLength();
263     OUString aFileName;
264     OUString aURL;
265     Reference< XInputStream > xInputStream;
266     for ( sal_Int32 i = 0 ; i < nLength; i++)
267     {
268         const OUString aName = aSourceData[i].Name;
269         if ( aName.equalsAscii( "InputStream" ) )
270             aSourceData[i].Value >>= xInputStream;
271         else if ( aName.equalsAscii( "FileName" ) )
272             aSourceData[i].Value >>= aFileName;
273         else if ( aName.equalsAscii( "URL" ) )
274             aSourceData[i].Value >>= aURL;
275     }
276     OSL_ASSERT(xInputStream.is());
277     if ( !xInputStream.is() )
278         return sal_False;
279 
280     // create SAX parser that will read the document file
281     // and provide events to xHandler passed to this call
282 	Reference < XParser > xSaxParser( m_rServiceFactory->createInstance(
283         OUString::createFromAscii("com.sun.star.xml.sax.Parser")), UNO_QUERY );
284     OSL_ASSERT(xSaxParser.is());
285 	if( !xSaxParser.is() )
286 	    return sal_False;
287 
288     // create transformer
289     Sequence< Any > args(3);
290     NamedValue nv;
291 
292     nv.Name = OUString::createFromAscii("StylesheetURL");
293     nv.Value <<= expandUrl(udStyleSheet); args[0] <<= nv;
294     nv.Name = OUString::createFromAscii("SourceURL");
295     nv.Value <<= aURL; args[1] <<= nv;
296     nv.Name = OUString::createFromAscii("SourceBaseURL");
297     nv.Value <<= OUString(INetURLObject(aURL).getBase());
298     args[2] <<= nv;
299 
300     m_tcontrol = Reference< XActiveDataControl >(m_rServiceFactory->createInstanceWithArguments(
301         OUString::createFromAscii("com.sun.star.comp.JAXTHelper"), args), UNO_QUERY);
302 
303     OSL_ASSERT(xHandler.is());
304     OSL_ASSERT(xInputStream.is());
305     OSL_ASSERT(m_tcontrol.is());
306     if (xHandler.is() && xInputStream.is() && m_tcontrol.is())
307     {
308         try
309     	{
310             // we want to be notified when the processing is done...
311             m_tcontrol->addListener(Reference< XStreamListener >(this));
312 
313             // connect input to transformer
314             Reference< XActiveDataSink > tsink(m_tcontrol, UNO_QUERY);
315             // UOF v2 import
316             UOF2Storage aUOF2Storage( m_rServiceFactory, xInputStream );
317             if ( aUOF2Storage.isValidUOF2Doc() )
318             {
319                 UOF2Merge aUOF2Merge( aUOF2Storage, m_rServiceFactory );
320                 aUOF2Merge.merge();
321                 tsink->setInputStream( aUOF2Merge.getMergedInStream() );
322             }
323             else
324             {
325                 tsink->setInputStream( xInputStream );
326             }
327 
328             // create pipe
329             Reference< XOutputStream > pipeout(m_rServiceFactory->createInstance(
330                 OUString::createFromAscii("com.sun.star.io.Pipe")), UNO_QUERY);
331             Reference< XInputStream > pipein(pipeout, UNO_QUERY);
332 
333             //connect transformer to pipe
334             Reference< XActiveDataSource > tsource(m_tcontrol, UNO_QUERY);
335             tsource->setOutputStream(pipeout);
336 
337             // connect pipe to sax parser
338 	        InputSource aInput;
339 	        aInput.sSystemId = aURL;
340             aInput.sPublicId = aURL;
341 	        aInput.aInputStream = pipein;
342 
343             // set doc handler
344             xSaxParser->setDocumentHandler(xHandler);
345 
346             // transform
347             m_tcontrol->start();
348             // osl_waitCondition(m_cTransformed, 0);
349             if (!m_bError && !m_bTerminated)
350             {
351                 // parse the transformed XML buffered in the pipe
352                 xSaxParser->parseStream(aInput);
353                 osl_waitCondition(m_cTransformed, 0);
354                 return sal_True;
355             } else {
356                 return sal_False;
357             }
358 	    }
359 #if OSL_DEBUG_LEVEL > 0
360 	    catch( Exception& exc)
361 #else
362 	    catch( Exception& )
363 #endif
364 	    {
365             // something went wrong
366             OSL_ENSURE(0, OUStringToOString(exc.Message, RTL_TEXTENCODING_ASCII_US).getStr());
367             return sal_False;
368 	    }
369     } else
370     {
371         return sal_False;
372     }
373 }
374 
isUOF2ExportStyleSheet(const OUString & rExportStyleSheet)375 bool XSLTFilter::isUOF2ExportStyleSheet( const OUString& rExportStyleSheet )
376 {
377     bool bIsUOFDocumentType = false;
378 
379     if ( rExportStyleSheet.endsWithAsciiL( "uof.xsl", 7 ) )
380     {
381         bIsUOFDocumentType = true;
382     }
383 
384     return bIsUOFDocumentType;
385 }
386 
exporter(const Sequence<PropertyValue> & aSourceData,const Sequence<OUString> & msUserData)387 sal_Bool XSLTFilter::exporter(
388         const Sequence<PropertyValue>& aSourceData,
389         const Sequence<OUString>& msUserData)
390     throw (RuntimeException)
391 {
392     if ( msUserData.getLength() < 6 )
393         return sal_False;
394 
395     // get interesting values from user data
396     const OUString udStyleSheet = rel2abs( msUserData[5] );
397 
398     // read source data
399     // we are especially interested in the output stream
400     // since that is where our xml-writer will push the data
401     // from its data-source interface
402     OUString sURL;
403     sal_Bool bIndent = sal_False;
404     OUString aDoctypePublic;
405     OUString aDoctypeSystem;
406     {
407         const sal_Int32 nLength = aSourceData.getLength();
408         for ( sal_Int32 i = 0; i < nLength; i++ )
409         {
410             const OUString aName = aSourceData[i].Name;
411             if ( aName.equalsAscii( "Indent" ) )
412                 aSourceData[i].Value >>= bIndent;
413             if ( aName.equalsAscii( "DocType_Public" ) )
414                 aSourceData[i].Value >>= aDoctypePublic;
415             if ( aName.equalsAscii( "DocType_System" ) )
416                 aSourceData[i].Value >>= aDoctypeSystem;
417             if ( aName.equalsAscii( "OutputStream" ) )
418                 aSourceData[i].Value >>= m_rOutputStream;
419             else if ( aName.equalsAscii( "URL" ) )
420                 aSourceData[i].Value >>= sURL;
421             // UOF v2.0 export, get Stream for constructing UOF2Storage
422             if ( aName.equalsAscii( "StreamForOutput" ) )
423                 aSourceData[i].Value >>= m_rStream;
424         }
425     }
426 
427     if (!m_rDocumentHandler.is())
428     {
429         // get the document writer
430         m_rDocumentHandler = Reference<XExtendedDocumentHandler>(
431             m_rServiceFactory->createInstance(
432                 OUString::createFromAscii("com.sun.star.xml.sax.Writer") ),
433             UNO_QUERY);
434     }
435 
436     // create transformer
437     Sequence< Any > args(4);
438     NamedValue nv;
439     nv.Name = OUString::createFromAscii("StylesheetURL");
440     nv.Value <<= expandUrl(udStyleSheet); args[0] <<= nv;
441     nv.Name = OUString::createFromAscii("TargetURL");
442     nv.Value <<= sURL; args[1] <<= nv;
443     nv.Name = OUString::createFromAscii("DoctypeSystem");
444     nv.Value <<= aDoctypeSystem; args[2] <<= nv;
445     nv.Name = OUString::createFromAscii("DoctypePublic");
446     nv.Value <<= aDoctypePublic; args[3] <<= nv;
447     nv.Name = OUString::createFromAscii("TargetBaseURL");
448     INetURLObject ineturl(sURL);
449     ineturl.removeSegment();
450     m_aExportBaseUrl = ineturl.GetMainURL(INetURLObject::NO_DECODE);
451     nv.Value <<= m_aExportBaseUrl;
452     args[3] <<= nv;
453 
454     m_tcontrol = Reference< XActiveDataControl >(m_rServiceFactory->createInstanceWithArguments(
455         OUString::createFromAscii("com.sun.star.comp.JAXTHelper"), args), UNO_QUERY);
456 
457     OSL_ASSERT(m_rDocumentHandler.is());
458     OSL_ASSERT(m_rOutputStream.is());
459     OSL_ASSERT(m_tcontrol.is());
460     if (m_tcontrol.is() && m_rOutputStream.is() && m_rDocumentHandler.is())
461     {
462         // we want to be notified when the processing is done...
463         m_tcontrol->addListener(Reference< XStreamListener >(this));
464 
465         // create pipe
466         Reference< XOutputStream > pipeout(m_rServiceFactory->createInstance(
467             OUString::createFromAscii("com.sun.star.io.Pipe")), UNO_QUERY);
468         Reference< XInputStream > pipein(pipeout, UNO_QUERY);
469 
470         // connect sax writer to pipe
471         Reference< XActiveDataSource > xmlsource(m_rDocumentHandler, UNO_QUERY);
472         xmlsource->setOutputStream(pipeout);
473 
474         // connect pipe to transformer
475         Reference< XActiveDataSink > tsink(m_tcontrol, UNO_QUERY);
476         tsink->setInputStream(pipein);
477 
478         // connect transformer to output
479         Reference< XActiveDataSource > tsource( m_tcontrol, UNO_QUERY );
480         if ( isUOF2ExportStyleSheet( udStyleSheet ) )
481         {
482             // special handling for UOF 2
483 
484             if ( !m_rStream.is() )
485             {
486                 return sal_False;
487             }
488 
489             // creating pipe2
490             Reference< XOutputStream > x_Pipeout(
491                 m_rServiceFactory->createInstance(
492                     OUString::createFromAscii( "com.sun.star.io.Pipe" ) ), UNO_QUERY );
493             Reference< XInputStream > x_Pipein( x_Pipeout, UNO_QUERY );
494 
495             // connect transformer to pipe2
496             tsource->setOutputStream( x_Pipeout );
497 
498             UOF2Splitter* pSplitter = new UOF2Splitter( m_rServiceFactory, sURL );
499             m_splitControl =
500                 Reference< XActiveDataControl >(
501                     static_cast< cppu::OWeakObject* >( pSplitter ), UNO_QUERY );
502             // connect pipe2 to splitter
503             Reference< XActiveDataSink > splitsink( m_splitControl, UNO_QUERY );
504             splitsink->setInputStream( x_Pipein );
505             // connect splitter to output
506             Reference< XActiveDataStreamer > splitout( m_splitControl, UNO_QUERY );
507             splitout->setStream( m_rStream );
508             m_rOutputStream = m_rStream->getOutputStream();
509         }
510         else
511         {
512             tsource->setOutputStream( m_rOutputStream );
513         }
514 
515         // we will start receiving events after returning 'true'.
516         // we will start the transformation as soon as we receive the startDocument event.
517         return sal_True;
518     }
519     else
520     {
521         return sal_False;
522     }
523 }
524 
525 // for the DocumentHandler implementation, we just proxy the the
526 // events to the XML writer that we created upon the output stream
527 // that was provided by the XMLFilterAdapter
startDocument()528 void XSLTFilter::startDocument() throw (SAXException,RuntimeException){
529     OSL_ASSERT(m_rDocumentHandler.is());
530     m_rDocumentHandler->startDocument();
531     m_tcontrol->start();
532 }
533 
endDocument()534 void XSLTFilter::endDocument() throw (SAXException, RuntimeException){
535     OSL_ASSERT(m_rDocumentHandler.is());
536     m_rDocumentHandler->endDocument();
537 
538     // m_splitControl only set for UOF 2
539     if ( m_splitControl.is() )
540     {
541         // when the inputStream(outputStream of filter) was closed, start to parse it.
542         m_splitControl->start();
543     }
544 
545     // wait for the transformer to finish
546     osl_waitCondition(m_cTransformed, 0);
547     if (!m_bError && !m_bTerminated)
548     {
549         return;
550     } else {
551         throw RuntimeException();
552     }
553 
554 }
555 
startElement(const OUString & str,const Reference<XAttributeList> & attriblist)556 void XSLTFilter::startElement(const OUString& str, const Reference<XAttributeList>& attriblist)
557     throw (SAXException, RuntimeException)
558 {
559     OSL_ASSERT(m_rDocumentHandler.is());
560 //	SvXMLAttributeList* _attriblist=SvXMLAttributeList::getImplementation(attriblist);
561     m_rDocumentHandler->startElement(str, attriblist);
562 }
563 
endElement(const OUString & str)564 void XSLTFilter::endElement(const OUString& str)
565     throw (SAXException, RuntimeException)
566 {
567     OSL_ASSERT(m_rDocumentHandler.is());
568     m_rDocumentHandler->endElement(str);
569 }
570 
characters(const OUString & str)571 void XSLTFilter::characters(const OUString& str)
572     throw (SAXException, RuntimeException)
573 {
574     OSL_ASSERT(m_rDocumentHandler.is());
575     m_rDocumentHandler->characters(str);
576 }
577 
ignorableWhitespace(const OUString & str)578 void XSLTFilter::ignorableWhitespace(const OUString& str)
579     throw (SAXException, RuntimeException)
580 {
581     OSL_ASSERT(m_rDocumentHandler.is());
582     if (!m_bPrettyPrint) return;
583     m_rDocumentHandler->ignorableWhitespace(str);
584 }
585 
processingInstruction(const OUString & str,const OUString & str2)586 void  XSLTFilter::processingInstruction(const OUString& str, const OUString& str2)
587     throw (SAXException, RuntimeException)
588 {
589     OSL_ASSERT(m_rDocumentHandler.is());
590     m_rDocumentHandler->processingInstruction(str, str2);
591 }
592 
setDocumentLocator(const Reference<XLocator> & doclocator)593 void XSLTFilter::setDocumentLocator(const Reference<XLocator>& doclocator)
594     throw (SAXException, RuntimeException)
595 {
596     OSL_ASSERT(m_rDocumentHandler.is());
597     m_rDocumentHandler->setDocumentLocator(doclocator);
598 }
599 
600 // --------------------------------------
601 // Component management
602 // --------------------------------------
603 #define SERVICE_NAME "com.sun.star.documentconversion.XSLTFilter"
604 #define IMPLEMENTATION_NAME "com.sun.star.comp.documentconversion.XSLTFilter"
605 
CreateInstance(const Reference<XMultiServiceFactory> & r)606 static Reference< XInterface > SAL_CALL CreateInstance( const Reference< XMultiServiceFactory > &r)
607 {
608     return Reference< XInterface >(( OWeakObject *)new XSLTFilter(r));
609 }
610 
getSupportedServiceNames()611 static Sequence< OUString > getSupportedServiceNames()
612 {
613 	static Sequence < OUString > *pNames = 0;
614 	if( ! pNames )
615 	{
616 		MutexGuard guard( Mutex::getGlobalMutex() );
617 		if( !pNames )
618 		{
619 			static Sequence< OUString > seqNames(1);
620 			    seqNames.getArray()[0] = OUString::createFromAscii(SERVICE_NAME);
621 			pNames = &seqNames;
622 		}
623 	}
624 	return *pNames;
625 }
626 
627 }
628 
629 using namespace XSLT;
630 
631 extern "C"
632 {
component_getImplementationEnvironment(const sal_Char ** ppEnvTypeName,uno_Environment **)633 void SAL_CALL component_getImplementationEnvironment(
634 	const sal_Char ** ppEnvTypeName, uno_Environment ** /* ppEnv */ )
635 {
636     *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
637 }
638 
component_writeInfo(void *,void * pRegistryKey)639 sal_Bool SAL_CALL component_writeInfo(void * /* pServiceManager */, void * pRegistryKey )
640 {
641     if (pRegistryKey)
642 	{
643         try
644         {
645             Reference< XRegistryKey > xNewKey(
646                 reinterpret_cast< XRegistryKey * >( pRegistryKey )->createKey(
647                     OUString::createFromAscii( "/" IMPLEMENTATION_NAME "/UNO/SERVICES" ) ) );
648 
649             const Sequence< OUString > & rSNL = getSupportedServiceNames();
650             const OUString * pArray = rSNL.getConstArray();
651             for ( sal_Int32 nPos = rSNL.getLength(); nPos--; )
652                 xNewKey->createKey( pArray[nPos] );
653 
654             return sal_True;
655         }
656         catch (InvalidRegistryException &)
657         {
658             OSL_ENSURE( sal_False, "### InvalidRegistryException!" );
659         }
660     }
661     return sal_False;
662 }
663 
component_getFactory(const sal_Char * pImplName,void * pServiceManager,void *)664 void * SAL_CALL component_getFactory(
665     const sal_Char * pImplName, void * pServiceManager, void * /* pRegistryKey */ )
666 {
667     void * pRet = 0;
668 
669     if (pServiceManager && rtl_str_compare( pImplName, IMPLEMENTATION_NAME ) == 0)
670     {
671         Reference< XSingleServiceFactory > xFactory( createSingleFactory(
672             reinterpret_cast< XMultiServiceFactory * >( pServiceManager ),
673             OUString::createFromAscii( pImplName ),
674             CreateInstance, getSupportedServiceNames() ) );
675 
676         if (xFactory.is())
677         {
678             xFactory->acquire();
679             pRet = xFactory.get();
680         }
681     }
682     return pRet;
683 }
684 
685 } // extern "C"
686