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 <stdio.h>
22 : #include <com/sun/star/io/XStream.hpp>
23 : #include <com/sun/star/embed/XTransactedObject.hpp>
24 : #include <com/sun/star/embed/XEmbedObjectCreator.hpp>
25 : #include <com/sun/star/embed/XEmbedObjectFactory.hpp>
26 : #include <com/sun/star/embed/ElementModes.hpp>
27 : #include <com/sun/star/embed/XEmbeddedObject.hpp>
28 : #include <com/sun/star/embed/XEmbedPersist.hpp>
29 : #include <com/sun/star/embed/EntryInitModes.hpp>
30 : #include <com/sun/star/embed/EmbedStates.hpp>
31 : #include <com/sun/star/embed/Aspects.hpp>
32 : #include <com/sun/star/beans/XPropertySet.hpp>
33 : #include <tools/debug.hxx>
34 : #include <unotools/streamwrap.hxx>
35 : #include <unotools/tempfile.hxx>
36 :
37 : #include <svtools/embedhlp.hxx>
38 : #include <unotools/ucbstreamhelper.hxx>
39 : #include <comphelper/processfactory.hxx>
40 : #include <comphelper/storagehelper.hxx>
41 : #include <comphelper/embeddedobjectcontainer.hxx>
42 :
43 : #include <comphelper/classids.hxx>
44 : #include <map>
45 : #include "svx/xmleohlp.hxx"
46 :
47 : using namespace ::osl;
48 : using namespace ::cppu;
49 : using namespace ::utl;
50 : using namespace ::com::sun::star;
51 : using namespace ::com::sun::star::document;
52 : using namespace ::com::sun::star::uno;
53 : using namespace ::com::sun::star::container;
54 : using namespace ::com::sun::star::io;
55 : using namespace ::com::sun::star::lang;
56 :
57 : #define XML_CONTAINERSTORAGE_NAME_60 "Pictures"
58 : #define XML_CONTAINERSTORAGE_NAME "ObjectReplacements"
59 : #define XML_EMBEDDEDOBJECT_URL_BASE "vnd.sun.star.EmbeddedObject:"
60 : #define XML_EMBEDDEDOBJECTGRAPHIC_URL_BASE "vnd.sun.star.GraphicObject:"
61 :
62 :
63 :
64 : class OutputStorageWrapper_Impl : public ::cppu::WeakImplHelper1<XOutputStream>
65 : {
66 : ::osl::Mutex maMutex;
67 : Reference < XOutputStream > xOut;
68 : TempFile aTempFile;
69 : bool bStreamClosed : 1;
70 : SvStream* pStream;
71 :
72 : public:
73 : OutputStorageWrapper_Impl();
74 : virtual ~OutputStorageWrapper_Impl();
75 :
76 : // stario::XOutputStream
77 : virtual void SAL_CALL writeBytes(const Sequence< sal_Int8 >& aData) throw(NotConnectedException, BufferSizeExceededException, RuntimeException, std::exception) SAL_OVERRIDE;
78 : virtual void SAL_CALL flush() throw(NotConnectedException, BufferSizeExceededException, RuntimeException, std::exception) SAL_OVERRIDE;
79 : virtual void SAL_CALL closeOutput() throw(NotConnectedException, BufferSizeExceededException, RuntimeException, std::exception) SAL_OVERRIDE;
80 :
81 : SvStream* GetStream();
82 : };
83 :
84 0 : OutputStorageWrapper_Impl::OutputStorageWrapper_Impl()
85 : : bStreamClosed( false )
86 0 : , pStream(0)
87 : {
88 0 : aTempFile.EnableKillingFile();
89 0 : pStream = aTempFile.GetStream( STREAM_READWRITE );
90 0 : xOut = new OOutputStreamWrapper( *pStream );
91 0 : }
92 :
93 0 : OutputStorageWrapper_Impl::~OutputStorageWrapper_Impl()
94 : {
95 0 : }
96 :
97 0 : SvStream *OutputStorageWrapper_Impl::GetStream()
98 : {
99 0 : if( bStreamClosed )
100 0 : return pStream;
101 0 : return NULL;
102 : }
103 :
104 0 : void SAL_CALL OutputStorageWrapper_Impl::writeBytes(
105 : const Sequence< sal_Int8 >& aData)
106 : throw(NotConnectedException, BufferSizeExceededException, RuntimeException, std::exception)
107 : {
108 0 : MutexGuard aGuard( maMutex );
109 0 : xOut->writeBytes( aData );
110 0 : }
111 :
112 0 : void SAL_CALL OutputStorageWrapper_Impl::flush()
113 : throw(NotConnectedException, BufferSizeExceededException, RuntimeException, std::exception)
114 : {
115 0 : MutexGuard aGuard( maMutex );
116 0 : xOut->flush();
117 0 : }
118 :
119 0 : void SAL_CALL OutputStorageWrapper_Impl::closeOutput()
120 : throw(NotConnectedException, BufferSizeExceededException, RuntimeException, std::exception)
121 : {
122 0 : MutexGuard aGuard( maMutex );
123 0 : xOut->closeOutput();
124 0 : bStreamClosed = true;
125 0 : }
126 :
127 : struct OUStringLess
128 : {
129 0 : bool operator() ( const OUString& r1, const OUString& r2 ) const
130 : {
131 0 : return r1 < r2;
132 : }
133 : };
134 :
135 0 : SvXMLEmbeddedObjectHelper::SvXMLEmbeddedObjectHelper() :
136 : WeakComponentImplHelper2< XEmbeddedObjectResolver, XNameAccess >( maMutex ),
137 : maReplacementGraphicsContainerStorageName( XML_CONTAINERSTORAGE_NAME ),
138 : maReplacementGraphicsContainerStorageName60( XML_CONTAINERSTORAGE_NAME_60 ),
139 : mpDocPersist( 0 ),
140 : meCreateMode( EMBEDDEDOBJECTHELPER_MODE_READ ),
141 0 : mpStreamMap( 0 )
142 : {
143 0 : }
144 :
145 0 : SvXMLEmbeddedObjectHelper::SvXMLEmbeddedObjectHelper( ::comphelper::IEmbeddedHelper& rDocPersist, SvXMLEmbeddedObjectHelperMode eCreateMode ) :
146 : WeakComponentImplHelper2< XEmbeddedObjectResolver, XNameAccess >( maMutex ),
147 : maReplacementGraphicsContainerStorageName( XML_CONTAINERSTORAGE_NAME ),
148 : maReplacementGraphicsContainerStorageName60( XML_CONTAINERSTORAGE_NAME_60 ),
149 : mpDocPersist( 0 ),
150 : meCreateMode( EMBEDDEDOBJECTHELPER_MODE_READ ),
151 0 : mpStreamMap( 0 )
152 : {
153 0 : Init( 0, rDocPersist, eCreateMode );
154 0 : }
155 :
156 0 : SvXMLEmbeddedObjectHelper::~SvXMLEmbeddedObjectHelper()
157 : {
158 0 : if( mpStreamMap )
159 : {
160 0 : SvXMLEmbeddedObjectHelper_Impl::iterator aIter = mpStreamMap->begin();
161 0 : SvXMLEmbeddedObjectHelper_Impl::iterator aEnd = mpStreamMap->end();
162 0 : for( ; aIter != aEnd; ++aIter )
163 : {
164 0 : if( aIter->second )
165 : {
166 0 : aIter->second->release();
167 0 : aIter->second = 0;
168 : }
169 : }
170 0 : delete mpStreamMap;
171 : }
172 0 : }
173 :
174 0 : void SAL_CALL SvXMLEmbeddedObjectHelper::disposing()
175 : {
176 0 : Flush();
177 0 : }
178 :
179 :
180 0 : void SvXMLEmbeddedObjectHelper::splitObjectURL(const OUString& _aURLNoPar,
181 : OUString& rContainerStorageName,
182 : OUString& rObjectStorageName)
183 : {
184 : DBG_ASSERT( '#' != _aURLNoPar[0], "invalid object URL" );
185 0 : OUString aURLNoPar = _aURLNoPar;
186 :
187 0 : sal_Int32 _nPos = aURLNoPar.lastIndexOf( '/' );
188 0 : if( -1 == _nPos )
189 : {
190 0 : rContainerStorageName = "";
191 0 : rObjectStorageName = aURLNoPar;
192 : }
193 : else
194 : {
195 : //eliminate 'superfluous' slashes at start and end
196 : //#i103076# load objects with all allowed xlink:href syntaxes
197 : {
198 : //eliminate './' at start
199 0 : sal_Int32 nStart = 0;
200 0 : sal_Int32 nCount = aURLNoPar.getLength();
201 0 : if( aURLNoPar.startsWith( "./" ) )
202 : {
203 0 : nStart = 2;
204 0 : nCount -= 2;
205 : }
206 :
207 : //eliminate '/' at end
208 0 : sal_Int32 nEnd = aURLNoPar.lastIndexOf( '/' );
209 0 : if( nEnd == aURLNoPar.getLength()-1 && nEnd != (nStart-1) )
210 0 : nCount--;
211 :
212 0 : aURLNoPar = aURLNoPar.copy( nStart, nCount );
213 : }
214 :
215 0 : _nPos = aURLNoPar.lastIndexOf( '/' );
216 0 : if( _nPos >= 0 )
217 0 : rContainerStorageName = aURLNoPar.copy( 0, _nPos );
218 0 : rObjectStorageName = aURLNoPar.copy( _nPos+1 );
219 0 : }
220 0 : }
221 :
222 0 : bool SvXMLEmbeddedObjectHelper::ImplGetStorageNames(
223 : const OUString& rURLStr,
224 : OUString& rContainerStorageName,
225 : OUString& rObjectStorageName,
226 : bool bInternalToExternal,
227 : bool *pGraphicRepl,
228 : bool *pOasisFormat ) const
229 : {
230 : // internal URL: vnd.sun.star.EmbeddedObject:<object-name>
231 : // or: vnd.sun.star.EmbeddedObject:<path>/<object-name>
232 : // internal replacement images:
233 : // vnd.sun.star.EmbeddedObjectGraphic:<object-name>
234 : // or: vnd.sun.star.EmbeddedObjectGraphic:<path>/<object-name>
235 : // external URL: ./<path>/<object-name>
236 : // or: <path>/<object-name>
237 : // or: <object-name>
238 : // currently, path may only consist of a single directory name
239 : // it is also possible to have additional arguments at the end of URL: <main URL>[?<name>=<value>[,<name>=<value>]*]
240 :
241 0 : if( pGraphicRepl )
242 0 : *pGraphicRepl = false;
243 :
244 0 : if( pOasisFormat )
245 0 : *pOasisFormat = true; // the default value
246 :
247 0 : if( rURLStr.isEmpty() )
248 0 : return false;
249 :
250 : // get rid of arguments
251 0 : sal_Int32 nPos = rURLStr.indexOf( '?' );
252 0 : OUString aURLNoPar;
253 0 : if ( nPos == -1 )
254 0 : aURLNoPar = rURLStr;
255 : else
256 : {
257 0 : aURLNoPar = rURLStr.copy( 0, nPos );
258 :
259 : // check the arguments
260 0 : nPos++;
261 0 : while( nPos >= 0 && nPos < rURLStr.getLength() )
262 : {
263 0 : OUString aToken = rURLStr.getToken( 0, ',', nPos );
264 0 : if ( aToken.equalsIgnoreAsciiCase( "oasis=false" ) )
265 : {
266 0 : if ( pOasisFormat )
267 0 : *pOasisFormat = false;
268 0 : break;
269 : }
270 : else
271 : {
272 : DBG_ASSERT( false, "invalid arguments was found in URL!" );
273 : }
274 0 : }
275 : }
276 :
277 0 : if( bInternalToExternal )
278 : {
279 0 : nPos = aURLNoPar.indexOf( ':' );
280 0 : if( -1 == nPos )
281 0 : return false;
282 0 : sal_Bool bObjUrl = aURLNoPar.startsWith( XML_EMBEDDEDOBJECT_URL_BASE );
283 0 : bool bGrUrl = !bObjUrl &&
284 0 : aURLNoPar.startsWith( XML_EMBEDDEDOBJECTGRAPHIC_URL_BASE );
285 0 : if( !(bObjUrl || bGrUrl) )
286 0 : return false;
287 :
288 0 : sal_Int32 nPathStart = nPos + 1;
289 0 : nPos = aURLNoPar.lastIndexOf( '/' );
290 0 : if( -1 == nPos )
291 : {
292 0 : rContainerStorageName = "";
293 0 : rObjectStorageName = aURLNoPar.copy( nPathStart );
294 : }
295 0 : else if( nPos > nPathStart )
296 : {
297 0 : rContainerStorageName = aURLNoPar.copy( nPathStart, nPos-nPathStart);
298 0 : rObjectStorageName = aURLNoPar.copy( nPos+1 );
299 : }
300 : else
301 0 : return false;
302 :
303 0 : if( bGrUrl )
304 : {
305 0 : bool bOASIS = mxRootStorage.is() &&
306 0 : ( SotStorage::GetVersion( mxRootStorage ) > SOFFICE_FILEFORMAT_60 );
307 0 : rContainerStorageName = bOASIS
308 : ? maReplacementGraphicsContainerStorageName
309 0 : : maReplacementGraphicsContainerStorageName60;
310 :
311 0 : if( pGraphicRepl )
312 0 : *pGraphicRepl = true;
313 : }
314 :
315 :
316 : }
317 : else
318 : {
319 0 : splitObjectURL(aURLNoPar, rContainerStorageName, rObjectStorageName);
320 : }
321 :
322 0 : if( -1 != rContainerStorageName.indexOf( '/' ) )
323 : {
324 : OSL_FAIL( "SvXMLEmbeddedObjectHelper: invalid path name" );
325 0 : return false;
326 : }
327 :
328 0 : return true;
329 : }
330 :
331 0 : uno::Reference < embed::XStorage > SvXMLEmbeddedObjectHelper::ImplGetContainerStorage(
332 : const OUString& rStorageName )
333 : {
334 : DBG_ASSERT( -1 == rStorageName.indexOf( '/' ) &&
335 : -1 == rStorageName.indexOf( '\\' ),
336 : "nested embedded storages aren't supported" );
337 0 : if( !mxContainerStorage.is() ||
338 0 : ( rStorageName != maCurContainerStorageName ) )
339 : {
340 0 : if( mxContainerStorage.is() &&
341 0 : !maCurContainerStorageName.isEmpty() &&
342 0 : EMBEDDEDOBJECTHELPER_MODE_WRITE == meCreateMode )
343 : {
344 0 : uno::Reference < embed::XTransactedObject > xTrans( mxContainerStorage, uno::UNO_QUERY );
345 0 : if ( xTrans.is() )
346 0 : xTrans->commit();
347 : }
348 :
349 0 : if( !rStorageName.isEmpty() && mxRootStorage.is() )
350 : {
351 0 : sal_Int32 nMode = EMBEDDEDOBJECTHELPER_MODE_WRITE == meCreateMode
352 : ? ::embed::ElementModes::READWRITE
353 0 : : ::embed::ElementModes::READ;
354 0 : mxContainerStorage = mxRootStorage->openStorageElement( rStorageName,
355 0 : nMode );
356 : }
357 : else
358 : {
359 0 : mxContainerStorage = mxRootStorage;
360 : }
361 0 : maCurContainerStorageName = rStorageName;
362 : }
363 :
364 0 : return mxContainerStorage;
365 : }
366 :
367 0 : bool SvXMLEmbeddedObjectHelper::ImplReadObject(
368 : const OUString& rContainerStorageName,
369 : OUString& rObjName,
370 : const SvGlobalName *pClassId,
371 : SvStream* pTemp )
372 : {
373 : (void)pClassId;
374 :
375 0 : uno::Reference < embed::XStorage > xDocStor( mpDocPersist->getStorage() );
376 0 : uno::Reference < embed::XStorage > xCntnrStor( ImplGetContainerStorage( rContainerStorageName ) );
377 :
378 0 : if( !xCntnrStor.is() && !pTemp )
379 0 : return false;
380 :
381 0 : OUString aSrcObjName( rObjName );
382 0 : comphelper::EmbeddedObjectContainer& rContainer = mpDocPersist->getEmbeddedObjectContainer();
383 :
384 : // Is the object name unique?
385 : // if the object is already instantiated by GetEmbeddedObject
386 : // that means that the duplication is being loaded
387 0 : sal_Bool bDuplicate = rContainer.HasInstantiatedEmbeddedObject( rObjName );
388 : DBG_ASSERT( !bDuplicate, "An object in the document is referenced twice!" );
389 :
390 0 : if( xDocStor != xCntnrStor || pTemp || bDuplicate )
391 : {
392 : // TODO/LATER: make this alltogether a method in the EmbeddedObjectContainer
393 :
394 : // create a unique name for the duplicate object
395 0 : if( bDuplicate )
396 0 : rObjName = rContainer.CreateUniqueObjectName();
397 :
398 0 : if( pTemp )
399 : {
400 : try
401 : {
402 0 : pTemp->Seek( 0 );
403 0 : uno::Reference < io::XStream > xStm = xDocStor->openStreamElement( rObjName,
404 0 : embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE );
405 0 : SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( xStm );
406 0 : pTemp->ReadStream( *pStream );
407 0 : delete pStream;
408 :
409 : // TODO/LATER: what to do when other types of objects are based on substream persistence?
410 : // This is an ole object
411 0 : uno::Reference< beans::XPropertySet > xProps( xStm, uno::UNO_QUERY_THROW );
412 0 : xProps->setPropertyValue(
413 : OUString( "MediaType" ),
414 0 : uno::makeAny( OUString( "application/vnd.sun.star.oleobject" ) ) );
415 :
416 0 : xStm->getOutputStream()->closeOutput();
417 : }
418 0 : catch ( uno::Exception& )
419 : {
420 0 : return false;
421 : }
422 : }
423 : else
424 : {
425 : try
426 : {
427 0 : xCntnrStor->copyElementTo( aSrcObjName, xDocStor, rObjName );
428 : }
429 0 : catch ( uno::Exception& )
430 : {
431 0 : return false;
432 : }
433 : }
434 : }
435 :
436 : // make object known to the container
437 : // TODO/LATER: could be done a little bit more efficient!
438 0 : OUString aName( rObjName );
439 :
440 : // TODO/LATER: The provided pClassId is ignored for now.
441 : // The stream contains OLE storage internally and this storage already has a class id specifying the
442 : // server that was used to create the object. pClassId could be used to specify the server that should
443 : // be used for the next opening, but this information seems to be out of the file format responsibility
444 : // area.
445 0 : rContainer.GetEmbeddedObject( aName );
446 :
447 0 : return true;
448 : }
449 :
450 0 : OUString SvXMLEmbeddedObjectHelper::ImplInsertEmbeddedObjectURL(
451 : const OUString& rURLStr )
452 : {
453 0 : OUString sRetURL;
454 :
455 0 : OUString aContainerStorageName, aObjectStorageName;
456 0 : if( !ImplGetStorageNames( rURLStr, aContainerStorageName,
457 : aObjectStorageName,
458 0 : EMBEDDEDOBJECTHELPER_MODE_WRITE == meCreateMode ) )
459 0 : return sRetURL;
460 :
461 0 : if( EMBEDDEDOBJECTHELPER_MODE_READ == meCreateMode )
462 : {
463 0 : OutputStorageWrapper_Impl *pOut = 0;
464 0 : SvXMLEmbeddedObjectHelper_Impl::iterator aIter;
465 :
466 0 : if( mpStreamMap )
467 : {
468 0 : aIter = mpStreamMap->find( rURLStr );
469 0 : if( aIter != mpStreamMap->end() && aIter->second )
470 0 : pOut = aIter->second;
471 : }
472 :
473 0 : SvGlobalName aClassId, *pClassId = 0;
474 0 : sal_Int32 nPos = aObjectStorageName.lastIndexOf( '!' );
475 0 : if( -1 != nPos && aClassId.MakeId( aObjectStorageName.copy( nPos+1 ) ) )
476 : {
477 0 : aObjectStorageName = aObjectStorageName.copy( 0, nPos );
478 0 : pClassId = &aClassId;
479 : }
480 :
481 0 : ImplReadObject( aContainerStorageName, aObjectStorageName, pClassId, pOut ? pOut->GetStream() : 0 );
482 0 : sRetURL = OUString( XML_EMBEDDEDOBJECT_URL_BASE );
483 0 : sRetURL += aObjectStorageName;
484 :
485 0 : if( pOut )
486 : {
487 0 : mpStreamMap->erase( aIter );
488 0 : pOut->release();
489 0 : }
490 : }
491 : else
492 : {
493 : // Objects are written using ::comphelper::IEmbeddedHelper::SaveAs
494 0 : sRetURL = "./";
495 0 : if( !aContainerStorageName.isEmpty() )
496 : {
497 0 : sRetURL += aContainerStorageName;
498 0 : sRetURL += "/";
499 : }
500 0 : sRetURL += aObjectStorageName;
501 : }
502 :
503 0 : return sRetURL;
504 : }
505 :
506 0 : uno::Reference< io::XInputStream > SvXMLEmbeddedObjectHelper::ImplGetReplacementImage(
507 : const uno::Reference< embed::XEmbeddedObject >& xObj )
508 : {
509 0 : uno::Reference< io::XInputStream > xStream;
510 :
511 0 : if( xObj.is() )
512 : {
513 : try
514 : {
515 0 : bool bSwitchBackToLoaded = false;
516 0 : sal_Int32 nCurState = xObj->getCurrentState();
517 0 : if ( nCurState == embed::EmbedStates::LOADED || nCurState == embed::EmbedStates::RUNNING )
518 : {
519 : // means that the object is not active
520 : // copy replacement image from old to new container
521 0 : OUString aMediaType;
522 0 : xStream = mpDocPersist->getEmbeddedObjectContainer().GetGraphicStream( xObj, &aMediaType );
523 : }
524 :
525 0 : if ( !xStream.is() )
526 : {
527 : // the image must be regenerated
528 : // TODO/LATER: another aspect could be used
529 0 : if ( nCurState == embed::EmbedStates::LOADED )
530 0 : bSwitchBackToLoaded = true;
531 :
532 0 : OUString aMediaType;
533 0 : xStream = svt::EmbeddedObjectRef::GetGraphicReplacementStream(
534 : embed::Aspects::MSOLE_CONTENT,
535 : xObj,
536 0 : &aMediaType );
537 : }
538 :
539 0 : if ( bSwitchBackToLoaded )
540 : // switch back to loaded state; that way we have a minimum cache confusion
541 0 : xObj->changeState( embed::EmbedStates::LOADED );
542 : }
543 0 : catch( uno::Exception& )
544 : {}
545 : }
546 :
547 0 : return xStream;
548 : }
549 :
550 0 : void SvXMLEmbeddedObjectHelper::Init(
551 : const uno::Reference < embed::XStorage >& rRootStorage,
552 : ::comphelper::IEmbeddedHelper& rPersist,
553 : SvXMLEmbeddedObjectHelperMode eCreateMode )
554 : {
555 0 : mxRootStorage = rRootStorage;
556 0 : mpDocPersist = &rPersist;
557 0 : meCreateMode = eCreateMode;
558 0 : }
559 :
560 0 : SvXMLEmbeddedObjectHelper* SvXMLEmbeddedObjectHelper::Create(
561 : const uno::Reference < embed::XStorage >& rRootStorage,
562 : ::comphelper::IEmbeddedHelper& rDocPersist,
563 : SvXMLEmbeddedObjectHelperMode eCreateMode,
564 : bool bDirect )
565 : {
566 : (void)bDirect;
567 :
568 0 : SvXMLEmbeddedObjectHelper* pThis = new SvXMLEmbeddedObjectHelper;
569 :
570 0 : pThis->acquire();
571 0 : pThis->Init( rRootStorage, rDocPersist, eCreateMode );
572 :
573 0 : return pThis;
574 : }
575 :
576 0 : SvXMLEmbeddedObjectHelper* SvXMLEmbeddedObjectHelper::Create(
577 : ::comphelper::IEmbeddedHelper& rDocPersist,
578 : SvXMLEmbeddedObjectHelperMode eCreateMode )
579 : {
580 0 : SvXMLEmbeddedObjectHelper* pThis = new SvXMLEmbeddedObjectHelper;
581 :
582 0 : pThis->acquire();
583 0 : pThis->Init( 0, rDocPersist, eCreateMode );
584 :
585 0 : return pThis;
586 : }
587 :
588 0 : void SvXMLEmbeddedObjectHelper::Destroy(
589 : SvXMLEmbeddedObjectHelper* pSvXMLEmbeddedObjectHelper )
590 : {
591 0 : if( pSvXMLEmbeddedObjectHelper )
592 : {
593 0 : pSvXMLEmbeddedObjectHelper->dispose();
594 0 : pSvXMLEmbeddedObjectHelper->release();
595 : }
596 0 : }
597 :
598 0 : void SvXMLEmbeddedObjectHelper::Flush()
599 : {
600 0 : if( mxTempStorage.is() )
601 : {
602 0 : Reference < XComponent > xComp( mxTempStorage, UNO_QUERY );
603 0 : xComp->dispose();
604 : }
605 0 : }
606 :
607 : // XGraphicObjectResolver: alien objects!
608 0 : OUString SAL_CALL SvXMLEmbeddedObjectHelper::resolveEmbeddedObjectURL( const OUString& aURL )
609 : throw(RuntimeException, std::exception)
610 : {
611 0 : MutexGuard aGuard( maMutex );
612 :
613 0 : return ImplInsertEmbeddedObjectURL( aURL );
614 : }
615 :
616 : // XNameAccess: alien objects!
617 0 : Any SAL_CALL SvXMLEmbeddedObjectHelper::getByName(
618 : const OUString& rURLStr )
619 : throw (NoSuchElementException, WrappedTargetException, RuntimeException, std::exception)
620 : {
621 0 : MutexGuard aGuard( maMutex );
622 0 : Any aRet;
623 0 : if( EMBEDDEDOBJECTHELPER_MODE_READ == meCreateMode )
624 : {
625 0 : Reference < XOutputStream > xStrm;
626 0 : if( mpStreamMap )
627 : {
628 : SvXMLEmbeddedObjectHelper_Impl::iterator aIter =
629 0 : mpStreamMap->find( rURLStr );
630 0 : if( aIter != mpStreamMap->end() && aIter->second )
631 0 : xStrm = aIter->second;
632 : }
633 0 : if( !xStrm.is() )
634 : {
635 0 : OutputStorageWrapper_Impl *pOut = new OutputStorageWrapper_Impl;
636 0 : pOut->acquire();
637 0 : if( !mpStreamMap )
638 0 : mpStreamMap = new SvXMLEmbeddedObjectHelper_Impl;
639 0 : (*mpStreamMap)[rURLStr] = pOut;
640 0 : xStrm = pOut;
641 : }
642 :
643 0 : aRet <<= xStrm;
644 : }
645 : else
646 : {
647 0 : bool bGraphicRepl = false;
648 0 : bool bOasisFormat = true;
649 0 : Reference < XInputStream > xStrm;
650 0 : OUString aContainerStorageName, aObjectStorageName;
651 0 : if( ImplGetStorageNames( rURLStr, aContainerStorageName,
652 : aObjectStorageName,
653 : true,
654 : &bGraphicRepl,
655 : &bOasisFormat ) )
656 : {
657 : try
658 : {
659 : comphelper::EmbeddedObjectContainer& rContainer =
660 0 : mpDocPersist->getEmbeddedObjectContainer();
661 :
662 0 : Reference < embed::XEmbeddedObject > xObj = rContainer.GetEmbeddedObject( aObjectStorageName );
663 : DBG_ASSERT( xObj.is(), "Didn't get object" );
664 :
665 0 : if( xObj.is() )
666 : {
667 0 : if( bGraphicRepl )
668 : {
669 0 : xStrm = ImplGetReplacementImage( xObj );
670 : }
671 : else
672 : {
673 0 : Reference < embed::XEmbedPersist > xPersist( xObj, UNO_QUERY );
674 0 : if( xPersist.is() )
675 : {
676 0 : if( !mxTempStorage.is() )
677 0 : mxTempStorage =
678 0 : comphelper::OStorageHelper::GetTemporaryStorage();
679 0 : Sequence < beans::PropertyValue > aDummy( 0 ), aEmbDescr( 1 );
680 0 : aEmbDescr[0].Name = "StoreVisualReplacement";
681 0 : aEmbDescr[0].Value <<= (sal_Bool)(!bOasisFormat);
682 0 : if ( !bOasisFormat )
683 : {
684 0 : uno::Reference< io::XInputStream > xGrInStream = ImplGetReplacementImage( xObj );
685 0 : if ( xGrInStream.is() )
686 : {
687 0 : aEmbDescr.realloc( 2 );
688 0 : aEmbDescr[1].Name = "VisualReplacement";
689 0 : aEmbDescr[1].Value <<= xGrInStream;
690 0 : }
691 : }
692 :
693 0 : xPersist->storeToEntry( mxTempStorage, aObjectStorageName,
694 0 : aDummy, aEmbDescr );
695 : Reference < io::XStream > xStream =
696 0 : mxTempStorage->openStreamElement(
697 : aObjectStorageName,
698 0 : embed::ElementModes::READ);
699 0 : if( xStream.is() )
700 0 : xStrm = xStream->getInputStream();
701 0 : }
702 : }
703 0 : }
704 : }
705 0 : catch ( uno::Exception& )
706 : {
707 : }
708 : }
709 :
710 0 : aRet <<= xStrm;
711 : }
712 :
713 0 : return aRet;
714 : }
715 :
716 0 : Sequence< OUString > SAL_CALL SvXMLEmbeddedObjectHelper::getElementNames()
717 : throw (RuntimeException, std::exception)
718 : {
719 0 : MutexGuard aGuard( maMutex );
720 0 : return Sequence< OUString >(0);
721 : }
722 :
723 0 : sal_Bool SAL_CALL SvXMLEmbeddedObjectHelper::hasByName( const OUString& rURLStr )
724 : throw (RuntimeException, std::exception)
725 : {
726 0 : MutexGuard aGuard( maMutex );
727 0 : if( EMBEDDEDOBJECTHELPER_MODE_READ == meCreateMode )
728 : {
729 0 : return sal_True;
730 : }
731 : else
732 : {
733 0 : OUString aContainerStorageName, aObjectStorageName;
734 0 : if( !ImplGetStorageNames( rURLStr, aContainerStorageName,
735 : aObjectStorageName,
736 0 : true ) )
737 0 : return sal_False;
738 :
739 0 : comphelper::EmbeddedObjectContainer& rContainer = mpDocPersist->getEmbeddedObjectContainer();
740 0 : return !aObjectStorageName.isEmpty() &&
741 0 : rContainer.HasEmbeddedObject( aObjectStorageName );
742 0 : }
743 : }
744 :
745 : // XNameAccess
746 0 : Type SAL_CALL SvXMLEmbeddedObjectHelper::getElementType()
747 : throw (RuntimeException, std::exception)
748 : {
749 0 : MutexGuard aGuard( maMutex );
750 0 : if( EMBEDDEDOBJECTHELPER_MODE_READ == meCreateMode )
751 0 : return ::getCppuType((const Reference<XOutputStream>*)0);
752 : else
753 0 : return ::getCppuType((const Reference<XInputStream>*)0);
754 : }
755 :
756 0 : sal_Bool SAL_CALL SvXMLEmbeddedObjectHelper::hasElements()
757 : throw (RuntimeException, std::exception)
758 : {
759 0 : MutexGuard aGuard( maMutex );
760 0 : if( EMBEDDEDOBJECTHELPER_MODE_READ == meCreateMode )
761 : {
762 0 : return sal_True;
763 : }
764 : else
765 : {
766 0 : comphelper::EmbeddedObjectContainer& rContainer = mpDocPersist->getEmbeddedObjectContainer();
767 0 : return rContainer.HasEmbeddedObjects();
768 0 : }
769 : }
770 :
771 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|