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