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