1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_embeddedobj.hxx"
26
27 #include <oleembobj.hxx>
28 #include <com/sun/star/embed/EmbedStates.hpp>
29 #include <com/sun/star/embed/EmbedVerbs.hpp>
30 #include <com/sun/star/embed/EntryInitModes.hpp>
31 #include <com/sun/star/embed/XStorage.hpp>
32 #include <com/sun/star/embed/XTransactedObject.hpp>
33 #include <com/sun/star/embed/ElementModes.hpp>
34 #include <com/sun/star/embed/EmbedUpdateModes.hpp>
35 #include <com/sun/star/embed/Aspects.hpp>
36 #include <com/sun/star/embed/XOptimizedStorage.hpp>
37 #include <com/sun/star/lang/XComponent.hpp>
38 #include <com/sun/star/lang/DisposedException.hpp>
39 #include <com/sun/star/container/XNameAccess.hpp>
40 #include <com/sun/star/container/XNameContainer.hpp>
41 #include <com/sun/star/io/XSeekable.hpp>
42 #include <com/sun/star/io/XTruncate.hpp>
43 #include <com/sun/star/beans/XPropertySet.hpp>
44 #include <com/sun/star/ucb/XSimpleFileAccess.hpp>
45
46 #include <rtl/logfile.hxx>
47
48 #include <comphelper/storagehelper.hxx>
49 #include <comphelper/mimeconfighelper.hxx>
50 #include <comphelper/classids.hxx>
51
52
53 #include <olecomponent.hxx>
54 #include <closepreventer.hxx>
55
56 using namespace ::com::sun::star;
57 using namespace ::comphelper;
58
59 //-------------------------------------------------------------------------
KillFile_Impl(const::rtl::OUString & aURL,const uno::Reference<lang::XMultiServiceFactory> & xFactory)60 sal_Bool KillFile_Impl( const ::rtl::OUString& aURL, const uno::Reference< lang::XMultiServiceFactory >& xFactory )
61 {
62 if ( !xFactory.is() )
63 return sal_False;
64
65 sal_Bool bRet = sal_False;
66
67 try
68 {
69 uno::Reference < ucb::XSimpleFileAccess > xAccess(
70 xFactory->createInstance (
71 ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ),
72 uno::UNO_QUERY );
73
74 if ( xAccess.is() )
75 {
76 xAccess->kill( aURL );
77 bRet = sal_True;
78 }
79 }
80 catch( uno::Exception& )
81 {
82 }
83
84 return bRet;
85 }
86
87 //----------------------------------------------
GetNewTempFileURL_Impl(const uno::Reference<lang::XMultiServiceFactory> & xFactory)88 ::rtl::OUString GetNewTempFileURL_Impl( const uno::Reference< lang::XMultiServiceFactory >& xFactory )
89 {
90 OSL_ENSURE( xFactory.is(), "No factory is provided!\n" );
91
92 ::rtl::OUString aResult;
93
94 uno::Reference < beans::XPropertySet > xTempFile(
95 xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ),
96 uno::UNO_QUERY );
97
98 if ( !xTempFile.is() )
99 throw uno::RuntimeException(); // TODO
100
101 try {
102 xTempFile->setPropertyValue( ::rtl::OUString::createFromAscii( "RemoveFile" ), uno::makeAny( sal_False ) );
103 uno::Any aUrl = xTempFile->getPropertyValue( ::rtl::OUString::createFromAscii( "Uri" ) );
104 aUrl >>= aResult;
105 }
106 catch ( uno::Exception& )
107 {
108 }
109
110 if ( !aResult.getLength() )
111 throw uno::RuntimeException(); // TODO: can not create tempfile
112
113 return aResult;
114 }
115
116 //-----------------------------------------------
GetNewFilledTempFile_Impl(const uno::Reference<io::XInputStream> & xInStream,const uno::Reference<lang::XMultiServiceFactory> & xFactory)117 ::rtl::OUString GetNewFilledTempFile_Impl( const uno::Reference< io::XInputStream >& xInStream,
118 const uno::Reference< lang::XMultiServiceFactory >& xFactory )
119 {
120 OSL_ENSURE( xInStream.is() && xFactory.is(), "Wrong parameters are provided!\n" );
121
122 ::rtl::OUString aResult = GetNewTempFileURL_Impl( xFactory );
123
124 if ( aResult.getLength() )
125 {
126 try {
127 uno::Reference < ucb::XSimpleFileAccess > xTempAccess(
128 xFactory->createInstance (
129 ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ),
130 uno::UNO_QUERY );
131
132 if ( !xTempAccess.is() )
133 throw uno::RuntimeException(); // TODO:
134
135 uno::Reference< io::XOutputStream > xTempOutStream = xTempAccess->openFileWrite( aResult );
136 if ( xTempOutStream.is() )
137 {
138 // copy stream contents to the file
139 ::comphelper::OStorageHelper::CopyInputToOutput( xInStream, xTempOutStream );
140 xTempOutStream->closeOutput();
141 xTempOutStream = uno::Reference< io::XOutputStream >();
142 }
143 else
144 throw io::IOException(); // TODO:
145 }
146 catch( packages::WrongPasswordException& )
147 {
148 KillFile_Impl( aResult, xFactory );
149 throw io::IOException(); //TODO:
150 }
151 catch( io::IOException& )
152 {
153 KillFile_Impl( aResult, xFactory );
154 throw;
155 }
156 catch( uno::RuntimeException& )
157 {
158 KillFile_Impl( aResult, xFactory );
159 throw;
160 }
161 catch( uno::Exception& )
162 {
163 KillFile_Impl( aResult, xFactory );
164 aResult = ::rtl::OUString();
165 }
166 }
167
168 return aResult;
169 }
170 #ifdef WNT
GetNewFilledTempFile_Impl(const uno::Reference<embed::XOptimizedStorage> & xParentStorage,const::rtl::OUString & aEntryName,const uno::Reference<lang::XMultiServiceFactory> & xFactory)171 ::rtl::OUString GetNewFilledTempFile_Impl( const uno::Reference< embed::XOptimizedStorage >& xParentStorage, const ::rtl::OUString& aEntryName, const uno::Reference< lang::XMultiServiceFactory >& xFactory )
172 {
173 ::rtl::OUString aResult;
174
175 try
176 {
177 uno::Reference < beans::XPropertySet > xTempFile(
178 xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ),
179 uno::UNO_QUERY );
180 uno::Reference < io::XStream > xTempStream( xTempFile, uno::UNO_QUERY_THROW );
181
182 xParentStorage->copyStreamElementData( aEntryName, xTempStream );
183
184 xTempFile->setPropertyValue( ::rtl::OUString::createFromAscii( "RemoveFile" ), uno::makeAny( sal_False ) );
185 uno::Any aUrl = xTempFile->getPropertyValue( ::rtl::OUString::createFromAscii( "Uri" ) );
186 aUrl >>= aResult;
187 }
188 catch( uno::RuntimeException& )
189 {
190 throw;
191 }
192 catch( uno::Exception& )
193 {
194 }
195
196 if ( !aResult.getLength() )
197 throw io::IOException();
198
199 return aResult;
200 }
201
202 //------------------------------------------------------
SetStreamMediaType_Impl(const uno::Reference<io::XStream> & xStream,const::rtl::OUString & aMediaType)203 void SetStreamMediaType_Impl( const uno::Reference< io::XStream >& xStream, const ::rtl::OUString& aMediaType )
204 {
205 uno::Reference< beans::XPropertySet > xPropSet( xStream, uno::UNO_QUERY );
206 if ( !xPropSet.is() )
207 throw uno::RuntimeException(); // TODO: all the storage streams must support XPropertySet
208
209 xPropSet->setPropertyValue( ::rtl::OUString::createFromAscii( "MediaType" ), uno::makeAny( aMediaType ) );
210 }
211 #endif
212 //------------------------------------------------------
LetCommonStoragePassBeUsed_Impl(const uno::Reference<io::XStream> & xStream)213 void LetCommonStoragePassBeUsed_Impl( const uno::Reference< io::XStream >& xStream )
214 {
215 uno::Reference< beans::XPropertySet > xPropSet( xStream, uno::UNO_QUERY );
216 if ( !xPropSet.is() )
217 throw uno::RuntimeException(); // Only StorageStreams must be provided here, they must implement the interface
218
219 xPropSet->setPropertyValue( ::rtl::OUString::createFromAscii( "UseCommonStoragePasswordEncryption" ),
220 uno::makeAny( (sal_Bool)sal_True ) );
221 }
222 #ifdef WNT
223 //------------------------------------------------------
StartControlExecution()224 void VerbExecutionController::StartControlExecution()
225 {
226 osl::MutexGuard aGuard( m_aVerbExecutionMutex );
227
228 // the class is used to detect STAMPIT object, that can never be active
229 if ( !m_bVerbExecutionInProgress && !m_bWasEverActive )
230 {
231 m_bVerbExecutionInProgress = sal_True;
232 m_nVerbExecutionThreadIdentifier = osl_getThreadIdentifier( NULL );
233 m_bChangedOnVerbExecution = sal_False;
234 }
235 }
236
237 //------------------------------------------------------
EndControlExecution_WasModified()238 sal_Bool VerbExecutionController::EndControlExecution_WasModified()
239 {
240 osl::MutexGuard aGuard( m_aVerbExecutionMutex );
241
242 sal_Bool bResult = sal_False;
243 if ( m_bVerbExecutionInProgress && m_nVerbExecutionThreadIdentifier == osl_getThreadIdentifier( NULL ) )
244 {
245 bResult = m_bChangedOnVerbExecution;
246 m_bVerbExecutionInProgress = sal_False;
247 }
248
249 return bResult;
250 }
251
252 //------------------------------------------------------
ModificationNotificationIsDone()253 void VerbExecutionController::ModificationNotificationIsDone()
254 {
255 osl::MutexGuard aGuard( m_aVerbExecutionMutex );
256
257 if ( m_bVerbExecutionInProgress && osl_getThreadIdentifier( NULL ) == m_nVerbExecutionThreadIdentifier )
258 m_bChangedOnVerbExecution = sal_True;
259 }
260 #endif
261 //-----------------------------------------------
LockNotification()262 void VerbExecutionController::LockNotification()
263 {
264 osl::MutexGuard aGuard( m_aVerbExecutionMutex );
265 if ( m_nNotificationLock < SAL_MAX_INT32 )
266 m_nNotificationLock++;
267 }
268
269 //-----------------------------------------------
UnlockNotification()270 void VerbExecutionController::UnlockNotification()
271 {
272 osl::MutexGuard aGuard( m_aVerbExecutionMutex );
273 if ( m_nNotificationLock > 0 )
274 m_nNotificationLock--;
275 }
276
277 //-----------------------------------------------
GetNewFilledTempStream_Impl(const uno::Reference<io::XInputStream> & xInStream)278 uno::Reference< io::XStream > OleEmbeddedObject::GetNewFilledTempStream_Impl( const uno::Reference< io::XInputStream >& xInStream )
279 {
280 OSL_ENSURE( xInStream.is(), "Wrong parameter is provided!\n" );
281
282 uno::Reference < io::XStream > xTempFile(
283 m_xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ),
284 uno::UNO_QUERY_THROW );
285
286 uno::Reference< io::XOutputStream > xTempOutStream = xTempFile->getOutputStream();
287 if ( xTempOutStream.is() )
288 {
289 ::comphelper::OStorageHelper::CopyInputToOutput( xInStream, xTempOutStream );
290 xTempOutStream->flush();
291 }
292 else
293 throw io::IOException(); // TODO:
294
295 return xTempFile;
296 }
297
298 //------------------------------------------------------
TryToGetAcceptableFormat_Impl(const uno::Reference<io::XStream> & xStream)299 uno::Reference< io::XStream > OleEmbeddedObject::TryToGetAcceptableFormat_Impl( const uno::Reference< io::XStream >& xStream )
300 {
301 // TODO/LATER: Actually this should be done by a centralized component ( may be a graphical filter )
302 if ( !m_xFactory.is() )
303 throw uno::RuntimeException();
304
305 uno::Reference< io::XInputStream > xInStream = xStream->getInputStream();
306 if ( !xInStream.is() )
307 throw uno::RuntimeException();
308
309 uno::Reference< io::XSeekable > xSeek( xStream, uno::UNO_QUERY_THROW );
310 xSeek->seek( 0 );
311
312 uno::Sequence< sal_Int8 > aData( 8 );
313 sal_Int32 nRead = xInStream->readBytes( aData, 8 );
314 xSeek->seek( 0 );
315
316 if ( ( nRead >= 2 && aData[0] == 'B' && aData[1] == 'M' )
317 || ( nRead >= 4 && aData[0] == 1 && aData[1] == 0 && aData[2] == 9 && aData[3] == 0 ) )
318 {
319 // it should be a bitmap or a Metafile
320 return xStream;
321 }
322
323 // sal_Bool bSetSizeToRepl = sal_False;
324 // awt::Size aSizeToSet;
325
326 sal_uInt32 nHeaderOffset = 0;
327 if ( ( nRead >= 8 && aData[0] == -1 && aData[1] == -1 && aData[2] == -1 && aData[3] == -1 )
328 && ( aData[4] == 2 || aData[4] == 3 || aData[4] == 14 ) && aData[5] == 0 && aData[6] == 0 && aData[7] == 0 )
329 {
330 nHeaderOffset = 40;
331 xSeek->seek( 8 );
332
333 // TargetDevice might be used in future, currently the cache has specified NULL
334 uno::Sequence< sal_Int8 > aHeadData( 4 );
335 nRead = xInStream->readBytes( aHeadData, 4 );
336 sal_uInt32 nLen = 0;
337 if ( nRead == 4 && aHeadData.getLength() == 4 )
338 nLen = ( ( ( (sal_uInt32)aHeadData[3] * 0x100 + (sal_uInt32)aHeadData[2] ) * 0x100 ) + (sal_uInt32)aHeadData[1] ) * 0x100 + (sal_uInt32)aHeadData[0];
339 if ( nLen > 4 )
340 {
341 xInStream->skipBytes( nLen - 4 );
342 nHeaderOffset += nLen - 4;
343 }
344
345 // if ( aData[4] == 3 )
346 // {
347 // try
348 // {
349 //
350 // aSizeToSet = getVisualAreaSize( embed::Aspects::MSOLE_CONTENT );
351 // aSizeToSet.Width /= 364; //2540; // let the size be in inches, as wmf requires
352 // aSizeToSet.Height /= 364; //2540; // let the size be in inches, as wmf requires
353 // bSetSizeToRepl = sal_True;
354 // }
355 // catch( uno::Exception& )
356 // {}
357 // }
358 }
359 else if ( nRead > 4 )
360 {
361 // check whether the first bytes represent the size
362 sal_uInt32 nSize = 0;
363 for ( sal_Int32 nInd = 3; nInd >= 0; nInd-- )
364 nSize = ( nSize << 8 ) + (sal_uInt8)aData[nInd];
365
366 if ( nSize == xSeek->getLength() - 4 )
367 nHeaderOffset = 4;
368 }
369
370 if ( nHeaderOffset )
371 {
372 // this is either a bitmap or a metafile clipboard format, retrieve the pure stream
373 uno::Reference < io::XStream > xResult(
374 m_xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ),
375 uno::UNO_QUERY_THROW );
376 uno::Reference < io::XSeekable > xResultSeek( xResult, uno::UNO_QUERY_THROW );
377 uno::Reference < io::XOutputStream > xResultOut = xResult->getOutputStream();
378 uno::Reference < io::XInputStream > xResultIn = xResult->getInputStream();
379 if ( !xResultOut.is() || !xResultIn.is() )
380 throw uno::RuntimeException();
381
382 // if it is windows metafile the size must be provided
383 // the solution is not used currently
384 // if ( bSetSizeToRepl && abs( aSizeToSet.Width ) < 0xFFFF && abs( aSizeToSet.Height ) < 0xFFFF )
385 // {
386 // uno::Sequence< sal_Int8 > aHeader(22);
387 // sal_uInt8* pBuffer = (sal_uInt8*)aHeader.getArray();
388 //
389 // // write 0x9ac6cdd7L
390 // pBuffer[0] = 0xd7;
391 // pBuffer[1] = 0xcd;
392 // pBuffer[2] = 0xc6;
393 // pBuffer[3] = 0x9a;
394 //
395 // // following data seems to have no value
396 // pBuffer[4] = 0;
397 // pBuffer[5] = 0;
398 //
399 // // must be set to 0
400 // pBuffer[6] = 0;
401 // pBuffer[7] = 0;
402 // pBuffer[8] = 0;
403 // pBuffer[9] = 0;
404 //
405 // // width of the picture
406 // pBuffer[10] = abs( aSizeToSet.Width ) % 0x100;
407 // pBuffer[11] = ( abs( aSizeToSet.Width ) / 0x100 ) % 0x100;
408 //
409 // // height of the picture
410 // pBuffer[12] = abs( aSizeToSet.Height ) % 0x100;
411 // pBuffer[13] = ( abs( aSizeToSet.Height ) / 0x100 ) % 0x100;
412 //
413 // // write 2540
414 // pBuffer[14] = 0x6c; //0xec;
415 // pBuffer[15] = 0x01; //0x09;
416 //
417 // // fill with 0
418 // for ( sal_Int32 nInd = 16; nInd < 22; nInd++ )
419 // pBuffer[nInd] = 0;
420 //
421 // xResultOut->writeBytes( aHeader );
422 // }
423
424 xSeek->seek( nHeaderOffset ); // header size for these formats
425 ::comphelper::OStorageHelper::CopyInputToOutput( xInStream, xResultOut );
426 xResultOut->closeOutput();
427 xResultSeek->seek( 0 );
428 xSeek->seek( 0 );
429
430 return xResult;
431 }
432
433 return uno::Reference< io::XStream >();
434 }
435
436 //------------------------------------------------------
InsertVisualCache_Impl(const uno::Reference<io::XStream> & xTargetStream,const uno::Reference<io::XStream> & xCachedVisualRepresentation)437 void OleEmbeddedObject::InsertVisualCache_Impl( const uno::Reference< io::XStream >& xTargetStream,
438 const uno::Reference< io::XStream >& xCachedVisualRepresentation )
439 {
440 OSL_ENSURE( xTargetStream.is() && xCachedVisualRepresentation.is(), "Invalid arguments!\n" );
441
442 if ( !xTargetStream.is() || !xCachedVisualRepresentation.is() )
443 throw uno::RuntimeException();
444
445 uno::Sequence< uno::Any > aArgs( 2 );
446 aArgs[0] <<= xTargetStream;
447 aArgs[1] <<= (sal_Bool)sal_True; // do not create copy
448
449 uno::Reference< container::XNameContainer > xNameContainer(
450 m_xFactory->createInstanceWithArguments(
451 ::rtl::OUString::createFromAscii( "com.sun.star.embed.OLESimpleStorage" ),
452 aArgs ),
453 uno::UNO_QUERY );
454
455 if ( !xNameContainer.is() )
456 throw uno::RuntimeException();
457
458 uno::Reference< io::XSeekable > xCachedSeek( xCachedVisualRepresentation, uno::UNO_QUERY_THROW );
459 if ( xCachedSeek.is() )
460 xCachedSeek->seek( 0 );
461
462 uno::Reference < io::XStream > xTempFile(
463 m_xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ),
464 uno::UNO_QUERY_THROW );
465
466 uno::Reference< io::XSeekable > xTempSeek( xTempFile, uno::UNO_QUERY_THROW );
467 uno::Reference< io::XOutputStream > xTempOutStream = xTempFile->getOutputStream();
468 if ( xTempOutStream.is() )
469 {
470 // the OlePres stream must have additional header
471 // TODO/LATER: might need to be extended in future ( actually makes sense only for SO7 format )
472 uno::Reference< io::XInputStream > xInCacheStream = xCachedVisualRepresentation->getInputStream();
473 if ( !xInCacheStream.is() )
474 throw uno::RuntimeException();
475
476 // write 0xFFFFFFFF at the beginning
477 uno::Sequence< sal_Int8 > aData( 4 );
478 *( (sal_uInt32*)aData.getArray() ) = 0xFFFFFFFF;
479
480 xTempOutStream->writeBytes( aData );
481
482 // write clipboard format
483 uno::Sequence< sal_Int8 > aSigData( 2 );
484 xInCacheStream->readBytes( aSigData, 2 );
485 if ( aSigData.getLength() < 2 )
486 throw io::IOException();
487
488 if ( aSigData[0] == 'B' && aSigData[1] == 'M' )
489 {
490 // it's a bitmap
491 aData[0] = 0x02; aData[1] = 0; aData[2] = 0; aData[3] = 0;
492 }
493 else
494 {
495 // treat it as a metafile
496 aData[0] = 0x03; aData[1] = 0; aData[2] = 0; aData[3] = 0;
497 }
498 xTempOutStream->writeBytes( aData );
499
500 // write job related information
501 aData[0] = 0x04; aData[1] = 0; aData[2] = 0; aData[3] = 0;
502 xTempOutStream->writeBytes( aData );
503
504 // write aspect
505 aData[0] = 0x01; aData[1] = 0; aData[2] = 0; aData[3] = 0;
506 xTempOutStream->writeBytes( aData );
507
508 // write l-index
509 *( (sal_uInt32*)aData.getArray() ) = 0xFFFFFFFF;
510 xTempOutStream->writeBytes( aData );
511
512 // write adv. flags
513 aData[0] = 0x02; aData[1] = 0; aData[2] = 0; aData[3] = 0;
514 xTempOutStream->writeBytes( aData );
515
516 // write compression
517 *( (sal_uInt32*)aData.getArray() ) = 0x0;
518 xTempOutStream->writeBytes( aData );
519
520 // get the size
521 awt::Size aSize = getVisualAreaSize( embed::Aspects::MSOLE_CONTENT );
522 sal_Int32 nIndex = 0;
523
524 // write width
525 for ( nIndex = 0; nIndex < 4; nIndex++ )
526 {
527 aData[nIndex] = (sal_Int8)( aSize.Width % 0x100 );
528 aSize.Width /= 0x100;
529 }
530 xTempOutStream->writeBytes( aData );
531
532 // write height
533 for ( nIndex = 0; nIndex < 4; nIndex++ )
534 {
535 aData[nIndex] = (sal_Int8)( aSize.Height % 0x100 );
536 aSize.Height /= 0x100;
537 }
538 xTempOutStream->writeBytes( aData );
539
540 // write garbage, it will be overwritten by the size
541 xTempOutStream->writeBytes( aData );
542
543 // write first bytes that was used to detect the type
544 xTempOutStream->writeBytes( aSigData );
545
546 // write the rest of the stream
547 ::comphelper::OStorageHelper::CopyInputToOutput( xInCacheStream, xTempOutStream );
548
549 // write the size of the stream
550 sal_Int64 nLength = xTempSeek->getLength() - 40;
551 if ( nLength < 0 || nLength >= 0xFFFFFFFF )
552 {
553 OSL_ENSURE( sal_False, "Length is not acceptable!" );
554 return;
555 }
556 for ( sal_Int32 nInd = 0; nInd < 4; nInd++ )
557 {
558 aData[nInd] = (sal_Int8)( ( (sal_uInt64) nLength ) % 0x100 );
559 nLength /= 0x100;
560 }
561 xTempSeek->seek( 36 );
562 xTempOutStream->writeBytes( aData );
563
564 xTempOutStream->flush();
565
566 xTempSeek->seek( 0 );
567 if ( xCachedSeek.is() )
568 xCachedSeek->seek( 0 );
569 }
570 else
571 throw io::IOException(); // TODO:
572
573 // insert the result file as replacement image
574 ::rtl::OUString aCacheName = ::rtl::OUString::createFromAscii( "\002OlePres000" );
575 if ( xNameContainer->hasByName( aCacheName ) )
576 xNameContainer->replaceByName( aCacheName, uno::makeAny( xTempFile ) );
577 else
578 xNameContainer->insertByName( aCacheName, uno::makeAny( xTempFile ) );
579
580 uno::Reference< embed::XTransactedObject > xTransacted( xNameContainer, uno::UNO_QUERY );
581 if ( !xTransacted.is() )
582 throw uno::RuntimeException();
583
584 xTransacted->commit();
585 }
586
587 //------------------------------------------------------
RemoveVisualCache_Impl(const uno::Reference<io::XStream> & xTargetStream)588 void OleEmbeddedObject::RemoveVisualCache_Impl( const uno::Reference< io::XStream >& xTargetStream )
589 {
590 OSL_ENSURE( xTargetStream.is(), "Invalid argument!\n" );
591 if ( !xTargetStream.is() )
592 throw uno::RuntimeException();
593
594 uno::Sequence< uno::Any > aArgs( 2 );
595 aArgs[0] <<= xTargetStream;
596 aArgs[1] <<= (sal_Bool)sal_True; // do not create copy
597 uno::Reference< container::XNameContainer > xNameContainer(
598 m_xFactory->createInstanceWithArguments(
599 ::rtl::OUString::createFromAscii( "com.sun.star.embed.OLESimpleStorage" ),
600 aArgs ),
601 uno::UNO_QUERY );
602
603 if ( !xNameContainer.is() )
604 throw uno::RuntimeException();
605
606 for ( sal_uInt8 nInd = 0; nInd < 10; nInd++ )
607 {
608 ::rtl::OUString aStreamName = ::rtl::OUString::createFromAscii( "\002OlePres00" );
609 aStreamName += ::rtl::OUString::valueOf( (sal_Int32)nInd );
610 if ( xNameContainer->hasByName( aStreamName ) )
611 xNameContainer->removeByName( aStreamName );
612 }
613
614 uno::Reference< embed::XTransactedObject > xTransacted( xNameContainer, uno::UNO_QUERY );
615 if ( !xTransacted.is() )
616 throw uno::RuntimeException();
617
618 xTransacted->commit();
619 }
620
621 //------------------------------------------------------
SetVisReplInStream(sal_Bool bExists)622 void OleEmbeddedObject::SetVisReplInStream( sal_Bool bExists )
623 {
624 m_bVisReplInitialized = sal_True;
625 m_bVisReplInStream = bExists;
626 }
627
628 //------------------------------------------------------
HasVisReplInStream()629 sal_Bool OleEmbeddedObject::HasVisReplInStream()
630 {
631 if ( !m_bVisReplInitialized )
632 {
633 if ( m_xCachedVisualRepresentation.is() )
634 SetVisReplInStream( sal_True );
635 else
636 {
637 RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OleEmbeddedObject::HasVisualReplInStream, analyzing" );
638
639 uno::Reference< io::XInputStream > xStream;
640
641 OSL_ENSURE( !m_pOleComponent || m_aTempURL.getLength(), "The temporary file must exist if there is a component!\n" );
642 if ( m_aTempURL.getLength() )
643 {
644 try
645 {
646 // open temporary file for reading
647 uno::Reference < ucb::XSimpleFileAccess > xTempAccess(
648 m_xFactory->createInstance (
649 ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ),
650 uno::UNO_QUERY );
651
652 if ( !xTempAccess.is() )
653 throw uno::RuntimeException(); // TODO:
654
655 xStream = xTempAccess->openFileRead( m_aTempURL );
656 }
657 catch( uno::Exception& )
658 {}
659 }
660
661 if ( !xStream.is() )
662 xStream = m_xObjectStream->getInputStream();
663
664 if ( xStream.is() )
665 {
666 sal_Bool bExists = sal_False;
667
668 uno::Sequence< uno::Any > aArgs( 2 );
669 aArgs[0] <<= xStream;
670 aArgs[1] <<= (sal_Bool)sal_True; // do not create copy
671 uno::Reference< container::XNameContainer > xNameContainer(
672 m_xFactory->createInstanceWithArguments(
673 ::rtl::OUString::createFromAscii( "com.sun.star.embed.OLESimpleStorage" ),
674 aArgs ),
675 uno::UNO_QUERY );
676
677 if ( xNameContainer.is() )
678 {
679 for ( sal_uInt8 nInd = 0; nInd < 10 && !bExists; nInd++ )
680 {
681 ::rtl::OUString aStreamName = ::rtl::OUString::createFromAscii( "\002OlePres00" );
682 aStreamName += ::rtl::OUString::valueOf( (sal_Int32)nInd );
683 try
684 {
685 bExists = xNameContainer->hasByName( aStreamName );
686 }
687 catch( uno::Exception& )
688 {}
689 }
690 }
691
692 SetVisReplInStream( bExists );
693 }
694 }
695 }
696
697 return m_bVisReplInStream;
698 }
699
700 //------------------------------------------------------
TryToRetrieveCachedVisualRepresentation_Impl(const uno::Reference<io::XStream> & xStream,sal_Bool bAllowToRepair50)701 uno::Reference< io::XStream > OleEmbeddedObject::TryToRetrieveCachedVisualRepresentation_Impl(
702 const uno::Reference< io::XStream >& xStream,
703 sal_Bool bAllowToRepair50 )
704 throw ()
705 {
706 uno::Reference< io::XStream > xResult;
707
708 if ( xStream.is() )
709 {
710 RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OleEmbeddedObject::TryToRetrieveCachedVisualRepresentation, retrieving" );
711
712 uno::Reference< container::XNameContainer > xNameContainer;
713 uno::Sequence< uno::Any > aArgs( 2 );
714 aArgs[0] <<= xStream;
715 aArgs[1] <<= (sal_Bool)sal_True; // do not create copy
716 try
717 {
718 xNameContainer = uno::Reference< container::XNameContainer >(
719 m_xFactory->createInstanceWithArguments(
720 ::rtl::OUString::createFromAscii( "com.sun.star.embed.OLESimpleStorage" ),
721 aArgs ),
722 uno::UNO_QUERY );
723 }
724 catch( uno::Exception& )
725 {}
726
727 if ( xNameContainer.is() )
728 {
729 for ( sal_uInt8 nInd = 0; nInd < 10; nInd++ )
730 {
731 ::rtl::OUString aStreamName = ::rtl::OUString::createFromAscii( "\002OlePres00" );
732 aStreamName += ::rtl::OUString::valueOf( (sal_Int32)nInd );
733 uno::Reference< io::XStream > xCachedCopyStream;
734 try
735 {
736 if ( ( xNameContainer->getByName( aStreamName ) >>= xCachedCopyStream ) && xCachedCopyStream.is() )
737 {
738 xResult = TryToGetAcceptableFormat_Impl( xCachedCopyStream );
739 if ( xResult.is() )
740 break;
741 }
742 }
743 catch( uno::Exception& )
744 {}
745
746 if ( nInd == 0 )
747 {
748 // to be compatible with the old versions Ole10Native is checked after OlePress000
749 aStreamName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "\001Ole10Native" ) );
750 try
751 {
752 if ( ( xNameContainer->getByName( aStreamName ) >>= xCachedCopyStream ) && xCachedCopyStream.is() )
753 {
754 xResult = TryToGetAcceptableFormat_Impl( xCachedCopyStream );
755 if ( xResult.is() )
756 break;
757 }
758 }
759 catch( uno::Exception& )
760 {}
761 }
762 }
763
764 try
765 {
766 if ( bAllowToRepair50 && !xResult.is() )
767 {
768 ::rtl::OUString aOrigContName( RTL_CONSTASCII_USTRINGPARAM( "Ole-Object" ) );
769 if ( xNameContainer->hasByName( aOrigContName ) )
770 {
771 uno::Reference< embed::XClassifiedObject > xClassified( xNameContainer, uno::UNO_QUERY_THROW );
772 uno::Sequence< sal_Int8 > aClassID;
773 if ( MimeConfigurationHelper::ClassIDsEqual( xClassified->getClassID(), MimeConfigurationHelper::GetSequenceClassID( SO3_OUT_CLASSID ) ) )
774 {
775 // this is an OLE object wrongly stored in 5.0 format
776 // this object must be repaired since SO7 has done it
777
778 uno::Reference< io::XOutputStream > xOutputStream = xStream->getOutputStream();
779 uno::Reference< io::XTruncate > xTruncate( xOutputStream, uno::UNO_QUERY_THROW );
780
781 uno::Reference< io::XInputStream > xOrigInputStream;
782 if ( ( xNameContainer->getByName( aOrigContName ) >>= xOrigInputStream )
783 && xOrigInputStream.is() )
784 {
785 // the provided input stream must be based on temporary medium and must be independent
786 // from the stream the storage is based on
787 uno::Reference< io::XSeekable > xOrigSeekable( xOrigInputStream, uno::UNO_QUERY );
788 if ( xOrigSeekable.is() )
789 xOrigSeekable->seek( 0 );
790
791 uno::Reference< lang::XComponent > xNameContDisp( xNameContainer, uno::UNO_QUERY_THROW );
792 xNameContDisp->dispose(); // free the original stream
793
794 xTruncate->truncate();
795 ::comphelper::OStorageHelper::CopyInputToOutput( xOrigInputStream, xOutputStream );
796 xOutputStream->flush();
797
798 if ( xStream == m_xObjectStream )
799 {
800 if ( m_aTempURL.getLength() )
801 {
802 // this is the own stream, so the temporary URL must be cleaned if it exists
803 KillFile_Impl( m_aTempURL, m_xFactory );
804 m_aTempURL = ::rtl::OUString();
805 }
806
807 #ifdef WNT
808 // retry to create the component after recovering
809 GetRidOfComponent();
810
811 try
812 {
813 CreateOleComponentAndLoad_Impl( NULL );
814 m_aClassID = m_pOleComponent->GetCLSID(); // was not set during construction
815 }
816 catch( uno::Exception& )
817 {
818 GetRidOfComponent();
819 }
820 #endif
821 }
822
823 xResult = TryToRetrieveCachedVisualRepresentation_Impl( xStream, sal_False );
824 }
825 }
826 }
827 }
828 }
829 catch( uno::Exception& )
830 {}
831 }
832 }
833
834 return xResult;
835 }
836
837 //------------------------------------------------------
SwitchOwnPersistence(const uno::Reference<embed::XStorage> & xNewParentStorage,const uno::Reference<io::XStream> & xNewObjectStream,const::rtl::OUString & aNewName)838 void OleEmbeddedObject::SwitchOwnPersistence( const uno::Reference< embed::XStorage >& xNewParentStorage,
839 const uno::Reference< io::XStream >& xNewObjectStream,
840 const ::rtl::OUString& aNewName )
841 {
842 if ( xNewParentStorage == m_xParentStorage && aNewName.equals( m_aEntryName ) )
843 {
844 OSL_ENSURE( xNewObjectStream == m_xObjectStream, "The streams must be the same!\n" );
845 return;
846 }
847
848 try {
849 uno::Reference< lang::XComponent > xComponent( m_xObjectStream, uno::UNO_QUERY );
850 OSL_ENSURE( !m_xObjectStream.is() || xComponent.is(), "Wrong stream implementation!" );
851 if ( xComponent.is() )
852 xComponent->dispose();
853 }
854 catch ( uno::Exception& )
855 {
856 }
857
858 m_xObjectStream = xNewObjectStream;
859 m_xParentStorage = xNewParentStorage;
860 m_aEntryName = aNewName;
861 }
862
863 //------------------------------------------------------
SwitchOwnPersistence(const uno::Reference<embed::XStorage> & xNewParentStorage,const::rtl::OUString & aNewName)864 void OleEmbeddedObject::SwitchOwnPersistence( const uno::Reference< embed::XStorage >& xNewParentStorage,
865 const ::rtl::OUString& aNewName )
866 {
867 if ( xNewParentStorage == m_xParentStorage && aNewName.equals( m_aEntryName ) )
868 return;
869
870 sal_Int32 nStreamMode = m_bReadOnly ? embed::ElementModes::READ : embed::ElementModes::READWRITE;
871
872 uno::Reference< io::XStream > xNewOwnStream = xNewParentStorage->openStreamElement( aNewName, nStreamMode );
873 OSL_ENSURE( xNewOwnStream.is(), "The method can not return empty reference!" );
874
875 SwitchOwnPersistence( xNewParentStorage, xNewOwnStream, aNewName );
876 }
877
878 #ifdef WNT
879 //----------------------------------------------
SaveObject_Impl()880 sal_Bool OleEmbeddedObject::SaveObject_Impl()
881 {
882 sal_Bool bResult = sal_False;
883
884 if ( m_xClientSite.is() )
885 {
886 try
887 {
888 m_xClientSite->saveObject();
889 bResult = sal_True;
890 }
891 catch( uno::Exception& )
892 {
893 }
894 }
895
896 return bResult;
897 }
898
899 //----------------------------------------------
OnShowWindow_Impl(sal_Bool bShow)900 sal_Bool OleEmbeddedObject::OnShowWindow_Impl( sal_Bool bShow )
901 {
902 ::osl::ResettableMutexGuard aGuard( m_aMutex );
903
904 sal_Bool bResult = sal_False;
905
906 OSL_ENSURE( m_nObjectState != -1, "The object has no persistence!\n" );
907 OSL_ENSURE( m_nObjectState != embed::EmbedStates::LOADED, "The object get OnShowWindow in loaded state!\n" );
908 if ( m_nObjectState == -1 || m_nObjectState == embed::EmbedStates::LOADED )
909 return sal_False;
910
911 // the object is either activated or deactivated
912 sal_Int32 nOldState = m_nObjectState;
913 if ( bShow && m_nObjectState == embed::EmbedStates::RUNNING )
914 {
915 m_nObjectState = embed::EmbedStates::ACTIVE;
916 m_aVerbExecutionController.ObjectIsActive();
917
918 aGuard.clear();
919 StateChangeNotification_Impl( sal_False, nOldState, m_nObjectState );
920 }
921 else if ( !bShow && m_nObjectState == embed::EmbedStates::ACTIVE )
922 {
923 m_nObjectState = embed::EmbedStates::RUNNING;
924 aGuard.clear();
925 StateChangeNotification_Impl( sal_False, nOldState, m_nObjectState );
926 }
927
928 if ( m_xClientSite.is() )
929 {
930 try
931 {
932 m_xClientSite->visibilityChanged( bShow );
933 bResult = sal_True;
934 }
935 catch( uno::Exception& )
936 {
937 }
938 }
939
940 return bResult;
941 }
942
943 //------------------------------------------------------
OnIconChanged_Impl()944 void OleEmbeddedObject::OnIconChanged_Impl()
945 {
946 // TODO/LATER: currently this notification seems to be impossible
947 // MakeEventListenerNotification_Impl( ::rtl::OUString::createFromAscii( "OnIconChanged" ) );
948 }
949
950 //------------------------------------------------------
OnViewChanged_Impl()951 void OleEmbeddedObject::OnViewChanged_Impl()
952 {
953 if ( m_bDisposed )
954 throw lang::DisposedException();
955
956 // For performance reasons the notification currently is ignored, STAMPIT object is the exception,
957 // it can never be active and never call SaveObject, so it is the only way to detect that it is changed
958
959 // ==== the STAMPIT related solution =============================
960 // the following variable is used to detect whether the object was modified during verb execution
961 m_aVerbExecutionController.ModificationNotificationIsDone();
962
963 // The following things are controlled by VerbExecutionController:
964 // - if the verb execution is in progress and the view is changed the object will be stored
965 // after the execution, so there is no need to send the notification.
966 // - the STAMPIT object can never be active.
967 if ( m_aVerbExecutionController.CanDoNotification()
968 && m_pOleComponent && m_nUpdateMode == embed::EmbedUpdateModes::ALWAYS_UPDATE )
969 {
970 OSL_ENSURE( MimeConfigurationHelper::ClassIDsEqual( m_aClassID, MimeConfigurationHelper::GetSequenceClassID( 0x852ee1c9, 0x9058, 0x44ba, 0x8c,0x6c,0x0c,0x5f,0xc6,0x6b,0xdb,0x8d ) )
971 || MimeConfigurationHelper::ClassIDsEqual( m_aClassID, MimeConfigurationHelper::GetSequenceClassID( 0xcf1b4491, 0xbea3, 0x4c9f, 0xa7,0x0f,0x22,0x1b,0x1e,0xca,0xef,0x3e ) ),
972 "Expected to be triggered for STAMPIT only! Please contact developers!\n" );
973
974 // The view is changed while the object is in running state, save the new object
975 m_xCachedVisualRepresentation = uno::Reference< io::XStream >();
976 SaveObject_Impl();
977 MakeEventListenerNotification_Impl( ::rtl::OUString::createFromAscii( "OnVisAreaChanged" ) );
978 }
979 // ===============================================================
980 }
981
982 //------------------------------------------------------
OnClosed_Impl()983 void OleEmbeddedObject::OnClosed_Impl()
984 {
985 if ( m_bDisposed )
986 throw lang::DisposedException();
987
988 if ( m_nObjectState != embed::EmbedStates::LOADED )
989 {
990 sal_Int32 nOldState = m_nObjectState;
991 m_nObjectState = embed::EmbedStates::LOADED;
992 StateChangeNotification_Impl( sal_False, nOldState, m_nObjectState );
993 }
994 }
995
996 //------------------------------------------------------
CreateTempURLEmpty_Impl()997 ::rtl::OUString OleEmbeddedObject::CreateTempURLEmpty_Impl()
998 {
999 OSL_ENSURE( !m_aTempURL.getLength(), "The object has already the temporary file!" );
1000 m_aTempURL = GetNewTempFileURL_Impl( m_xFactory );
1001
1002 return m_aTempURL;
1003 }
1004
1005 //------------------------------------------------------
GetTempURL_Impl()1006 ::rtl::OUString OleEmbeddedObject::GetTempURL_Impl()
1007 {
1008 if ( !m_aTempURL.getLength() )
1009 {
1010 RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OleEmbeddedObject::GetTempURL_Impl, tempfile creation" );
1011
1012 // if there is no temporary file, it will be created from the own entry
1013 uno::Reference< embed::XOptimizedStorage > xOptParStorage( m_xParentStorage, uno::UNO_QUERY );
1014 if ( xOptParStorage.is() )
1015 {
1016 m_aTempURL = GetNewFilledTempFile_Impl( xOptParStorage, m_aEntryName, m_xFactory );
1017 }
1018 else if ( m_xObjectStream.is() )
1019 {
1020 // load object from the stream
1021 uno::Reference< io::XInputStream > xInStream = m_xObjectStream->getInputStream();
1022 if ( !xInStream.is() )
1023 throw io::IOException(); // TODO: access denied
1024
1025 m_aTempURL = GetNewFilledTempFile_Impl( xInStream, m_xFactory );
1026 }
1027 }
1028
1029 return m_aTempURL;
1030 }
1031
1032 //------------------------------------------------------
CreateOleComponent_Impl(OleComponent * pOleComponent)1033 void OleEmbeddedObject::CreateOleComponent_Impl( OleComponent* pOleComponent )
1034 {
1035 if ( !m_pOleComponent )
1036 {
1037 m_pOleComponent = pOleComponent ? pOleComponent : new OleComponent( m_xFactory, this );
1038 m_pOleComponent->acquire(); // TODO: needs holder?
1039
1040 if ( !m_xClosePreventer.is() )
1041 m_xClosePreventer = uno::Reference< util::XCloseListener >(
1042 static_cast< ::cppu::OWeakObject* >( new OClosePreventer ),
1043 uno::UNO_QUERY );
1044
1045 m_pOleComponent->addCloseListener( m_xClosePreventer );
1046 }
1047 }
1048
1049 //------------------------------------------------------
CreateOleComponentAndLoad_Impl(OleComponent * pOleComponent)1050 void OleEmbeddedObject::CreateOleComponentAndLoad_Impl( OleComponent* pOleComponent )
1051 {
1052 if ( !m_pOleComponent )
1053 {
1054 if ( !m_xObjectStream.is() )
1055 throw uno::RuntimeException();
1056
1057 CreateOleComponent_Impl( pOleComponent );
1058
1059 // after the loading the object can appear as a link
1060 // will be detected later by olecomponent
1061
1062 GetTempURL_Impl();
1063 if ( !m_aTempURL.getLength() )
1064 throw uno::RuntimeException(); // TODO
1065
1066 m_pOleComponent->LoadEmbeddedObject( m_aTempURL );
1067 }
1068 }
1069
1070 //------------------------------------------------------
CreateOleComponentFromClipboard_Impl(OleComponent * pOleComponent)1071 void OleEmbeddedObject::CreateOleComponentFromClipboard_Impl( OleComponent* pOleComponent )
1072 {
1073 if ( !m_pOleComponent )
1074 {
1075 if ( !m_xObjectStream.is() )
1076 throw uno::RuntimeException();
1077
1078 CreateOleComponent_Impl( pOleComponent );
1079
1080 // after the loading the object can appear as a link
1081 // will be detected later by olecomponent
1082 m_pOleComponent->CreateObjectFromClipboard();
1083 }
1084 }
1085
1086 //------------------------------------------------------
GetStreamForSaving()1087 uno::Reference< io::XOutputStream > OleEmbeddedObject::GetStreamForSaving()
1088 {
1089 if ( !m_xObjectStream.is() )
1090 throw uno::RuntimeException(); //TODO:
1091
1092 uno::Reference< io::XOutputStream > xOutStream = m_xObjectStream->getOutputStream();
1093 if ( !xOutStream.is() )
1094 throw io::IOException(); //TODO: access denied
1095
1096 uno::Reference< io::XTruncate > xTruncate( xOutStream, uno::UNO_QUERY );
1097 if ( !xTruncate.is() )
1098 throw uno::RuntimeException(); //TODO:
1099
1100 xTruncate->truncate();
1101
1102 return xOutStream;
1103 }
1104
1105 //----------------------------------------------
StoreObjectToStream(uno::Reference<io::XOutputStream> xOutStream)1106 void OleEmbeddedObject::StoreObjectToStream( uno::Reference< io::XOutputStream > xOutStream )
1107 {
1108 // this method should be used only on windows
1109 if ( m_pOleComponent )
1110 m_pOleComponent->StoreOwnTmpIfNecessary();
1111
1112 // now all the changes should be in temporary location
1113 if( m_aTempURL.isEmpty() )
1114 throw uno::RuntimeException();
1115
1116 // open temporary file for reading
1117 uno::Reference < ucb::XSimpleFileAccess > xTempAccess(
1118 m_xFactory->createInstance (
1119 ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ),
1120 uno::UNO_QUERY );
1121
1122 if ( !xTempAccess.is() )
1123 throw uno::RuntimeException(); // TODO:
1124
1125 uno::Reference< io::XInputStream > xTempInStream = xTempAccess->openFileRead( m_aTempURL );
1126 OSL_ENSURE( xTempInStream.is(), "The object's temporary file can not be reopened for reading!\n" );
1127
1128 // TODO: use bStoreVisReplace
1129
1130 if ( xTempInStream.is() )
1131 {
1132 // write all the contents to XOutStream
1133 uno::Reference< io::XTruncate > xTrunc( xOutStream, uno::UNO_QUERY );
1134 if ( !xTrunc.is() )
1135 throw uno::RuntimeException(); //TODO:
1136
1137 xTrunc->truncate();
1138
1139 ::comphelper::OStorageHelper::CopyInputToOutput( xTempInStream, xOutStream );
1140 }
1141 else
1142 throw io::IOException(); // TODO:
1143
1144 // TODO: should the view replacement be in the stream ???
1145 // probably it must be specified on storing
1146 }
1147 #endif
1148 //------------------------------------------------------
StoreToLocation_Impl(const uno::Reference<embed::XStorage> & xStorage,const::rtl::OUString & sEntName,const uno::Sequence<beans::PropertyValue> &,const uno::Sequence<beans::PropertyValue> & lObjArgs,sal_Bool bSaveAs)1149 void OleEmbeddedObject::StoreToLocation_Impl(
1150 const uno::Reference< embed::XStorage >& xStorage,
1151 const ::rtl::OUString& sEntName,
1152 const uno::Sequence< beans::PropertyValue >& /*lArguments*/,
1153 const uno::Sequence< beans::PropertyValue >& lObjArgs,
1154 sal_Bool bSaveAs )
1155 {
1156 // TODO: use lObjArgs
1157 // TODO: exchange StoreVisualReplacement by SO file format version?
1158
1159 if ( m_nObjectState == -1 )
1160 {
1161 // the object is still not loaded
1162 throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "Can't store object without persistence!\n" ),
1163 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1164 }
1165
1166 if ( m_bWaitSaveCompleted )
1167 throw embed::WrongStateException(
1168 ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ),
1169 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1170
1171 OSL_ENSURE( m_xParentStorage.is() && m_xObjectStream.is(), "The object has no valid persistence!\n" );
1172
1173 sal_Bool bVisReplIsStored = sal_False;
1174
1175 sal_Bool bTryOptimization = sal_False;
1176 sal_Bool bStoreVis = m_bStoreVisRepl;
1177 uno::Reference< io::XStream > xCachedVisualRepresentation;
1178 for ( sal_Int32 nInd = 0; nInd < lObjArgs.getLength(); nInd++ )
1179 {
1180 if ( lObjArgs[nInd].Name.equalsAscii( "StoreVisualReplacement" ) )
1181 lObjArgs[nInd].Value >>= bStoreVis;
1182 else if ( lObjArgs[nInd].Name.equalsAscii( "VisualReplacement" ) )
1183 lObjArgs[nInd].Value >>= xCachedVisualRepresentation;
1184 else if ( lObjArgs[nInd].Name.equalsAscii( "CanTryOptimization" ) )
1185 lObjArgs[nInd].Value >>= bTryOptimization;
1186 }
1187
1188 // ignore visual representation provided from outside if it should not be stored
1189 if ( !bStoreVis )
1190 xCachedVisualRepresentation = uno::Reference< io::XStream >();
1191
1192 if ( bStoreVis && !HasVisReplInStream() && !xCachedVisualRepresentation.is() )
1193 throw io::IOException(); // TODO: there is no cached visual representation and nothing is provided from outside
1194
1195 // if the representation is provided from outside it should be copied to a local stream
1196 sal_Bool bNeedLocalCache = xCachedVisualRepresentation.is();
1197
1198 uno::Reference< io::XStream > xTargetStream;
1199
1200 sal_Bool bStoreLoaded = sal_False;
1201 if ( m_nObjectState == embed::EmbedStates::LOADED
1202 #ifdef WNT
1203 // if the object was NOT modified after storing it can be just copied
1204 // as if it was in loaded state
1205 || ( m_pOleComponent && !m_pOleComponent->IsDirty() )
1206 #endif
1207 )
1208 {
1209 sal_Bool bOptimizedCopyingDone = sal_False;
1210
1211 if ( bTryOptimization && bStoreVis == HasVisReplInStream() )
1212 {
1213 try
1214 {
1215 uno::Reference< embed::XOptimizedStorage > xSourceOptStor( m_xParentStorage, uno::UNO_QUERY_THROW );
1216 uno::Reference< embed::XOptimizedStorage > xTargetOptStor( xStorage, uno::UNO_QUERY_THROW );
1217 xSourceOptStor->copyElementDirectlyTo( m_aEntryName, xTargetOptStor, sEntName );
1218 bOptimizedCopyingDone = sal_True;
1219 }
1220 catch( uno::Exception& )
1221 {
1222 }
1223 }
1224
1225 if ( !bOptimizedCopyingDone )
1226 {
1227 // if optimized copying fails a normal one should be tried
1228 m_xParentStorage->copyElementTo( m_aEntryName, xStorage, sEntName );
1229 }
1230
1231 // the locally retrieved representation is always preferable
1232 // since the object is in loaded state the representation is unchanged
1233 if ( m_xCachedVisualRepresentation.is() )
1234 {
1235 xCachedVisualRepresentation = m_xCachedVisualRepresentation;
1236 bNeedLocalCache = sal_False;
1237 }
1238
1239 bVisReplIsStored = HasVisReplInStream();
1240 bStoreLoaded = sal_True;
1241 }
1242 #ifdef WNT
1243 else if ( m_pOleComponent )
1244 {
1245 xTargetStream =
1246 xStorage->openStreamElement( sEntName, embed::ElementModes::READWRITE );
1247 if ( !xTargetStream.is() )
1248 throw io::IOException(); //TODO: access denied
1249
1250 SetStreamMediaType_Impl( xTargetStream, ::rtl::OUString::createFromAscii( "application/vnd.sun.star.oleobject" ) );
1251 uno::Reference< io::XOutputStream > xOutStream = xTargetStream->getOutputStream();
1252 if ( !xOutStream.is() )
1253 throw io::IOException(); //TODO: access denied
1254
1255 StoreObjectToStream( xOutStream );
1256 bVisReplIsStored = sal_True;
1257
1258 if ( bSaveAs )
1259 {
1260 // no need to do it on StoreTo since in this case the replacement is in the stream
1261 // and there is no need to cache it even if it is thrown away because the object
1262 // is not changed by StoreTo action
1263
1264 uno::Reference< io::XStream > xTmpCVRepresentation =
1265 TryToRetrieveCachedVisualRepresentation_Impl( xTargetStream );
1266
1267 // the locally retrieved representation is always preferable
1268 if ( xTmpCVRepresentation.is() )
1269 {
1270 xCachedVisualRepresentation = xTmpCVRepresentation;
1271 bNeedLocalCache = sal_False;
1272 }
1273 }
1274 }
1275 #endif
1276 else
1277 {
1278 throw io::IOException(); // TODO
1279 }
1280
1281 if ( !xTargetStream.is() )
1282 {
1283 xTargetStream =
1284 xStorage->openStreamElement( sEntName, embed::ElementModes::READWRITE );
1285 if ( !xTargetStream.is() )
1286 throw io::IOException(); //TODO: access denied
1287 }
1288
1289 LetCommonStoragePassBeUsed_Impl( xTargetStream );
1290
1291 if ( bStoreVis != bVisReplIsStored )
1292 {
1293 if ( bStoreVis )
1294 {
1295 if ( !xCachedVisualRepresentation.is() )
1296 xCachedVisualRepresentation = TryToRetrieveCachedVisualRepresentation_Impl( xTargetStream );
1297
1298 OSL_ENSURE( xCachedVisualRepresentation.is(), "No representation is available!" );
1299
1300 // the following copying will be done in case it is SaveAs anyway
1301 // if it is not SaveAs the seekable access is not required currently
1302 // TODO/LATER: may be required in future
1303 if ( bSaveAs )
1304 {
1305 uno::Reference< io::XSeekable > xCachedSeek( xCachedVisualRepresentation, uno::UNO_QUERY );
1306 if ( !xCachedSeek.is() )
1307 {
1308 xCachedVisualRepresentation
1309 = GetNewFilledTempStream_Impl( xCachedVisualRepresentation->getInputStream() );
1310 bNeedLocalCache = sal_False;
1311 }
1312 }
1313
1314 InsertVisualCache_Impl( xTargetStream, xCachedVisualRepresentation );
1315 }
1316 else
1317 {
1318 // the removed representation could be cached by this method
1319 if ( !xCachedVisualRepresentation.is() )
1320 xCachedVisualRepresentation = TryToRetrieveCachedVisualRepresentation_Impl( xTargetStream );
1321
1322 RemoveVisualCache_Impl( xTargetStream );
1323 }
1324 }
1325
1326 if ( bSaveAs )
1327 {
1328 m_bWaitSaveCompleted = sal_True;
1329 m_xNewObjectStream = xTargetStream;
1330 m_xNewParentStorage = xStorage;
1331 m_aNewEntryName = sEntName;
1332 m_bNewVisReplInStream = bStoreVis;
1333 m_bStoreLoaded = bStoreLoaded;
1334
1335 if ( xCachedVisualRepresentation.is() )
1336 {
1337 if ( bNeedLocalCache )
1338 m_xNewCachedVisRepl = GetNewFilledTempStream_Impl( xCachedVisualRepresentation->getInputStream() );
1339 else
1340 m_xNewCachedVisRepl = xCachedVisualRepresentation;
1341 }
1342
1343 // TODO: register listeners for storages above, in case they are disposed
1344 // an exception will be thrown on saveCompleted( true )
1345 }
1346 else
1347 {
1348 uno::Reference< lang::XComponent > xComp( xTargetStream, uno::UNO_QUERY );
1349 if ( xComp.is() )
1350 {
1351 try {
1352 xComp->dispose();
1353 } catch( uno::Exception& )
1354 {
1355 }
1356 }
1357 }
1358 }
1359
1360 //------------------------------------------------------
setPersistentEntry(const uno::Reference<embed::XStorage> & xStorage,const::rtl::OUString & sEntName,sal_Int32 nEntryConnectionMode,const uno::Sequence<beans::PropertyValue> & lArguments,const uno::Sequence<beans::PropertyValue> & lObjArgs)1361 void SAL_CALL OleEmbeddedObject::setPersistentEntry(
1362 const uno::Reference< embed::XStorage >& xStorage,
1363 const ::rtl::OUString& sEntName,
1364 sal_Int32 nEntryConnectionMode,
1365 const uno::Sequence< beans::PropertyValue >& lArguments,
1366 const uno::Sequence< beans::PropertyValue >& lObjArgs )
1367 {
1368 RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OleEmbeddedObject::setPersistentEntry" );
1369
1370 // begin wrapping related part ====================
1371 uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
1372 if ( xWrappedObject.is() )
1373 {
1374 // the object was converted to AOO embedded object, the current implementation is now only a wrapper
1375 xWrappedObject->setPersistentEntry( xStorage, sEntName, nEntryConnectionMode, lArguments, lObjArgs );
1376 return;
1377 }
1378 // end wrapping related part ====================
1379
1380 // TODO: use lObjArgs
1381
1382 // the type of the object must be already set
1383 // a kind of typedetection should be done in the factory;
1384 // the only exception is object initialized from a stream,
1385 // the class ID will be detected from the stream
1386
1387 ::osl::MutexGuard aGuard( m_aMutex );
1388 if ( m_bDisposed )
1389 throw lang::DisposedException(); // TODO
1390
1391 if ( !xStorage.is() )
1392 throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "No parent storage is provided!\n" ),
1393 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ),
1394 1 );
1395
1396 if ( !sEntName.getLength() )
1397 throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "Empty element name is provided!\n" ),
1398 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ),
1399 2 );
1400
1401 // May be LOADED should be forbidden here ???
1402 if ( ( m_nObjectState != -1 || nEntryConnectionMode == embed::EntryInitModes::NO_INIT )
1403 && ( m_nObjectState == -1 || nEntryConnectionMode != embed::EntryInitModes::NO_INIT ) )
1404 {
1405 // if the object is not loaded
1406 // it can not get persistent representation without initialization
1407
1408 // if the object is loaded
1409 // it can switch persistent representation only without initialization
1410
1411 throw embed::WrongStateException(
1412 ::rtl::OUString::createFromAscii( "Can't change persistent representation of activated object!\n" ),
1413 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1414 }
1415
1416 if ( m_bWaitSaveCompleted )
1417 {
1418 if ( nEntryConnectionMode == embed::EntryInitModes::NO_INIT )
1419 saveCompleted( ( m_xParentStorage != xStorage || !m_aEntryName.equals( sEntName ) ) );
1420 else
1421 throw embed::WrongStateException(
1422 ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ),
1423 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1424 }
1425
1426 uno::Reference< container::XNameAccess > xNameAccess( xStorage, uno::UNO_QUERY );
1427 if ( !xNameAccess.is() )
1428 throw uno::RuntimeException(); //TODO
1429
1430 // detect entry existence
1431 sal_Bool bElExists = xNameAccess->hasByName( sEntName );
1432
1433 m_bReadOnly = sal_False;
1434 sal_Int32 nInd = 0;
1435 for ( nInd = 0; nInd < lArguments.getLength(); nInd++ )
1436 if ( lArguments[nInd].Name.equalsAscii( "ReadOnly" ) )
1437 lArguments[nInd].Value >>= m_bReadOnly;
1438
1439 #ifdef WNT
1440 sal_Int32 nStorageMode = m_bReadOnly ? embed::ElementModes::READ : embed::ElementModes::READWRITE;
1441 #endif
1442
1443 SwitchOwnPersistence( xStorage, sEntName );
1444
1445 for ( nInd = 0; nInd < lObjArgs.getLength(); nInd++ )
1446 if ( lObjArgs[nInd].Name.equalsAscii( "StoreVisualReplacement" ) )
1447 lObjArgs[nInd].Value >>= m_bStoreVisRepl;
1448
1449 #ifdef WNT
1450 if ( nEntryConnectionMode == embed::EntryInitModes::DEFAULT_INIT )
1451 {
1452 if ( m_bFromClipboard )
1453 {
1454 // the object should be initialized from clipboard
1455 // impossibility to initialize the object means error here
1456 CreateOleComponentFromClipboard_Impl( NULL );
1457 m_aClassID = m_pOleComponent->GetCLSID(); // was not set during construction
1458 m_pOleComponent->RunObject();
1459 m_nObjectState = embed::EmbedStates::RUNNING;
1460 }
1461 else if ( bElExists )
1462 {
1463 // load object from the stream
1464 // after the loading the object can appear as a link
1465 // will be detected by olecomponent
1466 try
1467 {
1468 CreateOleComponentAndLoad_Impl( NULL );
1469 m_aClassID = m_pOleComponent->GetCLSID(); // was not set during construction
1470 }
1471 catch( uno::Exception& )
1472 {
1473 // TODO/LATER: detect classID of the object if possible
1474 // means that the object inprocess server could not be successfully instantiated
1475 GetRidOfComponent();
1476 }
1477
1478 m_nObjectState = embed::EmbedStates::LOADED;
1479 }
1480 else
1481 {
1482 // create a new object
1483 CreateOleComponent_Impl();
1484 m_pOleComponent->CreateNewEmbeddedObject( m_aClassID );
1485 m_pOleComponent->RunObject();
1486 m_nObjectState = embed::EmbedStates::RUNNING;
1487 }
1488 }
1489 else
1490 {
1491 if ( ( nStorageMode & embed::ElementModes::READWRITE ) != embed::ElementModes::READWRITE )
1492 throw io::IOException();
1493
1494 if ( nEntryConnectionMode == embed::EntryInitModes::NO_INIT )
1495 {
1496 // the document just already changed its stream to store to;
1497 // the links to OLE documents switch their persistence in the same way
1498 // as normal embedded objects
1499 }
1500 else if ( nEntryConnectionMode == embed::EntryInitModes::TRUNCATE_INIT )
1501 {
1502 // create a new object, that will be stored in specified stream
1503 CreateOleComponent_Impl();
1504
1505 m_pOleComponent->CreateNewEmbeddedObject( m_aClassID );
1506 m_pOleComponent->RunObject();
1507 m_nObjectState = embed::EmbedStates::RUNNING;
1508 }
1509 else if ( nEntryConnectionMode == embed::EntryInitModes::MEDIA_DESCRIPTOR_INIT )
1510 {
1511 // use URL ( may be content or stream later ) from MediaDescriptor to initialize object
1512 ::rtl::OUString aURL;
1513 for ( sal_Int32 nInd = 0; nInd < lArguments.getLength(); nInd++ )
1514 if ( lArguments[nInd].Name.equalsAscii( "URL" ) )
1515 lArguments[nInd].Value >>= aURL;
1516
1517 if ( !aURL.getLength() )
1518 throw lang::IllegalArgumentException(
1519 ::rtl::OUString::createFromAscii( "Empty URL is provided in the media descriptor!\n" ),
1520 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ),
1521 4 );
1522
1523 CreateOleComponent_Impl();
1524
1525 // TODO: the m_bIsLink value must be set already
1526 if ( !m_bIsLink )
1527 m_pOleComponent->CreateObjectFromFile( aURL );
1528 else
1529 m_pOleComponent->CreateLinkFromFile( aURL );
1530
1531 m_pOleComponent->RunObject();
1532 m_aClassID = m_pOleComponent->GetCLSID(); // was not set during construction
1533
1534 m_nObjectState = embed::EmbedStates::RUNNING;
1535 }
1536 //else if ( nEntryConnectionMode == embed::EntryInitModes::TRANSFERABLE_INIT )
1537 //{
1538 //TODO:
1539 //}
1540 else
1541 throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "Wrong connection mode is provided!\n" ),
1542 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ),
1543 3 );
1544 }
1545 #else
1546 // On unix the ole object can not do anything except storing itself somewhere
1547 if ( nEntryConnectionMode == embed::EntryInitModes::DEFAULT_INIT && bElExists )
1548 {
1549 // TODO/LATER: detect classID of the object
1550 // can be a real problem for the links
1551
1552 m_nObjectState = embed::EmbedStates::LOADED;
1553 }
1554 else if ( nEntryConnectionMode == embed::EntryInitModes::NO_INIT )
1555 {
1556 // do nothing, the object has already switched its persistence
1557 }
1558 else
1559 throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "Wrong connection mode is provided!\n" ),
1560 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ),
1561 3 );
1562
1563 #endif
1564 }
1565
1566 //------------------------------------------------------
storeToEntry(const uno::Reference<embed::XStorage> & xStorage,const::rtl::OUString & sEntName,const uno::Sequence<beans::PropertyValue> & lArguments,const uno::Sequence<beans::PropertyValue> & lObjArgs)1567 void SAL_CALL OleEmbeddedObject::storeToEntry( const uno::Reference< embed::XStorage >& xStorage,
1568 const ::rtl::OUString& sEntName,
1569 const uno::Sequence< beans::PropertyValue >& lArguments,
1570 const uno::Sequence< beans::PropertyValue >& lObjArgs )
1571 {
1572 RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OleEmbeddedObject::storeToEntry" );
1573
1574 // begin wrapping related part ====================
1575 uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
1576 if ( xWrappedObject.is() )
1577 {
1578 // the object was converted to AOO embedded object, the current implementation is now only a wrapper
1579 xWrappedObject->storeToEntry( xStorage, sEntName, lArguments, lObjArgs );
1580 return;
1581 }
1582 // end wrapping related part ====================
1583
1584 ::osl::MutexGuard aGuard( m_aMutex );
1585 if ( m_bDisposed )
1586 throw lang::DisposedException(); // TODO
1587
1588 VerbExecutionControllerGuard aVerbGuard( m_aVerbExecutionController );
1589
1590 StoreToLocation_Impl( xStorage, sEntName, lArguments, lObjArgs, sal_False );
1591
1592 // TODO: should the listener notification be done?
1593 }
1594
1595 //------------------------------------------------------
storeAsEntry(const uno::Reference<embed::XStorage> & xStorage,const::rtl::OUString & sEntName,const uno::Sequence<beans::PropertyValue> & lArguments,const uno::Sequence<beans::PropertyValue> & lObjArgs)1596 void SAL_CALL OleEmbeddedObject::storeAsEntry( const uno::Reference< embed::XStorage >& xStorage,
1597 const ::rtl::OUString& sEntName,
1598 const uno::Sequence< beans::PropertyValue >& lArguments,
1599 const uno::Sequence< beans::PropertyValue >& lObjArgs )
1600 {
1601 RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OleEmbeddedObject::storeAsEntry" );
1602
1603 // begin wrapping related part ====================
1604 uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
1605 if ( xWrappedObject.is() )
1606 {
1607 // the object was converted to AOO embedded object, the current implementation is now only a wrapper
1608 xWrappedObject->storeAsEntry( xStorage, sEntName, lArguments, lObjArgs );
1609 return;
1610 }
1611 // end wrapping related part ====================
1612
1613 ::osl::MutexGuard aGuard( m_aMutex );
1614 if ( m_bDisposed )
1615 throw lang::DisposedException(); // TODO
1616
1617 VerbExecutionControllerGuard aVerbGuard( m_aVerbExecutionController );
1618
1619 StoreToLocation_Impl( xStorage, sEntName, lArguments, lObjArgs, sal_True );
1620
1621 // TODO: should the listener notification be done here or in saveCompleted?
1622 }
1623
1624 //------------------------------------------------------
saveCompleted(sal_Bool bUseNew)1625 void SAL_CALL OleEmbeddedObject::saveCompleted( sal_Bool bUseNew )
1626 {
1627 RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OleEmbeddedObject::saveCompleted" );
1628
1629 // begin wrapping related part ====================
1630 uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
1631 if ( xWrappedObject.is() )
1632 {
1633 // the object was converted to AOO embedded object, the current implementation is now only a wrapper
1634 xWrappedObject->saveCompleted( bUseNew );
1635 return;
1636 }
1637 // end wrapping related part ====================
1638
1639 ::osl::ResettableMutexGuard aGuard( m_aMutex );
1640 if ( m_bDisposed )
1641 throw lang::DisposedException(); // TODO
1642
1643 if ( m_nObjectState == -1 )
1644 {
1645 // the object is still not loaded
1646 throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "Can't store object without persistence!\n" ),
1647 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1648 }
1649
1650 // it is allowed to call saveCompleted( false ) for nonstored objects
1651 if ( !m_bWaitSaveCompleted && !bUseNew )
1652 return;
1653
1654 OSL_ENSURE( m_bWaitSaveCompleted, "Unexpected saveCompleted() call!\n" );
1655 if ( !m_bWaitSaveCompleted )
1656 throw io::IOException(); // TODO: illegal call
1657
1658 OSL_ENSURE( m_xNewObjectStream.is() && m_xNewParentStorage.is() , "Internal object information is broken!\n" );
1659 if ( !m_xNewObjectStream.is() || !m_xNewParentStorage.is() )
1660 throw uno::RuntimeException(); // TODO: broken internal information
1661
1662 if ( bUseNew )
1663 {
1664 SwitchOwnPersistence( m_xNewParentStorage, m_xNewObjectStream, m_aNewEntryName );
1665 m_bStoreVisRepl = m_bNewVisReplInStream;
1666 SetVisReplInStream( m_bNewVisReplInStream );
1667 m_xCachedVisualRepresentation = m_xNewCachedVisRepl;
1668 }
1669 else
1670 {
1671 // close remembered stream
1672 try {
1673 uno::Reference< lang::XComponent > xComponent( m_xNewObjectStream, uno::UNO_QUERY );
1674 OSL_ENSURE( xComponent.is(), "Wrong storage implementation!" );
1675 if ( xComponent.is() )
1676 xComponent->dispose();
1677 }
1678 catch ( uno::Exception& )
1679 {
1680 }
1681 }
1682
1683 sal_Bool bStoreLoaded = m_bStoreLoaded;
1684
1685 m_xNewObjectStream = uno::Reference< io::XStream >();
1686 m_xNewParentStorage = uno::Reference< embed::XStorage >();
1687 m_aNewEntryName = ::rtl::OUString();
1688 m_bWaitSaveCompleted = sal_False;
1689 m_bNewVisReplInStream = sal_False;
1690 m_xNewCachedVisRepl = uno::Reference< io::XStream >();
1691 m_bStoreLoaded = sal_False;
1692
1693 if ( bUseNew && m_pOleComponent && m_nUpdateMode == embed::EmbedUpdateModes::ALWAYS_UPDATE && !bStoreLoaded
1694 && m_nObjectState != embed::EmbedStates::LOADED )
1695 {
1696 // the object replacement image should be updated, so the cached size as well
1697 m_bHasCachedSize = sal_False;
1698 try
1699 {
1700 // the call will cache the size in case of success
1701 // probably it might need to be done earlier, while the object is in active state
1702 getVisualAreaSize( embed::Aspects::MSOLE_CONTENT );
1703 }
1704 catch( uno::Exception& )
1705 {}
1706 }
1707
1708 aGuard.clear();
1709 if ( bUseNew )
1710 {
1711 MakeEventListenerNotification_Impl( ::rtl::OUString::createFromAscii( "OnSaveAsDone" ) );
1712
1713 // the object can be changed only on windows
1714 // the notification should be done only if the object is not in loaded state
1715 if ( m_pOleComponent && m_nUpdateMode == embed::EmbedUpdateModes::ALWAYS_UPDATE && !bStoreLoaded )
1716 {
1717 MakeEventListenerNotification_Impl( ::rtl::OUString::createFromAscii( "OnVisAreaChanged" ) );
1718 }
1719 }
1720 }
1721
1722 //------------------------------------------------------
hasEntry()1723 sal_Bool SAL_CALL OleEmbeddedObject::hasEntry()
1724 {
1725 // begin wrapping related part ====================
1726 uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
1727 if ( xWrappedObject.is() )
1728 {
1729 // the object was converted to AOO embedded object, the current implementation is now only a wrapper
1730 return xWrappedObject->hasEntry();
1731 }
1732 // end wrapping related part ====================
1733
1734 ::osl::MutexGuard aGuard( m_aMutex );
1735 if ( m_bDisposed )
1736 throw lang::DisposedException(); // TODO
1737
1738 if ( m_bWaitSaveCompleted )
1739 throw embed::WrongStateException(
1740 ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ),
1741 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1742
1743 if ( m_xObjectStream.is() )
1744 return sal_True;
1745
1746 return sal_False;
1747 }
1748
1749 //------------------------------------------------------
getEntryName()1750 ::rtl::OUString SAL_CALL OleEmbeddedObject::getEntryName()
1751 {
1752 // begin wrapping related part ====================
1753 uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
1754 if ( xWrappedObject.is() )
1755 {
1756 // the object was converted to AOO embedded object, the current implementation is now only a wrapper
1757 return xWrappedObject->getEntryName();
1758 }
1759 // end wrapping related part ====================
1760
1761 ::osl::MutexGuard aGuard( m_aMutex );
1762 if ( m_bDisposed )
1763 throw lang::DisposedException(); // TODO
1764
1765 if ( m_nObjectState == -1 )
1766 {
1767 // the object is still not loaded
1768 throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "The object persistence is not initialized!\n" ),
1769 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1770 }
1771
1772 if ( m_bWaitSaveCompleted )
1773 throw embed::WrongStateException(
1774 ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ),
1775 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1776
1777 return m_aEntryName;
1778 }
1779
1780
1781 //------------------------------------------------------
storeOwn()1782 void SAL_CALL OleEmbeddedObject::storeOwn()
1783 {
1784 RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OleEmbeddedObject::storeOwn" );
1785
1786 // begin wrapping related part ====================
1787 uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
1788 if ( xWrappedObject.is() )
1789 {
1790 // the object was converted to AOO embedded object, the current implementation is now only a wrapper
1791 xWrappedObject->storeOwn();
1792 return;
1793 }
1794 // end wrapping related part ====================
1795
1796 // during switching from Activated to Running and from Running to Loaded states the object will
1797 // ask container to store the object, the container has to make decision
1798 // to do so or not
1799
1800 ::osl::ResettableMutexGuard aGuard( m_aMutex );
1801 if ( m_bDisposed )
1802 throw lang::DisposedException(); // TODO
1803
1804 VerbExecutionControllerGuard aVerbGuard( m_aVerbExecutionController );
1805
1806 if ( m_nObjectState == -1 )
1807 {
1808 // the object is still not loaded
1809 throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "Can't store object without persistence!\n" ),
1810 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1811 }
1812
1813 if ( m_bWaitSaveCompleted )
1814 throw embed::WrongStateException(
1815 ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ),
1816 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1817
1818 if ( m_bReadOnly )
1819 throw io::IOException(); // TODO: access denied
1820
1821 LetCommonStoragePassBeUsed_Impl( m_xObjectStream );
1822
1823 sal_Bool bStoreLoaded = sal_True;
1824
1825 #ifdef WNT
1826 if ( m_nObjectState != embed::EmbedStates::LOADED && m_pOleComponent && m_pOleComponent->IsDirty() )
1827 {
1828 bStoreLoaded = sal_False;
1829
1830 OSL_ENSURE( m_xParentStorage.is() && m_xObjectStream.is(), "The object has no valid persistence!\n" );
1831
1832 if ( !m_xObjectStream.is() )
1833 throw io::IOException(); //TODO: access denied
1834
1835 SetStreamMediaType_Impl( m_xObjectStream, ::rtl::OUString::createFromAscii( "application/vnd.sun.star.oleobject" ) );
1836 uno::Reference< io::XOutputStream > xOutStream = m_xObjectStream->getOutputStream();
1837 if ( !xOutStream.is() )
1838 throw io::IOException(); //TODO: access denied
1839
1840 if ( m_bIsLink )
1841 {
1842 // just let the link store itself
1843 // in case visual representation must be stored also
1844 // the procedure should be the same as for embedded objects
1845
1846 uno::Reference< io::XOutputStream > xOutStream = GetStreamForSaving();
1847
1848 // should the component detect that it is a link???
1849 StoreObjectToStream( xOutStream );
1850 }
1851 else
1852 {
1853 uno::Reference< io::XOutputStream > xOutStream = GetStreamForSaving();
1854 StoreObjectToStream( xOutStream );
1855 }
1856
1857 // the replacement is changed probably, and it must be in the object stream
1858 if ( !m_pOleComponent->IsWorkaroundActive() )
1859 m_xCachedVisualRepresentation = uno::Reference< io::XStream >();
1860 SetVisReplInStream( sal_True );
1861 }
1862 #endif
1863
1864 if ( m_bStoreVisRepl != HasVisReplInStream() )
1865 {
1866 if ( m_bStoreVisRepl )
1867 {
1868 // the m_xCachedVisualRepresentation must be set or it should be already stored
1869 if ( m_xCachedVisualRepresentation.is() )
1870 InsertVisualCache_Impl( m_xObjectStream, m_xCachedVisualRepresentation );
1871 else
1872 {
1873 m_xCachedVisualRepresentation = TryToRetrieveCachedVisualRepresentation_Impl( m_xObjectStream );
1874 OSL_ENSURE( m_xCachedVisualRepresentation.is(), "No representation is available!" );
1875 }
1876 }
1877 else
1878 {
1879 if ( !m_xCachedVisualRepresentation.is() )
1880 m_xCachedVisualRepresentation = TryToRetrieveCachedVisualRepresentation_Impl( m_xObjectStream );
1881 RemoveVisualCache_Impl( m_xObjectStream );
1882 }
1883
1884 SetVisReplInStream( m_bStoreVisRepl );
1885 }
1886
1887 if ( m_pOleComponent && m_nUpdateMode == embed::EmbedUpdateModes::ALWAYS_UPDATE && !bStoreLoaded )
1888 {
1889 // the object replacement image should be updated, so the cached size as well
1890 m_bHasCachedSize = sal_False;
1891 try
1892 {
1893 // the call will cache the size in case of success
1894 // probably it might need to be done earlier, while the object is in active state
1895 getVisualAreaSize( embed::Aspects::MSOLE_CONTENT );
1896 }
1897 catch( uno::Exception& )
1898 {}
1899 }
1900
1901 aGuard.clear();
1902
1903 MakeEventListenerNotification_Impl( ::rtl::OUString::createFromAscii( "OnSaveDone" ) );
1904
1905 // the object can be changed only on Windows
1906 // the notification should be done only if the object is not in loaded state
1907 if ( m_pOleComponent && m_nUpdateMode == embed::EmbedUpdateModes::ALWAYS_UPDATE && !bStoreLoaded )
1908 MakeEventListenerNotification_Impl( ::rtl::OUString::createFromAscii( "OnVisAreaChanged" ) );
1909 }
1910
1911 //------------------------------------------------------
isReadonly()1912 sal_Bool SAL_CALL OleEmbeddedObject::isReadonly()
1913 {
1914 // begin wrapping related part ====================
1915 uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
1916 if ( xWrappedObject.is() )
1917 {
1918 // the object was converted to AOO embedded object, the current implementation is now only a wrapper
1919 return xWrappedObject->isReadonly();
1920 }
1921 // end wrapping related part ====================
1922
1923 ::osl::MutexGuard aGuard( m_aMutex );
1924 if ( m_bDisposed )
1925 throw lang::DisposedException(); // TODO
1926
1927 if ( m_nObjectState == -1 )
1928 {
1929 // the object is still not loaded
1930 throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "The object persistence is not initialized!\n" ),
1931 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1932 }
1933
1934 if ( m_bWaitSaveCompleted )
1935 throw embed::WrongStateException(
1936 ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ),
1937 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1938
1939 return m_bReadOnly;
1940 }
1941
1942 //------------------------------------------------------
reload(const uno::Sequence<beans::PropertyValue> & lArguments,const uno::Sequence<beans::PropertyValue> & lObjArgs)1943 void SAL_CALL OleEmbeddedObject::reload(
1944 const uno::Sequence< beans::PropertyValue >& lArguments,
1945 const uno::Sequence< beans::PropertyValue >& lObjArgs )
1946 {
1947 // begin wrapping related part ====================
1948 uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
1949 if ( xWrappedObject.is() )
1950 {
1951 // the object was converted to AOO embedded object, the current implementation is now only a wrapper
1952 xWrappedObject->reload( lArguments, lObjArgs );
1953 return;
1954 }
1955 // end wrapping related part ====================
1956
1957 // TODO: use lObjArgs
1958
1959 ::osl::MutexGuard aGuard( m_aMutex );
1960 if ( m_bDisposed )
1961 throw lang::DisposedException(); // TODO
1962
1963 if ( m_nObjectState == -1 )
1964 {
1965 // the object is still not loaded
1966 throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "The object persistence is not initialized!\n" ),
1967 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1968 }
1969
1970 if ( m_bWaitSaveCompleted )
1971 throw embed::WrongStateException(
1972 ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ),
1973 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
1974
1975 // TODO:
1976 // throw away current document
1977 // load new document from current storage
1978 // use meaningful part of lArguments
1979 }
1980
1981 //------------------------------------------------------
breakLink(const uno::Reference<embed::XStorage> & xStorage,const::rtl::OUString & sEntName)1982 void SAL_CALL OleEmbeddedObject::breakLink( const uno::Reference< embed::XStorage >& xStorage,
1983 const ::rtl::OUString& sEntName )
1984 {
1985 // begin wrapping related part ====================
1986 uno::Reference< embed::XLinkageSupport > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
1987 if ( xWrappedObject.is() )
1988 {
1989 // the object was converted to AOO embedded object, the current implementation is now only a wrapper
1990 xWrappedObject->breakLink( xStorage, sEntName );
1991 return;
1992 }
1993 // end wrapping related part ====================
1994
1995 ::osl::MutexGuard aGuard( m_aMutex );
1996 if ( m_bDisposed )
1997 throw lang::DisposedException(); // TODO
1998
1999 if ( !xStorage.is() )
2000 throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "No parent storage is provided!\n" ),
2001 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ),
2002 1 );
2003
2004 if ( !sEntName.getLength() )
2005 throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "Empty element name is provided!\n" ),
2006 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ),
2007 2 );
2008
2009 // TODO: The object must be at least in Running state;
2010 if ( !m_bIsLink || m_nObjectState == -1 || !m_pOleComponent )
2011 {
2012 // it must be a linked initialized object
2013 throw embed::WrongStateException(
2014 ::rtl::OUString::createFromAscii( "The object is not a valid linked object!\n" ),
2015 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
2016 }
2017
2018 if ( m_bReadOnly )
2019 throw io::IOException(); // TODO: Access denied
2020
2021 if ( m_bWaitSaveCompleted )
2022 throw embed::WrongStateException(
2023 ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ),
2024 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
2025
2026
2027 #ifdef WNT
2028 if ( m_pOleComponent )
2029 {
2030 // TODO: create an object based on the link
2031
2032 // disconnect the old temporary URL
2033 ::rtl::OUString aOldTempURL = m_aTempURL;
2034 m_aTempURL = ::rtl::OUString();
2035
2036 OleComponent* pNewOleComponent = new OleComponent( m_xFactory, this );
2037 try {
2038 pNewOleComponent->InitEmbeddedCopyOfLink( m_pOleComponent );
2039 }
2040 catch ( uno::Exception& )
2041 {
2042 delete pNewOleComponent;
2043 if( !m_aTempURL.isEmpty() )
2044 KillFile_Impl( m_aTempURL, m_xFactory );
2045 m_aTempURL = aOldTempURL;
2046 throw;
2047 }
2048
2049 try {
2050 GetRidOfComponent();
2051 }
2052 catch( uno::Exception& )
2053 {
2054 delete pNewOleComponent;
2055 if( !m_aTempURL.isEmpty() )
2056 KillFile_Impl( m_aTempURL, m_xFactory );
2057 m_aTempURL = aOldTempURL;
2058 throw;
2059 }
2060
2061 KillFile_Impl( aOldTempURL, m_xFactory );
2062
2063 CreateOleComponent_Impl( pNewOleComponent );
2064
2065 if ( m_xParentStorage != xStorage || !m_aEntryName.equals( sEntName ) )
2066 SwitchOwnPersistence( xStorage, sEntName );
2067
2068 if ( m_nObjectState != embed::EmbedStates::LOADED )
2069 {
2070 // TODO: should we activate the new object if the link was activated?
2071
2072 sal_Int32 nTargetState = m_nObjectState;
2073 m_nObjectState = embed::EmbedStates::LOADED;
2074
2075 if ( m_nObjectState == embed::EmbedStates::RUNNING )
2076 m_pOleComponent->RunObject(); // the object already was in running state, the server must be installed
2077 else // m_nObjectState == embed::EmbedStates::ACTIVE
2078 {
2079 m_pOleComponent->RunObject(); // the object already was in running state, the server must be installed
2080 m_pOleComponent->ExecuteVerb( embed::EmbedVerbs::MS_OLEVERB_OPEN );
2081 }
2082
2083 m_nObjectState = nTargetState;
2084 }
2085
2086 m_bIsLink = sal_False;
2087 m_aLinkURL = ::rtl::OUString();
2088 }
2089 else
2090 #endif
2091 {
2092 throw io::IOException(); //TODO:
2093 }
2094 }
2095
2096 //------------------------------------------------------
isLink()2097 sal_Bool SAL_CALL OleEmbeddedObject::isLink()
2098 {
2099 // begin wrapping related part ====================
2100 uno::Reference< embed::XLinkageSupport > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
2101 if ( xWrappedObject.is() )
2102 {
2103 // the object was converted to AOO embedded object, the current implementation is now only a wrapper
2104 return xWrappedObject->isLink();
2105 }
2106 // end wrapping related part ====================
2107
2108 ::osl::MutexGuard aGuard( m_aMutex );
2109 if ( m_bDisposed )
2110 throw lang::DisposedException(); // TODO
2111
2112 return m_bIsLink;
2113 }
2114
2115 //------------------------------------------------------
getLinkURL()2116 ::rtl::OUString SAL_CALL OleEmbeddedObject::getLinkURL()
2117 {
2118 // begin wrapping related part ====================
2119 uno::Reference< embed::XLinkageSupport > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
2120 if ( xWrappedObject.is() )
2121 {
2122 // the object was converted to AOO embedded object, the current implementation is now only a wrapper
2123 return xWrappedObject->getLinkURL();
2124 }
2125 // end wrapping related part ====================
2126
2127 ::osl::MutexGuard aGuard( m_aMutex );
2128 if ( m_bDisposed )
2129 throw lang::DisposedException(); // TODO
2130
2131 if ( m_bWaitSaveCompleted )
2132 throw embed::WrongStateException(
2133 ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ),
2134 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
2135
2136 if ( !m_bIsLink )
2137 throw embed::WrongStateException(
2138 ::rtl::OUString::createFromAscii( "The object is not a link object!\n" ),
2139 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
2140
2141 // TODO: probably the link URL can be retrieved from OLE
2142
2143 return m_aLinkURL;
2144 }
2145