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