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