sc/Library_sc.mk | 1 sc/inc/document.hxx | 2 sc/inc/documentlinkmgr.hxx | 6 - sc/source/core/data/formulacell.cxx | 4 - sc/source/core/inc/webservicelink.hxx | 49 +++++++++++++ sc/source/core/tool/interpr7.cxx | 105 ++++++++++++++++++++--------- sc/source/core/tool/webservicelink.cxx | 106 ++++++++++++++++++++++++++++++ sc/source/ui/docshell/docsh4.cxx | 2 sc/source/ui/docshell/documentlinkmgr.cxx | 20 ++++- sc/source/ui/view/tabvwsh4.cxx | 2 10 files changed, 252 insertions(+), 45 deletions(-)
New commits: commit e1946d75a1095c2596d7815600454ff01fcd3270 Author: Caolán McNamara <caol...@redhat.com> Date: Thu Jan 11 20:43:28 2018 +0000 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/47819 Tested-by: Jenkins <c...@libreoffice.org> Reviewed-by: Eike Rathke <er...@redhat.com> diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk index 8a07d1628be9..a04e92d6a731 100644 --- a/sc/Library_sc.mk +++ b/sc/Library_sc.mk @@ -276,6 +276,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 2b12dd412643..30c15bcea696 100644 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -457,7 +457,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 55353067bc29..444a66b33196 100644 --- a/sc/source/core/data/formulacell.cxx +++ b/sc/source/core/data/formulacell.cxx @@ -1368,9 +1368,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 025b1ba0a3d0..9af943e05bca 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 826bfc7f7478..da4ec0ac70e8 100644 --- a/sc/source/ui/docshell/docsh4.cxx +++ b/sc/source/ui/docshell/docsh4.cxx @@ -450,7 +450,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 cdabc4674044..e723ee709b13 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 <scres.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 488dd048b164..bf31e60c5e19 100644 --- a/sc/source/ui/view/tabvwsh4.cxx +++ b/sc/source/ui/view/tabvwsh4.cxx @@ -1570,7 +1570,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) _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits