summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCaolán McNamara <caolanm@redhat.com>2018-01-11 20:43:28 +0000
committerAndras Timar <andras.timar@collabora.com>2018-01-17 11:22:41 +0100
commita09ca6b29b16f29e21ea65658c112eaf1cf7d819 (patch)
tree6d356ec2d303417130a5ee492746c07f860a8ba4
parentef93fb5ae0691cba777c9d2b24a3180e14281cbc (diff)
handle ocWebservice similarly to ocDde
might have too much in here seeing as we don't need to worry about ocWebservice calling into itself Reviewed-on: https://gerrit.libreoffice.org/47819 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Eike Rathke <erack@redhat.com> (cherry picked from commit e1946d75a1095c2596d7815600454ff01fcd3270) Signed-off-by: Andras Timar <andras.timar@collabora.com> (cherry picked from commit 78c1ae24007d8098ee4f4add6d72e84411181785) Change-Id: I0145f38cc1c1f9ff514a496f7101d81cde9e7c67
-rw-r--r--sc/Library_sc.mk1
-rw-r--r--sc/inc/document.hxx2
-rw-r--r--sc/inc/documentlinkmgr.hxx6
-rw-r--r--sc/source/core/data/formulacell.cxx4
-rw-r--r--sc/source/core/inc/webservicelink.hxx49
-rw-r--r--sc/source/core/tool/interpr7.cxx105
-rw-r--r--sc/source/core/tool/webservicelink.cxx106
-rw-r--r--sc/source/ui/docshell/docsh4.cxx2
-rw-r--r--sc/source/ui/docshell/documentlinkmgr.cxx20
-rw-r--r--sc/source/ui/view/tabvwsh4.cxx2
10 files changed, 252 insertions, 45 deletions
diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk
index 329fe87840b8..765aa6364756 100644
--- a/sc/Library_sc.mk
+++ b/sc/Library_sc.mk
@@ -286,6 +286,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\
sc/source/core/tool/unitconv \
sc/source/core/tool/userlist \
sc/source/core/tool/viewopti \
+ sc/source/core/tool/webservicelink \
sc/source/core/tool/zforauto \
sc/source/filter/xml/datastreamimport \
sc/source/filter/xml/XMLCalculationSettingsContext \
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index 9a0b41a58785..671528d8d43c 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -449,7 +449,7 @@ private:
// for detective update, is set for each change of a formula
bool bDetectiveDirty;
- bool bLinkFormulaNeedingCheck; // valid only after loading, for ocDde
+ bool bLinkFormulaNeedingCheck; // valid only after loading, for ocDde and ocWebservice
sal_uInt8 nAsianCompression;
sal_uInt8 nAsianKerning;
diff --git a/sc/inc/documentlinkmgr.hxx b/sc/inc/documentlinkmgr.hxx
index d5d801a4aeb2..86dba66f2d3d 100644
--- a/sc/inc/documentlinkmgr.hxx
+++ b/sc/inc/documentlinkmgr.hxx
@@ -55,9 +55,9 @@ public:
bool idleCheckLinks();
bool hasDdeLinks() const;
- bool hasDdeOrOleLinks() const;
+ bool hasDdeOrOleOrWebServiceLinks() const;
- bool updateDdeOrOleLinks(vcl::Window* pWin);
+ bool updateDdeOrOleOrWebServiceLinks(vcl::Window* pWin);
void updateDdeLink( const OUString& rAppl, const OUString& rTopic, const OUString& rItem );
@@ -65,7 +65,7 @@ public:
void disconnectDdeLinks();
private:
- bool hasDdeOrOleLinks(bool bDde, bool bOle) const;
+ bool hasDdeOrOleOrWebServiceLinks(bool bDde, bool bOle, bool bWebService) const;
};
}
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index 8b3cb09b515d..dbd472272048 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -1379,9 +1379,9 @@ void ScFormulaCell::CompileXML( sc::CompileFormulaContext& rCxt, ScProgress& rPr
bChanged = true;
}
- // After loading, it must be known if ocDde is in any formula
+ // After loading, it must be known if ocDde/ocWebservice is in any formula
// (for external links warning, CompileXML is called at the end of loading XML file)
- if (!pDocument->HasLinkFormulaNeedingCheck() && pCode->HasOpCodeRPN(ocDde))
+ if (!pDocument->HasLinkFormulaNeedingCheck() && (pCode->HasOpCodeRPN(ocDde) || pCode->HasOpCodeRPN(ocWebservice)))
pDocument->SetLinkFormulaNeedingCheck(true);
//volatile cells must be added here for import
diff --git a/sc/source/core/inc/webservicelink.hxx b/sc/source/core/inc/webservicelink.hxx
new file mode 100644
index 000000000000..e61ebfdb4347
--- /dev/null
+++ b/sc/source/core/inc/webservicelink.hxx
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_SC_SOURCE_CORE_INC_WEBSERVICE_HXX
+#define INCLUDED_SC_SOURCE_CORE_INC_WEBSERVICE_HXX
+
+#include <address.hxx>
+#include <sfx2/lnkbase.hxx>
+#include <svl/broadcast.hxx>
+#include <types.hxx>
+
+class ScDocument;
+
+class ScWebServiceLink : public ::sfx2::SvBaseLink, public SvtBroadcaster
+{
+private:
+ ScDocument* pDoc;
+ OUString aURL; // connection/ link data
+ bool bHasResult; // is set aResult is useful
+ OUString aResult;
+
+public:
+ ScWebServiceLink(ScDocument* pD, const OUString& rURL);
+ virtual ~ScWebServiceLink() override;
+
+ // SvBaseLink override:
+ virtual ::sfx2::SvBaseLink::UpdateResult DataChanged(const OUString& rMimeType,
+ const css::uno::Any& rValue) override;
+
+ // SvtBroadcaster override:
+ virtual void ListenersGone() override;
+
+ // for interpreter:
+
+ const OUString& GetResult() const { return aResult; }
+ bool HasResult() const { return bHasResult; }
+
+ const OUString& GetURL() const { return aURL; }
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/sc/source/core/tool/interpr7.cxx b/sc/source/core/tool/interpr7.cxx
index 9112c24e7584..e2f562848a31 100644
--- a/sc/source/core/tool/interpr7.cxx
+++ b/sc/source/core/tool/interpr7.cxx
@@ -13,6 +13,7 @@
#include "scmatrix.hxx"
#include <rtl/strbuf.hxx>
#include <formula/errorcodes.hxx>
+#include <sfx2/bindings.hxx>
#include <svtools/miscopt.hxx>
#include <tools/urlobj.hxx>
@@ -24,6 +25,10 @@
#include <datastreamgettime.hxx>
#include <dpobject.hxx>
#include <document.hxx>
+#include <tokenarray.hxx>
+#include <webservicelink.hxx>
+
+#include <sc.hrc>
#include <cstring>
#include <memory>
@@ -235,6 +240,22 @@ void ScInterpreter::ScFilterXML()
}
}
+static ScWebServiceLink* lcl_GetWebServiceLink(const sfx2::LinkManager* pLinkMgr, const OUString& rURL)
+{
+ size_t nCount = pLinkMgr->GetLinks().size();
+ for (size_t i=0; i<nCount; ++i)
+ {
+ ::sfx2::SvBaseLink* pBase = pLinkMgr->GetLinks()[i].get();
+ if (ScWebServiceLink* pLink = dynamic_cast<ScWebServiceLink*>(pBase))
+ {
+ if (pLink->GetURL() == rURL)
+ return pLink;
+ }
+ }
+
+ return nullptr;
+}
+
void ScInterpreter::ScWebservice()
{
sal_uInt8 nParamCount = GetByte();
@@ -242,7 +263,7 @@ void ScInterpreter::ScWebservice()
{
OUString aURI = GetString().getString();
- if(aURI.isEmpty())
+ if (aURI.isEmpty())
{
PushError( FormulaError::NoValue );
return;
@@ -252,52 +273,72 @@ void ScInterpreter::ScWebservice()
INetProtocol eProtocol = aObj.GetProtocol();
if (eProtocol != INetProtocol::Http && eProtocol != INetProtocol::Https)
{
- PushError( FormulaError::NoValue );
+ PushError(FormulaError::NoValue);
return;
}
- uno::Reference< ucb::XSimpleFileAccess3 > xFileAccess( ucb::SimpleFileAccess::create( comphelper::getProcessComponentContext() ), uno::UNO_QUERY );
- if(!xFileAccess.is())
+ if (!mpLinkManager)
{
- PushError( FormulaError::NoValue );
+ PushError(FormulaError::NoValue);
return;
}
- uno::Reference< io::XInputStream > xStream;
- try {
- xStream = xFileAccess->openFileRead( aURI );
- }
- catch (...)
- {
- // don't let any exceptions pass
- PushError( FormulaError::NoValue );
- return;
- }
- if ( !xStream.is() )
- {
- PushError( FormulaError::NoValue );
- return;
- }
+ // Need to reinterpret after loading (build links)
+ if (rArr.IsRecalcModeNormal())
+ rArr.SetExclusiveRecalcModeOnLoad();
- const sal_Int32 BUF_LEN = 8000;
- uno::Sequence< sal_Int8 > buffer( BUF_LEN );
- OStringBuffer aBuffer( 64000 );
+ // while the link is not evaluated, idle must be disabled (to avoid circular references)
+ bool bOldEnabled = pDok->IsIdleEnabled();
+ pDok->EnableIdle(false);
- sal_Int32 nRead = 0;
- while ( ( nRead = xStream->readBytes( buffer, BUF_LEN ) ) == BUF_LEN )
+ // Get/ Create link object
+ ScWebServiceLink* pLink = lcl_GetWebServiceLink(mpLinkManager, aURI);
+
+ bool bWasError = (pMyFormulaCell && pMyFormulaCell->GetRawError() != FormulaError::NONE);
+
+ if (!pLink)
{
- aBuffer.append( reinterpret_cast< const char* >( buffer.getConstArray() ), nRead );
- }
+ pLink = new ScWebServiceLink(pDok, aURI);
+ mpLinkManager->InsertFileLink(*pLink, OBJECT_CLIENT_FILE, aURI);
+ if ( mpLinkManager->GetLinks().size() == 1 ) // the first one?
+ {
+ SfxBindings* pBindings = pDok->GetViewBindings();
+ if (pBindings)
+ pBindings->Invalidate( SID_LINKS ); // Link-Manager enabled
+ }
+
+ //if the document was just loaded, but the ScDdeLink entry was missing, then
+ //don't update this link until the links are updated in response to the users
+ //decision
+ if (!pDok->HasLinkFormulaNeedingCheck())
+ {
+ pLink->Update();
+ }
- if ( nRead > 0 )
+ if (pMyFormulaCell)
+ {
+ // StartListening after the Update to avoid circular references
+ pMyFormulaCell->StartListening(*pLink);
+ }
+ }
+ else
{
- aBuffer.append( reinterpret_cast< const char* >( buffer.getConstArray() ), nRead );
+ if (pMyFormulaCell)
+ pMyFormulaCell->StartListening(*pLink);
}
- xStream->closeInput();
+ // If an new Error from Reschedule appears when the link is executed then reset the errorflag
+ if (pMyFormulaCell && pMyFormulaCell->GetRawError() != FormulaError::NONE && !bWasError)
+ pMyFormulaCell->SetErrCode(FormulaError::NONE);
+
+ // check the value
+ if (pLink->HasResult())
+ PushString(pLink->GetResult());
+ else
+ PushError(FormulaError::NoValue);
- OUString aContent = OStringToOUString( aBuffer.makeStringAndClear(), RTL_TEXTENCODING_UTF8 );
- PushString( aContent );
+ pDok->EnableIdle(bOldEnabled);
+ mpLinkManager->CloseCachedComps();
}
}
diff --git a/sc/source/core/tool/webservicelink.cxx b/sc/source/core/tool/webservicelink.cxx
new file mode 100644
index 000000000000..0d9e32cdef60
--- /dev/null
+++ b/sc/source/core/tool/webservicelink.cxx
@@ -0,0 +1,106 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <comphelper/fileformat.h>
+#include <comphelper/string.hxx>
+#include <osl/thread.h>
+#include <sfx2/linkmgr.hxx>
+#include <sfx2/bindings.hxx>
+
+#include <com/sun/star/ucb/XSimpleFileAccess3.hpp>
+#include <com/sun/star/ucb/SimpleFileAccess.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+
+#include <webservicelink.hxx>
+#include <brdcst.hxx>
+#include <document.hxx>
+#include <scmatrix.hxx>
+#include <patattr.hxx>
+#include <rechead.hxx>
+#include <rangeseq.hxx>
+#include <sc.hrc>
+#include <hints.hxx>
+
+ScWebServiceLink::ScWebServiceLink(ScDocument* pD, const OUString& rURL)
+ : ::sfx2::SvBaseLink(SfxLinkUpdateMode::ALWAYS, SotClipboardFormatId::STRING)
+ , pDoc(pD)
+ , aURL(rURL)
+ , bHasResult(false)
+{
+}
+
+ScWebServiceLink::~ScWebServiceLink() {}
+
+sfx2::SvBaseLink::UpdateResult ScWebServiceLink::DataChanged(const OUString&, const css::uno::Any&)
+{
+ aResult.clear();
+ bHasResult = false;
+
+ css::uno::Reference<css::ucb::XSimpleFileAccess3> xFileAccess(
+ css::ucb::SimpleFileAccess::create(comphelper::getProcessComponentContext()),
+ css::uno::UNO_QUERY);
+ if (!xFileAccess.is())
+ return ERROR_GENERAL;
+
+ css::uno::Reference<css::io::XInputStream> xStream;
+ try
+ {
+ xStream = xFileAccess->openFileRead(aURL);
+ }
+ catch (...)
+ {
+ // don't let any exceptions pass
+ return ERROR_GENERAL;
+ }
+ if (!xStream.is())
+ return ERROR_GENERAL;
+
+ const sal_Int32 BUF_LEN = 8000;
+ css::uno::Sequence<sal_Int8> buffer(BUF_LEN);
+ OStringBuffer aBuffer(64000);
+
+ sal_Int32 nRead = 0;
+ while ((nRead = xStream->readBytes(buffer, BUF_LEN)) == BUF_LEN)
+ aBuffer.append(reinterpret_cast<const char*>(buffer.getConstArray()), nRead);
+
+ if (nRead > 0)
+ aBuffer.append(reinterpret_cast<const char*>(buffer.getConstArray()), nRead);
+
+ xStream->closeInput();
+
+ aResult = OStringToOUString(aBuffer.makeStringAndClear(), RTL_TEXTENCODING_UTF8);
+ bHasResult = true;
+
+ // Something happened...
+ if (HasListeners())
+ {
+ Broadcast(ScHint(SFX_HINT_DATACHANGED, ScAddress()));
+ pDoc->TrackFormulas(); // must happen immediately
+ pDoc->StartTrackTimer();
+ }
+
+ return SUCCESS;
+}
+
+void ScWebServiceLink::ListenersGone()
+{
+ ScDocument* pStackDoc = pDoc; // member pDoc can't be used after removing the link
+
+ sfx2::LinkManager* pLinkMgr = pDoc->GetLinkManager();
+ pLinkMgr->Remove(this); // deletes this
+
+ if (pLinkMgr->GetLinks().empty()) // deleted the last one ?
+ {
+ SfxBindings* pBindings = pStackDoc->GetViewBindings(); // don't use member pDoc!
+ if (pBindings)
+ pBindings->Invalidate(SID_LINKS);
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/sc/source/ui/docshell/docsh4.cxx b/sc/source/ui/docshell/docsh4.cxx
index 9f87407590c0..5677e613db97 100644
--- a/sc/source/ui/docshell/docsh4.cxx
+++ b/sc/source/ui/docshell/docsh4.cxx
@@ -458,7 +458,7 @@ void ScDocShell::Execute( SfxRequest& rReq )
ReloadTabLinks();
aDocument.UpdateExternalRefLinks(GetActiveDialogParent());
- bool bAnyDde = aDocument.GetDocLinkManager().updateDdeOrOleLinks(GetActiveDialogParent());
+ bool bAnyDde = aDocument.GetDocLinkManager().updateDdeOrOleOrWebServiceLinks(GetActiveDialogParent());
if (bAnyDde)
{
diff --git a/sc/source/ui/docshell/documentlinkmgr.cxx b/sc/source/ui/docshell/documentlinkmgr.cxx
index 520b8542afc0..b8a9df65cb6b 100644
--- a/sc/source/ui/docshell/documentlinkmgr.cxx
+++ b/sc/source/ui/docshell/documentlinkmgr.cxx
@@ -20,6 +20,7 @@
#include <documentlinkmgr.hxx>
#include <datastream.hxx>
#include <ddelink.hxx>
+#include <webservicelink.hxx>
#include <sc.hrc>
#include <scresid.hxx>
@@ -115,15 +116,15 @@ bool DocumentLinkManager::idleCheckLinks()
bool DocumentLinkManager::hasDdeLinks() const
{
- return hasDdeOrOleLinks(true, false);
+ return hasDdeOrOleOrWebServiceLinks(true, false, false);
}
-bool DocumentLinkManager::hasDdeOrOleLinks() const
+bool DocumentLinkManager::hasDdeOrOleOrWebServiceLinks() const
{
- return hasDdeOrOleLinks(true, true);
+ return hasDdeOrOleOrWebServiceLinks(true, true, true);
}
-bool DocumentLinkManager::hasDdeOrOleLinks(bool bDde, bool bOle) const
+bool DocumentLinkManager::hasDdeOrOleOrWebServiceLinks(bool bDde, bool bOle, bool bWebService) const
{
if (!mpImpl->mpLinkManager)
return false;
@@ -136,12 +137,14 @@ bool DocumentLinkManager::hasDdeOrOleLinks(bool bDde, bool bOle) const
return true;
if (bOle && dynamic_cast<SdrEmbedObjectLink*>(pBase))
return true;
+ if (bWebService && dynamic_cast<ScWebServiceLink*>(pBase))
+ return true;
}
return false;
}
-bool DocumentLinkManager::updateDdeOrOleLinks( vcl::Window* pWin )
+bool DocumentLinkManager::updateDdeOrOleOrWebServiceLinks(vcl::Window* pWin)
{
if (!mpImpl->mpLinkManager)
return false;
@@ -163,6 +166,13 @@ bool DocumentLinkManager::updateDdeOrOleLinks( vcl::Window* pWin )
continue;
}
+ ScWebServiceLink* pWebserviceLink = dynamic_cast<ScWebServiceLink*>(pBase);
+ if (pWebserviceLink)
+ {
+ pWebserviceLink->Update();
+ continue;
+ }
+
ScDdeLink* pDdeLink = dynamic_cast<ScDdeLink*>(pBase);
if (!pDdeLink)
continue;
diff --git a/sc/source/ui/view/tabvwsh4.cxx b/sc/source/ui/view/tabvwsh4.cxx
index 59763e2cfc43..134030fea6ed 100644
--- a/sc/source/ui/view/tabvwsh4.cxx
+++ b/sc/source/ui/view/tabvwsh4.cxx
@@ -1575,7 +1575,7 @@ void ScTabViewShell::Construct( TriState nForceDesignMode )
if (!bLink)
{
const sc::DocumentLinkManager& rMgr = rDoc.GetDocLinkManager();
- if (rMgr.hasDdeOrOleLinks() || rDoc.HasAreaLinks() || rDoc.HasLinkFormulaNeedingCheck())
+ if (rDoc.HasLinkFormulaNeedingCheck() || rDoc.HasAreaLinks() || rMgr.hasDdeOrOleOrWebServiceLinks())
bLink = true;
}
if (bLink)