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