xref: /trunk/main/chart2/source/model/filter/XMLFilter.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_chartmodel.hxx"
26 
27 #include "XMLFilter.hxx"
28 #include "macros.hxx"
29 #include "MediaDescriptorHelper.hxx"
30 #include "ContainerHelper.hxx"
31 #include <comphelper/mediadescriptor.hxx>
32 
33 // for ERRCODE_SFX_GENERAL etc.
34 // header contains only macros
35 #include <svtools/sfxecode.hxx>
36 // header for class SvtSaveOptions
37 #include <unotools/saveopt.hxx>
38 #include <comphelper/genericpropertyset.hxx>
39 // header for struct PropertyMapEntry
40 #include <comphelper/propertysetinfo.hxx>
41 #include <comphelper/documentconstants.hxx>
42 
43 // header for class SotStorage
44 #include <sot/storage.hxx>
45 #include <com/sun/star/beans/PropertyAttribute.hpp>
46 #include <com/sun/star/xml/sax/InputSource.hpp>
47 #include <com/sun/star/lang/XMultiComponentFactory.hpp>
48 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
49 #include <com/sun/star/embed/ElementModes.hpp>
50 #include <com/sun/star/embed/XStorage.hpp>
51 #include <com/sun/star/embed/XTransactedObject.hpp>
52 #include <com/sun/star/frame/XModel.hpp>
53 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
54 #include <com/sun/star/xml/sax/XParser.hpp>
55 #include <com/sun/star/xml/sax/SAXParseException.hpp>
56 #include <com/sun/star/packages/zip/ZipIOException.hpp>
57 #include <com/sun/star/document/XGraphicObjectResolver.hpp>
58 #include <com/sun/star/container/XNameAccess.hpp>
59 
60 using namespace ::com::sun::star;
61 
62 using ::com::sun::star::uno::Reference;
63 using ::com::sun::star::uno::Sequence;
64 using ::rtl::OUString;
65 using ::osl::MutexGuard;
66 
67 // ----------------------------------------
68 namespace
69 {
70 #define LOCAL_CONST_STR(i, x) sal_Char __READONLY_DATA i[sizeof(x)] = x
71 #define MAP_LEN(x) x, sizeof(x) - 1
72 
73 LOCAL_CONST_STR( sXML_metaStreamName,       "meta.xml");
74 LOCAL_CONST_STR( sXML_styleStreamName,      "styles.xml" );
75 LOCAL_CONST_STR( sXML_contentStreamName,    "content.xml" );
76 LOCAL_CONST_STR( sXML_oldContentStreamName, "Content.xml" );
77 
78 // soffice 6/7
79 // LOCAL_CONST_STR( sXML_export_chart_meta_service,            "com.sun.star.comp.Chart.XMLMetaExporter" );
80 LOCAL_CONST_STR( sXML_export_chart_styles_service,          "com.sun.star.comp.Chart.XMLStylesExporter" );
81 LOCAL_CONST_STR( sXML_export_chart_content_service,         "com.sun.star.comp.Chart.XMLContentExporter" );
82 
83 // LOCAL_CONST_STR( sXML_import_chart_meta_service,            "com.sun.star.comp.Chart.XMLMetaImporter" );
84 LOCAL_CONST_STR( sXML_import_chart_styles_service,          "com.sun.star.comp.Chart.XMLStylesImporter" );
85 LOCAL_CONST_STR( sXML_import_chart_content_service,         "com.sun.star.comp.Chart.XMLContentImporter" );
86 LOCAL_CONST_STR( sXML_import_chart_old_content_service,     "com.sun.star.office.sax.importer.Chart" );
87 
88 // Oasis
89 LOCAL_CONST_STR( sXML_export_chart_oasis_styles_service,    "com.sun.star.comp.Chart.XMLOasisStylesExporter" );
90 LOCAL_CONST_STR( sXML_export_chart_oasis_content_service,   "com.sun.star.comp.Chart.XMLOasisContentExporter" );
91 LOCAL_CONST_STR( sXML_export_chart_oasis_meta_service,      "com.sun.star.comp.Chart.XMLOasisMetaExporter" );
92 
93 LOCAL_CONST_STR( sXML_import_chart_oasis_styles_service,    "com.sun.star.comp.Chart.XMLOasisStylesImporter" );
94 LOCAL_CONST_STR( sXML_import_chart_oasis_content_service,   "com.sun.star.comp.Chart.XMLOasisContentImporter" );
95 LOCAL_CONST_STR( sXML_import_chart_oasis_meta_service,      "com.sun.star.comp.Chart.XMLOasisMetaImporter" );
96 
lcl_getWriteStorage(const Sequence<beans::PropertyValue> & rMediaDescriptor,const uno::Reference<uno::XComponentContext> & xContext,const::rtl::OUString & _sMediaType)97 uno::Reference< embed::XStorage > lcl_getWriteStorage(
98     const Sequence< beans::PropertyValue >& rMediaDescriptor,
99     const uno::Reference< uno::XComponentContext >& xContext,const ::rtl::OUString& _sMediaType)
100 {
101     uno::Reference< embed::XStorage > xStorage;
102     try
103     {
104         apphelper::MediaDescriptorHelper aMDHelper( rMediaDescriptor );
105         if( aMDHelper.ISSET_Storage )
106         {
107             xStorage = aMDHelper.Storage;
108         }
109         else
110         {
111             Reference< lang::XSingleServiceFactory > xStorageFact(
112                 xContext->getServiceManager()->createInstanceWithContext(
113                     C2U("com.sun.star.embed.StorageFactory"),
114                     xContext ), uno::UNO_QUERY_THROW );
115 
116             ::std::vector< beans::PropertyValue > aPropertiesForStorage;
117 
118             for( sal_Int32 i=rMediaDescriptor.getLength(); i--; )
119             {
120                 // properties understood by storage factory
121                 // (see package/source/xstor/xfactory.cxx for details)
122                 if ( rMediaDescriptor[i].Name.equalsAsciiL(
123                         RTL_CONSTASCII_STRINGPARAM( "InteractionHandler" ))
124                     || rMediaDescriptor[i].Name.equalsAsciiL(
125                         RTL_CONSTASCII_STRINGPARAM( "Password" ))
126                     || rMediaDescriptor[i].Name.equalsAsciiL(
127                         RTL_CONSTASCII_STRINGPARAM( "RepairPackage" ))
128     //                  || rMediaDescriptor[i].Name.equalsAsciiL(
129     //                      RTL_CONSTASCII_STRINGPARAM( "StatusIndicator" ))
130     //                  || rMediaDescriptor[i].Name.equalsAsciiL(
131     //                      RTL_CONSTASCII_STRINGPARAM( "Unpacked" ))
132                     )
133                 {
134                     aPropertiesForStorage.push_back( rMediaDescriptor[i] );
135                 }
136             }
137 
138             if( aMDHelper.ISSET_Storage )
139                 xStorage.set( aMDHelper.Storage );
140             else
141             {
142                 Sequence< uno::Any > aStorageArgs( 3 );
143                 if( aMDHelper.ISSET_OutputStream  )
144                     aStorageArgs[0] <<= aMDHelper.OutputStream;
145                 else
146                     aStorageArgs[0] <<= aMDHelper.URL;
147                 aStorageArgs[1] <<= (embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE);
148                 aStorageArgs[2] <<= ::chart::ContainerHelper::ContainerToSequence( aPropertiesForStorage );
149 
150                 xStorage.set(
151                     xStorageFact->createInstanceWithArguments( aStorageArgs ),
152                     uno::UNO_QUERY_THROW );
153             }
154         }
155 
156         // set correct media type at storage
157         uno::Reference<beans::XPropertySet> xProp(xStorage,uno::UNO_QUERY);
158         OUString aMediaType;
159         if ( ! xProp.is() ||
160              ! ( xProp->getPropertyValue( C2U("MediaType")) >>= aMediaType ) ||
161              aMediaType.isEmpty() )
162         {
163             xProp->setPropertyValue( C2U("MediaType"), uno::makeAny( _sMediaType ));
164         }
165     }
166     catch( uno::Exception & ex )
167     {
168         ASSERT_EXCEPTION( ex );
169     }
170     return xStorage;
171 }
172 
lcl_getReadStorage(const Sequence<beans::PropertyValue> & rMediaDescriptor,const uno::Reference<uno::XComponentContext> & xContext)173 uno::Reference< embed::XStorage > lcl_getReadStorage(
174     const Sequence< beans::PropertyValue >& rMediaDescriptor,
175     const uno::Reference< uno::XComponentContext >& xContext)
176 {
177     uno::Reference< embed::XStorage > xStorage;
178 
179     try
180     {
181         apphelper::MediaDescriptorHelper aMDHelper( rMediaDescriptor );
182         if( aMDHelper.ISSET_Storage )
183         {
184             xStorage = aMDHelper.Storage;
185         }
186         else
187         {
188             // get XStream from MediaDescriptor
189             uno::Reference< io::XInputStream > xStream;
190             ::std::vector< beans::PropertyValue > aPropertiesForStorage;
191             for( sal_Int32 i=rMediaDescriptor.getLength(); i--; )
192             {
193                 if( rMediaDescriptor[i].Name.equalsAsciiL(
194                         RTL_CONSTASCII_STRINGPARAM( "InputStream" )))
195                     xStream.set( rMediaDescriptor[i].Value, uno::UNO_QUERY );
196 
197                 // properties understood by storage factory
198                 // (see package/source/xstor/xfactory.cxx for details)
199                 if ( rMediaDescriptor[i].Name.equalsAsciiL(
200                          RTL_CONSTASCII_STRINGPARAM( "InteractionHandler" ))
201                      || rMediaDescriptor[i].Name.equalsAsciiL(
202                          RTL_CONSTASCII_STRINGPARAM( "Password" ))
203                      || rMediaDescriptor[i].Name.equalsAsciiL(
204                          RTL_CONSTASCII_STRINGPARAM( "RepairPackage" ))
205 //                  || rMediaDescriptor[i].Name.equalsAsciiL(
206 //                      RTL_CONSTASCII_STRINGPARAM( "StatusIndicator" ))
207 //                  || rMediaDescriptor[i].Name.equalsAsciiL(
208 //                      RTL_CONSTASCII_STRINGPARAM( "Unpacked" ))
209                     )
210                 {
211                     aPropertiesForStorage.push_back( rMediaDescriptor[i] );
212                 }
213             }
214             OSL_ENSURE( xStream.is(), "No Stream" );
215             if( ! xStream.is())
216                 return xStorage;
217 
218             // convert XInputStream to XStorage via the storage factory
219             Reference< lang::XSingleServiceFactory > xStorageFact(
220                 xContext->getServiceManager()->createInstanceWithContext(
221                     C2U("com.sun.star.embed.StorageFactory"),
222                     xContext ),
223                 uno::UNO_QUERY_THROW );
224             Sequence< uno::Any > aStorageArgs( 3 );
225             aStorageArgs[0] <<= xStream;
226             aStorageArgs[1] <<= (embed::ElementModes::READ | embed::ElementModes::NOCREATE);
227             aStorageArgs[2] <<= ::chart::ContainerHelper::ContainerToSequence( aPropertiesForStorage );
228             xStorage.set(
229                 xStorageFact->createInstanceWithArguments( aStorageArgs ), uno::UNO_QUERY_THROW );
230         }
231 
232         OSL_ENSURE( xStorage.is(), "No Storage" );
233     }
234     catch( uno::Exception & ex )
235     {
236         ASSERT_EXCEPTION( ex );
237     }
238 
239     return xStorage;
240 }
241 
242 
243 } // anonymous namespace
244 
245 // ----------------------------------------
246 
247 namespace chart
248 {
249 
XMLFilter(Reference<uno::XComponentContext> const & xContext)250 XMLFilter::XMLFilter( Reference< uno::XComponentContext > const & xContext ) :
251         m_xContext( xContext ),
252         m_bCancelOperation( false )
253 {}
254 
~XMLFilter()255 XMLFilter::~XMLFilter()
256 {}
257 
258 // ____ XFilter ____
filter(const Sequence<beans::PropertyValue> & aDescriptor)259 sal_Bool SAL_CALL XMLFilter::filter(
260     const Sequence< beans::PropertyValue >& aDescriptor )
261 {
262     bool bResult = false;
263 
264     MutexGuard aGuard( m_aMutex );
265 
266     // ignore cancel flag at start of function
267     // note: is currently ignored during import/export
268     if( m_bCancelOperation )
269         m_bCancelOperation = false;
270 
271     if( m_xSourceDoc.is())
272     {
273         OSL_ENSURE( ! m_xTargetDoc.is(), "source doc is set -> target document should not be set" );
274         if( impl_Export( m_xSourceDoc,
275                          aDescriptor ) == 0 )
276         {
277             m_xSourceDoc = NULL;
278             bResult = true;
279         }
280     }
281     else if( m_xTargetDoc.is())
282     {
283         if( impl_Import( m_xTargetDoc,
284                          aDescriptor ) == 0 )
285         {
286             m_xTargetDoc = NULL;
287             bResult = true;
288         }
289     }
290     else
291     {
292         OSL_ENSURE( false, "filter() called with no document set" );
293     }
294 
295     return bResult;
296 }
297 
cancel()298 void SAL_CALL XMLFilter::cancel()
299 {
300     // if mutex is locked set "cancel state"
301     // note: is currently ignored in filter-method
302     if( ! m_aMutex.tryToAcquire())
303     {
304         m_bCancelOperation = true;
305     }
306 }
307 
308 // ____ XImporter ____
setTargetDocument(const Reference<lang::XComponent> & Document)309 void SAL_CALL XMLFilter::setTargetDocument(
310     const Reference< lang::XComponent >& Document )
311 {
312     MutexGuard aGuard( m_aMutex );
313     OSL_ENSURE( ! m_xSourceDoc.is(), "Setting target doc while source doc is set" );
314 
315     m_xTargetDoc = Document;
316 }
317 
318 
319 // ____ XExporter ____
setSourceDocument(const Reference<lang::XComponent> & Document)320 void SAL_CALL XMLFilter::setSourceDocument(
321     const Reference< lang::XComponent >& Document )
322 {
323     MutexGuard aGuard( m_aMutex );
324     OSL_ENSURE( ! m_xTargetDoc.is(), "Setting source doc while target doc is set" );
325 
326     m_xSourceDoc = Document;
327 }
328 
329 
impl_Import(const Reference<lang::XComponent> & xDocumentComp,const Sequence<beans::PropertyValue> & rMediaDescriptor)330 sal_Int32 XMLFilter::impl_Import(
331     const Reference< lang::XComponent > & xDocumentComp,
332     const Sequence< beans::PropertyValue > & rMediaDescriptor )
333 {
334     sal_Int32 nWarning = 0;
335 
336     OSL_ENSURE( xDocumentComp.is(), "Import: No Model" );
337     OSL_ENSURE( m_xContext.is(), "Import: No ComponentContext" );
338 
339     if( ! (xDocumentComp.is() &&
340            m_xContext.is()))
341         return nWarning;
342 
343     try
344     {
345         Reference< lang::XServiceInfo > xServInfo( xDocumentComp, uno::UNO_QUERY_THROW );
346         if( ! xServInfo->supportsService( C2U( "com.sun.star.chart2.ChartDocument" )))
347         {
348             OSL_ENSURE( false, "Import: No ChartDocument" );
349             return ERRCODE_SFX_GENERAL;
350         }
351 
352         Reference< lang::XMultiComponentFactory > xFactory( m_xContext->getServiceManager());
353         OSL_ENSURE( xFactory.is(), "Import: No Factory" );
354         if( ! xFactory.is())
355             return ERRCODE_SFX_GENERAL;
356 
357         // create a sax parser
358         Reference< xml::sax::XParser > xSaxParser(
359             xFactory->createInstanceWithContext( C2U( "com.sun.star.xml.sax.Parser" ), m_xContext ),
360             uno::UNO_QUERY_THROW );
361 
362         bool bOasis = true;
363         isOasisFormat( rMediaDescriptor, bOasis );
364         Reference< embed::XStorage > xStorage( lcl_getReadStorage( rMediaDescriptor, m_xContext));
365         if( ! xStorage.is())
366             return ERRCODE_SFX_GENERAL;
367 
368 //         bool bOasis = (SotStorage::GetVersion( xStorage ) > SOFFICE_FILEFORMAT_60);
369 
370         Reference< document::XGraphicObjectResolver > xGraphicObjectResolver;
371         uno::Reference< lang::XMultiServiceFactory > xServiceFactory( xFactory, uno::UNO_QUERY);
372         if( xServiceFactory.is())
373         {
374             uno::Sequence< uno::Any > aArgs(1);
375             aArgs[0] <<= xStorage;
376             xGraphicObjectResolver.set(
377                 xServiceFactory->createInstanceWithArguments(
378                     C2U("com.sun.star.comp.Svx.GraphicImportHelper"), aArgs ), uno::UNO_QUERY );
379         }
380 
381         // create XPropertySet with extra informatio for the filter
382         /** property map for import info set */
383         comphelper::PropertyMapEntry aImportInfoMap[] =
384         {
385             // #80365# necessary properties for XML progress bar at load time
386             { MAP_LEN( "ProgressRange" ),   0, &::getCppuType((const sal_Int32*)0), ::com::sun::star::beans::PropertyAttribute::MAYBEVOID, 0},
387             { MAP_LEN( "ProgressMax" ),     0, &::getCppuType((const sal_Int32*)0), ::com::sun::star::beans::PropertyAttribute::MAYBEVOID, 0},
388             { MAP_LEN( "ProgressCurrent" ), 0, &::getCppuType((const sal_Int32*)0), ::com::sun::star::beans::PropertyAttribute::MAYBEVOID, 0},
389             { MAP_LEN( "PrivateData" ), 0,
390                 &::getCppuType( (Reference<XInterface> *)0 ),
391                 ::com::sun::star::beans::PropertyAttribute::MAYBEVOID, 0 },
392             { MAP_LEN( "BaseURI" ), 0,
393                 &::getCppuType( (OUString *)0 ),
394                 ::com::sun::star::beans::PropertyAttribute::MAYBEVOID, 0 },
395             { MAP_LEN( "StreamRelPath" ), 0,
396                 &::getCppuType( (OUString *)0 ),
397                 ::com::sun::star::beans::PropertyAttribute::MAYBEVOID, 0 },
398             { MAP_LEN( "StreamName" ), 0,
399                 &::getCppuType( (OUString *)0 ),
400                 ::com::sun::star::beans::PropertyAttribute::MAYBEVOID, 0 },
401             { MAP_LEN( "BuildId" ), 0,
402                 &::getCppuType( (OUString *)0 ),
403                 ::com::sun::star::beans::PropertyAttribute::MAYBEVOID, 0 },
404             { NULL, 0, 0, NULL, 0, 0 }
405         };
406         uno::Reference< beans::XPropertySet > xImportInfo(
407                     comphelper::GenericPropertySet_CreateInstance(
408                                 new comphelper::PropertySetInfo( aImportInfoMap ) ) );
409 
410         // Set base URI and Hierarchical Name
411         OUString aHierarchName, aBaseUri;
412         uno::Reference< frame::XModel > xModel( m_xSourceDoc, uno::UNO_QUERY );
413         if( xModel.is() )
414         {
415             uno::Sequence< beans::PropertyValue > aModProps = xModel->getArgs();
416             for( sal_Int32 nInd = 0; nInd < aModProps.getLength(); nInd++ )
417             {
418                 if( aModProps[nInd].Name.equals( C2U( "HierarchicalDocumentName" ) ) )
419                 {
420                     // Actually this argument only has meaning for embedded documents
421                     aModProps[nInd].Value >>= aHierarchName;
422                 }
423                 else if( aModProps[nInd].Name.equals( C2U( "DocumentBaseURL" ) ) )
424                 {
425                     aModProps[nInd].Value >>= aBaseUri;
426                 }
427             }
428         }
429 
430         if( !aBaseUri.isEmpty() )
431             xImportInfo->setPropertyValue( C2U("BaseURI"), uno::makeAny( aBaseUri ) );
432 
433         if( !aHierarchName.isEmpty() )
434             xImportInfo->setPropertyValue( C2U("StreamRelPath"), uno::makeAny( aHierarchName ) );
435 
436         // import meta information
437         if( bOasis )
438             nWarning |= impl_ImportStream(
439                 C2U( sXML_metaStreamName ),
440                 C2U( sXML_import_chart_oasis_meta_service ),
441                 xStorage, xSaxParser, xFactory, xGraphicObjectResolver, xImportInfo );
442 
443         // import styles
444         nWarning |= impl_ImportStream(
445             C2U( sXML_styleStreamName ),
446             bOasis
447             ? C2U( sXML_import_chart_oasis_styles_service )
448             : C2U( sXML_import_chart_styles_service ),
449             xStorage, xSaxParser, xFactory, xGraphicObjectResolver, xImportInfo );
450 
451         // import content
452         sal_Int32 nContentWarning = impl_ImportStream(
453             C2U( sXML_contentStreamName ),
454             bOasis
455             ? C2U( sXML_import_chart_oasis_content_service )
456             : C2U( sXML_import_chart_content_service ),
457             xStorage, xSaxParser, xFactory, xGraphicObjectResolver, xImportInfo );
458         nWarning |= nContentWarning;
459 
460         // import of "content.xml" didn't work - try old "Content.xml" stream
461         if( nContentWarning != 0 )
462         {
463             nWarning = impl_ImportStream(
464                 C2U( sXML_oldContentStreamName ),
465                 C2U( sXML_import_chart_old_content_service ),
466                 xStorage, xSaxParser, xFactory, xGraphicObjectResolver, xImportInfo );
467         }
468     }
469     catch( uno::Exception & ex )
470     {
471         ASSERT_EXCEPTION( ex );
472 
473         // something went awry
474         nWarning = ERRCODE_SFX_GENERAL;
475     }
476 
477     return nWarning;
478 }
479 
impl_ImportStream(const OUString & rStreamName,const OUString & rServiceName,const Reference<embed::XStorage> & xStorage,const Reference<xml::sax::XParser> & xParser,const Reference<lang::XMultiComponentFactory> & xFactory,const Reference<document::XGraphicObjectResolver> & xGraphicObjectResolver,uno::Reference<beans::XPropertySet> & xImportInfo)480 sal_Int32 XMLFilter::impl_ImportStream(
481     const OUString & rStreamName,
482     const OUString & rServiceName,
483     const Reference< embed::XStorage > & xStorage,
484     const Reference< xml::sax::XParser > & xParser,
485     const Reference< lang::XMultiComponentFactory > & xFactory,
486     const Reference< document::XGraphicObjectResolver > & xGraphicObjectResolver,
487     uno::Reference< beans::XPropertySet >& xImportInfo )
488 {
489     sal_Int32 nWarning = ERRCODE_SFX_GENERAL;
490 
491     Reference< container::XNameAccess > xNameAcc( xStorage, uno::UNO_QUERY );
492     if( ! (xNameAcc.is() &&
493            xNameAcc->hasByName( rStreamName )))
494         return 0;
495 
496     if( xImportInfo.is() )
497         xImportInfo->setPropertyValue( C2U("StreamName"), uno::makeAny( rStreamName ) );
498 
499     if( xStorage.is() &&
500         xStorage->isStreamElement( rStreamName ) )
501     {
502         try
503         {
504             xml::sax::InputSource aParserInput;
505             aParserInput.aInputStream.set(
506                 xStorage->openStreamElement(
507                     rStreamName,
508                     embed::ElementModes::READ | embed::ElementModes::NOCREATE ),
509                 uno::UNO_QUERY );
510 
511             // todo: encryption
512 
513             if( aParserInput.aInputStream.is())
514             {
515                 sal_Int32 nArgs = 0;
516                 //if( m_xStatusIndicator.is())
517                 //    nArgs++;
518                 if( xGraphicObjectResolver.is())
519                     nArgs++;
520                 if( xImportInfo.is())
521                     nArgs++;
522 
523                 uno::Sequence< uno::Any > aFilterCompArgs( nArgs );
524 
525                 nArgs = 0;
526                 //if( m_xStatusIndicator.is())
527                 //    aFilterCompArgs[ nArgs++ ] <<= m_xStatusIndicator;
528                 if( xGraphicObjectResolver.is())
529                     aFilterCompArgs[nArgs++] <<= xGraphicObjectResolver;
530                 if( xImportInfo.is())
531                     aFilterCompArgs[ nArgs++ ] <<= xImportInfo;
532 
533                 Reference< xml::sax::XDocumentHandler > xDocHandler(
534                     xFactory->createInstanceWithArgumentsAndContext( rServiceName, aFilterCompArgs, m_xContext ),
535                     uno::UNO_QUERY_THROW );
536 
537 
538                 Reference< document::XImporter > xImporter( xDocHandler, uno::UNO_QUERY_THROW );
539                 xImporter->setTargetDocument( Reference< lang::XComponent >( m_xTargetDoc, uno::UNO_QUERY_THROW ));
540 
541                 if ( !m_sDocumentHandler.isEmpty() )
542                 {
543                     try
544                     {
545                         uno::Sequence< uno::Any > aArgs(2);
546                         beans::NamedValue aValue;
547                         aValue.Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DocumentHandler"));
548                         aValue.Value <<= xDocHandler;
549                         aArgs[0] <<= aValue;
550                         aValue.Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Model"));
551                         aValue.Value <<= m_xTargetDoc;
552                         aArgs[1] <<= aValue;
553 
554                         xDocHandler.set(xFactory->createInstanceWithArgumentsAndContext(m_sDocumentHandler,aArgs,m_xContext), uno::UNO_QUERY );
555                         xImporter.set(xDocHandler,uno::UNO_QUERY);
556                     }
557                     catch(uno::Exception&)
558                     {
559                         OSL_ENSURE(0,"Exception caught!");
560                     }
561                 }
562                 xParser->setDocumentHandler( xDocHandler );
563                 xParser->parseStream( aParserInput );
564             }
565 
566             // load was successful
567             nWarning = 0;
568         }
569         catch( xml::sax::SAXParseException )
570         {
571             // todo: if encrypted: ERRCODE_SFX_WRONGPASSWORD
572         }
573         catch( xml::sax::SAXException )
574         {
575             // todo: if encrypted: ERRCODE_SFX_WRONGPASSWORD
576         }
577         catch( packages::zip::ZipIOException )
578         {
579             nWarning = ERRCODE_IO_BROKENPACKAGE;
580         }
581         catch( io::IOException )
582         {
583         }
584         catch( uno::Exception& aEx )
585         {
586             ASSERT_EXCEPTION( aEx );
587         }
588     }
589 
590     return nWarning;
591 }
592 
impl_Export(const Reference<lang::XComponent> & xDocumentComp,const Sequence<beans::PropertyValue> & rMediaDescriptor)593 sal_Int32 XMLFilter::impl_Export(
594     const Reference< lang::XComponent > & xDocumentComp,
595     const Sequence< beans::PropertyValue > & rMediaDescriptor )
596 {
597     //save
598 
599     sal_Int32 nWarning = 0;
600 
601     OSL_ENSURE( xDocumentComp.is(), "Export: No Model" );
602     OSL_ENSURE( m_xContext.is(), "Export: No ComponentContext" );
603 
604     if( !xDocumentComp.is() || !m_xContext.is() )
605         return nWarning;
606 
607     try
608     {
609         Reference< lang::XServiceInfo > xServInfo( xDocumentComp, uno::UNO_QUERY_THROW );
610         if( ! xServInfo->supportsService( C2U( "com.sun.star.chart2.ChartDocument" )))
611         {
612             OSL_ENSURE( false, "Export: No ChartDocument" );
613             return ERRCODE_SFX_GENERAL;
614         }
615 
616         Reference< lang::XMultiComponentFactory > xFactory( m_xContext->getServiceManager());
617         OSL_ENSURE( xFactory.is(), "Export: No Factory" );
618         if( ! xFactory.is())
619             return ERRCODE_SFX_GENERAL;
620         uno::Reference< lang::XMultiServiceFactory > xServiceFactory( m_xContext->getServiceManager(), uno::UNO_QUERY);
621         if( ! xServiceFactory.is())
622             return ERRCODE_SFX_GENERAL;
623 
624         uno::Reference< io::XActiveDataSource > xSaxWriter( xServiceFactory->createInstance(
625                 C2U("com.sun.star.xml.sax.Writer")), uno::UNO_QUERY );
626         if ( !xSaxWriter.is() )
627             return ERRCODE_SFX_GENERAL;
628 
629         bool bOasis = true;
630         isOasisFormat( rMediaDescriptor, bOasis );
631 
632         uno::Reference< embed::XStorage > xStorage( lcl_getWriteStorage( rMediaDescriptor, m_xContext, getMediaType(bOasis) ) );
633         OSL_ENSURE( xStorage.is(), "No Storage" );
634         if( ! xStorage.is())
635             return ERRCODE_SFX_GENERAL;
636 
637         uno::Reference< xml::sax::XDocumentHandler> xDocHandler( xSaxWriter, uno::UNO_QUERY );
638 
639         if ( !m_sDocumentHandler.isEmpty() )
640         {
641             try
642             {
643                 uno::Sequence< uno::Any > aArgs(2);
644                 beans::NamedValue aValue;
645                 aValue.Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DocumentHandler"));
646                 aValue.Value <<= xDocHandler;
647                 aArgs[0] <<= aValue;
648                 aValue.Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Model"));
649                 aValue.Value <<= xDocumentComp;
650                 aArgs[1] <<= aValue;
651 
652                 xDocHandler.set(xServiceFactory->createInstanceWithArguments(m_sDocumentHandler,aArgs), uno::UNO_QUERY );
653                 xSaxWriter.set(xDocHandler,uno::UNO_QUERY);
654             }
655             catch(uno::Exception&)
656             {
657                 OSL_ENSURE(0,"Exception caught!");
658             }
659         }
660 
661         uno::Sequence< uno::Any > aGraphicResolverArgs(1);
662         aGraphicResolverArgs[0] <<= xStorage;
663         Reference< document::XGraphicObjectResolver > xGraphicObjectResolver(
664             xServiceFactory->createInstanceWithArguments(
665                 C2U("com.sun.star.comp.Svx.GraphicExportHelper"), aGraphicResolverArgs ), uno::UNO_QUERY );
666 
667         uno::Reference< beans::XPropertySet > xInfoSet;
668         {
669             // property map for export info set
670             comphelper::PropertyMapEntry aExportInfoMap[] =
671             {
672                 { MAP_LEN("UsePrettyPrinting"), 0, &::getBooleanCppuType(), beans::PropertyAttribute::MAYBEVOID, 0},
673                 { MAP_LEN("BaseURI"), 0, &::getCppuType( (OUString *)0 ), beans::PropertyAttribute::MAYBEVOID, 0 },
674                 { MAP_LEN("StreamRelPath"), 0, &::getCppuType( (OUString *)0 ), beans::PropertyAttribute::MAYBEVOID, 0 },
675                 { MAP_LEN("StreamName"), 0, &::getCppuType( (OUString *)0 ), beans::PropertyAttribute::MAYBEVOID, 0 },
676                 { MAP_LEN("ExportTableNumberList"), 0, &::getBooleanCppuType(), beans::PropertyAttribute::MAYBEVOID, 0 },
677                 { NULL, 0, 0, NULL, 0, 0 }
678             };
679 
680             xInfoSet = comphelper::GenericPropertySet_CreateInstance( new comphelper::PropertySetInfo( aExportInfoMap ) );
681 
682             SvtSaveOptions aSaveOpt;
683             OUString sUsePrettyPrinting(RTL_CONSTASCII_USTRINGPARAM("UsePrettyPrinting"));
684             sal_Bool bUsePrettyPrinting( aSaveOpt.IsPrettyPrinting() );
685             xInfoSet->setPropertyValue( sUsePrettyPrinting, uno::makeAny( bUsePrettyPrinting ) );
686             if( ! bOasis )
687                 xInfoSet->setPropertyValue( C2U("ExportTableNumberList"), uno::makeAny( true ));
688         }
689 
690         sal_Int32 nArgs = 2;
691         if( xGraphicObjectResolver.is())
692             nArgs++;
693 
694         uno::Sequence< uno::Any > aFilterProperties( nArgs );
695         {
696             nArgs = 0;
697             aFilterProperties[ nArgs++ ] <<= xInfoSet;
698             aFilterProperties[ nArgs++ ] <<= xDocHandler;
699             if( xGraphicObjectResolver.is())
700                 aFilterProperties[ nArgs++ ] <<= xGraphicObjectResolver;
701         }
702 
703 //         bool bOasis = (SotStorage::GetVersion( xStorage ) > SOFFICE_FILEFORMAT_60);
704 
705         // export meta information
706         if( bOasis )
707             nWarning |= impl_ExportStream(
708                 C2U( sXML_metaStreamName ),
709                 C2U( sXML_export_chart_oasis_meta_service ),
710                 xStorage, xSaxWriter, xServiceFactory, aFilterProperties );
711 
712         // export styles
713         nWarning |= impl_ExportStream(
714             C2U( sXML_styleStreamName ),
715             bOasis
716             ? C2U( sXML_export_chart_oasis_styles_service )
717             : C2U( sXML_export_chart_styles_service ),
718             xStorage, xSaxWriter, xServiceFactory, aFilterProperties );
719 
720         // export content
721         sal_Int32 nContentWarning = impl_ExportStream(
722             C2U( sXML_contentStreamName ),
723             bOasis
724             ? C2U( sXML_export_chart_oasis_content_service )
725             : C2U( sXML_export_chart_content_service ),
726             xStorage, xSaxWriter, xServiceFactory, aFilterProperties );
727         nWarning |= nContentWarning;
728 
729         Reference< lang::XComponent > xComp( xGraphicObjectResolver, uno::UNO_QUERY );
730         if( xComp.is())
731             xComp->dispose();
732 
733         uno::Reference<embed::XTransactedObject> xTransact( xStorage ,uno::UNO_QUERY);
734         if ( xTransact.is() )
735             xTransact->commit();
736     }
737     catch( uno::Exception & ex )
738     {
739         ASSERT_EXCEPTION( ex );
740 
741         // something went awry
742         nWarning = ERRCODE_SFX_GENERAL;
743     }
744 
745     return nWarning;
746 }
747 
impl_ExportStream(const OUString & rStreamName,const OUString & rServiceName,const Reference<embed::XStorage> & xStorage,const uno::Reference<io::XActiveDataSource> & xActiveDataSource,const Reference<lang::XMultiServiceFactory> & xServiceFactory,const Sequence<uno::Any> & rFilterProperties)748 sal_Int32 XMLFilter::impl_ExportStream(
749     const OUString & rStreamName,
750     const OUString & rServiceName,
751     const Reference< embed::XStorage > & xStorage,
752     const uno::Reference< io::XActiveDataSource >& xActiveDataSource,
753     const Reference< lang::XMultiServiceFactory >& xServiceFactory,
754     const Sequence< uno::Any > & rFilterProperties )
755 {
756     sal_Int32 nWarning = 0;
757 
758     try
759     {
760         if( !xServiceFactory.is() )
761             return ERRCODE_SFX_GENERAL;
762         if( !xStorage.is() )
763             return ERRCODE_SFX_GENERAL;
764         if ( !xActiveDataSource.is() )
765             return ERRCODE_SFX_GENERAL;
766 
767         uno::Reference< io::XStream > xStream( xStorage->openStreamElement(
768             rStreamName, embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE ) );
769         if ( !xStream.is() )
770             return ERRCODE_SFX_GENERAL;
771         uno::Reference< io::XOutputStream > xOutputStream( xStream->getOutputStream() );
772         if ( !xOutputStream.is() )
773             return ERRCODE_SFX_GENERAL;
774 
775         uno::Reference< beans::XPropertySet > xStreamProp( xOutputStream, uno::UNO_QUERY );
776         if(xStreamProp.is()) try
777         {
778             xStreamProp->setPropertyValue( C2U("MediaType"), uno::makeAny( C2U("text/xml") ) );
779             xStreamProp->setPropertyValue( C2U("Compressed"), uno::makeAny( sal_True ) );//@todo?
780             xStreamProp->setPropertyValue( C2U("UseCommonStoragePasswordEncryption"), uno::makeAny( sal_True ) );
781         }
782         catch( uno::Exception& rEx )
783         {
784             ASSERT_EXCEPTION( rEx );
785         }
786 
787         xActiveDataSource->setOutputStream(xOutputStream);
788 
789         // set Base URL
790         {
791             uno::Reference< beans::XPropertySet > xInfoSet;
792             if( rFilterProperties.getLength() > 0 )
793                 rFilterProperties.getConstArray()[0] >>= xInfoSet;
794             OSL_ENSURE( xInfoSet.is(), "missing infoset for export" );
795             if( xInfoSet.is() )
796                 xInfoSet->setPropertyValue( C2U("StreamName"), uno::makeAny( rStreamName ) );
797         }
798 
799         Reference< XExporter > xExporter( xServiceFactory->createInstanceWithArguments(
800             rServiceName, rFilterProperties ), uno::UNO_QUERY);
801         if ( !xExporter.is() )
802             return ERRCODE_SFX_GENERAL;
803 
804         xExporter->setSourceDocument( m_xSourceDoc );
805 
806         uno::Reference< document::XFilter > xFilter( xExporter, uno::UNO_QUERY );
807         if ( !xFilter.is() )
808             return ERRCODE_SFX_GENERAL;
809 
810         uno::Sequence < beans::PropertyValue > aMediaDesc(0);
811         //@todo? filter properties? ... url? ...
812         xFilter->filter( aMediaDesc );
813     }
814     catch( uno::Exception& rEx )
815     {
816         ASSERT_EXCEPTION( rEx );
817     }
818     return nWarning;
819 }
820 
821 // --------------------------------------------------------------------------------
822 
getSupportedServiceNames_Static()823 Sequence< OUString > XMLFilter::getSupportedServiceNames_Static()
824 {
825     Sequence< OUString > aServices( 2 );
826     aServices[ 0 ] = C2U( "com.sun.star.document.ImportFilter" );
827     aServices[ 1 ] = C2U( "com.sun.star.document.ExportFilter" );
828 
829     // todo: services are incomplete.  Missing:
830     // XInitialization, XNamed
831     return aServices;
832 }
833 // -----------------------------------------------------------------------------
834 
isOasisFormat(const Sequence<beans::PropertyValue> & _rMediaDescriptor,bool & rOutOASIS)835 void XMLFilter::isOasisFormat(const Sequence< beans::PropertyValue >& _rMediaDescriptor, bool & rOutOASIS )
836 {
837     apphelper::MediaDescriptorHelper aMDHelper( _rMediaDescriptor );
838     if( aMDHelper.ISSET_FilterName )
839         rOutOASIS = aMDHelper.FilterName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("chart8"));
840 }
841 // -----------------------------------------------------------------------------
getMediaType(bool _bOasis)842 ::rtl::OUString XMLFilter::getMediaType(bool _bOasis)
843 {
844     return _bOasis ? MIMETYPE_OASIS_OPENDOCUMENT_CHART : MIMETYPE_VND_SUN_XML_CHART;
845 }
846 // -----------------------------------------------------------------------------
847 
848 APPHELPER_XSERVICEINFO_IMPL( XMLFilter, C2U( "com.sun.star.comp.chart2.XMLFilter" ) );
849 // -----------------------------------------------------------------------------
850 
isOasisFormat(const Sequence<beans::PropertyValue> & _rMediaDescriptor,bool & rOutOASIS)851 void XMLReportFilterHelper::isOasisFormat(const Sequence< beans::PropertyValue >& _rMediaDescriptor, bool & rOutOASIS )
852 {
853     apphelper::MediaDescriptorHelper aMDHelper( _rMediaDescriptor );
854     if( aMDHelper.ISSET_FilterName )
855         rOutOASIS = aMDHelper.FilterName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("StarOffice XML (Base) Report Chart"));
856 }
857 // -----------------------------------------------------------------------------
getMediaType(bool)858 ::rtl::OUString XMLReportFilterHelper::getMediaType(bool )
859 {
860     return MIMETYPE_OASIS_OPENDOCUMENT_REPORT_CHART;
861 }
862 
863 } //  namespace chart
864