summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.co.uk>2015-06-10 19:04:04 +0200
committerMiklos Vajna <vmiklos@collabora.co.uk>2015-06-10 19:04:27 +0200
commitb8b4ac9e6e8f03fb84bddb714d3c5908a45153b1 (patch)
treeda7740d86917d2fe8b1d0119fa0915fbffae2e9a
parentb04e1e79e64cb7bb3106fd08a019c27b09bdd5c6 (diff)
sw: remove embedded data source on location deregistration
Change-Id: I5b2a24fee50a25a41ba26787f7e30409348d7808
-rw-r--r--sw/inc/dbmgr.hxx10
-rw-r--r--sw/source/core/doc/docnew.cxx6
-rw-r--r--sw/source/uibase/app/applab.cxx2
-rw-r--r--sw/source/uibase/dbui/dbmgr.cxx100
4 files changed, 114 insertions, 4 deletions
diff --git a/sw/inc/dbmgr.hxx b/sw/inc/dbmgr.hxx
index 5bf15427e828..0b809f9d928f 100644
--- a/sw/inc/dbmgr.hxx
+++ b/sw/inc/dbmgr.hxx
@@ -184,6 +184,7 @@ struct SwMergeDescriptor
struct SwDBManager_Impl;
class SwConnectionDisposedListener_Impl;
class AbstractMailMergeDlg;
+class SwDoc;
class SW_DLLPUBLIC SwDBManager
{
@@ -205,6 +206,9 @@ friend class SwConnectionDisposedListener_Impl;
/// Name of the embedded database that's included in the current document.
OUString m_sEmbeddedName;
+ /// The document that owns this manager.
+ SwDoc* m_pDoc;
+
SAL_DLLPRIVATE SwDSParam* FindDSData(const SwDBData& rData, bool bCreate);
SAL_DLLPRIVATE SwDSParam* FindDSConnection(const OUString& rSource, bool bCreate);
@@ -222,7 +226,7 @@ friend class SwConnectionDisposedListener_Impl;
SAL_DLLPRIVATE bool ToNextRecord(SwDSParam* pParam);
public:
- SwDBManager();
+ SwDBManager(SwDoc* pDoc);
~SwDBManager();
enum DBConnURITypes {
@@ -421,6 +425,10 @@ public:
const css::uno::Reference<css::embed::XStorage>& xStorage,
const OUString& rStreamRelPath,
const OUString& rOwnURL);
+
+ SwDoc* getDoc() const;
+ /// Stop reacting to removed database registrations.
+ void releaseRevokeListener();
};
#endif
diff --git a/sw/source/core/doc/docnew.cxx b/sw/source/core/doc/docnew.cxx
index ef6b904587db..939f270e88f4 100644
--- a/sw/source/core/doc/docnew.cxx
+++ b/sw/source/core/doc/docnew.cxx
@@ -343,7 +343,7 @@ SwDoc::SwDoc()
#if HAVE_FEATURE_DBCONNECTIVITY
// Create DBManager
- mpDBManager = new SwDBManager;
+ mpDBManager = new SwDBManager(this);
#endif
// create TOXTypes
@@ -543,7 +543,11 @@ SwDoc::~SwDoc()
// On load, SwDBManager::setEmbeddedName() may register a data source.
// If we have an embedded one, then sDataSoure points to the registered name, so revoke it here.
if (!mpDBManager->getEmbeddedName().isEmpty() && !maDBData.sDataSource.isEmpty())
+ {
+ // Remove the revoke listener here first, so that we don't remove the data source from the document.
+ mpDBManager->releaseRevokeListener();
SwDBManager::RevokeDataSource(maDBData.sDataSource);
+ }
DELETEZ( mpDBManager );
#endif
diff --git a/sw/source/uibase/app/applab.cxx b/sw/source/uibase/app/applab.cxx
index 2521c995a0a2..4858f898f19b 100644
--- a/sw/source/uibase/app/applab.cxx
+++ b/sw/source/uibase/app/applab.cxx
@@ -159,7 +159,7 @@ void SwModule::InsertLab(SfxRequest& rReq, bool bLabel)
#if HAVE_FEATURE_DBCONNECTIVITY
// Create DB-Manager
- boost::scoped_ptr<SwDBManager> pDBManager(new SwDBManager);
+ boost::scoped_ptr<SwDBManager> pDBManager(new SwDBManager(0));
#endif
// Read SwLabItem from Config
diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx
index 6dc0bb4a4cac..48077f6f05be 100644
--- a/sw/source/uibase/dbui/dbmgr.cxx
+++ b/sw/source/uibase/dbui/dbmgr.cxx
@@ -204,11 +204,90 @@ public:
};
+/// Listens to removed data sources, and if it's one that's embedded into this document, triggers embedding removal.
+class SwDataSourceRemovedListener : public cppu::WeakImplHelper<sdb::XDatabaseRegistrationsListener>
+{
+ uno::Reference<sdb::XDatabaseContext> m_xDatabaseContext;
+ SwDBManager* m_pDBManager;
+
+public:
+ SwDataSourceRemovedListener(SwDBManager& rDBManager);
+ virtual ~SwDataSourceRemovedListener();
+ virtual void SAL_CALL registeredDatabaseLocation(const sdb::DatabaseRegistrationEvent& rEvent) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
+ virtual void SAL_CALL revokedDatabaseLocation(const sdb::DatabaseRegistrationEvent& rEvent) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
+ virtual void SAL_CALL changedDatabaseLocation(const sdb::DatabaseRegistrationEvent& rEvent) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
+ virtual void SAL_CALL disposing(const lang::EventObject& rObject) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
+ void Dispose();
+};
+
+SwDataSourceRemovedListener::SwDataSourceRemovedListener(SwDBManager& rDBManager)
+ : m_pDBManager(&rDBManager)
+{
+ uno::Reference<uno::XComponentContext> xComponentContext(comphelper::getProcessComponentContext());
+ m_xDatabaseContext = sdb::DatabaseContext::create(xComponentContext);
+ m_xDatabaseContext->addDatabaseRegistrationsListener(this);
+}
+
+SwDataSourceRemovedListener::~SwDataSourceRemovedListener()
+{
+ if (m_xDatabaseContext.is())
+ m_xDatabaseContext->removeDatabaseRegistrationsListener(this);
+}
+
+void SAL_CALL SwDataSourceRemovedListener::registeredDatabaseLocation(const sdb::DatabaseRegistrationEvent& /*rEvent*/) throw (uno::RuntimeException, std::exception)
+{
+}
+
+void SAL_CALL SwDataSourceRemovedListener::revokedDatabaseLocation(const sdb::DatabaseRegistrationEvent& rEvent) throw (uno::RuntimeException, std::exception)
+{
+ if (!m_pDBManager || m_pDBManager->getEmbeddedName().isEmpty())
+ return;
+
+ SwDoc* pDoc = m_pDBManager->getDoc();
+ if (!pDoc)
+ return;
+
+ SwDocShell* pDocShell = pDoc->GetDocShell();
+ if (!pDocShell)
+ return;
+
+ OUString aOwnURL = pDocShell->GetMedium()->GetURLObject().GetMainURL(INetURLObject::DECODE_WITH_CHARSET);
+ OUString sTmpName = "vnd.sun.star.pkg://";
+ sTmpName += INetURLObject::encode(aOwnURL, INetURLObject::PART_AUTHORITY, INetURLObject::ENCODE_ALL);
+ sTmpName += "/" + m_pDBManager->getEmbeddedName();
+
+ if (sTmpName != rEvent.OldLocation)
+ return;
+
+ // The revoked database location is inside this document, then remove the
+ // embedding, as otherwise it would be back on the next reload of the
+ // document.
+ pDocShell->GetStorage()->removeElement(m_pDBManager->getEmbeddedName());
+ m_pDBManager->setEmbeddedName(OUString(), *pDocShell);
+}
+
+void SAL_CALL SwDataSourceRemovedListener::changedDatabaseLocation(const sdb::DatabaseRegistrationEvent& rEvent) throw (uno::RuntimeException, std::exception)
+{
+ if (rEvent.OldLocation != rEvent.NewLocation)
+ revokedDatabaseLocation(rEvent);
+}
+
+void SwDataSourceRemovedListener::disposing(const lang::EventObject& /*rObject*/) throw (uno::RuntimeException, std::exception)
+{
+ m_xDatabaseContext.clear();
+}
+
+void SwDataSourceRemovedListener::Dispose()
+{
+ m_pDBManager = 0;
+}
+
struct SwDBManager_Impl
{
SwDSParam* pMergeData;
AbstractMailMergeDlg* pMergeDialog;
::rtl::Reference<SwConnectionDisposedListener_Impl> m_xDisposeListener;
+ rtl::Reference<SwDataSourceRemovedListener> m_xDataSourceRemovedListener;
explicit SwDBManager_Impl(SwDBManager& rDBManager)
:pMergeData(0)
@@ -219,6 +298,8 @@ struct SwDBManager_Impl
~SwDBManager_Impl()
{
m_xDisposeListener->Dispose();
+ if (m_xDataSourceRemovedListener.is())
+ m_xDataSourceRemovedListener->Dispose();
}
};
@@ -693,7 +774,7 @@ void SwDBManager::GetColumnNames(ListBox* pListBox,
}
}
-SwDBManager::SwDBManager()
+SwDBManager::SwDBManager(SwDoc* pDoc)
: bCancel(false)
, bInitDBFields(false)
, bSingleJobs(false)
@@ -702,6 +783,7 @@ SwDBManager::SwDBManager()
, bMergeLock(false)
, pImpl(new SwDBManager_Impl(*this))
, pMergeEvtSrc(NULL)
+ , m_pDoc(pDoc)
{
}
@@ -2973,6 +3055,7 @@ uno::Reference<sdbc::XResultSet> SwDBManager::createCursor(const OUString& _sDat
void SwDBManager::setEmbeddedName(const OUString& rEmbeddedName, SwDocShell& rDocShell)
{
bool bLoad = m_sEmbeddedName != rEmbeddedName && !rEmbeddedName.isEmpty();
+ bool bRegisterListener = m_sEmbeddedName.isEmpty() && !rEmbeddedName.isEmpty();
m_sEmbeddedName = rEmbeddedName;
@@ -2984,6 +3067,10 @@ void SwDBManager::setEmbeddedName(const OUString& rEmbeddedName, SwDocShell& rDo
if (xStorage->hasByName(rEmbeddedName))
LoadAndRegisterEmbeddedDataSource(rDocShell.GetDoc()->GetDBData(), rDocShell);
}
+
+ if (bRegisterListener)
+ // Register a remove listener, so we know when the embedded data source is removed.
+ pImpl->m_xDataSourceRemovedListener = new SwDataSourceRemovedListener(*this);
}
OUString SwDBManager::getEmbeddedName() const
@@ -2991,6 +3078,17 @@ OUString SwDBManager::getEmbeddedName() const
return m_sEmbeddedName;
}
+SwDoc* SwDBManager::getDoc() const
+{
+ return m_pDoc;
+}
+
+void SwDBManager::releaseRevokeListener()
+{
+ pImpl->m_xDataSourceRemovedListener->Dispose();
+ pImpl->m_xDataSourceRemovedListener.clear();
+}
+
SwConnectionDisposedListener_Impl::SwConnectionDisposedListener_Impl(SwDBManager& rManager)
: m_pDBManager(&rManager)
{