diff options
author | Caolán McNamara <caolanm@redhat.com> | 2018-01-11 20:43:28 +0000 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2018-01-12 16:19:37 +0100 |
commit | 93ea7cb6b5ab3c9b964b2b38e8f4a3bde71dbadf (patch) | |
tree | 3d09cebe5512d98f6c814fdf61c0960af72cebf0 /sc | |
parent | dabcc069de794f38a04625cbc1cb5f70dcd3dff9 (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
Change-Id: I0145f38cc1c1f9ff514a496f7101d81cde9e7c67
Reviewed-on: https://gerrit.libreoffice.org/47777
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
Diffstat (limited to 'sc')
-rw-r--r-- | sc/Library_sc.mk | 1 | ||||
-rw-r--r-- | sc/inc/document.hxx | 2 | ||||
-rw-r--r-- | sc/inc/documentlinkmgr.hxx | 6 | ||||
-rw-r--r-- | sc/source/core/data/formulacell.cxx | 4 | ||||
-rw-r--r-- | sc/source/core/inc/webservicelink.hxx | 49 | ||||
-rw-r--r-- | sc/source/core/tool/interpr7.cxx | 105 | ||||
-rw-r--r-- | sc/source/core/tool/webservicelink.cxx | 106 | ||||
-rw-r--r-- | sc/source/ui/docshell/docsh4.cxx | 2 | ||||
-rw-r--r-- | sc/source/ui/docshell/documentlinkmgr.cxx | 20 | ||||
-rw-r--r-- | sc/source/ui/view/tabvwsh4.cxx | 2 |
10 files changed, 252 insertions, 45 deletions
diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk index 890cafe689c2..9e1432c0a8c3 100644 --- a/sc/Library_sc.mk +++ b/sc/Library_sc.mk @@ -277,6 +277,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 28d815a748aa..b83aadc30a60 100644 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -500,7 +500,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 CharCompressType 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 813f74f29655..7c52d3ff9c29 100644 --- a/sc/source/core/data/formulacell.cxx +++ b/sc/source/core/data/formulacell.cxx @@ -1358,9 +1358,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 863664cc5309..9bb77db8b577 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..9dd5fa7007b8 --- /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(SfxHintId::ScDataChanged, 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 d555c99aaea3..98b8d998d22e 100644 --- a/sc/source/ui/docshell/docsh4.cxx +++ b/sc/source/ui/docshell/docsh4.cxx @@ -454,7 +454,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 aa508dca8ef0..f71fe99d1bb3 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 <strings.hrc> #include <scresid.hxx> #include <o3tl/deleter.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 969dfb7efd8b..5c0b1e8ab594 100644 --- a/sc/source/ui/view/tabvwsh4.cxx +++ b/sc/source/ui/view/tabvwsh4.cxx @@ -1567,7 +1567,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) |