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