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 "core_resource.hxx"
21 : #include "core_resource.hrc"
22 : #include "datasource.hxx"
23 : #include "databasedocument.hxx"
24 : #include "dbastrings.hrc"
25 : #include "module_dba.hxx"
26 : #include "services.hxx"
27 : #include "documenteventexecutor.hxx"
28 : #include "databasecontext.hxx"
29 : #include "documentcontainer.hxx"
30 : #include "sdbcoretools.hxx"
31 : #include "recovery/dbdocrecovery.hxx"
32 :
33 : #include <com/sun/star/beans/Optional.hpp>
34 : #include <com/sun/star/document/XExporter.hpp>
35 : #include <com/sun/star/document/XFilter.hpp>
36 : #include <com/sun/star/document/XImporter.hpp>
37 : #include <com/sun/star/document/GraphicObjectResolver.hpp>
38 : #include <com/sun/star/embed/EntryInitModes.hpp>
39 : #include <com/sun/star/embed/XEmbedPersist.hpp>
40 : #include <com/sun/star/embed/XTransactedObject.hpp>
41 : #include <com/sun/star/embed/XTransactionBroadcaster.hpp>
42 : #include <com/sun/star/frame/Desktop.hpp>
43 : #include <com/sun/star/frame/ModuleManager.hpp>
44 : #include <com/sun/star/io/XActiveDataSource.hpp>
45 : #include <com/sun/star/io/XSeekable.hpp>
46 : #include <com/sun/star/io/XOutputStream.hpp>
47 : #include <com/sun/star/io/XTruncate.hpp>
48 : #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
49 : #include <com/sun/star/script/provider/theMasterScriptProviderFactory.hpp>
50 : #include <com/sun/star/sdb/DatabaseContext.hpp>
51 : #include <com/sun/star/sdb/application/XDatabaseDocumentUI.hpp>
52 : #include <com/sun/star/task/XStatusIndicator.hpp>
53 : #include <com/sun/star/task/XStatusIndicatorFactory.hpp>
54 : #include <com/sun/star/ucb/SimpleFileAccess.hpp>
55 : #include <com/sun/star/ucb/XContent.hpp>
56 : #include <com/sun/star/ui/UIConfigurationManager.hpp>
57 : #include <com/sun/star/ui/XUIConfigurationStorage.hpp>
58 : #include <com/sun/star/view/XSelectionSupplier.hpp>
59 : #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
60 : #include <com/sun/star/xml/sax/Writer.hpp>
61 :
62 : #include <com/sun/star/script/XStorageBasedLibraryContainer.hpp>
63 : #include <com/sun/star/awt/XControl.hpp>
64 : #include <com/sun/star/awt/DialogProvider.hpp>
65 : #include <com/sun/star/document/XGraphicObjectResolver.hpp>
66 :
67 : #include <comphelper/documentconstants.hxx>
68 : #include <comphelper/enumhelper.hxx>
69 : #include <comphelper/genericpropertyset.hxx>
70 : #include <comphelper/interaction.hxx>
71 : #include <comphelper/namedvaluecollection.hxx>
72 : #include <comphelper/numberedcollection.hxx>
73 : #include <comphelper/property.hxx>
74 : #include <comphelper/storagehelper.hxx>
75 :
76 : #include <connectivity/dbtools.hxx>
77 :
78 : #include <cppuhelper/exc_hlp.hxx>
79 : #include <cppuhelper/supportsservice.hxx>
80 : #include <framework/titlehelper.hxx>
81 : #include <unotools/saveopt.hxx>
82 : #include <tools/debug.hxx>
83 : #include <tools/diagnose_ex.h>
84 : #include <osl/diagnose.h>
85 : #include <tools/errcode.hxx>
86 :
87 : #include <boost/bind.hpp>
88 :
89 : #include <algorithm>
90 : #include <functional>
91 : #include <list>
92 :
93 : #include <svtools/grfmgr.hxx>
94 : #include <tools/urlobj.hxx>
95 :
96 : using namespace ::com::sun::star::uno;
97 : using namespace ::com::sun::star::beans;
98 : using namespace ::com::sun::star::frame;
99 : using namespace ::com::sun::star::lang;
100 : using namespace ::com::sun::star::container;
101 : using namespace ::com::sun::star::document;
102 : using namespace ::com::sun::star::io;
103 : using namespace ::com::sun::star::util;
104 : using namespace ::com::sun::star::embed;
105 : using namespace ::com::sun::star::task;
106 : using namespace ::com::sun::star::view;
107 : using namespace ::com::sun::star::sdb;
108 : using namespace ::com::sun::star::sdbc;
109 : using namespace ::com::sun::star;
110 : using namespace ::com::sun::star::xml::sax;
111 : using namespace ::com::sun::star::script;
112 : using namespace ::com::sun::star::script::provider;
113 : using namespace ::com::sun::star::ui;
114 : using namespace ::cppu;
115 : using namespace ::osl;
116 :
117 : using ::com::sun::star::awt::XWindow;
118 : using ::com::sun::star::ucb::XContent;
119 : using ::com::sun::star::sdb::application::XDatabaseDocumentUI;
120 :
121 : namespace dbaccess
122 : {
123 :
124 : // ViewMonitor
125 :
126 7 : bool ViewMonitor::onControllerConnected( const Reference< XController >& _rxController )
127 : {
128 7 : bool bFirstControllerEver = !m_bEverHadController;
129 7 : m_bEverHadController = true;
130 :
131 7 : m_xLastConnectedController = _rxController;
132 7 : m_bLastIsFirstEverController = bFirstControllerEver;
133 :
134 7 : return bFirstControllerEver;
135 : }
136 :
137 7 : bool ViewMonitor::onSetCurrentController( const Reference< XController >& _rxController )
138 : {
139 : // we interpret this as "loading the document (including UI) is finished",
140 : // if and only if this is the controller which was last connected, and it was the
141 : // first controller ever connected
142 7 : bool bLoadFinished = ( _rxController == m_xLastConnectedController ) && m_bLastIsFirstEverController;
143 :
144 : // notify the respective events
145 7 : if ( bLoadFinished )
146 7 : m_rEventNotifier.notifyDocumentEventAsync( m_bIsNewDocument ? "OnNew" : "OnLoad" );
147 :
148 7 : return bLoadFinished;
149 : }
150 :
151 : } // namespace dbaccess
152 :
153 : // ODatabaseDocument
154 :
155 20 : extern "C" void SAL_CALL createRegistryInfo_ODatabaseDocument()
156 : {
157 20 : static ::dba::OAutoRegistration< ::dbaccess::ODatabaseDocument > aAutoRegistration;
158 20 : }
159 :
160 : namespace dbaccess
161 : {
162 :
163 109 : ODatabaseDocument::ODatabaseDocument(const ::rtl::Reference<ODatabaseModelImpl>& _pImpl )
164 : :ModelDependentComponent( _pImpl )
165 109 : ,ODatabaseDocument_OfficeDocument( getMutex() )
166 109 : ,m_aModifyListeners( getMutex() )
167 109 : ,m_aCloseListener( getMutex() )
168 109 : ,m_aStorageListeners( getMutex() )
169 327 : ,m_pEventContainer( new DocumentEvents( *this, getMutex(), _pImpl->getDocumentEvents() ) )
170 : ,m_pEventExecutor( NULL ) // initialized below, ref-count-protected
171 109 : ,m_aEventNotifier( *this, getMutex() )
172 : ,m_aViewMonitor( m_aEventNotifier )
173 : ,m_eInitState( NotInitialized )
174 : ,m_bClosing( false )
175 : ,m_bAllowDocumentScripting( false )
176 : ,m_bHasBeenRecovered( false )
177 981 : ,m_bEmbedded(false)
178 : {
179 : OSL_TRACE( "DD: ctor: %p: %p", this, m_pImpl.get() );
180 :
181 109 : osl_atomic_increment( &m_refCount );
182 : {
183 109 : impl_reparent_nothrow( m_xForms );
184 109 : impl_reparent_nothrow( m_xReports );
185 109 : impl_reparent_nothrow( m_pImpl->m_xTableDefinitions );
186 109 : impl_reparent_nothrow( m_pImpl->m_xCommandDefinitions );
187 :
188 109 : m_pEventExecutor = new DocumentEventExecutor( m_pImpl->m_aContext, this );
189 : }
190 109 : osl_atomic_decrement( &m_refCount );
191 :
192 : // if there previously was a document instance for the same Impl which was already initialized,
193 : // then consider ourself initialized, too.
194 : // #i94840#
195 109 : if ( m_pImpl->hadInitializedDocument() )
196 : {
197 : // Note we set our init-state to "Initializing", not "Initialized". We're created from inside the ModelImpl,
198 : // which is expected to call attachResource in case there was a previous incarnation of the document,
199 : // so we can properly finish our initialization then.
200 1 : impl_setInitializing();
201 :
202 1 : if ( !m_pImpl->getURL().isEmpty() )
203 : {
204 : // if the previous incarnation of the DatabaseDocument already had an URL, then creating this incarnation
205 : // here is effectively loading the document.
206 : // #i105505#
207 1 : m_aViewMonitor.onLoadedDocument();
208 : }
209 : }
210 109 : }
211 :
212 303 : ODatabaseDocument::~ODatabaseDocument()
213 : {
214 : OSL_TRACE( "DD: dtor: %p: %p", this, m_pImpl.get() );
215 101 : if ( !ODatabaseDocument_OfficeDocument::rBHelper.bInDispose && !ODatabaseDocument_OfficeDocument::rBHelper.bDisposed )
216 : {
217 0 : acquire();
218 0 : dispose();
219 : }
220 :
221 101 : delete m_pEventContainer, m_pEventContainer = NULL;
222 202 : }
223 :
224 15943 : Any SAL_CALL ODatabaseDocument::queryInterface( const Type& _rType ) throw (RuntimeException, std::exception)
225 : {
226 : // strip XEmbeddedScripts and XScriptInvocationContext if we have any form/report
227 : // which already contains macros. In this case, the database document itself is not
228 : // allowed to contain macros, too.
229 31886 : if ( !m_bAllowDocumentScripting
230 15943 : && ( _rType.equals( cppu::UnoType<XEmbeddedScripts>::get() )
231 6489 : || _rType.equals( cppu::UnoType<XScriptInvocationContext>::get() )
232 : )
233 : )
234 0 : return Any();
235 :
236 15943 : Any aReturn = ODatabaseDocument_OfficeDocument::queryInterface(_rType);
237 15943 : if (!aReturn.hasValue())
238 3321 : aReturn = ODatabaseDocument_Title::queryInterface(_rType);
239 15943 : return aReturn;
240 : }
241 :
242 40341 : void SAL_CALL ODatabaseDocument::acquire( ) throw ()
243 : {
244 40341 : ODatabaseDocument_OfficeDocument::acquire();
245 40343 : }
246 :
247 40324 : void SAL_CALL ODatabaseDocument::release( ) throw ()
248 : {
249 40324 : ODatabaseDocument_OfficeDocument::release();
250 40326 : }
251 :
252 2 : Sequence< Type > SAL_CALL ODatabaseDocument::getTypes( ) throw (RuntimeException, std::exception)
253 : {
254 : Sequence< Type > aTypes = ::comphelper::concatSequences(
255 : ODatabaseDocument_OfficeDocument::getTypes(),
256 : ODatabaseDocument_Title::getTypes()
257 2 : );
258 :
259 : // strip XEmbeddedScripts and XScriptInvocationContext if we have any form/report
260 : // which already contains macros. In this case, the database document itself is not
261 : // allowed to contain macros, too.
262 2 : if ( !m_bAllowDocumentScripting )
263 : {
264 0 : Sequence< Type > aStrippedTypes( aTypes.getLength() );
265 0 : Type* pStripTo( aStrippedTypes.getArray() );
266 :
267 : // strip XEmbeddedScripts, and immediately re-assign to aTypes
268 0 : aTypes = Sequence< Type >(
269 : pStripTo,
270 : ::std::remove_copy_if(
271 : aTypes.getConstArray(),
272 0 : aTypes.getConstArray() + aTypes.getLength(),
273 : pStripTo,
274 0 : ::std::bind2nd( ::std::equal_to< Type >(), cppu::UnoType<XEmbeddedScripts>::get() )
275 0 : ) - pStripTo
276 0 : );
277 :
278 : // strip XScriptInvocationContext, and immediately re-assign to aTypes
279 0 : aTypes = Sequence< Type >(
280 : pStripTo,
281 : ::std::remove_copy_if(
282 : aTypes.getConstArray(),
283 0 : aTypes.getConstArray() + aTypes.getLength(),
284 : pStripTo,
285 0 : ::std::bind2nd( ::std::equal_to< Type >(), cppu::UnoType<XScriptInvocationContext>::get() )
286 0 : ) - pStripTo
287 0 : );
288 : }
289 :
290 2 : return aTypes;
291 : }
292 :
293 0 : Sequence< sal_Int8 > SAL_CALL ODatabaseDocument::getImplementationId( ) throw (RuntimeException, std::exception)
294 : {
295 0 : return css::uno::Sequence<sal_Int8>();
296 : }
297 :
298 : // local functions
299 : namespace
300 : {
301 304 : Reference< XStatusIndicator > lcl_extractStatusIndicator( const ::comphelper::NamedValueCollection& _rArguments )
302 : {
303 304 : Reference< XStatusIndicator > xStatusIndicator;
304 304 : return _rArguments.getOrDefault( "StatusIndicator", xStatusIndicator );
305 : }
306 :
307 192 : static void lcl_triggerStatusIndicator_throw( const ::comphelper::NamedValueCollection& _rArguments, DocumentGuard& _rGuard, const bool _bStart )
308 : {
309 192 : Reference< XStatusIndicator > xStatusIndicator( lcl_extractStatusIndicator( _rArguments ) );
310 192 : if ( !xStatusIndicator.is() )
311 378 : return;
312 :
313 6 : _rGuard.clear();
314 : try
315 : {
316 6 : if ( _bStart )
317 3 : xStatusIndicator->start( OUString(), (sal_Int32)1000000 );
318 : else
319 3 : xStatusIndicator->end();
320 : }
321 0 : catch( const Exception& )
322 : {
323 : DBG_UNHANDLED_EXCEPTION();
324 : }
325 6 : _rGuard.reset();
326 : // note that |reset| can throw a DisposedException
327 : }
328 :
329 96 : static void lcl_extractStatusIndicator( const ::comphelper::NamedValueCollection& _rArguments, Sequence< Any >& _rCallArgs )
330 : {
331 96 : Reference< XStatusIndicator > xStatusIndicator( lcl_extractStatusIndicator( _rArguments ) );
332 96 : if ( !xStatusIndicator.is() )
333 189 : return;
334 :
335 3 : sal_Int32 nLength = _rCallArgs.getLength();
336 3 : _rCallArgs.realloc( nLength + 1 );
337 3 : _rCallArgs[ nLength ] <<= xStatusIndicator;
338 : }
339 :
340 16 : static void lcl_extractAndStartStatusIndicator( const ::comphelper::NamedValueCollection& _rArguments, Reference< XStatusIndicator >& _rxStatusIndicator,
341 : Sequence< Any >& _rCallArgs )
342 : {
343 16 : _rxStatusIndicator = lcl_extractStatusIndicator( _rArguments );
344 16 : if ( !_rxStatusIndicator.is() )
345 26 : return;
346 :
347 : try
348 : {
349 6 : _rxStatusIndicator->start( OUString(), (sal_Int32)1000000 );
350 :
351 6 : sal_Int32 nLength = _rCallArgs.getLength();
352 6 : _rCallArgs.realloc( nLength + 1 );
353 6 : _rCallArgs[ nLength ] <<= _rxStatusIndicator;
354 : }
355 0 : catch( const Exception& )
356 : {
357 : DBG_UNHANDLED_EXCEPTION();
358 : }
359 : }
360 :
361 96 : static Sequence< PropertyValue > lcl_appendFileNameToDescriptor( const ::comphelper::NamedValueCollection& _rDescriptor, const OUString& _rURL )
362 : {
363 96 : ::comphelper::NamedValueCollection aMutableDescriptor( _rDescriptor );
364 96 : if ( !_rURL.isEmpty() )
365 : {
366 96 : aMutableDescriptor.put( "FileName", _rURL );
367 96 : aMutableDescriptor.put( "URL", _rURL );
368 : }
369 96 : return aMutableDescriptor.getPropertyValues();
370 : }
371 : }
372 :
373 : static const char sPictures[] = "Pictures";
374 :
375 : // base documents seem to have a different behaviour to other documents, the
376 : // root storage contents at least seem to be re-used over different saves, thus if there is a
377 : // top level Picture directory it is never cleared.
378 : // If we delete the 'Pictures' directory then the dialog library storage which does store
379 : // any embed images will not work properly. ( this is due to the fact it will
380 : // try to load the dialog which will try and access the embed images, if those images are not cached in
381 : // memory it will try to read them from the Picture directory which is now gone, so... we have to use this
382 : // inglorious hack below which basically will
383 : //
384 : // a) create a temp storage
385 : //
386 : // b) introspect any dialogs for any embed graphics and grab the associate URL(s)
387 : //
388 : // c) populate the temp storage with the associated embed images ( will be stored in a 'Pictures' folder )
389 : //
390 : // d) delete the 'Picture' element from the root storage
391 : //
392 : // e) copy the Pictures element of the temp storage to the root storage
393 : //
394 : // this assumes that we don't use the Pictures folder in the root of the base
395 : // document for anything, I believe this is a valid assumption ( as much as
396 : // I could check anyway )
397 :
398 0 : void lcl_uglyHackToStoreDialogeEmbedImages( const Reference< XStorageBasedLibraryContainer >& xDlgCont, const Reference< XStorage >& xStorage, const Reference< XModel >& rxModel, const Reference<XComponentContext >& rxContext ) throw ( RuntimeException )
399 : {
400 0 : Sequence< OUString > sLibraries = xDlgCont->getElementNames();
401 0 : Reference< XStorage > xTmpPic = xStorage->openStorageElement( "tempPictures", ElementModes::READWRITE );
402 :
403 0 : std::vector< OUString > vEmbedImgUrls;
404 0 : for ( sal_Int32 i=0; i < sLibraries.getLength(); ++i )
405 : {
406 0 : OUString sLibrary( sLibraries[ i ] );
407 0 : xDlgCont->loadLibrary( sLibrary );
408 0 : Reference< XNameContainer > xLib;
409 0 : xDlgCont->getByName( sLibrary ) >>= xLib;
410 0 : if ( xLib.is() )
411 : {
412 0 : Sequence< OUString > sDialogs = xLib->getElementNames();
413 0 : sal_Int32 nDialogs( sDialogs.getLength() );
414 0 : for ( sal_Int32 j=0; j < nDialogs; ++j )
415 : {
416 0 : Reference < awt::XDialogProvider > xDlgPrv = awt::DialogProvider::createWithModel(rxContext, rxModel);
417 0 : OUString sDialogUrl = "vnd.sun.star.script:";
418 0 : sDialogUrl = sDialogUrl.concat( sLibraries[ i ] ).concat( "." ).concat ( sDialogs[ j ] ).concat( "?location=document" );
419 :
420 0 : Reference< ::com::sun::star::awt::XControl > xDialog( xDlgPrv->createDialog( sDialogUrl ), UNO_QUERY );
421 0 : Reference< XInterface > xModel( xDialog->getModel() );
422 0 : GraphicObject::InspectForGraphicObjectImageURL( xModel, vEmbedImgUrls );
423 0 : }
424 : }
425 0 : }
426 : // if we have any image urls, make sure we copy the associated images into tempPictures
427 0 : if ( !vEmbedImgUrls.empty() )
428 : {
429 : // Export the images to the storage
430 0 : Reference< XGraphicObjectResolver > xGraphicResolver = GraphicObjectResolver::createWithStorage(rxContext, xTmpPic);
431 0 : std::vector< OUString >::iterator it = vEmbedImgUrls.begin();
432 0 : std::vector< OUString >::iterator it_end = vEmbedImgUrls.end();
433 0 : if ( xGraphicResolver.is() )
434 : {
435 0 : for ( sal_Int32 count = 0; it != it_end; ++it, ++count )
436 0 : xGraphicResolver->resolveGraphicObjectURL( *it );
437 : }
438 :
439 : // delete old 'Pictures' storage and copy the contents of tempPictures into xStorage
440 0 : xStorage->removeElement( sPictures );
441 0 : xTmpPic->copyElementTo( sPictures, xStorage, sPictures );
442 : }
443 : else
444 : {
445 : // clean up an existing Pictures dir
446 0 : if ( xStorage->isStorageElement( sPictures ) )
447 0 : xStorage->removeElement( sPictures );
448 0 : }
449 0 : }
450 :
451 108 : void ODatabaseDocument::impl_setInitialized()
452 : {
453 108 : m_eInitState = Initialized;
454 :
455 : // start event notifications
456 108 : m_aEventNotifier.onDocumentInitialized();
457 108 : }
458 :
459 16 : void ODatabaseDocument::impl_reset_nothrow()
460 : {
461 : try
462 : {
463 16 : m_pImpl->clearConnections();
464 16 : m_pImpl->disposeStorages();
465 16 : m_pImpl->resetRootStorage();
466 :
467 16 : clearObjectContainer( m_xForms );
468 16 : clearObjectContainer( m_xReports );
469 16 : clearObjectContainer( m_pImpl->m_xTableDefinitions );
470 16 : clearObjectContainer( m_pImpl->m_xCommandDefinitions );
471 :
472 16 : m_eInitState = NotInitialized;
473 :
474 16 : m_pImpl->reset();
475 : }
476 0 : catch(const Exception&)
477 : {
478 : DBG_UNHANDLED_EXCEPTION();
479 : }
480 16 : m_pImpl->m_bDocumentReadOnly = false;
481 16 : }
482 :
483 : namespace
484 : {
485 : /** property map for import/exmport info set */
486 90 : comphelper::PropertyMapEntry const aExportInfoMap[] =
487 : {
488 45 : { OUString("BaseURI"), 0, ::cppu::UnoType<OUString>::get(), beans::PropertyAttribute::MAYBEVOID, 0 },
489 45 : { OUString("StreamName"), 0, ::cppu::UnoType<OUString>::get(), beans::PropertyAttribute::MAYBEVOID, 0 },
490 45 : { OUString("UsePrettyPrinting"), 0, ::cppu::UnoType<sal_Bool>::get(), beans::PropertyAttribute::MAYBEVOID, 0},
491 45 : {OUString("TargetStorage"), 0, cppu::UnoType<embed::XStorage>::get(), beans::PropertyAttribute::MAYBEVOID, 0},
492 45 : {OUString("StreamRelPath"), 0, cppu::UnoType<OUString>::get(), beans::PropertyAttribute::MAYBEVOID, 0},
493 : { OUString(), 0, css::uno::Type(), 0, 0 }
494 270 : };
495 : }
496 :
497 16 : void ODatabaseDocument::impl_import_nolck_throw( const Reference< XComponentContext >& _rContext, const Reference< XInterface >& _rxTargetComponent,
498 : const ::comphelper::NamedValueCollection& _rResource )
499 : {
500 16 : Sequence< Any > aFilterCreationArgs;
501 32 : Reference< XStatusIndicator > xStatusIndicator;
502 16 : lcl_extractAndStartStatusIndicator( _rResource, xStatusIndicator, aFilterCreationArgs );
503 :
504 32 : uno::Reference< beans::XPropertySet > xInfoSet( comphelper::GenericPropertySet_CreateInstance( new comphelper::PropertySetInfo( aExportInfoMap ) ) );
505 32 : OUString sBaseURI = _rResource.getOrDefault("BaseURI", OUString());
506 16 : if (sBaseURI.isEmpty())
507 15 : sBaseURI = _rResource.getOrDefault("URL",OUString());
508 16 : xInfoSet->setPropertyValue("BaseURI", uno::makeAny(sBaseURI));
509 16 : xInfoSet->setPropertyValue("StreamName", uno::makeAny(OUString("content.xml")));
510 :
511 16 : const sal_Int32 nCount = aFilterCreationArgs.getLength();
512 16 : aFilterCreationArgs.realloc(nCount + 1);
513 16 : aFilterCreationArgs[nCount] <<= xInfoSet;
514 :
515 : Reference< XImporter > xImporter(
516 32 : _rContext->getServiceManager()->createInstanceWithArgumentsAndContext("com.sun.star.comp.sdb.DBFilter", aFilterCreationArgs, _rContext),
517 32 : UNO_QUERY_THROW );
518 :
519 32 : Reference< XComponent > xComponent( _rxTargetComponent, UNO_QUERY_THROW );
520 16 : xImporter->setTargetDocument( xComponent );
521 :
522 32 : Reference< XFilter > xFilter( xImporter, UNO_QUERY_THROW );
523 32 : Sequence< PropertyValue > aFilterArgs( ODatabaseModelImpl::stripLoadArguments( _rResource ).getPropertyValues() );
524 16 : xFilter->filter( aFilterArgs );
525 :
526 16 : if ( xStatusIndicator.is() )
527 22 : xStatusIndicator->end();
528 16 : }
529 :
530 0 : void SAL_CALL ODatabaseDocument::initNew( ) throw (DoubleInitializationException, IOException, Exception, RuntimeException, std::exception)
531 : {
532 : // SYNCHRONIZED ->
533 0 : DocumentGuard aGuard( *this, DocumentGuard::InitMethod );
534 :
535 0 : impl_reset_nothrow();
536 :
537 0 : impl_setInitializing();
538 :
539 : // create a temporary storage
540 0 : Reference< XStorage > xTempStor( ::comphelper::OStorageHelper::GetTemporaryStorage( m_pImpl->m_aContext ) );
541 :
542 : // store therein
543 0 : impl_storeToStorage_throw( xTempStor, Sequence< PropertyValue >(), aGuard );
544 :
545 : // let the impl know we're now based on this storage
546 0 : m_pImpl->switchToStorage( xTempStor );
547 :
548 : // for the newly created document, allow document-wide scripting
549 0 : m_bAllowDocumentScripting = true;
550 :
551 0 : impl_setInitialized();
552 :
553 0 : m_aEventNotifier.notifyDocumentEventAsync( "OnTitleChanged" );
554 :
555 0 : impl_setModified_nothrow( false, aGuard );
556 : // <- SYNCHRONIZED
557 :
558 0 : m_aEventNotifier.notifyDocumentEvent( "OnCreate" );
559 :
560 0 : impl_notifyStorageChange_nolck_nothrow( xTempStor );
561 0 : }
562 :
563 16 : void SAL_CALL ODatabaseDocument::load( const Sequence< PropertyValue >& _Arguments ) throw (DoubleInitializationException, IOException, Exception, RuntimeException, std::exception)
564 : {
565 : // SYNCHRONIZED ->
566 16 : DocumentGuard aGuard( *this, DocumentGuard::InitMethod );
567 :
568 16 : impl_reset_nothrow();
569 :
570 32 : ::comphelper::NamedValueCollection aResource( _Arguments );
571 16 : if ( aResource.has( "FileName" ) && !aResource.has( "URL" ) )
572 : // FileName is the compatibility name for URL, so we might have clients passing
573 : // a FileName only. However, some of our code works with the URL only, so ensure
574 : // we have one.
575 0 : aResource.put( "URL", aResource.get( "FileName" ) );
576 16 : if ( aResource.has( "URL" ) && !aResource.has( "FileName" ) )
577 : // similar ... just in case there is legacy code which expects a FileName only
578 9 : aResource.put( "FileName", aResource.get( "URL" ) );
579 :
580 : // now that somebody (perhaps) told us an macro execution mode, remember it as
581 : // ImposedMacroExecMode
582 : m_pImpl->setImposedMacroExecMode(
583 16 : aResource.getOrDefault( "MacroExecutionMode", m_pImpl->getImposedMacroExecMode() ) );
584 :
585 16 : impl_setInitializing();
586 : try
587 : {
588 16 : aGuard.clear();
589 16 : impl_import_nolck_throw( m_pImpl->m_aContext, *this, aResource );
590 16 : aGuard.reset();
591 : }
592 0 : catch( const Exception& )
593 : {
594 0 : impl_reset_nothrow();
595 0 : throw;
596 : }
597 : // tell our view monitor that the document has been loaded - this way it will fire the proper
598 : // event (OnLoad instead of OnCreate) later on
599 16 : m_aViewMonitor.onLoadedDocument();
600 :
601 : // note that we do *not* call impl_setInitialized() here: The initialization is only complete
602 : // when the XModel::attachResource has been called, not sooner.
603 : // however, in case of embedding, XModel::attachResource is already called.
604 16 : if (m_bEmbedded)
605 0 : impl_setInitialized();
606 :
607 32 : impl_setModified_nothrow( false, aGuard );
608 : // <- SYNCHRONIZED
609 16 : }
610 :
611 : namespace
612 : {
613 0 : bool lcl_hasAnyModifiedSubComponent_throw( const Reference< XController >& i_rController )
614 : {
615 0 : Reference< XDatabaseDocumentUI > xDatabaseUI( i_rController, UNO_QUERY_THROW );
616 :
617 0 : Sequence< Reference< XComponent > > aComponents( xDatabaseUI->getSubComponents() );
618 0 : const Reference< XComponent >* component = aComponents.getConstArray();
619 0 : const Reference< XComponent >* componentsEnd = aComponents.getConstArray() + aComponents.getLength();
620 :
621 0 : bool isAnyModified = false;
622 0 : for ( ; component != componentsEnd; ++component )
623 : {
624 0 : Reference< XModifiable > xModify( *component, UNO_QUERY );
625 0 : if ( xModify.is() )
626 : {
627 0 : isAnyModified = xModify->isModified();
628 0 : continue;
629 : }
630 :
631 : // TODO: clarify: anything else to care for? Both the sub componbents with and without model
632 : // should support the XModifiable interface, so I think nothing more is needed here.
633 : OSL_FAIL( "lcl_hasAnyModifiedSubComponent_throw: anything left to do here?" );
634 0 : }
635 :
636 0 : return isAnyModified;
637 : }
638 : }
639 :
640 0 : sal_Bool SAL_CALL ODatabaseDocument::wasModifiedSinceLastSave() throw ( RuntimeException, std::exception )
641 : {
642 0 : DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
643 :
644 : // The implementation here is somewhat sloppy, in that it returns whether *any* part of the whole
645 : // database document, including opened sub components, is modified. This is more than what is requested:
646 : // We need to return <TRUE/> if the doc itself, or any of the opened sub components, has been modified
647 : // since the last call to any of the save* methods, or since the document has been loaded/created.
648 : // However, the API definition explicitly allows to be that sloppy ...
649 :
650 0 : if ( isModified() )
651 0 : return sal_True;
652 :
653 : // auto recovery is an "UI feature", it is to restore the UI the user knows. Thus,
654 : // we ask our connected controllers, not simply our existing form/report definitions.
655 : // (There is some information which even cannot be obtained without asking the controller.
656 : // For instance, newly created, but not yet saved, forms/reports are accessible via the
657 : // controller only, but not via the model.)
658 :
659 : try
660 : {
661 0 : for ( Controllers::const_iterator ctrl = m_aControllers.begin();
662 0 : ctrl != m_aControllers.end();
663 : ++ctrl
664 : )
665 : {
666 0 : if ( lcl_hasAnyModifiedSubComponent_throw( *ctrl ) )
667 0 : return sal_True;
668 : }
669 : }
670 0 : catch( const Exception& )
671 : {
672 : DBG_UNHANDLED_EXCEPTION();
673 : }
674 :
675 0 : return sal_False;
676 : }
677 :
678 0 : void SAL_CALL ODatabaseDocument::storeToRecoveryFile( const OUString& i_TargetLocation, const Sequence< PropertyValue >& i_MediaDescriptor ) throw ( RuntimeException, IOException, WrappedTargetException, std::exception )
679 : {
680 0 : DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
681 0 : ModifyLock aLock( *this );
682 :
683 : try
684 : {
685 : // create a storage for the target location
686 0 : Reference< XStorage > xTargetStorage( impl_createStorageFor_throw( i_TargetLocation ) );
687 :
688 : // first store the document as a whole into this storage
689 0 : impl_storeToStorage_throw( xTargetStorage, i_MediaDescriptor, aGuard );
690 :
691 : // save the sub components which need saving
692 0 : DatabaseDocumentRecovery aDocRecovery( m_pImpl->m_aContext);
693 0 : aDocRecovery.saveModifiedSubComponents( xTargetStorage, m_aControllers );
694 :
695 : // commit the root storage
696 0 : tools::stor::commitStorageIfWriteable( xTargetStorage );
697 : }
698 0 : catch( const Exception& )
699 : {
700 0 : Any aError = ::cppu::getCaughtException();
701 0 : if ( aError.isExtractableTo( ::cppu::UnoType< IOException >::get() )
702 0 : || aError.isExtractableTo( ::cppu::UnoType< RuntimeException >::get() )
703 0 : || aError.isExtractableTo( ::cppu::UnoType< WrappedTargetException >::get() )
704 : )
705 : {
706 : // allowed to leave
707 0 : throw;
708 : }
709 :
710 0 : throw WrappedTargetException( OUString(), *this, aError );
711 0 : }
712 0 : }
713 :
714 0 : void SAL_CALL ODatabaseDocument::recoverFromFile( const OUString& i_SourceLocation, const OUString& i_SalvagedFile, const Sequence< PropertyValue >& i_MediaDescriptor ) throw ( RuntimeException, IOException, WrappedTargetException, std::exception )
715 : {
716 : try
717 : {
718 0 : DocumentGuard aGuard( *this, DocumentGuard::InitMethod );
719 :
720 0 : if ( i_SourceLocation.isEmpty() )
721 0 : throw IllegalArgumentException( OUString(), *this, 1 );
722 :
723 :
724 : // load the document itself, by simply delegating to our "load" method
725 :
726 : // our load implementation expects the SalvagedFile and URL to be in the media descriptor
727 0 : ::comphelper::NamedValueCollection aMediaDescriptor( i_MediaDescriptor );
728 0 : aMediaDescriptor.put( "SalvagedFile", i_SalvagedFile );
729 0 : aMediaDescriptor.put( "URL", i_SourceLocation );
730 :
731 0 : aGuard.clear(); // (load has an own guarding scheme)
732 0 : load( aMediaDescriptor.getPropertyValues() );
733 :
734 : // Without a controller, we are unable to recover the sub components, as they're always tied to a controller.
735 : // So, everything else is done when the first controller is connected.
736 0 : m_bHasBeenRecovered = true;
737 :
738 : // tell the impl that we've been loaded from the given location
739 0 : m_pImpl->setDocFileLocation( i_SourceLocation );
740 :
741 : // by definition (of XDocumentRecovery), we're responsible for delivering a fully-initialized document,
742 : // which includes an attachResource call.
743 0 : const OUString sLogicalDocumentURL( i_SalvagedFile.isEmpty() ? i_SourceLocation : i_SalvagedFile );
744 0 : impl_attachResource( sLogicalDocumentURL, aMediaDescriptor.getPropertyValues(), aGuard );
745 : // <- SYNCHRONIZED
746 : }
747 0 : catch( const IOException& )
748 : {
749 0 : throw;
750 : }
751 0 : catch( const RuntimeException& )
752 : {
753 0 : throw;
754 : }
755 0 : catch( const WrappedTargetException& )
756 : {
757 0 : throw;
758 : }
759 0 : catch( const Exception& )
760 : {
761 0 : Any aError = ::cppu::getCaughtException();
762 0 : throw WrappedTargetException( OUString(), *this, aError );
763 : }
764 0 : }
765 :
766 : // XModel
767 17 : sal_Bool SAL_CALL ODatabaseDocument::attachResource( const OUString& _rURL, const Sequence< PropertyValue >& _rArguments ) throw (RuntimeException, std::exception)
768 : {
769 17 : if (_rURL.isEmpty() && _rArguments.getLength() == 1 && _rArguments[0].Name == "SetEmbedded")
770 : {
771 0 : m_bEmbedded = true;
772 0 : return true;
773 : }
774 :
775 17 : DocumentGuard aGuard( *this, DocumentGuard::MethodUsedDuringInit );
776 17 : bool bRet = false;
777 : try
778 : {
779 17 : bRet = impl_attachResource( _rURL, _rArguments, aGuard );
780 : }
781 0 : catch( const RuntimeException& )
782 : {
783 0 : throw;
784 : }
785 0 : catch( const Exception& )
786 : {
787 0 : Any aError = ::cppu::getCaughtException();
788 0 : throw WrappedTargetRuntimeException( OUString(), *this, aError );
789 : }
790 17 : return bRet;
791 : }
792 :
793 17 : bool ODatabaseDocument::impl_attachResource( const OUString& i_rLogicalDocumentURL,
794 : const Sequence< PropertyValue >& i_rMediaDescriptor, DocumentGuard& _rDocGuard )
795 : {
796 51 : if ( ( i_rLogicalDocumentURL == getURL() )
797 1 : && ( i_rMediaDescriptor.getLength() == 1 )
798 51 : && ( i_rMediaDescriptor[0].Name == "BreakMacroSignature" )
799 : )
800 : {
801 : // this is a BAD hack of the Basic importer code ... there should be a dedicated API for this,
802 : // not this bad mis-using of existing interfaces
803 0 : return false;
804 : // (we do not support macro signatures, so we can ignore this call)
805 : }
806 :
807 : // if no URL has been provided, the caller was lazy enough to not call our getURL - which is not allowed anymore,
808 : // now since getURL and getLocation both return the same, so calling one of those should be simple.
809 17 : OUString sDocumentURL( i_rLogicalDocumentURL );
810 : OSL_ENSURE( !sDocumentURL.isEmpty(), "ODatabaseDocument::impl_attachResource: invalid URL!" );
811 17 : if ( sDocumentURL.isEmpty() )
812 0 : sDocumentURL = getURL();
813 :
814 17 : m_pImpl->setResource( sDocumentURL, i_rMediaDescriptor );
815 :
816 17 : if ( impl_isInitializing() )
817 : { // this means we've just been loaded, and this is the attachResource call which follows
818 : // the load call.
819 17 : impl_setInitialized();
820 :
821 : // determine whether the document as a whole, or sub documents, have macros. Especially the latter
822 : // controls the availability of our XEmbeddedScripts and XScriptInvocationContext interfaces, and we
823 : // should know this before anybody actually uses the object.
824 17 : m_bAllowDocumentScripting = ( m_pImpl->determineEmbeddedMacros() != ODatabaseModelImpl::eSubDocumentMacros );
825 :
826 17 : _rDocGuard.clear();
827 : // <- SYNCHRONIZED
828 17 : m_aEventNotifier.notifyDocumentEvent( "OnLoadFinished" );
829 : }
830 :
831 17 : return true;
832 : }
833 :
834 184 : OUString SAL_CALL ODatabaseDocument::getURL( ) throw (RuntimeException, std::exception)
835 : {
836 184 : DocumentGuard aGuard( *this, DocumentGuard::MethodWithoutInit );
837 184 : return m_pImpl->getURL();
838 : }
839 :
840 32 : Sequence< PropertyValue > SAL_CALL ODatabaseDocument::getArgs( ) throw (RuntimeException, std::exception)
841 : {
842 32 : DocumentGuard aGuard( *this, DocumentGuard::MethodWithoutInit );
843 32 : return m_pImpl->getMediaDescriptor().getPropertyValues();
844 : }
845 :
846 7 : void SAL_CALL ODatabaseDocument::connectController( const Reference< XController >& _xController ) throw (RuntimeException, std::exception)
847 : {
848 7 : DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
849 :
850 : #if OSL_DEBUG_LEVEL > 0
851 : for ( Controllers::const_iterator controller = m_aControllers.begin();
852 : controller != m_aControllers.end();
853 : ++controller
854 : )
855 : {
856 : OSL_ENSURE( *controller != _xController, "ODatabaseDocument::connectController: this controller is already connected!" );
857 : }
858 : #endif
859 :
860 7 : m_aControllers.push_back( _xController );
861 :
862 7 : m_aEventNotifier.notifyDocumentEventAsync( "OnViewCreated", Reference< XController2 >( _xController, UNO_QUERY ) );
863 :
864 7 : bool bFirstControllerEver = m_aViewMonitor.onControllerConnected( _xController );
865 7 : if ( !bFirstControllerEver )
866 7 : return;
867 :
868 : // check/adjust our macro mode.
869 7 : m_pImpl->checkMacrosOnLoading();
870 : }
871 :
872 5 : void SAL_CALL ODatabaseDocument::disconnectController( const Reference< XController >& _xController ) throw (RuntimeException, std::exception)
873 : {
874 5 : bool bNotifyViewClosed = false;
875 5 : bool bLastControllerGone = false;
876 5 : bool bIsClosing = false;
877 :
878 : // SYNCHRONIZED ->
879 : {
880 5 : DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
881 :
882 5 : Controllers::iterator pos = ::std::find( m_aControllers.begin(), m_aControllers.end(), _xController );
883 : OSL_ENSURE( pos != m_aControllers.end(), "ODatabaseDocument::disconnectController: don't know this controller!" );
884 5 : if ( pos != m_aControllers.end() )
885 : {
886 5 : m_aControllers.erase( pos );
887 5 : bNotifyViewClosed = true;
888 : }
889 :
890 5 : if ( m_xCurrentController == _xController )
891 5 : m_xCurrentController = NULL;
892 :
893 5 : bLastControllerGone = m_aControllers.empty();
894 5 : bIsClosing = m_bClosing;
895 : }
896 : // <- SYNCHRONIZED
897 :
898 5 : if ( bNotifyViewClosed )
899 5 : m_aEventNotifier.notifyDocumentEvent( "OnViewClosed", Reference< XController2 >( _xController, UNO_QUERY ) );
900 :
901 5 : if ( bLastControllerGone && !bIsClosing )
902 : {
903 : // if this was the last view, close the document as a whole
904 : // #i51157#
905 : try
906 : {
907 0 : close( sal_True );
908 : }
909 0 : catch( const CloseVetoException& )
910 : {
911 : // okay, somebody vetoed and took ownership
912 : }
913 : }
914 5 : }
915 :
916 0 : void SAL_CALL ODatabaseDocument::lockControllers( ) throw (RuntimeException, std::exception)
917 : {
918 0 : DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
919 :
920 0 : ++m_pImpl->m_nControllerLockCount;
921 0 : }
922 :
923 0 : void SAL_CALL ODatabaseDocument::unlockControllers( ) throw (RuntimeException, std::exception)
924 : {
925 0 : DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
926 :
927 0 : --m_pImpl->m_nControllerLockCount;
928 0 : }
929 :
930 0 : sal_Bool SAL_CALL ODatabaseDocument::hasControllersLocked( ) throw (RuntimeException, std::exception)
931 : {
932 0 : DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
933 :
934 0 : return m_pImpl->m_nControllerLockCount != 0;
935 : }
936 :
937 30 : Reference< XController > SAL_CALL ODatabaseDocument::getCurrentController() throw (RuntimeException, std::exception)
938 : {
939 30 : DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
940 :
941 30 : return m_xCurrentController.is() ? m_xCurrentController : ( m_aControllers.empty() ? Reference< XController >() : *m_aControllers.begin() );
942 : }
943 :
944 7 : void SAL_CALL ODatabaseDocument::setCurrentController( const Reference< XController >& _xController ) throw (NoSuchElementException, RuntimeException, std::exception)
945 : {
946 7 : DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
947 :
948 7 : m_xCurrentController = _xController;
949 :
950 7 : if ( !m_aViewMonitor.onSetCurrentController( _xController ) )
951 0 : return;
952 :
953 : // check if there are sub components to recover from our document storage
954 7 : bool bAttemptRecovery = m_bHasBeenRecovered;
955 7 : if ( !bAttemptRecovery && m_pImpl->getMediaDescriptor().has( "ForceRecovery" ) )
956 : // do not use getOrDefault, it will throw for invalid types, which is not desired here
957 0 : m_pImpl->getMediaDescriptor().get( "ForceRecovery" ) >>= bAttemptRecovery;
958 :
959 7 : if ( !bAttemptRecovery )
960 7 : return;
961 :
962 : try
963 : {
964 0 : DatabaseDocumentRecovery aDocRecovery( m_pImpl->m_aContext );
965 0 : aDocRecovery.recoverSubDocuments( m_pImpl->getRootStorage(), _xController );
966 : }
967 0 : catch( const Exception& )
968 : {
969 : DBG_UNHANDLED_EXCEPTION();
970 0 : }
971 : }
972 :
973 0 : Reference< XInterface > SAL_CALL ODatabaseDocument::getCurrentSelection( ) throw (RuntimeException, std::exception)
974 : {
975 0 : DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
976 :
977 0 : Reference< XInterface > xRet;
978 0 : Reference< XSelectionSupplier > xDocView( getCurrentController(), UNO_QUERY );
979 0 : if ( xDocView.is() )
980 0 : xRet.set(xDocView->getSelection(),UNO_QUERY);
981 :
982 0 : return xRet;
983 : }
984 :
985 : // XStorable
986 0 : sal_Bool SAL_CALL ODatabaseDocument::hasLocation( ) throw (RuntimeException, std::exception)
987 : {
988 0 : return !getLocation().isEmpty();
989 : }
990 :
991 19 : OUString SAL_CALL ODatabaseDocument::getLocation( ) throw (RuntimeException, std::exception)
992 : {
993 19 : DocumentGuard aGuard( *this, DocumentGuard::MethodWithoutInit );
994 19 : return m_pImpl->getURL();
995 : // both XStorable::getLocation and XModel::getURL have to return the URL of the document, *not*
996 : // the location of the file which the docunment was possibly recovered from (which would be getDocFileLocation)
997 : }
998 :
999 244 : sal_Bool SAL_CALL ODatabaseDocument::isReadonly( ) throw (RuntimeException, std::exception)
1000 : {
1001 244 : DocumentGuard aGuard( *this, DocumentGuard::MethodWithoutInit );
1002 244 : return m_pImpl->m_bDocumentReadOnly;
1003 : }
1004 :
1005 4 : void SAL_CALL ODatabaseDocument::store( ) throw (IOException, RuntimeException, std::exception)
1006 : {
1007 4 : DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
1008 :
1009 4 : OUString sDocumentURL( m_pImpl->getURL() );
1010 4 : if ( !sDocumentURL.isEmpty() )
1011 : {
1012 4 : if ( m_pImpl->getDocFileLocation() == m_pImpl->getURL() )
1013 4 : if ( m_pImpl->m_bDocumentReadOnly )
1014 0 : throw IOException();
1015 :
1016 4 : impl_storeAs_throw( m_pImpl->getURL(), m_pImpl->getMediaDescriptor(), SAVE, aGuard );
1017 8 : return;
1018 : }
1019 :
1020 : // if we have no URL, but did survive the DocumentGuard above, then we've been inited via XLoadable::initNew,
1021 : // i.e. we're based on a temporary storage
1022 : OSL_ENSURE( m_pImpl->getDocFileLocation().isEmpty(), "ODatabaseDocument::store: unexpected URL inconsistency!" );
1023 :
1024 : try
1025 : {
1026 0 : impl_storeToStorage_throw( m_pImpl->getRootStorage(), m_pImpl->getMediaDescriptor().getPropertyValues(), aGuard );
1027 : }
1028 0 : catch( const Exception& )
1029 : {
1030 0 : Any aError = ::cppu::getCaughtException();
1031 0 : if ( aError.isExtractableTo( ::cppu::UnoType< IOException >::get() )
1032 0 : || aError.isExtractableTo( ::cppu::UnoType< RuntimeException >::get() )
1033 : )
1034 : {
1035 : // allowed to leave
1036 0 : throw;
1037 : }
1038 0 : impl_throwIOExceptionCausedBySave_throw( aError, OUString() );
1039 0 : }
1040 : }
1041 :
1042 0 : void ODatabaseDocument::impl_throwIOExceptionCausedBySave_throw( const Any& i_rError, const OUString& i_rTargetURL ) const
1043 : {
1044 0 : OUString sErrorMessage = extractExceptionMessage( m_pImpl->m_aContext, i_rError );
1045 0 : sErrorMessage = ResourceManager::loadString(
1046 : RID_STR_ERROR_WHILE_SAVING,
1047 : "$location$", i_rTargetURL,
1048 : "$message$", sErrorMessage
1049 0 : );
1050 0 : throw IOException( sErrorMessage, *const_cast< ODatabaseDocument* >( this ) );
1051 : }
1052 :
1053 96 : void ODatabaseDocument::impl_storeAs_throw( const OUString& _rURL, const ::comphelper::NamedValueCollection& _rArguments,
1054 : const StoreType _eType, DocumentGuard& _rGuard ) throw (IOException, RuntimeException, std::exception)
1055 : {
1056 : OSL_PRECOND( ( _eType == SAVE ) || ( _eType == SAVE_AS ),
1057 : "ODatabaseDocument::impl_storeAs_throw: you introduced a new type which cannot be handled here!" );
1058 :
1059 : // if we're in the process of initializing the document (which effectively means it is an implicit
1060 : // initialization triggered in storeAsURL), the we do not notify events, since to an observer, the SaveAs
1061 : // should not be noticeable
1062 96 : bool bIsInitializationProcess = impl_isInitializing();
1063 :
1064 96 : if ( !bIsInitializationProcess )
1065 : {
1066 5 : _rGuard.clear();
1067 5 : m_aEventNotifier.notifyDocumentEvent( _eType == SAVE ? "OnSave" : "OnSaveAs", NULL, makeAny( _rURL ) );
1068 5 : _rGuard.reset();
1069 : }
1070 :
1071 96 : Reference< XStorage > xNewRootStorage;
1072 : // will be non-NULL if our storage changed
1073 :
1074 : try
1075 : {
1076 96 : ModifyLock aLock( *this );
1077 : // ignore all changes of our "modified" state during storing
1078 :
1079 96 : bool bLocationChanged = ( _rURL != m_pImpl->getDocFileLocation() );
1080 96 : if ( bLocationChanged )
1081 : {
1082 : // create storage for target URL
1083 92 : uno::Reference<embed::XStorage> xTargetStorage;
1084 92 : _rArguments.get("TargetStorage") >>= xTargetStorage;
1085 92 : if (!xTargetStorage.is())
1086 91 : xTargetStorage = impl_createStorageFor_throw(_rURL);
1087 :
1088 : // In case we got a StreamRelPath, then xTargetStorage should reference that sub-storage.
1089 184 : OUString sStreamRelPath = _rArguments.getOrDefault("StreamRelPath", OUString());
1090 92 : if (!sStreamRelPath.isEmpty())
1091 1 : xTargetStorage = xTargetStorage->openStorageElement(sStreamRelPath, embed::ElementModes::READWRITE);
1092 :
1093 92 : if ( m_pImpl->isEmbeddedDatabase() )
1094 6 : m_pImpl->clearConnections();
1095 :
1096 : // commit everything
1097 92 : m_pImpl->commitEmbeddedStorage();
1098 92 : m_pImpl->commitStorages();
1099 :
1100 : // copy own storage to target storage
1101 184 : Reference< XStorage > xCurrentStorage( m_pImpl->getRootStorage() );
1102 92 : if ( xCurrentStorage.is() )
1103 0 : xCurrentStorage->copyToStorage( xTargetStorage );
1104 :
1105 92 : m_pImpl->disposeStorages();
1106 :
1107 : // each and every document definition obtained via m_xForms and m_xReports depends
1108 : // on the sub storages which we just disposed. So, dispose the forms/reports collections, too.
1109 : // This ensures that they're re-created when needed.
1110 92 : clearObjectContainer( m_xForms );
1111 92 : clearObjectContainer( m_xReports );
1112 :
1113 92 : xNewRootStorage = m_pImpl->switchToStorage( xTargetStorage );
1114 :
1115 184 : m_pImpl->m_bDocumentReadOnly = false;
1116 : }
1117 :
1118 : // store to current storage
1119 192 : Reference< XStorage > xCurrentStorage( m_pImpl->getOrCreateRootStorage(), UNO_QUERY_THROW );
1120 192 : Sequence< PropertyValue > aMediaDescriptor( lcl_appendFileNameToDescriptor( _rArguments, _rURL ) );
1121 96 : impl_storeToStorage_throw( xCurrentStorage, aMediaDescriptor, _rGuard );
1122 :
1123 : // success - tell our impl
1124 96 : m_pImpl->setDocFileLocation( _rURL );
1125 96 : m_pImpl->setResource( _rURL, aMediaDescriptor );
1126 :
1127 : // if we are in an initialization process, then this is finished, now that we stored the document
1128 96 : if ( bIsInitializationProcess )
1129 187 : impl_setInitialized();
1130 : }
1131 0 : catch( const IOException& )
1132 : {
1133 0 : if ( !bIsInitializationProcess )
1134 0 : m_aEventNotifier.notifyDocumentEventAsync( _eType == SAVE ? "OnSaveFailed" : "OnSaveAsFailed", NULL, makeAny( _rURL ) );
1135 0 : throw;
1136 : }
1137 0 : catch( const RuntimeException& )
1138 : {
1139 0 : if ( !bIsInitializationProcess )
1140 0 : m_aEventNotifier.notifyDocumentEventAsync( _eType == SAVE ? "OnSaveFailed" : "OnSaveAsFailed", NULL, makeAny( _rURL ) );
1141 0 : throw;
1142 : }
1143 0 : catch( const Exception& )
1144 : {
1145 0 : Any aError = ::cppu::getCaughtException();
1146 :
1147 : // notify the failure
1148 0 : if ( !bIsInitializationProcess )
1149 0 : m_aEventNotifier.notifyDocumentEventAsync( _eType == SAVE ? "OnSaveFailed" : "OnSaveAsFailed", NULL, makeAny( _rURL ) );
1150 :
1151 0 : impl_throwIOExceptionCausedBySave_throw( aError, _rURL );
1152 : }
1153 :
1154 : // notify the document event
1155 96 : if ( !bIsInitializationProcess )
1156 5 : m_aEventNotifier.notifyDocumentEventAsync( _eType == SAVE ? "OnSaveDone" : "OnSaveAsDone", NULL, makeAny( _rURL ) );
1157 :
1158 : // reset our "modified" flag, and clear the guard
1159 96 : impl_setModified_nothrow( false, _rGuard );
1160 : // <- SYNCHRONIZED
1161 :
1162 : // notify storage listeners
1163 96 : if ( xNewRootStorage.is() )
1164 92 : impl_notifyStorageChange_nolck_nothrow( xNewRootStorage );
1165 96 : }
1166 :
1167 91 : Reference< XStorage > ODatabaseDocument::impl_createStorageFor_throw( const OUString& _rURL ) const
1168 : {
1169 91 : Reference< ucb::XSimpleFileAccess3 > xTempAccess(ucb::SimpleFileAccess::create(m_pImpl->m_aContext));
1170 182 : Reference< io::XStream > xStream = xTempAccess->openFileReadWrite( _rURL );
1171 182 : Reference< io::XTruncate > xTruncate(xStream,UNO_QUERY);
1172 91 : if ( xTruncate.is() )
1173 : {
1174 91 : xTruncate->truncate();
1175 : }
1176 182 : Sequence<Any> aParam(2);
1177 91 : aParam[0] <<= xStream;
1178 91 : aParam[1] <<= ElementModes::READWRITE | ElementModes::TRUNCATE;
1179 :
1180 182 : Reference< XSingleServiceFactory > xStorageFactory( m_pImpl->createStorageFactory(), UNO_SET_THROW );
1181 182 : return Reference< XStorage >( xStorageFactory->createInstanceWithArguments( aParam ), UNO_QUERY_THROW );
1182 : }
1183 :
1184 92 : void SAL_CALL ODatabaseDocument::storeAsURL( const OUString& _rURL, const Sequence< PropertyValue >& _rArguments ) throw (IOException, RuntimeException, std::exception)
1185 : {
1186 : // SYNCHRONIZED ->
1187 92 : DocumentGuard aGuard( *this, DocumentGuard::MethodWithoutInit );
1188 :
1189 : // Normally, a document initialization is done via XLoadable::load or XLoadable::initNew. For convenience
1190 : // reasons, and to not break existing API clients, it's allowed to call storeAsURL without having initialized
1191 : // the document, in which case the initialization will be done implicitly.
1192 92 : bool bImplicitInitialization = !impl_isInitialized();
1193 : // implicit initialization while another initialization is just running is not possible
1194 92 : if ( bImplicitInitialization && impl_isInitializing() )
1195 0 : throw RuntimeException();
1196 :
1197 92 : if ( bImplicitInitialization )
1198 91 : impl_setInitializing();
1199 :
1200 : try
1201 : {
1202 92 : impl_storeAs_throw( _rURL, _rArguments, SAVE_AS, aGuard );
1203 : // <- SYNCHRONIZED
1204 :
1205 : // impl_storeAs_throw cleared the lock on our mutex, but the below lines need this lock
1206 : // SYNCHRONIZED ->
1207 92 : aGuard.reset();
1208 :
1209 : // our title might have changed, potentially at least
1210 : // Sadly, we cannot check this: Calling getTitle here and now would not deliver
1211 : // an up-to-date result, as the call is delegated to our TitleHelper instance, which itself
1212 : // updates its title only if it gets the OnSaveAsDone event (which was sent asynchronously
1213 : // by impl_storeAs_throw). So, we simply notify always, and also asynchronously
1214 92 : m_aEventNotifier.notifyDocumentEventAsync( "OnTitleChanged" );
1215 : }
1216 0 : catch( const Exception& )
1217 : {
1218 0 : impl_reset_nothrow();
1219 0 : throw;
1220 : }
1221 :
1222 92 : if ( bImplicitInitialization )
1223 91 : m_bAllowDocumentScripting = true;
1224 :
1225 92 : aGuard.clear();
1226 : // <- SYNCHRONIZED
1227 :
1228 92 : if ( bImplicitInitialization )
1229 91 : m_aEventNotifier.notifyDocumentEvent( "OnCreate" );
1230 92 : }
1231 :
1232 96 : void ODatabaseDocument::impl_storeToStorage_throw( const Reference< XStorage >& _rxTargetStorage, const Sequence< PropertyValue >& _rMediaDescriptor,
1233 : DocumentGuard& _rDocGuard ) const
1234 : {
1235 96 : if ( !_rxTargetStorage.is() )
1236 0 : throw IllegalArgumentException( OUString(), *const_cast< ODatabaseDocument* >( this ), 1 );
1237 :
1238 96 : if ( !m_pImpl.is() )
1239 0 : throw DisposedException( OUString(), *const_cast< ODatabaseDocument* >( this ) );
1240 :
1241 : try
1242 : {
1243 : // commit everything
1244 96 : m_pImpl->commitEmbeddedStorage();
1245 96 : m_pImpl->commitStorages();
1246 :
1247 : // copy own storage to target storage
1248 96 : if ( impl_isInitialized() )
1249 : {
1250 5 : Reference< XStorage > xCurrentStorage = m_pImpl->getOrCreateRootStorage();
1251 : // Root storage may be empty in case of embedding.
1252 5 : if ( xCurrentStorage.is() && xCurrentStorage != _rxTargetStorage )
1253 0 : xCurrentStorage->copyToStorage( _rxTargetStorage );
1254 : }
1255 :
1256 : // write into target storage
1257 96 : ::comphelper::NamedValueCollection aWriteArgs( _rMediaDescriptor );
1258 96 : lcl_triggerStatusIndicator_throw( aWriteArgs, _rDocGuard, true );
1259 96 : impl_writeStorage_throw( _rxTargetStorage, aWriteArgs );
1260 96 : lcl_triggerStatusIndicator_throw( aWriteArgs, _rDocGuard, false );
1261 :
1262 : // commit target storage
1263 96 : OSL_VERIFY( tools::stor::commitStorageIfWriteable( _rxTargetStorage ) );
1264 : }
1265 0 : catch( const IOException& ) { throw; }
1266 0 : catch( const RuntimeException& ) { throw; }
1267 0 : catch ( const Exception& e )
1268 : {
1269 0 : throw IOException( e.Message, *const_cast< ODatabaseDocument* >( this ) );
1270 : }
1271 96 : }
1272 :
1273 0 : void SAL_CALL ODatabaseDocument::storeToURL( const OUString& _rURL, const Sequence< PropertyValue >& _rArguments ) throw (IOException, RuntimeException, std::exception)
1274 : {
1275 0 : DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
1276 0 : ModifyLock aLock( *this );
1277 :
1278 : {
1279 0 : aGuard.clear();
1280 0 : m_aEventNotifier.notifyDocumentEvent( "OnSaveTo", NULL, makeAny( _rURL ) );
1281 0 : aGuard.reset();
1282 : }
1283 :
1284 : try
1285 : {
1286 : // create storage for target URL
1287 0 : Reference< XStorage > xTargetStorage( impl_createStorageFor_throw( _rURL ) );
1288 :
1289 : // extend media descriptor with URL
1290 0 : Sequence< PropertyValue > aMediaDescriptor( lcl_appendFileNameToDescriptor( _rArguments, _rURL ) );
1291 :
1292 : // store to this storage
1293 0 : impl_storeToStorage_throw( xTargetStorage, aMediaDescriptor, aGuard );
1294 : }
1295 0 : catch( const Exception& )
1296 : {
1297 0 : Any aError = ::cppu::getCaughtException();
1298 0 : m_aEventNotifier.notifyDocumentEventAsync( "OnSaveToFailed", NULL, aError );
1299 :
1300 0 : if ( aError.isExtractableTo( ::cppu::UnoType< IOException >::get() )
1301 0 : || aError.isExtractableTo( ::cppu::UnoType< RuntimeException >::get() )
1302 : )
1303 : {
1304 : // allowed to leave
1305 0 : throw;
1306 : }
1307 :
1308 0 : impl_throwIOExceptionCausedBySave_throw( aError, _rURL );
1309 : }
1310 :
1311 0 : m_aEventNotifier.notifyDocumentEventAsync( "OnSaveToDone", NULL, makeAny( _rURL ) );
1312 0 : }
1313 :
1314 : // XModifyBroadcaster
1315 14 : void SAL_CALL ODatabaseDocument::addModifyListener( const Reference< XModifyListener >& _xListener ) throw (RuntimeException, std::exception)
1316 : {
1317 14 : DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
1318 14 : m_aModifyListeners.addInterface(_xListener);
1319 14 : }
1320 :
1321 5 : void SAL_CALL ODatabaseDocument::removeModifyListener( const Reference< XModifyListener >& _xListener ) throw (RuntimeException, std::exception)
1322 : {
1323 5 : DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
1324 5 : m_aModifyListeners.removeInterface(_xListener);
1325 5 : }
1326 :
1327 : // XModifiable
1328 11 : sal_Bool SAL_CALL ODatabaseDocument::isModified( ) throw (RuntimeException, std::exception)
1329 : {
1330 11 : DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
1331 :
1332 11 : return m_pImpl->m_bModified;
1333 : }
1334 :
1335 1307 : void SAL_CALL ODatabaseDocument::setModified( sal_Bool _bModified ) throw (PropertyVetoException, RuntimeException, std::exception)
1336 : {
1337 1307 : DocumentGuard aGuard( *this, DocumentGuard::MethodWithoutInit );
1338 1307 : if ( impl_isInitialized() )
1339 63 : impl_setModified_nothrow( _bModified, aGuard );
1340 : // it's allowed to call setModified without the document being initialized already. In this case,
1341 : // we simply ignore the call - when the initialization is finished, the respective code will set
1342 : // a proper "modified" flag
1343 1307 : }
1344 :
1345 175 : void ODatabaseDocument::impl_setModified_nothrow( bool _bModified, DocumentGuard& _rGuard )
1346 : {
1347 : // SYNCHRONIZED ->
1348 175 : bool bModifiedChanged = ( m_pImpl->m_bModified != _bModified ) && ( !m_pImpl->isModifyLocked() );
1349 :
1350 175 : if ( bModifiedChanged )
1351 : {
1352 103 : m_pImpl->m_bModified = _bModified;
1353 103 : m_aEventNotifier.notifyDocumentEventAsync( "OnModifyChanged" );
1354 : }
1355 175 : _rGuard.clear();
1356 : // <- SYNCHRONIZED
1357 :
1358 175 : if ( bModifiedChanged )
1359 : {
1360 103 : lang::EventObject aEvent( *this );
1361 103 : m_aModifyListeners.notifyEach( &XModifyListener::modified, aEvent );
1362 : }
1363 175 : }
1364 :
1365 : // ::com::sun::star::document::XEventBroadcaster
1366 0 : void SAL_CALL ODatabaseDocument::addEventListener(const uno::Reference< document::XEventListener >& _Listener ) throw (uno::RuntimeException, std::exception)
1367 : {
1368 0 : m_aEventNotifier.addLegacyEventListener( _Listener );
1369 0 : }
1370 :
1371 0 : void SAL_CALL ODatabaseDocument::removeEventListener( const uno::Reference< document::XEventListener >& _Listener ) throw (uno::RuntimeException, std::exception)
1372 : {
1373 0 : m_aEventNotifier.removeLegacyEventListener( _Listener );
1374 0 : }
1375 :
1376 231 : void SAL_CALL ODatabaseDocument::addDocumentEventListener( const Reference< XDocumentEventListener >& _Listener ) throw (RuntimeException, std::exception)
1377 : {
1378 231 : m_aEventNotifier.addDocumentEventListener( _Listener );
1379 231 : }
1380 :
1381 0 : void SAL_CALL ODatabaseDocument::removeDocumentEventListener( const Reference< XDocumentEventListener >& _Listener ) throw (RuntimeException, std::exception)
1382 : {
1383 0 : m_aEventNotifier.removeDocumentEventListener( _Listener );
1384 0 : }
1385 :
1386 6 : void SAL_CALL ODatabaseDocument::notifyDocumentEvent( const OUString& _EventName, const Reference< XController2 >& _ViewController, const Any& _Supplement ) throw (IllegalArgumentException, NoSupportException, RuntimeException, std::exception)
1387 : {
1388 6 : if ( _EventName.isEmpty() )
1389 0 : throw IllegalArgumentException( OUString(), *this, 1 );
1390 :
1391 : // SYNCHRONIZED ->
1392 6 : DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
1393 :
1394 6 : if ( !DocumentEvents::needsSynchronousNotification( _EventName ) )
1395 : {
1396 6 : m_aEventNotifier.notifyDocumentEventAsync( _EventName, _ViewController, _Supplement );
1397 12 : return;
1398 : }
1399 0 : aGuard.clear();
1400 : // <- SYNCHRONIZED
1401 :
1402 0 : m_aEventNotifier.notifyDocumentEvent( _EventName, _ViewController, _Supplement );
1403 : }
1404 :
1405 0 : Sequence< PropertyValue > SAL_CALL ODatabaseDocument::getPrinter( ) throw (RuntimeException, std::exception)
1406 : {
1407 : OSL_FAIL( "ODatabaseDocument::getPrinter: not supported!" );
1408 0 : return Sequence< PropertyValue >();
1409 : }
1410 :
1411 0 : void SAL_CALL ODatabaseDocument::setPrinter( const Sequence< PropertyValue >& /*aPrinter*/ ) throw (IllegalArgumentException, RuntimeException, std::exception)
1412 : {
1413 : OSL_FAIL( "ODatabaseDocument::setPrinter: not supported!" );
1414 0 : }
1415 :
1416 0 : void SAL_CALL ODatabaseDocument::print( const Sequence< PropertyValue >& /*xOptions*/ ) throw (IllegalArgumentException, RuntimeException, std::exception)
1417 : {
1418 : OSL_FAIL( "ODatabaseDocument::print: not supported!" );
1419 0 : }
1420 :
1421 632 : void ODatabaseDocument::impl_reparent_nothrow( const WeakReference< XNameAccess >& _rxContainer )
1422 : {
1423 632 : Reference< XChild > xChild( _rxContainer.get(), UNO_QUERY );
1424 632 : if ( xChild.is() )
1425 196 : xChild->setParent( *this );
1426 632 : }
1427 :
1428 974 : void ODatabaseDocument::clearObjectContainer( WeakReference< XNameAccess >& _rxContainer)
1429 : {
1430 974 : Reference< XNameAccess > xContainer = _rxContainer;
1431 974 : ::comphelper::disposeComponent( xContainer );
1432 :
1433 1948 : Reference< XChild > xChild( _rxContainer.get(),UNO_QUERY );
1434 974 : if ( xChild.is() )
1435 20 : xChild->setParent( NULL );
1436 1948 : _rxContainer.clear();
1437 974 : }
1438 :
1439 199 : Reference< XNameAccess > ODatabaseDocument::impl_getDocumentContainer_throw( ODatabaseModelImpl::ObjectType _eType )
1440 : {
1441 199 : if ( ( _eType != ODatabaseModelImpl::E_FORM ) && ( _eType != ODatabaseModelImpl::E_REPORT ) )
1442 0 : throw IllegalArgumentException();
1443 :
1444 199 : bool bFormsContainer = _eType == ODatabaseModelImpl::E_FORM;
1445 :
1446 199 : WeakReference< XNameAccess >& rContainerRef( bFormsContainer ? m_xForms : m_xReports );
1447 199 : Reference< XNameAccess > xContainer = rContainerRef;
1448 199 : if ( !xContainer.is() )
1449 : {
1450 196 : Any aValue;
1451 392 : ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > xMy(*this);
1452 196 : if ( dbtools::getDataSourceSetting(xMy,bFormsContainer ? "Forms" : "Reports",aValue) )
1453 : {
1454 196 : OUString sSupportService;
1455 196 : aValue >>= sSupportService;
1456 196 : if ( !sSupportService.isEmpty() )
1457 : {
1458 0 : Sequence<Any> aArgs(1);
1459 0 : aArgs[0] <<= NamedValue("DatabaseDocument",makeAny(xMy));
1460 : xContainer.set(
1461 0 : m_pImpl->m_aContext->getServiceManager()->createInstanceWithArgumentsAndContext(sSupportService, aArgs, m_pImpl->m_aContext),
1462 0 : UNO_QUERY);
1463 0 : rContainerRef = xContainer;
1464 196 : }
1465 : }
1466 196 : if ( !xContainer.is() )
1467 : {
1468 196 : TContentPtr& rContainerData( m_pImpl->getObjectContainer( _eType ) );
1469 196 : rContainerRef = xContainer = new ODocumentContainer( m_pImpl->m_aContext, *this, rContainerData, bFormsContainer );
1470 : }
1471 392 : impl_reparent_nothrow( xContainer );
1472 : }
1473 199 : return xContainer;
1474 : }
1475 :
1476 102 : void ODatabaseDocument::impl_closeControllerFrames_nolck_throw( bool _bDeliverOwnership )
1477 : {
1478 102 : Controllers aCopy = m_aControllers;
1479 :
1480 102 : Controllers::iterator aEnd = aCopy.end();
1481 107 : for ( Controllers::iterator aIter = aCopy.begin(); aIter != aEnd ; ++aIter )
1482 : {
1483 5 : if ( !aIter->is() )
1484 0 : continue;
1485 :
1486 : try
1487 : {
1488 5 : Reference< XCloseable> xFrame( (*aIter)->getFrame(), UNO_QUERY );
1489 5 : if ( xFrame.is() )
1490 5 : xFrame->close( _bDeliverOwnership );
1491 : }
1492 0 : catch( const CloseVetoException& ) { throw; }
1493 0 : catch( const Exception& )
1494 : {
1495 : DBG_UNHANDLED_EXCEPTION();
1496 : }
1497 102 : }
1498 102 : }
1499 :
1500 : struct DisposeControllerFrame : public ::std::unary_function< Reference< XController >, void >
1501 : {
1502 2 : void operator()( const Reference< XController >& _rxController ) const
1503 : {
1504 : try
1505 : {
1506 2 : if ( !_rxController.is() )
1507 2 : return;
1508 :
1509 2 : Reference< XFrame > xFrame( _rxController->getFrame() );
1510 4 : ::comphelper::disposeComponent( xFrame );
1511 : }
1512 2 : catch( const Exception& )
1513 : {
1514 : DBG_UNHANDLED_EXCEPTION();
1515 : }
1516 : };
1517 : };
1518 :
1519 108 : void ODatabaseDocument::impl_disposeControllerFrames_nothrow()
1520 : {
1521 108 : Controllers aCopy;
1522 108 : aCopy.swap( m_aControllers ); // ensure m_aControllers is empty afterwards
1523 108 : ::std::for_each( aCopy.begin(), aCopy.end(), DisposeControllerFrame() );
1524 108 : }
1525 :
1526 102 : void SAL_CALL ODatabaseDocument::close( sal_Bool _bDeliverOwnership ) throw (CloseVetoException, RuntimeException, std::exception)
1527 : {
1528 : // nearly everything below can/must be done without our mutex locked, the below is just for
1529 : // the checks for being disposed and the like
1530 : // SYNCHRONIZED ->
1531 : {
1532 102 : DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
1533 : assert (!m_bClosing);
1534 102 : m_bClosing = true;
1535 : }
1536 : // <- SYNCHRONIZED
1537 :
1538 : try
1539 : {
1540 : // allow listeners to veto
1541 102 : lang::EventObject aEvent( *this );
1542 : m_aCloseListener.forEach< XCloseListener >(
1543 102 : boost::bind( &XCloseListener::queryClosing, _1, boost::cref( aEvent ), boost::cref( _bDeliverOwnership ) ) );
1544 :
1545 : // notify that we're going to unload
1546 102 : m_aEventNotifier.notifyDocumentEvent( "OnPrepareUnload" );
1547 :
1548 102 : impl_closeControllerFrames_nolck_throw( _bDeliverOwnership );
1549 :
1550 102 : m_aCloseListener.notifyEach( &XCloseListener::notifyClosing, (const lang::EventObject&)aEvent );
1551 :
1552 102 : dispose();
1553 : }
1554 0 : catch ( const Exception& )
1555 : {
1556 0 : ::osl::MutexGuard aGuard( m_aMutex );
1557 0 : m_bClosing = false;
1558 0 : throw;
1559 : }
1560 :
1561 : // SYNCHRONIZED ->
1562 102 : ::osl::MutexGuard aGuard( m_aMutex );
1563 102 : m_bClosing = false;
1564 : // <- SYNCHRONIZED
1565 102 : }
1566 :
1567 21 : void SAL_CALL ODatabaseDocument::addCloseListener( const Reference< ::com::sun::star::util::XCloseListener >& Listener ) throw (RuntimeException, std::exception)
1568 : {
1569 21 : DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
1570 21 : m_aCloseListener.addInterface(Listener);
1571 21 : }
1572 :
1573 16 : void SAL_CALL ODatabaseDocument::removeCloseListener( const Reference< ::com::sun::star::util::XCloseListener >& Listener ) throw (RuntimeException, std::exception)
1574 : {
1575 16 : DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
1576 16 : m_aCloseListener.removeInterface(Listener);
1577 16 : }
1578 :
1579 99 : Reference< XNameAccess > SAL_CALL ODatabaseDocument::getFormDocuments( ) throw (RuntimeException, std::exception)
1580 : {
1581 99 : DocumentGuard aGuard( *this, DocumentGuard::MethodUsedDuringInit );
1582 99 : return impl_getDocumentContainer_throw( ODatabaseModelImpl::E_FORM );
1583 : }
1584 :
1585 100 : Reference< XNameAccess > SAL_CALL ODatabaseDocument::getReportDocuments( ) throw (RuntimeException, std::exception)
1586 : {
1587 100 : DocumentGuard aGuard( *this, DocumentGuard::MethodUsedDuringInit );
1588 100 : return impl_getDocumentContainer_throw( ODatabaseModelImpl::E_REPORT );
1589 : }
1590 :
1591 192 : void ODatabaseDocument::WriteThroughComponent( const Reference< XComponent >& xComponent, const sal_Char* pStreamName,
1592 : const sal_Char* pServiceName, const Sequence< Any >& _rArguments, const Sequence< PropertyValue >& rMediaDesc,
1593 : const Reference<XStorage>& _xStorageToSaveTo ) const
1594 : {
1595 : OSL_ENSURE( pStreamName, "Need stream name!" );
1596 : OSL_ENSURE( pServiceName, "Need service name!" );
1597 :
1598 : // open stream
1599 192 : OUString sStreamName = OUString::createFromAscii( pStreamName );
1600 384 : Reference< XStream > xStream = _xStorageToSaveTo->openStreamElement( sStreamName, ElementModes::READWRITE | ElementModes::TRUNCATE );
1601 192 : if ( !xStream.is() )
1602 0 : return;
1603 :
1604 384 : Reference< XOutputStream > xOutputStream( xStream->getOutputStream() );
1605 : OSL_ENSURE( xOutputStream.is(), "Can't create output stream in package!" );
1606 192 : if ( !xOutputStream.is() )
1607 0 : return;
1608 :
1609 384 : Reference< XSeekable > xSeek( xOutputStream, UNO_QUERY );
1610 192 : if ( xSeek.is() )
1611 192 : xSeek->seek(0);
1612 :
1613 384 : Reference< XPropertySet > xStreamProp( xOutputStream, UNO_QUERY_THROW );
1614 192 : xStreamProp->setPropertyValue( INFO_MEDIATYPE, makeAny( OUString( "text/xml" ) ) );
1615 192 : xStreamProp->setPropertyValue( "Compressed", makeAny( true ) );
1616 :
1617 : // write the stuff
1618 384 : WriteThroughComponent( xOutputStream, xComponent, pServiceName, _rArguments, rMediaDesc );
1619 : }
1620 :
1621 192 : void ODatabaseDocument::WriteThroughComponent( const Reference< XOutputStream >& xOutputStream,
1622 : const Reference< XComponent >& xComponent, const sal_Char* pServiceName, const Sequence< Any >& _rArguments,
1623 : const Sequence< PropertyValue >& rMediaDesc ) const
1624 : {
1625 : OSL_ENSURE( xOutputStream.is(), "I really need an output stream!" );
1626 : OSL_ENSURE( xComponent.is(), "Need component!" );
1627 : OSL_ENSURE( NULL != pServiceName, "Need component name!" );
1628 :
1629 : // get component
1630 192 : Reference< XWriter > xSaxWriter = xml::sax::Writer::create( m_pImpl->m_aContext );
1631 :
1632 : // connect XML writer to output stream
1633 192 : xSaxWriter->setOutputStream( xOutputStream );
1634 :
1635 : // prepare arguments (prepend doc handler to given arguments)
1636 384 : Reference< XDocumentHandler > xDocHandler( xSaxWriter,UNO_QUERY);
1637 384 : Sequence<Any> aArgs( 1 + _rArguments.getLength() );
1638 192 : aArgs[0] <<= xDocHandler;
1639 390 : for ( sal_Int32 i = 0; i < _rArguments.getLength(); ++i )
1640 198 : aArgs[ i+1 ] = _rArguments[i];
1641 :
1642 : // get filter component
1643 384 : Reference< XExporter > xExporter( m_pImpl->m_aContext->getServiceManager()->createInstanceWithArgumentsAndContext(OUString::createFromAscii(pServiceName), aArgs, m_pImpl->m_aContext), UNO_QUERY_THROW );
1644 :
1645 : // connect model and filter
1646 192 : xExporter->setSourceDocument( xComponent );
1647 :
1648 : // filter
1649 384 : Reference< XFilter > xFilter( xExporter, UNO_QUERY_THROW );
1650 384 : xFilter->filter( rMediaDesc );
1651 192 : }
1652 :
1653 96 : void ODatabaseDocument::impl_writeStorage_throw( const Reference< XStorage >& _rxTargetStorage, const ::comphelper::NamedValueCollection& _rMediaDescriptor ) const
1654 : {
1655 : // extract status indicator
1656 96 : Sequence< Any > aDelegatorArguments;
1657 96 : lcl_extractStatusIndicator( _rMediaDescriptor, aDelegatorArguments );
1658 :
1659 192 : uno::Reference< beans::XPropertySet > xInfoSet( comphelper::GenericPropertySet_CreateInstance( new comphelper::PropertySetInfo( aExportInfoMap ) ) );
1660 :
1661 192 : SvtSaveOptions aSaveOpt;
1662 96 : xInfoSet->setPropertyValue("UsePrettyPrinting", uno::makeAny(aSaveOpt.IsPrettyPrinting()));
1663 96 : if ( aSaveOpt.IsSaveRelFSys() )
1664 : {
1665 96 : OUString sBaseURI = _rMediaDescriptor.getOrDefault("BaseURI", OUString());
1666 96 : if (sBaseURI.isEmpty())
1667 95 : sBaseURI = _rMediaDescriptor.getOrDefault("URL",OUString());
1668 96 : xInfoSet->setPropertyValue("BaseURI", uno::makeAny(sBaseURI));
1669 : }
1670 :
1671 : // Set TargetStorage, so it doesn't have to be re-constructed based on possibly empty URL.
1672 96 : xInfoSet->setPropertyValue("TargetStorage", uno::makeAny(m_pImpl->getRootStorage()));
1673 :
1674 : // Set StreamRelPath, in case this document is an embedded one.
1675 192 : OUString sStreamRelPath;
1676 192 : OUString sURL = _rMediaDescriptor.getOrDefault("URL", OUString());
1677 96 : if (sURL.startsWithIgnoreAsciiCase("vnd.sun.star.pkg:"))
1678 : {
1679 : // In this case the host contains the real path, and the path is the embedded stream name.
1680 1 : INetURLObject aURL(sURL);
1681 1 : sStreamRelPath = aURL.GetURLPath(INetURLObject::DECODE_WITH_CHARSET);
1682 1 : if (sStreamRelPath.startsWith("/"))
1683 1 : sStreamRelPath = sStreamRelPath.copy(1);
1684 : }
1685 96 : if (!sStreamRelPath.isEmpty())
1686 1 : xInfoSet->setPropertyValue("StreamRelPath", uno::makeAny(sStreamRelPath));
1687 :
1688 96 : sal_Int32 nArgsLen = aDelegatorArguments.getLength();
1689 96 : aDelegatorArguments.realloc(nArgsLen+1);
1690 96 : aDelegatorArguments[nArgsLen++] <<= xInfoSet;
1691 :
1692 192 : Reference< XPropertySet > xProp( _rxTargetStorage, UNO_QUERY_THROW );
1693 96 : xProp->setPropertyValue( INFO_MEDIATYPE, makeAny( OUString(MIMETYPE_OASIS_OPENDOCUMENT_DATABASE_ASCII) ) );
1694 :
1695 192 : OUString aVersion;
1696 : SvtSaveOptions::ODFDefaultVersion const nDefVersion =
1697 96 : aSaveOpt.GetODFDefaultVersion();
1698 : // older versions can not have this property set,
1699 : // it exists only starting from ODF1.2
1700 96 : if (nDefVersion >= SvtSaveOptions::ODFVER_012)
1701 96 : aVersion = ODFVER_012_TEXT;
1702 :
1703 96 : if (!aVersion.isEmpty())
1704 : {
1705 : try
1706 : {
1707 96 : xProp->setPropertyValue("Version" , uno::makeAny(aVersion));
1708 : }
1709 0 : catch (const uno::Exception& e)
1710 : {
1711 : SAL_WARN("dbaccess", "exception setting Version: " << e.Message);
1712 : }
1713 : }
1714 :
1715 192 : Reference< XComponent > xComponent( *const_cast< ODatabaseDocument* >( this ), UNO_QUERY_THROW );
1716 :
1717 192 : Sequence< PropertyValue > aMediaDescriptor;
1718 96 : _rMediaDescriptor >>= aMediaDescriptor;
1719 :
1720 96 : xInfoSet->setPropertyValue("StreamName", uno::makeAny(OUString("settings.xml")));
1721 : WriteThroughComponent( xComponent, "settings.xml", "com.sun.star.comp.sdb.XMLSettingsExporter",
1722 96 : aDelegatorArguments, aMediaDescriptor, _rxTargetStorage );
1723 :
1724 96 : xInfoSet->setPropertyValue("StreamName", uno::makeAny(OUString("content.xml")));
1725 : WriteThroughComponent( xComponent, "content.xml", "com.sun.star.comp.sdb.DBExportFilter",
1726 96 : aDelegatorArguments, aMediaDescriptor, _rxTargetStorage );
1727 :
1728 96 : if ( _rxTargetStorage->hasByName ( sPictures ) )
1729 : {
1730 : try
1731 : {
1732 : // Delete any previously existing Pictures folder and regenerate
1733 : // any needed content if needed
1734 0 : Reference< XStorageBasedLibraryContainer > xDlgs = m_pImpl->getLibraryContainer( false );
1735 0 : if ( xDlgs.is() )
1736 : {
1737 0 : Reference< XModel > xModel(const_cast< ODatabaseDocument*>(this));
1738 0 : lcl_uglyHackToStoreDialogeEmbedImages( m_pImpl->getLibraryContainer(false), _rxTargetStorage, xModel, m_pImpl->m_aContext );
1739 0 : }
1740 : }
1741 0 : catch ( const Exception& )
1742 : {
1743 : DBG_UNHANDLED_EXCEPTION();
1744 : }
1745 : }
1746 192 : m_pImpl->storeLibraryContainersTo( _rxTargetStorage );
1747 96 : }
1748 :
1749 85 : Reference< XUIConfigurationManager > SAL_CALL ODatabaseDocument::getUIConfigurationManager( ) throw (RuntimeException, std::exception)
1750 : {
1751 85 : return Reference< XUIConfigurationManager >( getUIConfigurationManager2(), UNO_QUERY_THROW );
1752 : }
1753 :
1754 85 : Reference< XUIConfigurationManager2 > ODatabaseDocument::getUIConfigurationManager2( ) throw (RuntimeException)
1755 : {
1756 85 : DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
1757 :
1758 85 : if ( !m_xUIConfigurationManager.is() )
1759 : {
1760 7 : m_xUIConfigurationManager = UIConfigurationManager::create( m_pImpl->m_aContext );
1761 :
1762 7 : OUString aUIConfigFolderName( "Configurations2" );
1763 14 : Reference< XStorage > xConfigStorage;
1764 :
1765 : // First try to open with READWRITE and then READ
1766 7 : xConfigStorage = getDocumentSubStorage( aUIConfigFolderName, ElementModes::READWRITE );
1767 7 : if ( xConfigStorage.is() )
1768 : {
1769 7 : OUString aUIConfigMediaType( "application/vnd.sun.xml.ui.configuration" );
1770 14 : OUString aMediaType;
1771 14 : Reference< XPropertySet > xPropSet( xConfigStorage, UNO_QUERY );
1772 14 : Any a = xPropSet->getPropertyValue( INFO_MEDIATYPE );
1773 7 : if ( !( a >>= aMediaType ) || aMediaType.isEmpty() )
1774 : {
1775 1 : a <<= aUIConfigMediaType;
1776 1 : xPropSet->setPropertyValue( INFO_MEDIATYPE, a );
1777 7 : }
1778 : }
1779 : else
1780 0 : xConfigStorage = getDocumentSubStorage( aUIConfigFolderName, ElementModes::READ );
1781 :
1782 : // initialize ui configuration manager with document substorage
1783 14 : m_xUIConfigurationManager->setStorage( xConfigStorage );
1784 : }
1785 :
1786 85 : return m_xUIConfigurationManager;
1787 : }
1788 :
1789 7 : Reference< XStorage > SAL_CALL ODatabaseDocument::getDocumentSubStorage( const OUString& aStorageName, sal_Int32 nMode ) throw (RuntimeException, std::exception)
1790 : {
1791 7 : DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
1792 :
1793 14 : Reference< XDocumentSubStorageSupplier > xStorageAccess( m_pImpl->getDocumentSubStorageSupplier() );
1794 14 : return xStorageAccess->getDocumentSubStorage( aStorageName, nMode );
1795 : }
1796 :
1797 0 : Sequence< OUString > SAL_CALL ODatabaseDocument::getDocumentSubStoragesNames( ) throw (::com::sun::star::io::IOException, RuntimeException, std::exception)
1798 : {
1799 0 : Reference< XDocumentSubStorageSupplier > xStorageAccess( m_pImpl->getDocumentSubStorageSupplier() );
1800 0 : return xStorageAccess->getDocumentSubStoragesNames();
1801 : }
1802 :
1803 92 : void ODatabaseDocument::impl_notifyStorageChange_nolck_nothrow( const Reference< XStorage >& _rxNewRootStorage )
1804 : {
1805 92 : Reference< XInterface > xMe( *this );
1806 :
1807 : m_aStorageListeners.forEach< XStorageChangeListener >(
1808 92 : boost::bind( &XStorageChangeListener::notifyStorageChange, _1, boost::cref( xMe ), boost::cref( _rxNewRootStorage ) ) );
1809 92 : }
1810 :
1811 108 : void ODatabaseDocument::disposing()
1812 : {
1813 : OSL_TRACE( "DD: disp: %p: %p", this, m_pImpl.get() );
1814 108 : if ( !m_pImpl.is() )
1815 : {
1816 : // this means that we're already disposed
1817 : OSL_ENSURE( ODatabaseDocument_OfficeDocument::rBHelper.bDisposed, "ODatabaseDocument::disposing: no impl anymore, but not yet disposed!" );
1818 108 : return;
1819 : }
1820 :
1821 108 : if ( impl_isInitialized() )
1822 107 : m_aEventNotifier.notifyDocumentEvent( "OnUnload" );
1823 :
1824 108 : Reference< XModel > xHoldAlive( this );
1825 :
1826 108 : m_aEventNotifier.disposing();
1827 :
1828 216 : lang::EventObject aDisposeEvent(static_cast<XWeak*>(this));
1829 108 : m_aModifyListeners.disposeAndClear( aDisposeEvent );
1830 108 : m_aCloseListener.disposeAndClear( aDisposeEvent );
1831 108 : m_aStorageListeners.disposeAndClear( aDisposeEvent );
1832 :
1833 : // this is the list of objects which we currently hold as member. Upon resetting
1834 : // those members, we can (potentially) release the last reference to them, in which
1835 : // case they will be deleted - if they're C++ implementations, that is :).
1836 : // Some of those implementations are offending enough to require the SolarMutex, which
1837 : // means we should not release the last reference while our own mutex is locked ...
1838 216 : ::std::list< Reference< XInterface > > aKeepAlive;
1839 :
1840 : // SYNCHRONIZED ->
1841 216 : ::osl::ClearableMutexGuard aGuard( m_aMutex );
1842 :
1843 : OSL_ENSURE( m_aControllers.empty(), "ODatabaseDocument::disposing: there still are controllers!" );
1844 : // normally, nobody should explicitly dispose, but only XCloseable::close
1845 : // the document. And upon closing, our controllers are closed, too
1846 :
1847 : {
1848 108 : uno::Reference<uno::XInterface> xUIInterface( m_xUIConfigurationManager );
1849 108 : aKeepAlive.push_back( xUIInterface );
1850 : }
1851 108 : m_xUIConfigurationManager = NULL;
1852 :
1853 108 : clearObjectContainer( m_xForms );
1854 108 : clearObjectContainer( m_xReports );
1855 :
1856 : // reset the macro mode: in case the our impl struct stays alive (e.g. because our DataSource
1857 : // object still exists), and somebody subsequently re-opens the document, we want to have
1858 : // the security warning, again.
1859 108 : m_pImpl->resetMacroExecutionMode();
1860 :
1861 : // similar arguing for our ViewMonitor
1862 108 : m_aViewMonitor.reset();
1863 :
1864 : // tell our Impl to forget us
1865 108 : m_pImpl->modelIsDisposing( impl_isInitialized(), ODatabaseModelImpl::ResetModelAccess() );
1866 :
1867 : // now, at the latest, the controller array should be empty. Controllers are
1868 : // expected to listen for our disposal, and disconnect then
1869 : OSL_ENSURE( m_aControllers.empty(), "ODatabaseDocument::disposing: there still are controllers!" );
1870 108 : impl_disposeControllerFrames_nothrow();
1871 :
1872 : {
1873 108 : uno::Reference<uno::XInterface> xModuleInterface( m_xModuleManager );
1874 108 : aKeepAlive.push_back( xModuleInterface );
1875 : }
1876 108 : m_xModuleManager.clear();
1877 :
1878 : {
1879 108 : uno::Reference<uno::XInterface> xTitleInterface( m_xTitleHelper );
1880 108 : aKeepAlive.push_back( xTitleInterface );
1881 : }
1882 108 : m_xTitleHelper.clear();
1883 :
1884 108 : m_pImpl.clear();
1885 :
1886 108 : aGuard.clear();
1887 : // <- SYNCHRONIZED
1888 :
1889 216 : aKeepAlive.clear();
1890 : }
1891 :
1892 : // XComponent
1893 108 : void SAL_CALL ODatabaseDocument::dispose( ) throw (RuntimeException, std::exception)
1894 : {
1895 108 : ::cppu::WeakComponentImplHelperBase::dispose();
1896 108 : }
1897 :
1898 217 : void SAL_CALL ODatabaseDocument::addEventListener( const Reference< lang::XEventListener >& _xListener ) throw (RuntimeException, std::exception)
1899 : {
1900 217 : ::cppu::WeakComponentImplHelperBase::addEventListener( _xListener );
1901 217 : }
1902 :
1903 208 : void SAL_CALL ODatabaseDocument::removeEventListener( const Reference< lang::XEventListener >& _xListener ) throw (RuntimeException, std::exception)
1904 : {
1905 208 : ::cppu::WeakComponentImplHelperBase::removeEventListener( _xListener );
1906 208 : }
1907 :
1908 : // XServiceInfo
1909 1 : OUString ODatabaseDocument::getImplementationName( ) throw(RuntimeException, std::exception)
1910 : {
1911 1 : return getImplementationName_static();
1912 : }
1913 :
1914 21 : OUString ODatabaseDocument::getImplementationName_static( ) throw(RuntimeException)
1915 : {
1916 21 : return OUString("com.sun.star.comp.dba.ODatabaseDocument");
1917 : }
1918 :
1919 15665 : Sequence< OUString > ODatabaseDocument::getSupportedServiceNames( ) throw (RuntimeException, std::exception)
1920 : {
1921 15665 : return getSupportedServiceNames_static();
1922 : }
1923 :
1924 8 : Reference< XInterface > ODatabaseDocument::Create( const Reference< XComponentContext >& _rxContext )
1925 : {
1926 8 : Reference< XUnoTunnel > xDBContextTunnel( DatabaseContext::create(_rxContext), UNO_QUERY_THROW );
1927 8 : ODatabaseContext* pContext = reinterpret_cast< ODatabaseContext* >( xDBContextTunnel->getSomething( ODatabaseContext::getUnoTunnelImplementationId() ) );
1928 :
1929 16 : ::rtl::Reference<ODatabaseModelImpl> pImpl( new ODatabaseModelImpl( _rxContext, *pContext ) );
1930 16 : Reference< XModel > xModel( pImpl->createNewModel_deliverOwnership( false ) );
1931 16 : return xModel.get();
1932 : }
1933 :
1934 15685 : Sequence< OUString > ODatabaseDocument::getSupportedServiceNames_static( ) throw (RuntimeException)
1935 : {
1936 15685 : Sequence< OUString > aSNS( 2 );
1937 15685 : aSNS[0] = "com.sun.star.sdb.OfficeDatabaseDocument";
1938 15685 : aSNS[1] = "com.sun.star.document.OfficeDocument";
1939 15685 : return aSNS;
1940 : }
1941 :
1942 15465 : sal_Bool ODatabaseDocument::supportsService( const OUString& _rServiceName ) throw (RuntimeException, std::exception)
1943 : {
1944 15465 : return cppu::supportsService(this, _rServiceName);
1945 : }
1946 :
1947 433 : Reference< XDataSource > SAL_CALL ODatabaseDocument::getDataSource() throw (RuntimeException, std::exception)
1948 : {
1949 433 : DocumentGuard aGuard( *this, DocumentGuard::MethodWithoutInit );
1950 433 : return m_pImpl->getOrCreateDataSource();
1951 : }
1952 :
1953 : namespace
1954 : {
1955 : /// Property map for embedded import info set.
1956 90 : comphelper::PropertyMapEntry const aEmbeddedImportInfoMap[] =
1957 : {
1958 45 : {OUString("StreamRelPath"), 0, cppu::UnoType<OUString>::get(), beans::PropertyAttribute::MAYBEVOID, 0},
1959 45 : {OUString("StreamName"), 0, cppu::UnoType<OUString>::get(), beans::PropertyAttribute::MAYBEVOID, 0},
1960 45 : {OUString("SourceStorage"), 0, cppu::UnoType<embed::XStorage>::get(), beans::PropertyAttribute::MAYBEVOID, 0},
1961 : {OUString(), 0, css::uno::Type(), 0, 0}
1962 180 : };
1963 : }
1964 :
1965 0 : void SAL_CALL ODatabaseDocument::loadFromStorage(const Reference<XStorage>& xStorage, const Sequence<PropertyValue>& rMediaDescriptor) throw (IllegalArgumentException, DoubleInitializationException, IOException, Exception, RuntimeException, std::exception)
1966 : {
1967 0 : DocumentGuard aGuard(*this, DocumentGuard::InitMethod);
1968 :
1969 0 : uno::Reference<beans::XPropertySet> xInfoSet(comphelper::GenericPropertySet_CreateInstance(new comphelper::PropertySetInfo(aEmbeddedImportInfoMap)));
1970 0 : comphelper::NamedValueCollection aDescriptor(rMediaDescriptor);
1971 0 : xInfoSet->setPropertyValue("StreamRelPath", uno::makeAny(aDescriptor.getOrDefault("HierarchicalDocumentName", OUString())));
1972 0 : xInfoSet->setPropertyValue("StreamName", uno::makeAny(OUString("content.xml")));
1973 0 : xInfoSet->setPropertyValue("SourceStorage", uno::makeAny(xStorage));
1974 :
1975 0 : uno::Sequence<uno::Any> aFilterCreationArgs(1);
1976 0 : aFilterCreationArgs[0] <<= xInfoSet;
1977 :
1978 0 : uno::Reference<document::XImporter> xImporter(m_pImpl->m_aContext->getServiceManager()->createInstanceWithArgumentsAndContext("com.sun.star.comp.sdb.DBFilter", aFilterCreationArgs, m_pImpl->m_aContext), uno::UNO_QUERY_THROW);
1979 :
1980 0 : uno::Reference<lang::XComponent> xComponent(*this, uno::UNO_QUERY_THROW);
1981 0 : xImporter->setTargetDocument(xComponent);
1982 :
1983 0 : uno::Reference<document::XFilter> xFilter(xImporter, uno::UNO_QUERY_THROW);
1984 0 : uno::Sequence<beans::PropertyValue> aFilterArgs;
1985 0 : xFilter->filter(aFilterArgs);
1986 :
1987 : // In case of embedding, XModel::attachResource is already called.
1988 0 : if (m_bEmbedded)
1989 0 : impl_setInitialized();
1990 :
1991 0 : impl_setModified_nothrow(false, aGuard);
1992 0 : }
1993 :
1994 0 : void SAL_CALL ODatabaseDocument::storeToStorage( const Reference< XStorage >& _rxStorage, const Sequence< PropertyValue >& _rMediaDescriptor ) throw (IllegalArgumentException, IOException, Exception, RuntimeException, std::exception)
1995 : {
1996 0 : DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
1997 0 : impl_storeToStorage_throw( _rxStorage, _rMediaDescriptor, aGuard );
1998 0 : }
1999 :
2000 0 : void SAL_CALL ODatabaseDocument::switchToStorage( const Reference< XStorage >& _rxNewRootStorage ) throw (IllegalArgumentException, IOException, Exception, RuntimeException, std::exception)
2001 : {
2002 0 : DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
2003 :
2004 0 : Reference< XStorage > xNewRootStorage( m_pImpl->switchToStorage( _rxNewRootStorage ) );
2005 :
2006 0 : aGuard.clear();
2007 0 : impl_notifyStorageChange_nolck_nothrow( xNewRootStorage );
2008 0 : }
2009 :
2010 109 : Reference< XStorage > SAL_CALL ODatabaseDocument::getDocumentStorage( ) throw (IOException, Exception, RuntimeException, std::exception)
2011 : {
2012 109 : DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
2013 29 : return m_pImpl->getOrCreateRootStorage();
2014 : }
2015 :
2016 0 : void SAL_CALL ODatabaseDocument::addStorageChangeListener( const Reference< XStorageChangeListener >& _Listener ) throw (RuntimeException, std::exception)
2017 : {
2018 0 : DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
2019 0 : m_aStorageListeners.addInterface( _Listener );
2020 0 : }
2021 :
2022 0 : void SAL_CALL ODatabaseDocument::removeStorageChangeListener( const Reference< XStorageChangeListener >& _Listener ) throw (RuntimeException, std::exception)
2023 : {
2024 0 : DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
2025 0 : m_aStorageListeners.addInterface( _Listener );
2026 0 : }
2027 :
2028 6 : Reference< XStorageBasedLibraryContainer > SAL_CALL ODatabaseDocument::getBasicLibraries() throw (RuntimeException, std::exception)
2029 : {
2030 6 : DocumentGuard aGuard( *this, DocumentGuard::MethodUsedDuringInit );
2031 6 : return m_pImpl->getLibraryContainer( true );
2032 : }
2033 :
2034 3 : Reference< XStorageBasedLibraryContainer > SAL_CALL ODatabaseDocument::getDialogLibraries() throw (RuntimeException, std::exception)
2035 : {
2036 3 : DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
2037 3 : return m_pImpl->getLibraryContainer( false );
2038 : }
2039 :
2040 0 : sal_Bool SAL_CALL ODatabaseDocument::getAllowMacroExecution() throw (RuntimeException, std::exception)
2041 : {
2042 0 : DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
2043 0 : return m_pImpl->adjustMacroMode_AutoReject();
2044 : }
2045 :
2046 0 : Reference< XEmbeddedScripts > SAL_CALL ODatabaseDocument::getScriptContainer() throw (RuntimeException, std::exception)
2047 : {
2048 0 : DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
2049 0 : return this;
2050 : }
2051 :
2052 0 : Reference< provider::XScriptProvider > SAL_CALL ODatabaseDocument::getScriptProvider( ) throw (RuntimeException, std::exception)
2053 : {
2054 0 : DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
2055 :
2056 0 : Reference< XScriptProvider > xScriptProvider( m_xScriptProvider );
2057 0 : if ( !xScriptProvider.is() )
2058 : {
2059 : Reference < XScriptProviderFactory > xFactory =
2060 0 : theMasterScriptProviderFactory::get( m_pImpl->m_aContext );
2061 :
2062 0 : Any aScriptProviderContext;
2063 0 : if ( m_bAllowDocumentScripting )
2064 0 : aScriptProviderContext <<= Reference< XModel >( this );
2065 :
2066 0 : xScriptProvider.set( xFactory->createScriptProvider( aScriptProviderContext ), UNO_SET_THROW );
2067 0 : m_xScriptProvider = xScriptProvider;
2068 : }
2069 :
2070 0 : return xScriptProvider;
2071 : }
2072 :
2073 646 : Reference< XNameReplace > SAL_CALL ODatabaseDocument::getEvents( ) throw (RuntimeException, std::exception)
2074 : {
2075 646 : DocumentGuard aGuard( *this, DocumentGuard::MethodUsedDuringInit );
2076 645 : return m_pEventContainer;
2077 : }
2078 :
2079 94 : Reference< XInterface > ODatabaseDocument::getThis() const
2080 : {
2081 94 : return *const_cast< ODatabaseDocument* >( this );
2082 : }
2083 :
2084 : struct CreateAny : public ::std::unary_function< Reference<XController>, Any>
2085 : {
2086 7 : Any operator() (const Reference<XController>& lhs) const
2087 : {
2088 7 : return makeAny(lhs);
2089 : }
2090 : };
2091 :
2092 : // XModel2
2093 14 : Reference< XEnumeration > SAL_CALL ODatabaseDocument::getControllers( ) throw (RuntimeException, std::exception)
2094 : {
2095 14 : DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
2096 28 : uno::Sequence< Any> aController( m_aControllers.size() );
2097 14 : ::std::transform( m_aControllers.begin(), m_aControllers.end(), aController.getArray(), CreateAny() );
2098 28 : return new ::comphelper::OAnyEnumeration(aController);
2099 : }
2100 :
2101 0 : Sequence< OUString > SAL_CALL ODatabaseDocument::getAvailableViewControllerNames( ) throw (RuntimeException, std::exception)
2102 : {
2103 0 : Sequence< OUString > aNames(1);
2104 0 : aNames[0] = SERVICE_SDB_APPLICATIONCONTROLLER;
2105 0 : return aNames;
2106 : }
2107 :
2108 0 : Reference< XController2 > SAL_CALL ODatabaseDocument::createDefaultViewController( const Reference< XFrame >& _Frame ) throw (IllegalArgumentException, Exception, RuntimeException, std::exception)
2109 : {
2110 0 : return createViewController( "Default", Sequence< PropertyValue >(), _Frame);
2111 : }
2112 :
2113 7 : Reference< XController2 > SAL_CALL ODatabaseDocument::createViewController( const OUString& _ViewName, const Sequence< PropertyValue >& _Arguments, const Reference< XFrame >& _Frame ) throw (IllegalArgumentException, Exception, RuntimeException, std::exception)
2114 : {
2115 7 : if ( _ViewName != "Default" && _ViewName != "Preview" )
2116 0 : throw IllegalArgumentException( OUString(), *this, 1 );
2117 7 : if ( !_Frame.is() )
2118 0 : throw IllegalArgumentException( OUString(), *this, 3 );
2119 :
2120 7 : DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
2121 7 : aGuard.clear();
2122 :
2123 : Reference< XController2 > xController(
2124 14 : m_pImpl->m_aContext->getServiceManager()->createInstanceWithContext("org.openoffice.comp.dbu.OApplicationController", m_pImpl->m_aContext),
2125 7 : UNO_QUERY_THROW );
2126 :
2127 14 : ::comphelper::NamedValueCollection aInitArgs( _Arguments );
2128 7 : aInitArgs.put( "Frame", _Frame );
2129 7 : if ( _ViewName == "Preview" )
2130 0 : aInitArgs.put( "Preview", true );
2131 14 : Reference< XInitialization > xInitController( xController, UNO_QUERY_THROW );
2132 7 : xInitController->initialize( aInitArgs.getWrappedPropertyValues() );
2133 :
2134 14 : return xController;
2135 : }
2136 :
2137 33 : Reference< XTitle > ODatabaseDocument::impl_getTitleHelper_throw()
2138 : {
2139 33 : if ( ! m_xTitleHelper.is ())
2140 : {
2141 13 : Reference< XUntitledNumbers > xDesktop(Desktop::create(m_pImpl->m_aContext), uno::UNO_QUERY_THROW);
2142 26 : Reference< frame::XModel > xThis (getThis(), uno::UNO_QUERY_THROW);
2143 :
2144 13 : ::framework::TitleHelper* pHelper = new ::framework::TitleHelper(m_pImpl->m_aContext);
2145 13 : m_xTitleHelper.set(static_cast< ::cppu::OWeakObject* >(pHelper), uno::UNO_QUERY_THROW);
2146 13 : pHelper->setOwner (xThis );
2147 26 : pHelper->connectWithUntitledNumbers (xDesktop);
2148 : }
2149 :
2150 33 : return m_xTitleHelper;
2151 : }
2152 :
2153 7 : uno::Reference< frame::XUntitledNumbers > ODatabaseDocument::impl_getUntitledHelper_throw(const uno::Reference< uno::XInterface >& _xComponent)
2154 : {
2155 7 : if ( !m_xModuleManager.is() )
2156 7 : m_xModuleManager.set( ModuleManager::create(m_pImpl->m_aContext) );
2157 :
2158 7 : OUString sModuleId;
2159 : try
2160 : {
2161 7 : sModuleId = m_xModuleManager->identify( _xComponent );
2162 : }
2163 0 : catch(const uno::Exception&)
2164 : {
2165 : }
2166 7 : uno::Reference< frame::XUntitledNumbers > xNumberedControllers;
2167 :
2168 7 : TNumberedController::iterator aFind = m_aNumberedControllers.find(sModuleId);
2169 7 : if ( aFind == m_aNumberedControllers.end() )
2170 : {
2171 7 : uno::Reference< frame::XModel > xThis(static_cast< frame::XModel* >(this), uno::UNO_QUERY_THROW);
2172 7 : ::comphelper::NumberedCollection* pHelper = new ::comphelper::NumberedCollection();
2173 7 : xNumberedControllers.set(static_cast< ::cppu::OWeakObject* >(pHelper), uno::UNO_QUERY_THROW);
2174 :
2175 7 : pHelper->setOwner (xThis);
2176 :
2177 7 : m_aNumberedControllers.insert(TNumberedController::value_type(sModuleId,xNumberedControllers));
2178 : }
2179 : else
2180 0 : xNumberedControllers = aFind->second;
2181 :
2182 7 : return xNumberedControllers;
2183 : }
2184 :
2185 : // css.frame.XTitle
2186 26 : OUString SAL_CALL ODatabaseDocument::getTitle()
2187 : throw (uno::RuntimeException, std::exception)
2188 : {
2189 : // SYNCHRONIZED ->
2190 26 : DocumentGuard aGuard( *this, DocumentGuard::MethodUsedDuringInit );
2191 26 : return impl_getTitleHelper_throw()->getTitle();
2192 : }
2193 :
2194 : // css.frame.XTitle
2195 0 : void SAL_CALL ODatabaseDocument::setTitle( const OUString& sTitle )
2196 : throw (uno::RuntimeException, std::exception)
2197 : {
2198 : // SYNCHRONIZED ->
2199 0 : DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
2200 0 : impl_getTitleHelper_throw()->setTitle( sTitle );
2201 0 : m_aEventNotifier.notifyDocumentEventAsync( "OnTitleChanged" );
2202 : // <- SYNCHRONIZED
2203 0 : }
2204 :
2205 : // css.frame.XTitleChangeBroadcaster
2206 7 : void SAL_CALL ODatabaseDocument::addTitleChangeListener( const uno::Reference< frame::XTitleChangeListener >& xListener )
2207 : throw (uno::RuntimeException, std::exception)
2208 : {
2209 : // SYNCHRONIZED ->
2210 7 : DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
2211 :
2212 14 : uno::Reference< frame::XTitleChangeBroadcaster > xBroadcaster( impl_getTitleHelper_throw(), uno::UNO_QUERY_THROW );
2213 14 : xBroadcaster->addTitleChangeListener( xListener );
2214 7 : }
2215 :
2216 : // css.frame.XTitleChangeBroadcaster
2217 0 : void SAL_CALL ODatabaseDocument::removeTitleChangeListener( const uno::Reference< frame::XTitleChangeListener >& xListener )
2218 : throw (uno::RuntimeException, std::exception)
2219 : {
2220 : // SYNCHRONIZED ->
2221 0 : DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
2222 :
2223 0 : uno::Reference< frame::XTitleChangeBroadcaster > xBroadcaster( impl_getTitleHelper_throw(), uno::UNO_QUERY_THROW );
2224 0 : xBroadcaster->removeTitleChangeListener( xListener );
2225 0 : }
2226 :
2227 : // css.frame.XUntitledNumbers
2228 7 : ::sal_Int32 SAL_CALL ODatabaseDocument::leaseNumber( const uno::Reference< uno::XInterface >& xComponent )
2229 : throw (lang::IllegalArgumentException,
2230 : uno::RuntimeException, std::exception )
2231 : {
2232 7 : DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
2233 7 : return impl_getUntitledHelper_throw(xComponent)->leaseNumber (xComponent);
2234 : }
2235 :
2236 : // css.frame.XUntitledNumbers
2237 0 : void SAL_CALL ODatabaseDocument::releaseNumber( ::sal_Int32 nNumber )
2238 : throw (lang::IllegalArgumentException,
2239 : uno::RuntimeException, std::exception )
2240 : {
2241 0 : DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
2242 0 : impl_getUntitledHelper_throw()->releaseNumber (nNumber);
2243 0 : }
2244 :
2245 : // css.frame.XUntitledNumbers
2246 0 : void SAL_CALL ODatabaseDocument::releaseNumberForComponent( const uno::Reference< uno::XInterface >& xComponent )
2247 : throw (lang::IllegalArgumentException,
2248 : uno::RuntimeException, std::exception )
2249 : {
2250 0 : DocumentGuard aGuard(*this, DocumentGuard::DefaultMethod);
2251 0 : impl_getUntitledHelper_throw(xComponent)->releaseNumberForComponent (xComponent);
2252 0 : }
2253 :
2254 : // css.frame.XUntitledNumbers
2255 0 : OUString SAL_CALL ODatabaseDocument::getUntitledPrefix() throw (uno::RuntimeException, std::exception)
2256 : {
2257 0 : return OUString();
2258 : }
2259 :
2260 135 : } // namespace dbaccess
2261 :
2262 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|