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