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_xmlscript.hxx"
30 #include "xmlbas_export.hxx"
31 #include "xmlscript/xmlns.h"
32 #include "xmlscript/xml_helper.hxx"
33 #include <com/sun/star/beans/XPropertySet.hpp>
34 #include <com/sun/star/lang/XMultiComponentFactory.hpp>
35 #include <com/sun/star/script/XLibraryContainer2.hpp>
36 #include <com/sun/star/script/XLibraryContainerPassword.hpp>
37 #include <com/sun/star/document/XEmbeddedScripts.hpp>
38 #include <cppuhelper/implementationentry.hxx>
39 
40 using namespace ::com::sun::star;
41 using namespace ::com::sun::star::lang;
42 using namespace ::com::sun::star::uno;
43 
44 
45 //.........................................................................
46 namespace xmlscript
47 {
48 //.........................................................................
49 
50     // =============================================================================
51     // component operations
52     // =============================================================================
53 
54     ::rtl::OUString getImplementationName_XMLBasicExporter()
55     {
56         static ::rtl::OUString* pImplName = 0;
57 	    if ( !pImplName )
58 	    {
59             ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
60             if ( !pImplName )
61 		    {
62                 static ::rtl::OUString aImplName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.xmlscript.XMLBasicExporter" ) );
63 			    pImplName = &aImplName;
64 		    }
65 	    }
66 	    return *pImplName;
67     }
68 
69     // -----------------------------------------------------------------------------
70 
71     Sequence< ::rtl::OUString > getSupportedServiceNames_XMLBasicExporter()
72     {
73         static Sequence< ::rtl::OUString >* pNames = 0;
74 	    if ( !pNames )
75 	    {
76             ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
77 		    if ( !pNames )
78 		    {
79                 static Sequence< ::rtl::OUString > aNames(1);
80                 aNames.getArray()[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.document.XMLBasicExporter" ) );
81                 pNames = &aNames;
82 		    }
83 	    }
84 	    return *pNames;
85     }
86 
87     // -----------------------------------------------------------------------------
88 
89     ::rtl::OUString getImplementationName_XMLOasisBasicExporter()
90     {
91         static ::rtl::OUString* pImplName = 0;
92 	    if ( !pImplName )
93 	    {
94             ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
95             if ( !pImplName )
96 		    {
97                 static ::rtl::OUString aImplName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.xmlscript.XMLOasisBasicExporter" ) );
98 			    pImplName = &aImplName;
99 		    }
100 	    }
101 	    return *pImplName;
102     }
103 
104     // -----------------------------------------------------------------------------
105 
106     Sequence< ::rtl::OUString > getSupportedServiceNames_XMLOasisBasicExporter()
107     {
108         static Sequence< ::rtl::OUString >* pNames = 0;
109 	    if ( !pNames )
110 	    {
111             ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
112 		    if ( !pNames )
113 		    {
114                 static Sequence< ::rtl::OUString > aNames(1);
115                 aNames.getArray()[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.document.XMLOasisBasicExporter" ) );
116                 pNames = &aNames;
117 		    }
118 	    }
119 	    return *pNames;
120     }
121 
122 
123     // =============================================================================
124     // XMLBasicExporterBase
125     // =============================================================================
126 
127     XMLBasicExporterBase::XMLBasicExporterBase( const Reference< XComponentContext >& rxContext, sal_Bool bOasis )
128         :m_xContext( rxContext )
129         ,m_bOasis( bOasis )
130     {
131     }
132 
133     // -----------------------------------------------------------------------------
134 
135     XMLBasicExporterBase::~XMLBasicExporterBase()
136     {
137     }
138 
139     // -----------------------------------------------------------------------------
140     // XServiceInfo
141     // -----------------------------------------------------------------------------
142 
143     sal_Bool XMLBasicExporterBase::supportsService( const ::rtl::OUString& rServiceName ) throw (RuntimeException)
144     {
145 	    Sequence< ::rtl::OUString > aNames( getSupportedServiceNames() );
146 	    const ::rtl::OUString* pNames = aNames.getConstArray();
147 	    const ::rtl::OUString* pEnd = pNames + aNames.getLength();
148 	    for ( ; pNames != pEnd && !pNames->equals( rServiceName ); ++pNames )
149 		    ;
150 
151 	    return pNames != pEnd;
152     }
153 
154     // -----------------------------------------------------------------------------
155     // XInitialization
156     // -----------------------------------------------------------------------------
157 
158     void XMLBasicExporterBase::initialize( const Sequence< Any >& aArguments ) throw (Exception, RuntimeException)
159     {
160         ::osl::MutexGuard aGuard( m_aMutex );
161 
162         if ( aArguments.getLength() == 1 )
163         {
164             aArguments[0] >>= m_xHandler;
165 
166             if ( !m_xHandler.is() )
167             {
168                 throw RuntimeException(
169                     ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "XMLBasicExporterBase::initialize: invalid argument format!" ) ),
170                     Reference< XInterface >() );
171             }
172         }
173         else
174         {
175             throw RuntimeException(
176                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "XMLBasicExporterBase::initialize: invalid number of arguments!" ) ),
177                 Reference< XInterface >() );
178         }
179     }
180 
181     // -----------------------------------------------------------------------------
182     // XExporter
183     // -----------------------------------------------------------------------------
184 
185     void XMLBasicExporterBase::setSourceDocument( const Reference< XComponent >& rxDoc )
186 	    throw (IllegalArgumentException, RuntimeException)
187     {
188         ::osl::MutexGuard aGuard( m_aMutex );
189 
190         m_xModel.set( rxDoc, UNO_QUERY );
191 
192         if ( !m_xModel.is() )
193         {
194             throw IllegalArgumentException(
195                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "XMLBasicExporter::setSourceDocument: no document model!" ) ),
196                 Reference< XInterface >(), 1 );
197         }
198     }
199 
200     // -----------------------------------------------------------------------------
201     // XFilter
202     // -----------------------------------------------------------------------------
203 
204 sal_Bool XMLBasicExporterBase::filter( const Sequence< beans::PropertyValue >& /*aDescriptor*/ )
205         throw (RuntimeException)
206     {
207         ::osl::MutexGuard aGuard( m_aMutex );
208 
209         sal_Bool bReturn = sal_True;
210 
211         try
212         {
213             if ( m_xHandler.is() )
214             {
215                 m_xHandler->startDocument();
216 
217                 // ooo/script prefix and URI
218                 ::rtl::OUString aPrefix;
219                 ::rtl::OUString aURI;
220                 if ( m_bOasis )
221                 {
222                     aPrefix = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( XMLNS_OOO_PREFIX ) );
223                     aURI = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( XMLNS_OOO_URI ) );
224                 }
225                 else
226                 {
227                     aPrefix = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( XMLNS_SCRIPT_PREFIX ) );
228                     aURI = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( XMLNS_SCRIPT_URI ) );
229                 }
230 
231                 // ooo/script:libraries element
232                 ::rtl::OUString aLibContElementName( aPrefix );
233                 aLibContElementName += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ":libraries" ) );
234                 XMLElement* pLibContElement = new XMLElement( aLibContElementName );
235                 Reference< xml::sax::XAttributeList > xLibContAttribs( pLibContElement );
236 
237                 // ooo/script namespace attribute
238                 pLibContElement->addAttribute( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "xmlns:" ) ) + aPrefix,
239                     aURI );
240 
241                 // xlink namespace attribute
242                 pLibContElement->addAttribute( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "xmlns:" XMLNS_XLINK_PREFIX ) ),
243                     ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( XMLNS_XLINK_URI ) ) );
244 
245                 // <ooo/script:libraries...
246                 m_xHandler->ignorableWhitespace( ::rtl::OUString() );
247                 m_xHandler->startElement( aLibContElementName, xLibContAttribs );
248 
249                 Reference< script::XLibraryContainer2 > xLibContainer;
250 
251                 // try the XEmbeddedScripts interface
252                 Reference< document::XEmbeddedScripts > xDocumentScripts( m_xModel, UNO_QUERY );
253                 if ( xDocumentScripts.is() )
254                     xLibContainer.set( xDocumentScripts->getBasicLibraries().get() );
255 
256                 if ( !xLibContainer.is() )
257                 {
258                     // try the "BasicLibraries" property (old-style, for compatibility)
259                     Reference< beans::XPropertySet > xPSet( m_xModel, UNO_QUERY );
260                     if ( xPSet.is() )
261                         xPSet->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "BasicLibraries" ) ) ) >>= xLibContainer;
262                 }
263 
264                 OSL_ENSURE( xLibContainer.is(), "XMLBasicExporterBase::filter: nowhere to export to!" );
265 
266                 if ( xLibContainer.is() )
267                 {
268                     Sequence< ::rtl::OUString > aLibNames = xLibContainer->getElementNames();
269                     sal_Int32 nLibCount = aLibNames.getLength();
270                     const ::rtl::OUString* pLibNames = aLibNames.getConstArray();
271                     for ( sal_Int32 i = 0 ; i < nLibCount ; ++i )
272                     {
273                         ::rtl::OUString aLibName( pLibNames[i] );
274 
275                         if ( xLibContainer->hasByName( aLibName ) )
276                         {
277                             ::rtl::OUString aTrueStr( RTL_CONSTASCII_USTRINGPARAM( "true" ) );
278 
279                             if ( xLibContainer->isLibraryLink( aLibName ) )
280                             {
281                                 // ooo/script:library-linked element
282                                 ::rtl::OUString aLibElementName( aPrefix );
283                                 aLibElementName += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ":library-linked" ) );
284                                 XMLElement* pLibElement = new XMLElement( aLibElementName );
285                                 Reference< xml::sax::XAttributeList > xLibAttribs;
286                                 xLibAttribs = static_cast< xml::sax::XAttributeList* >( pLibElement );
287 
288                                 // ooo/script:name attribute
289                                 pLibElement->addAttribute( aPrefix + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ":name" ) ),
290                                     aLibName );
291 
292                                 ::rtl::OUString aLinkURL( xLibContainer->getLibraryLinkURL( aLibName ) );
293                                 if ( aLinkURL.getLength() )
294                                 {
295                                     // xlink:href attribute
296                                     pLibElement->addAttribute( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( XMLNS_XLINK_PREFIX ":href" ) ),
297                                         aLinkURL );
298 
299                                     // xlink:type attribute
300                                     pLibElement->addAttribute( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( XMLNS_XLINK_PREFIX ":type" ) ),
301                                         ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "simple" ) ) );
302                                 }
303 
304                                 if ( xLibContainer->isLibraryReadOnly( aLibName ) )
305                                 {
306                                     // ooo/script:readonly attribute
307                                     pLibElement->addAttribute( aPrefix + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ":readonly" ) ),
308                                         aTrueStr );
309                                 }
310 
311                                 // <ooo/script:library-linked...
312                                 m_xHandler->ignorableWhitespace( ::rtl::OUString() );
313                                 m_xHandler->startElement( aLibElementName, xLibAttribs );
314 
315                                 // ...ooo/script:library-linked>
316                                 m_xHandler->ignorableWhitespace( ::rtl::OUString() );
317                                 m_xHandler->endElement( aLibElementName );
318                             }
319                             else
320                             {
321                                 // ooo/script:library-embedded element
322                                 ::rtl::OUString aLibElementName( aPrefix );
323                                 aLibElementName += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ":library-embedded" ) );
324                                 XMLElement* pLibElement = new XMLElement( aLibElementName );
325                                 Reference< xml::sax::XAttributeList > xLibAttribs;
326                                 xLibAttribs = static_cast< xml::sax::XAttributeList* >( pLibElement );
327 
328                                 // ooo/script:name attribute
329                                 pLibElement->addAttribute( aPrefix + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ":name" ) ),
330                                     aLibName );
331 
332                                 if ( xLibContainer->isLibraryReadOnly( aLibName ) )
333                                 {
334                                     // ooo/script:readonly attribute
335                                     pLibElement->addAttribute( aPrefix + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ":readonly" ) ),
336                                         aTrueStr );
337                                 }
338 
339                                 // TODO: password protected libraries
340                                 Reference< script::XLibraryContainerPassword > xPasswd( xLibContainer, UNO_QUERY );
341                                 if ( xPasswd.is() && xPasswd->isLibraryPasswordProtected( aLibName ) )
342                                     continue;
343 
344                                 // <ooo/script:library-embedded...
345                                 m_xHandler->ignorableWhitespace( ::rtl::OUString() );
346                                 m_xHandler->startElement( aLibElementName, xLibAttribs );
347 
348                                 if ( !xLibContainer->isLibraryLoaded( aLibName ) )
349                                     xLibContainer->loadLibrary( aLibName );
350 
351                                 Reference< container::XNameContainer > xLib;
352 	                            xLibContainer->getByName( aLibName ) >>= xLib;
353 
354                                 if ( xLib.is() )
355                                 {
356                                     Sequence< ::rtl::OUString > aModNames = xLib->getElementNames();
357                                     sal_Int32 nModCount = aModNames.getLength();
358                                     const ::rtl::OUString* pModNames = aModNames.getConstArray();
359                                     for ( sal_Int32 j = 0 ; j < nModCount ; ++j )
360                                     {
361                                         ::rtl::OUString aModName( pModNames[j] );
362                                         if ( xLib->hasByName( aModName ) )
363                                         {
364                                             // ooo/script:module element
365                                             ::rtl::OUString aModElementName( aPrefix );
366                                             aModElementName += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ":module" ) );
367                                             XMLElement* pModElement = new XMLElement( aModElementName );
368                                             Reference< xml::sax::XAttributeList > xModAttribs;
369                                             xModAttribs = static_cast< xml::sax::XAttributeList* >( pModElement );
370 
371                                             // ooo/script:name attribute
372                                             pModElement->addAttribute( aPrefix + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ":name" ) ),
373                                                 aModName );
374 
375                                             // <ooo/script:module...
376                                             m_xHandler->ignorableWhitespace( ::rtl::OUString() );
377                                             m_xHandler->startElement( aModElementName, xModAttribs );
378 
379                                             // ooo/script:source-code element
380                                             ::rtl::OUString aSourceElementName( aPrefix );
381                                             aSourceElementName += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ":source-code" ) );
382                                             XMLElement* pSourceElement = new XMLElement( aSourceElementName );
383                                             Reference< xml::sax::XAttributeList > xSourceAttribs;
384                                             xSourceAttribs = static_cast< xml::sax::XAttributeList* >( pSourceElement );
385 
386                                             // <ooo/script:source-code...
387                                             m_xHandler->ignorableWhitespace( ::rtl::OUString() );
388                                             m_xHandler->startElement( aSourceElementName, xSourceAttribs );
389 
390                                             // module data
391                                             // TODO: write encrypted data for password protected libraries
392                                             ::rtl::OUString aSource;
393 	                                        xLib->getByName( aModName ) >>= aSource;
394                                             m_xHandler->characters( aSource );
395 
396                                             // TODO: <ooo/script:byte-code>
397 
398                                             // ...ooo/script:source-code>
399                                             m_xHandler->ignorableWhitespace( ::rtl::OUString() );
400                                             m_xHandler->endElement( aSourceElementName );
401 
402                                             // ...ooo/script:module>
403                                             m_xHandler->ignorableWhitespace( ::rtl::OUString() );
404                                             m_xHandler->endElement( aModElementName );
405                                         }
406                                     }
407                                 }
408 
409                                 // ...ooo/script:library-embedded>
410                                 m_xHandler->ignorableWhitespace( ::rtl::OUString() );
411                                 m_xHandler->endElement( aLibElementName );
412                             }
413                         }
414                     }
415                 }
416 
417                 // ...ooo/script:libraries>
418                 m_xHandler->ignorableWhitespace( ::rtl::OUString() );
419                 m_xHandler->endElement( aLibContElementName );
420 
421                 m_xHandler->endDocument();
422             }
423         }
424         catch ( container::NoSuchElementException& e )
425         {
426             OSL_TRACE( "XMLBasicExporterBase::filter: caught NoSuchElementException reason %s",
427                 ::rtl::OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US ).pData->buffer );
428             bReturn = sal_False;
429         }
430         catch ( lang::IllegalArgumentException& e )
431         {
432             OSL_TRACE( "XMLBasicExporterBase::filter: caught IllegalArgumentException reason %s",
433                 ::rtl::OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US ).pData->buffer );
434             bReturn = sal_False;
435         }
436         catch ( lang::WrappedTargetException& e )
437         {
438             OSL_TRACE( "XMLBasicExporterBase::filter: caught WrappedTargetException reason %s",
439                 ::rtl::OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US ).pData->buffer );
440             bReturn = sal_False;
441         }
442         catch ( xml::sax::SAXException& e )
443         {
444             OSL_TRACE( "XMLBasicExporterBase::filter: caught SAXException reason %s",
445                 ::rtl::OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US ).pData->buffer );
446             bReturn = sal_False;
447         }
448 
449         return bReturn;
450     }
451 
452     // -----------------------------------------------------------------------------
453 
454     void XMLBasicExporterBase::cancel()
455         throw (RuntimeException)
456     {
457         ::osl::MutexGuard aGuard( m_aMutex );
458 
459         // cancel export
460     }
461 
462 
463     // =============================================================================
464     // XMLBasicExporter
465     // =============================================================================
466 
467     XMLBasicExporter::XMLBasicExporter( const Reference< XComponentContext >& rxContext )
468         :XMLBasicExporterBase( rxContext, sal_False )
469     {
470     }
471 
472     // -----------------------------------------------------------------------------
473 
474     XMLBasicExporter::~XMLBasicExporter()
475     {
476     }
477 
478     // -----------------------------------------------------------------------------
479     // XServiceInfo
480     // -----------------------------------------------------------------------------
481 
482     ::rtl::OUString XMLBasicExporter::getImplementationName(  ) throw (RuntimeException)
483     {
484         return getImplementationName_XMLBasicExporter();
485     }
486 
487     // -----------------------------------------------------------------------------
488 
489     Sequence< ::rtl::OUString > XMLBasicExporter::getSupportedServiceNames(  ) throw (RuntimeException)
490     {
491         return getSupportedServiceNames_XMLBasicExporter();
492     }
493 
494 
495     // =============================================================================
496     // XMLOasisBasicExporter
497     // =============================================================================
498 
499     XMLOasisBasicExporter::XMLOasisBasicExporter( const Reference< XComponentContext >& rxContext )
500         :XMLBasicExporterBase( rxContext, sal_True )
501     {
502     }
503 
504     // -----------------------------------------------------------------------------
505 
506     XMLOasisBasicExporter::~XMLOasisBasicExporter()
507     {
508     }
509 
510     // -----------------------------------------------------------------------------
511     // XServiceInfo
512     // -----------------------------------------------------------------------------
513 
514     ::rtl::OUString XMLOasisBasicExporter::getImplementationName(  ) throw (RuntimeException)
515     {
516         return getImplementationName_XMLOasisBasicExporter();
517     }
518 
519     // -----------------------------------------------------------------------------
520 
521     Sequence< ::rtl::OUString > XMLOasisBasicExporter::getSupportedServiceNames(  ) throw (RuntimeException)
522     {
523         return getSupportedServiceNames_XMLOasisBasicExporter();
524     }
525 
526 
527     // =============================================================================
528     // component operations
529     // =============================================================================
530 
531     Reference< XInterface > SAL_CALL create_XMLBasicExporter(
532         Reference< XComponentContext > const & xContext )
533         SAL_THROW( () )
534     {
535         return static_cast< lang::XTypeProvider * >( new XMLBasicExporter( xContext ) );
536     }
537 
538     // -----------------------------------------------------------------------------
539 
540     Reference< XInterface > SAL_CALL create_XMLOasisBasicExporter(
541         Reference< XComponentContext > const & xContext )
542         SAL_THROW( () )
543     {
544         return static_cast< lang::XTypeProvider * >( new XMLOasisBasicExporter( xContext ) );
545     }
546 
547     // -----------------------------------------------------------------------------
548 
549 //.........................................................................
550 }	// namespace xmlscript
551 //.........................................................................
552