summaryrefslogtreecommitdiff
path: root/desktop/source/deployment/misc
diff options
context:
space:
mode:
Diffstat (limited to 'desktop/source/deployment/misc')
-rw-r--r--desktop/source/deployment/misc/dp_descriptioninfoset.cxx250
-rw-r--r--desktop/source/deployment/misc/dp_misc.cxx177
-rw-r--r--desktop/source/deployment/misc/dp_ucb.cxx46
-rwxr-xr-xdesktop/source/deployment/misc/dp_update.cxx397
-rw-r--r--desktop/source/deployment/misc/dp_version.cxx6
-rw-r--r--desktop/source/deployment/misc/makefile.mk6
6 files changed, 862 insertions, 20 deletions
diff --git a/desktop/source/deployment/misc/dp_descriptioninfoset.cxx b/desktop/source/deployment/misc/dp_descriptioninfoset.cxx
index 049f781dfd90..b4132db61f03 100644
--- a/desktop/source/deployment/misc/dp_descriptioninfoset.cxx
+++ b/desktop/source/deployment/misc/dp_descriptioninfoset.cxx
@@ -35,6 +35,7 @@
#include "comphelper/sequence.hxx"
#include "comphelper/makesequence.hxx"
+#include "comphelper/processfactory.hxx"
#include "boost/optional.hpp"
#include "com/sun/star/beans/Optional.hpp"
#include "com/sun/star/lang/XMultiComponentFactory.hpp"
@@ -47,17 +48,23 @@
#include "com/sun/star/xml/dom/DOMException.hpp"
#include "com/sun/star/xml/dom/XNode.hpp"
#include "com/sun/star/xml/dom/XNodeList.hpp"
+#include "com/sun/star/xml/dom/XDocumentBuilder.hpp"
#include "com/sun/star/xml/xpath/XXPathAPI.hpp"
+#include "com/sun/star/ucb/InteractiveAugmentedIOException.hpp"
#include "cppuhelper/implbase1.hxx"
+#include "cppuhelper/implbase2.hxx"
#include "cppuhelper/weak.hxx"
+#include "cppuhelper/exc_hlp.hxx"
#include "rtl/ustring.h"
#include "rtl/ustring.hxx"
#include "sal/types.h"
-
+#include "ucbhelper/content.hxx"
namespace {
namespace css = ::com::sun::star;
+using css::uno::Reference;
+using ::rtl::OUString;
class EmptyNodeList: public ::cppu::WeakImplHelper1< css::xml::dom::XNodeList >
{
@@ -110,10 +117,251 @@ css::uno::Reference< css::xml::dom::XNode > EmptyNodeList::item(::sal_Int32)
}
}
+/**The class uses the UCB to access the description.xml file in an
+ extension. The UCB must have been initialized already. It also
+ requires that the extension has already be unzipped to a particular
+ location.
+ */
+class ExtensionDescription
+{
+public:
+ /**throws an exception if the description.xml is not
+ available, cannot be read, does not contain the expected data,
+ or any other error occured. Therefore it shoult only be used with
+ new extensions.
+
+ Throws com::sun::star::uno::RuntimeException,
+ com::sun::star::deployment::DeploymentException,
+ dp_registry::backend::bundle::NoDescriptionException.
+ */
+ ExtensionDescription(
+ const css::uno::Reference<css::uno::XComponentContext>& xContext,
+ const ::rtl::OUString& installDir,
+ const css::uno::Reference< css::ucb::XCommandEnvironment >& xCmdEnv);
+
+ ~ExtensionDescription();
+
+ css::uno::Reference<css::xml::dom::XNode> getRootElement() const
+ {
+ return m_xRoot;
+ }
+
+ ::rtl::OUString getExtensionRootUrl() const
+ {
+ return m_sExtensionRootUrl;
+ }
+
+
+private:
+ css::uno::Reference<css::xml::dom::XNode> m_xRoot;
+ ::rtl::OUString m_sExtensionRootUrl;
+};
+
+class NoDescriptionException
+{
+};
+
+class FileDoesNotExistFilter
+ : public ::cppu::WeakImplHelper2< css::ucb::XCommandEnvironment,
+ css::task::XInteractionHandler >
+
+{
+ //css::uno::Reference<css::task::XInteractionHandler> m_xHandler;
+ bool m_bExist;
+ css::uno::Reference< css::ucb::XCommandEnvironment > m_xCommandEnv;
+
+public:
+ virtual ~FileDoesNotExistFilter();
+ FileDoesNotExistFilter(
+ const css::uno::Reference< css::ucb::XCommandEnvironment >& xCmdEnv);
+
+ bool exist();
+ // XCommandEnvironment
+ virtual css::uno::Reference<css::task::XInteractionHandler > SAL_CALL
+ getInteractionHandler() throw (css::uno::RuntimeException);
+ virtual css::uno::Reference<css::ucb::XProgressHandler >
+ SAL_CALL getProgressHandler() throw (css::uno::RuntimeException);
+
+ // XInteractionHandler
+ virtual void SAL_CALL handle(
+ css::uno::Reference<css::task::XInteractionRequest > const & xRequest )
+ throw (css::uno::RuntimeException);
+};
+
+ExtensionDescription::ExtensionDescription(
+ const Reference<css::uno::XComponentContext>& xContext,
+ const OUString& installDir,
+ const Reference< css::ucb::XCommandEnvironment >& xCmdEnv)
+{
+ try {
+ m_sExtensionRootUrl = installDir;
+ //may throw ::com::sun::star::ucb::ContentCreationException
+ //If there is no description.xml then ucb will start an interaction which
+ //brings up a dialog.We want to prevent this. Therefore we wrap the xCmdEnv
+ //and filter the respective exception out.
+ OUString sDescriptionUri(installDir + OUSTR("/description.xml"));
+ Reference<css::ucb::XCommandEnvironment> xFilter =
+ static_cast<css::ucb::XCommandEnvironment*>(
+ new FileDoesNotExistFilter(xCmdEnv));
+ ::ucbhelper::Content descContent(sDescriptionUri, xFilter);
+
+ //throws an com::sun::star::uno::Exception if the file is not available
+ Reference<css::io::XInputStream> xIn;
+ try
+ { //throws com.sun.star.ucb.InteractiveAugmentedIOException
+ xIn = descContent.openStream();
+ }
+ catch (css::uno::Exception& )
+ {
+ if ( ! static_cast<FileDoesNotExistFilter*>(xFilter.get())->exist())
+ throw NoDescriptionException();
+ throw;
+ }
+ if (!xIn.is())
+ {
+ throw css::uno::Exception(
+ OUSTR("Could not get XInputStream for description.xml of extension ") +
+ sDescriptionUri, 0);
+ }
+
+ //get root node of description.xml
+ Reference<css::xml::dom::XDocumentBuilder> xDocBuilder(
+ xContext->getServiceManager()->createInstanceWithContext(
+ OUSTR("com.sun.star.xml.dom.DocumentBuilder"),
+ xContext ), css::uno::UNO_QUERY);
+ if (!xDocBuilder.is())
+ throw css::uno::Exception(OUSTR(" Could not create service com.sun.star.xml.dom.DocumentBuilder"), 0);
+
+ if (xDocBuilder->isNamespaceAware() == sal_False)
+ {
+ throw css::uno::Exception(
+ OUSTR("Service com.sun.star.xml.dom.DocumentBuilder is not namespace aware."), 0);
+ }
+
+ Reference<css::xml::dom::XDocument> xDoc = xDocBuilder->parse(xIn);
+ if (!xDoc.is())
+ {
+ throw css::uno::Exception(sDescriptionUri + OUSTR(" contains data which cannot be parsed. "), 0);
+ }
+
+ //check for proper root element and namespace
+ Reference<css::xml::dom::XElement> xRoot = xDoc->getDocumentElement();
+ if (!xRoot.is())
+ {
+ throw css::uno::Exception(
+ sDescriptionUri + OUSTR(" contains no root element."), 0);
+ }
+
+ if ( ! xRoot->getTagName().equals(OUSTR("description")))
+ {
+ throw css::uno::Exception(
+ sDescriptionUri + OUSTR(" does not contain the root element <description>."), 0);
+ }
+
+ m_xRoot = Reference<css::xml::dom::XNode>(
+ xRoot, css::uno::UNO_QUERY_THROW);
+ OUString nsDescription = xRoot->getNamespaceURI();
+
+ //check if this namespace is supported
+ if ( ! nsDescription.equals(OUSTR("http://openoffice.org/extensions/description/2006")))
+ {
+ throw css::uno::Exception(sDescriptionUri + OUSTR(" contains a root element with an unsupported namespace. "), 0);
+ }
+ } catch (css::uno::RuntimeException &) {
+ throw;
+ } catch (css::deployment::DeploymentException &) {
+ throw;
+ } catch (css::uno::Exception & e) {
+ css::uno::Any a(cppu::getCaughtException());
+ throw css::deployment::DeploymentException(
+ e.Message, Reference< css::uno::XInterface >(), a);
+ }
+}
+
+ExtensionDescription::~ExtensionDescription()
+{
+}
+
+//======================================================================
+FileDoesNotExistFilter::FileDoesNotExistFilter(
+ const Reference< css::ucb::XCommandEnvironment >& xCmdEnv):
+ m_bExist(true), m_xCommandEnv(xCmdEnv)
+{}
+
+FileDoesNotExistFilter::~FileDoesNotExistFilter()
+{
+};
+
+bool FileDoesNotExistFilter::exist()
+{
+ return m_bExist;
+}
+ // XCommandEnvironment
+Reference<css::task::XInteractionHandler >
+ FileDoesNotExistFilter::getInteractionHandler() throw (css::uno::RuntimeException)
+{
+ return static_cast<css::task::XInteractionHandler*>(this);
+}
+
+Reference<css::ucb::XProgressHandler >
+ FileDoesNotExistFilter::getProgressHandler() throw (css::uno::RuntimeException)
+{
+ return m_xCommandEnv.is()
+ ? m_xCommandEnv->getProgressHandler()
+ : Reference<css::ucb::XProgressHandler>();
+}
+
+// XInteractionHandler
+//If the interaction was caused by a non-existing file which is specified in the ctor
+//of FileDoesNotExistFilter, then we do nothing
+void FileDoesNotExistFilter::handle(
+ Reference<css::task::XInteractionRequest > const & xRequest )
+ throw (css::uno::RuntimeException)
+{
+ css::uno::Any request( xRequest->getRequest() );
+
+ css::ucb::InteractiveAugmentedIOException ioexc;
+ if ((request>>= ioexc) && ioexc.Code == css::ucb::IOErrorCode_NOT_EXISTING )
+ {
+ m_bExist = false;
+ return;
+ }
+ Reference<css::task::XInteractionHandler> xInteraction;
+ if (m_xCommandEnv.is()) {
+ xInteraction = m_xCommandEnv->getInteractionHandler();
+ }
+ if (xInteraction.is()) {
+ xInteraction->handle(xRequest);
+ }
+}
+
}
namespace dp_misc {
+DescriptionInfoset getDescriptionInfoset(OUString const & sExtensionFolderURL)
+{
+ Reference< css::xml::dom::XNode > root;
+ Reference<css::uno::XComponentContext> context =
+ comphelper_getProcessComponentContext();
+ OSL_ASSERT(context.is());
+ try {
+ root =
+ ExtensionDescription(
+ context, sExtensionFolderURL,
+ Reference< css::ucb::XCommandEnvironment >()).
+ getRootElement();
+ } catch (NoDescriptionException &) {
+ } catch (css::deployment::DeploymentException & e) {
+ throw css::uno::RuntimeException(
+ (OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.deployment.DeploymentException: ")) +
+ e.Message), 0);
+ }
+ return DescriptionInfoset(context, root);
+}
+
DescriptionInfoset::DescriptionInfoset(
css::uno::Reference< css::uno::XComponentContext > const & context,
css::uno::Reference< css::xml::dom::XNode > const & element):
diff --git a/desktop/source/deployment/misc/dp_misc.cxx b/desktop/source/deployment/misc/dp_misc.cxx
index 3ed2d554b59f..fe3490903043 100644
--- a/desktop/source/deployment/misc/dp_misc.cxx
+++ b/desktop/source/deployment/misc/dp_misc.cxx
@@ -30,6 +30,7 @@
#include "dp_misc.h"
+#include "dp_version.hxx"
#include "dp_interact.h"
#include "rtl/uri.hxx"
#include "rtl/digest.h"
@@ -42,10 +43,14 @@
#include "osl/thread.hxx"
#include "osl/mutex.hxx"
#include "com/sun/star/ucb/CommandAbortedException.hpp"
+#include "com/sun/star/task/XInteractionHandler.hpp"
#include "com/sun/star/bridge/UnoUrlResolver.hpp"
#include "com/sun/star/bridge/XUnoUrlResolver.hpp"
+#include "com/sun/star/deployment/ExtensionManager.hpp"
+#include "com/sun/star/task/XRestartManager.hpp"
#include "boost/scoped_array.hpp"
#include "boost/shared_ptr.hpp"
+#include <comphelper/processfactory.hxx>
#ifdef WNT
//#include "tools/prewin.h"
@@ -138,6 +143,103 @@ bool existsOfficePipe()
return pipe.is();
}
+
+//Returns true if the Folder was more recently modified then
+//the lastsynchronized file. That is the repository needs to
+//be synchronized.
+bool compareExtensionFolderWithLastSynchronizedFile(
+ OUString const & folderURL, OUString const & fileURL)
+{
+ bool bNeedsSync = false;
+ ::osl::DirectoryItem itemExtFolder;
+ ::osl::File::RC err1 =
+ ::osl::DirectoryItem::get(folderURL, itemExtFolder);
+ //If it does not exist, then there is nothing to be done
+ if (err1 == ::osl::File::E_NOENT)
+ {
+ return false;
+ }
+ else if (err1 != ::osl::File::E_None)
+ {
+ OSL_ENSURE(0, "Cannot access extension folder");
+ return true; //sync just in case
+ }
+
+ //If last synchronized does not exist, then OOo is started for the first time
+ ::osl::DirectoryItem itemFile;
+ ::osl::File::RC err2 = ::osl::DirectoryItem::get(fileURL, itemFile);
+ if (err2 == ::osl::File::E_NOENT)
+ {
+ return true;
+
+ }
+ else if (err2 != ::osl::File::E_None)
+ {
+ OSL_ENSURE(0, "Cannot access file lastsynchronized");
+ return true; //sync just in case
+ }
+
+ //compare the modification time of the extension folder and the last
+ //modified file
+ ::osl::FileStatus statFolder(FileStatusMask_ModifyTime);
+ ::osl::FileStatus statFile(FileStatusMask_ModifyTime);
+ if (itemExtFolder.getFileStatus(statFolder) == ::osl::File::E_None)
+ {
+ if (itemFile.getFileStatus(statFile) == ::osl::File::E_None)
+ {
+ TimeValue timeFolder = statFolder.getModifyTime();
+ TimeValue timeFile = statFile.getModifyTime();
+
+ if (timeFile.Seconds < timeFolder.Seconds)
+ bNeedsSync = true;
+ }
+ else
+ {
+ OSL_ASSERT(0);
+ bNeedsSync = true;
+ }
+ }
+ else
+ {
+ OSL_ASSERT(0);
+ bNeedsSync = true;
+ }
+ return bNeedsSync;
+}
+
+bool needToSyncRepostitory(OUString const & name)
+{
+ OUString folder;
+ OUString file;
+ if (name.equals(OUString(RTL_CONSTASCII_USTRINGPARAM("bundled"))))
+ {
+ folder = OUString(
+ RTL_CONSTASCII_USTRINGPARAM("$BUNDLED_EXTENSIONS"));
+ file = OUString (
+ RTL_CONSTASCII_USTRINGPARAM(
+ "$BUNDLED_EXTENSIONS_USER/lastsynchronized"));
+ }
+ else if (name.equals(OUString(RTL_CONSTASCII_USTRINGPARAM("shared"))))
+ {
+ folder = OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "$UNO_SHARED_PACKAGES_CACHE/uno_packages"));
+ file = OUString (
+ RTL_CONSTASCII_USTRINGPARAM(
+ "$SHARED_EXTENSIONS_USER/lastsynchronized"));
+ }
+ else
+ {
+ OSL_ASSERT(0);
+ return true;
+ }
+ ::rtl::Bootstrap::expandMacros(folder);
+ ::rtl::Bootstrap::expandMacros(file);
+ return compareExtensionFolderWithLastSynchronizedFile(
+ folder, file);
+}
+
+
} // anon namespace
//==============================================================================
@@ -197,6 +299,19 @@ OUString makeURL( OUString const & baseURL, OUString const & relPath_ )
return buf.makeStringAndClear();
}
+OUString makeURLAppendSysPathSegment( OUString const & baseURL, OUString const & relPath_ )
+{
+ OUString segment = relPath_;
+ OSL_ASSERT(segment.indexOf(static_cast<sal_Unicode>('/')) == -1);
+
+ ::rtl::Uri::encode(
+ segment, rtl_UriCharClassPchar, rtl_UriEncodeIgnoreEscapes,
+ RTL_TEXTENCODING_UTF8);
+ return makeURL(baseURL, segment);
+}
+
+
+
//==============================================================================
OUString expandUnoRcTerm( OUString const & term_ )
{
@@ -205,6 +320,22 @@ OUString expandUnoRcTerm( OUString const & term_ )
return term;
}
+OUString makeRcTerm( OUString const & url )
+{
+ OSL_ASSERT( url.matchAsciiL( RTL_CONSTASCII_STRINGPARAM(
+ "vnd.sun.star.expand:") ) );
+ if (url.matchAsciiL( RTL_CONSTASCII_STRINGPARAM("vnd.sun.star.expand:") )) {
+ // cut protocol:
+ OUString rcterm( url.copy( sizeof ("vnd.sun.star.expand:") - 1 ) );
+ // decode uric class chars:
+ rcterm = ::rtl::Uri::decode(
+ rcterm, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8 );
+ return rcterm;
+ }
+ else
+ return url;
+}
+
//==============================================================================
OUString expandUnoRcUrl( OUString const & url )
{
@@ -346,17 +477,6 @@ Reference<XInterface> resolveUnoURL(
}
}
-OUString getExtensionDefaultUpdateURL()
-{
- ::rtl::OUString sUrl(
- RTL_CONSTASCII_USTRINGPARAM(
- "${$BRAND_BASE_DIR/program/" SAL_CONFIGFILE("version")
- ":Version:ExtensionUpdateURL}"));
- ::rtl::Bootstrap::expandMacros(sUrl);
- return sUrl;
-}
-
-
#ifdef WNT
void writeConsoleWithStream(::rtl::OUString const & sText, HANDLE stream)
{
@@ -467,4 +587,39 @@ void TRACE(::rtl::OString const & sText)
#endif
}
+void syncRepositories(Reference<ucb::XCommandEnvironment> const & xCmdEnv)
+{
+ Reference<deployment::XExtensionManager> xExtensionManager;
+ //synchronize shared before bundled otherewise there are
+ //more revoke and registration calls.
+ sal_Bool bModified = false;
+ if (needToSyncRepostitory(OUString(RTL_CONSTASCII_USTRINGPARAM("shared")))
+ || needToSyncRepostitory(OUString(RTL_CONSTASCII_USTRINGPARAM("bundled"))))
+ {
+ xExtensionManager =
+ deployment::ExtensionManager::get(
+ comphelper_getProcessComponentContext());
+
+ if (xExtensionManager.is())
+ {
+ bModified = xExtensionManager->synchronize(
+ Reference<task::XAbortChannel>(), xCmdEnv);
+ }
+ }
+
+ if (bModified)
+ {
+ Reference<task::XRestartManager> restarter(
+ comphelper_getProcessComponentContext()->getValueByName(
+ OUSTR( "/singletons/com.sun.star.task.OfficeRestartManager") ), UNO_QUERY );
+ if (restarter.is())
+ {
+ restarter->requestRestart(xCmdEnv.is() == sal_True ? xCmdEnv->getInteractionHandler() :
+ Reference<task::XInteractionHandler>());
+ }
+ }
+}
+
+
+
}
diff --git a/desktop/source/deployment/misc/dp_ucb.cxx b/desktop/source/deployment/misc/dp_ucb.cxx
index 571aef9c1b95..795a492aa0d5 100644
--- a/desktop/source/deployment/misc/dp_ucb.cxx
+++ b/desktop/source/deployment/misc/dp_ucb.cxx
@@ -271,4 +271,50 @@ bool readLine( OUString * res, OUString const & startingWith,
return false;
}
+bool readProperties( ::std::list< ::std::pair< ::rtl::OUString, ::rtl::OUString> > & out_result,
+ ::ucbhelper::Content & ucb_content )
+{
+ // read whole file:
+ ::rtl::ByteSequence bytes( readFile( ucb_content ) );
+ OUString file( reinterpret_cast<sal_Char const *>(bytes.getConstArray()),
+ bytes.getLength(), RTL_TEXTENCODING_UTF8);
+ sal_Int32 pos = 0;
+
+ for (;;)
+ {
+
+ ::rtl::OUStringBuffer buf;
+ sal_Int32 start = pos;
+
+ bool bEOF = false;
+ pos = file.indexOf( LF, pos );
+ if (pos < 0) { // EOF
+ buf.append( file.copy( start ) );
+ bEOF = true;
+ }
+ else
+ {
+ if (pos > 0 && file[ pos - 1 ] == CR)
+ // consume extra CR
+ buf.append( file.copy( start, pos - start - 1 ) );
+ else
+ buf.append( file.copy( start, pos - start ) );
+ pos++;
+ }
+ OUString aLine = buf.makeStringAndClear();
+
+ sal_Int32 posEqual = aLine.indexOf('=');
+ if (posEqual > 0 && (posEqual + 1) < aLine.getLength())
+ {
+ OUString name = aLine.copy(0, posEqual);
+ OUString value = aLine.copy(posEqual + 1);
+ out_result.push_back(::std::make_pair(name, value));
+ }
+
+ if (bEOF)
+ break;
+ }
+ return false;
+}
+
}
diff --git a/desktop/source/deployment/misc/dp_update.cxx b/desktop/source/deployment/misc/dp_update.cxx
new file mode 100755
index 000000000000..52011f1f0ca0
--- /dev/null
+++ b/desktop/source/deployment/misc/dp_update.cxx
@@ -0,0 +1,397 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_desktop.hxx"
+
+
+#include "dp_update.hxx"
+#include "dp_version.hxx"
+#include "dp_identifier.hxx"
+#include "dp_descriptioninfoset.hxx"
+
+#include "rtl/bootstrap.hxx"
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using ::rtl::OUString;
+using ::rtl::OString;
+
+
+namespace dp_misc {
+namespace {
+
+int determineHighestVersion(
+ ::rtl::OUString const & userVersion,
+ ::rtl::OUString const & sharedVersion,
+ ::rtl::OUString const & bundledVersion,
+ ::rtl::OUString const & onlineVersion)
+{
+ int index = 0;
+ OUString greatest = userVersion;
+ if (dp_misc::compareVersions(sharedVersion, greatest) == dp_misc::GREATER)
+ {
+ index = 1;
+ greatest = sharedVersion;
+ }
+ if (dp_misc::compareVersions(bundledVersion, greatest) == dp_misc::GREATER)
+ {
+ index = 2;
+ greatest = bundledVersion;
+ }
+ if (dp_misc::compareVersions(onlineVersion, greatest) == dp_misc::GREATER)
+ {
+ index = 3;
+ }
+ return index;
+}
+
+Sequence< Reference< xml::dom::XElement > >
+getUpdateInformation( Reference<deployment::XUpdateInformationProvider > const & updateInformation,
+ Sequence< OUString > const & urls,
+ OUString const & identifier,
+ uno::Any & out_error)
+{
+ try {
+ return updateInformation->getUpdateInformation(urls, identifier);
+ } catch (uno::RuntimeException &) {
+ throw;
+ } catch (ucb::CommandFailedException & e) {
+ out_error = e.Reason;
+ } catch (ucb::CommandAbortedException &) {
+ } catch (uno::Exception & e) {
+ out_error = uno::makeAny(e);
+ }
+ return
+ Sequence<Reference< xml::dom::XElement > >();
+}
+
+//Put in anonymous namespace
+
+void getOwnUpdateInfos(
+ Reference<uno::XComponentContext> const & xContext,
+ Reference<deployment::XUpdateInformationProvider > const & updateInformation,
+ UpdateInfoMap& inout_map, std::vector<std::pair<Reference<deployment::XPackage>, uno::Any> > & out_errors,
+ bool & out_allFound)
+{
+ bool allHaveOwnUpdateInformation = true;
+ for (UpdateInfoMap::iterator i = inout_map.begin(); i != inout_map.end(); i++)
+ {
+ OSL_ASSERT(i->second.extension.is());
+ Sequence<OUString> urls(i->second.extension->getUpdateInformationURLs());
+ if (urls.getLength())
+ {
+ const OUString id = dp_misc::getIdentifier(i->second.extension);
+ uno::Any anyError;
+ //It is unclear from the idl if there can be a null reference returned.
+ //However all valid information should be the same
+ Sequence<Reference< xml::dom::XElement > >
+ infos(getUpdateInformation(updateInformation, urls, id, anyError));
+ if (anyError.hasValue())
+ out_errors.push_back(std::make_pair(i->second.extension, anyError));
+
+ for (sal_Int32 j = 0; j < infos.getLength(); ++j)
+ {
+ dp_misc::DescriptionInfoset infoset(
+ xContext,
+ Reference< xml::dom::XNode >(infos[j], UNO_QUERY_THROW));
+ if (!infoset.hasDescription())
+ continue;
+ boost::optional< OUString > id2(infoset.getIdentifier());
+ if (!id2)
+ continue;
+ OSL_ASSERT(*id2 == id);
+ if (*id2 == id)
+ {
+ i->second.version = infoset.getVersion();
+ i->second.info = Reference< xml::dom::XNode >(
+ infos[j], UNO_QUERY_THROW);
+ }
+ break;
+ }
+ }
+ else
+ {
+ allHaveOwnUpdateInformation &= false;
+ }
+ }
+ out_allFound = allHaveOwnUpdateInformation;
+}
+
+void getDefaultUpdateInfos(
+ Reference<uno::XComponentContext> const & xContext,
+ Reference<deployment::XUpdateInformationProvider > const & updateInformation,
+ UpdateInfoMap& inout_map,
+ std::vector<std::pair<Reference<deployment::XPackage>, uno::Any> > & out_errors)
+{
+ const rtl::OUString sDefaultURL(dp_misc::getExtensionDefaultUpdateURL());
+ OSL_ASSERT(sDefaultURL.getLength());
+
+ Any anyError;
+ Sequence< Reference< xml::dom::XElement > >
+ infos(
+ getUpdateInformation(
+ updateInformation,
+ Sequence< OUString >(&sDefaultURL, 1), OUString(), anyError));
+ if (anyError.hasValue())
+ out_errors.push_back(std::make_pair(Reference<deployment::XPackage>(), anyError));
+ for (sal_Int32 i = 0; i < infos.getLength(); ++i)
+ {
+ Reference< xml::dom::XNode > node(infos[i], UNO_QUERY_THROW);
+ dp_misc::DescriptionInfoset infoset(xContext, node);
+ boost::optional< OUString > id(infoset.getIdentifier());
+ if (!id) {
+ continue;
+ }
+ UpdateInfoMap::iterator j = inout_map.find(*id);
+ if (j != inout_map.end())
+ {
+ //skip those extension which provide its own update urls
+ if (j->second.extension->getUpdateInformationURLs().getLength())
+ continue;
+ OUString v(infoset.getVersion());
+ //look for the highest version in the online repository
+ if (dp_misc::compareVersions(v, j->second.version) ==
+ dp_misc::GREATER)
+ {
+ j->second.version = v;
+ j->second.info = node;
+ }
+ }
+ }
+}
+
+
+} // anon namespace
+
+
+OUString getExtensionDefaultUpdateURL()
+{
+ ::rtl::OUString sUrl(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "${$BRAND_BASE_DIR/program/" SAL_CONFIGFILE("version")
+ ":Version:ExtensionUpdateURL}"));
+ ::rtl::Bootstrap::expandMacros(sUrl);
+ return sUrl;
+}
+
+/* returns the index of the greatest version, starting with 0
+
+ */
+UPDATE_SOURCE isUpdateUserExtension(
+ bool bReadOnlyShared,
+ ::rtl::OUString const & userVersion,
+ ::rtl::OUString const & sharedVersion,
+ ::rtl::OUString const & bundledVersion,
+ ::rtl::OUString const & onlineVersion)
+{
+ UPDATE_SOURCE retVal = UPDATE_SOURCE_NONE;
+ if (bReadOnlyShared)
+ {
+ if (userVersion.getLength())
+ {
+ int index = determineHighestVersion(
+ userVersion, sharedVersion, bundledVersion, onlineVersion);
+ if (index == 1)
+ retVal = UPDATE_SOURCE_SHARED;
+ else if (index == 2)
+ retVal = UPDATE_SOURCE_BUNDLED;
+ else if (index == 3)
+ retVal = UPDATE_SOURCE_ONLINE;
+ }
+ else if (sharedVersion.getLength())
+ {
+ int index = determineHighestVersion(
+ OUString(), sharedVersion, bundledVersion, onlineVersion);
+ if (index == 2)
+ retVal = UPDATE_SOURCE_BUNDLED;
+ else if (index == 3)
+ retVal = UPDATE_SOURCE_ONLINE;
+
+ }
+ else if (bundledVersion.getLength())
+ {
+ int index = determineHighestVersion(
+ OUString(), OUString(), bundledVersion, onlineVersion);
+ if (index == 3)
+ retVal = UPDATE_SOURCE_ONLINE;
+ }
+ }
+ else
+ {
+ if (userVersion.getLength())
+ {
+ int index = determineHighestVersion(
+ userVersion, sharedVersion, bundledVersion, onlineVersion);
+ if (index == 1)
+ retVal = UPDATE_SOURCE_SHARED;
+ else if (index == 2)
+ retVal = UPDATE_SOURCE_BUNDLED;
+ else if (index == 3)
+ retVal = UPDATE_SOURCE_ONLINE;
+ }
+ }
+
+ return retVal;
+}
+
+UPDATE_SOURCE isUpdateSharedExtension(
+ bool bReadOnlyShared,
+ ::rtl::OUString const & sharedVersion,
+ ::rtl::OUString const & bundledVersion,
+ ::rtl::OUString const & onlineVersion)
+{
+ if (bReadOnlyShared)
+ return UPDATE_SOURCE_NONE;
+ UPDATE_SOURCE retVal = UPDATE_SOURCE_NONE;
+
+ if (sharedVersion.getLength())
+ {
+ int index = determineHighestVersion(
+ OUString(), sharedVersion, bundledVersion, onlineVersion);
+ if (index == 2)
+ retVal = UPDATE_SOURCE_BUNDLED;
+ else if (index == 3)
+ retVal = UPDATE_SOURCE_ONLINE;
+ }
+ else if (bundledVersion.getLength())
+ {
+ int index = determineHighestVersion(
+ OUString(), OUString(), bundledVersion, onlineVersion);
+ if (index == 3)
+ retVal = UPDATE_SOURCE_ONLINE;
+ }
+ return retVal;
+}
+
+Reference<deployment::XPackage>
+getExtensionWithHighestVersion(
+ Sequence<Reference<deployment::XPackage> > const & seqExt)
+{
+ if (seqExt.getLength() == 0)
+ return Reference<deployment::XPackage>();
+
+ Reference<deployment::XPackage> greatest;
+ sal_Int32 len = seqExt.getLength();
+
+ for (sal_Int32 i = 0; i < len; i++)
+ {
+ if (!greatest.is())
+ {
+ greatest = seqExt[i];
+ continue;
+ }
+ Reference<deployment::XPackage> const & current = seqExt[i];
+ //greatest has a value
+ if (! current.is())
+ continue;
+
+ if (dp_misc::compareVersions(current->getVersion(), greatest->getVersion()) == dp_misc::GREATER)
+ greatest = current;
+ }
+ return greatest;
+}
+
+UpdateInfo::UpdateInfo( Reference< deployment::XPackage> const & ext):
+extension(ext)
+{
+}
+
+
+
+UpdateInfoMap getOnlineUpdateInfos(
+ Reference<uno::XComponentContext> const &xContext,
+ Reference<deployment::XExtensionManager> const & xExtMgr,
+ Reference<deployment::XUpdateInformationProvider > const & updateInformation,
+ std::vector<Reference<deployment::XPackage > > const * extensionList,
+ std::vector<std::pair< Reference<deployment::XPackage>, uno::Any> > & out_errors)
+{
+ OSL_ASSERT(xExtMgr.is());
+ UpdateInfoMap infoMap;
+ if (!xExtMgr.is())
+ return infoMap;
+
+ if (!extensionList)
+ {
+ const uno::Sequence< uno::Sequence< Reference<deployment::XPackage > > > seqAllExt = xExtMgr->getAllExtensions(
+ Reference<task::XAbortChannel>(), Reference<ucb::XCommandEnvironment>());
+
+ //fill the UpdateInfoMap. key = extension identifier, value = UpdateInfo
+ for (int pos = seqAllExt.getLength(); pos --; )
+ {
+ uno::Sequence<Reference<deployment::XPackage> > const & seqExt = seqAllExt[pos];
+
+ Reference<deployment::XPackage> extension = getExtensionWithHighestVersion(seqExt);
+ OSL_ASSERT(extension.is());
+
+ std::pair<UpdateInfoMap::iterator, bool> insertRet = infoMap.insert(
+ UpdateInfoMap::value_type(
+ dp_misc::getIdentifier(extension), UpdateInfo(extension)));
+ OSL_ASSERT(insertRet.second == true);
+ }
+ }
+ else
+ {
+ typedef std::vector<Reference<deployment::XPackage > >::const_iterator CIT;
+ for (CIT i = extensionList->begin(); i != extensionList->end(); i++)
+ {
+ OSL_ASSERT(i->is());
+ std::pair<UpdateInfoMap::iterator, bool> insertRet = infoMap.insert(
+ UpdateInfoMap::value_type(
+ dp_misc::getIdentifier(*i), UpdateInfo(*i)));
+ OSL_ASSERT(insertRet.second == true);
+ }
+ }
+
+ //Now find the update information for the extensions which provide their own
+ //URLs to update information.
+ bool allInfosObtained = false;
+ getOwnUpdateInfos(xContext, updateInformation, infoMap, out_errors, allInfosObtained);
+
+ if (!allInfosObtained)
+ getDefaultUpdateInfos(xContext, updateInformation, infoMap, out_errors);
+ return infoMap;
+}
+OUString getHighestVersion(
+ ::rtl::OUString const & userVersion,
+ ::rtl::OUString const & sharedVersion,
+ ::rtl::OUString const & bundledVersion,
+ ::rtl::OUString const & onlineVersion)
+{
+ int index = determineHighestVersion(userVersion, sharedVersion, bundledVersion, onlineVersion);
+ switch (index)
+ {
+ case 0: return userVersion;
+ case 1: return sharedVersion;
+ case 2: return bundledVersion;
+ case 3: return onlineVersion;
+ default: OSL_ASSERT(0);
+ }
+
+ return OUString();
+}
+} //namespace dp_misc
diff --git a/desktop/source/deployment/misc/dp_version.cxx b/desktop/source/deployment/misc/dp_version.cxx
index 1668ebe4a0b7..c0da0533b54c 100644
--- a/desktop/source/deployment/misc/dp_version.cxx
+++ b/desktop/source/deployment/misc/dp_version.cxx
@@ -70,11 +70,5 @@ namespace dp_misc {
return ::dp_misc::EQUAL;
}
-::dp_misc::Order comparePackageVersions(
- css::uno::Reference< css::deployment::XPackage > const & package1,
- css::uno::Reference< css::deployment::XPackage > const & package2)
-{
- return compareVersions(package1->getVersion(), package2->getVersion());
-}
}
diff --git a/desktop/source/deployment/misc/makefile.mk b/desktop/source/deployment/misc/makefile.mk
index e191169202fd..3e4bd68cb4c0 100644
--- a/desktop/source/deployment/misc/makefile.mk
+++ b/desktop/source/deployment/misc/makefile.mk
@@ -65,7 +65,8 @@ SHL1OBJS = \
$(SLO)$/dp_version.obj \
$(SLO)$/dp_descriptioninfoset.obj \
$(SLO)$/dp_dependencies.obj \
- $(SLO)$/dp_platform.obj
+ $(SLO)$/dp_platform.obj \
+ $(SLO)$/dp_update.obj
SHL1STDLIBS = \
$(BERKELEYLIB) \
@@ -75,7 +76,8 @@ SHL1STDLIBS = \
$(TOOLSLIB) \
$(UCBHELPERLIB) \
$(UNOTOOLSLIB) \
- $(XMLSCRIPTLIB)
+ $(XMLSCRIPTLIB) \
+ $(COMPHELPERLIB)
.IF "$(GUI)"=="OS2"
SHL1IMPLIB = ideploymentmisc$(DLLPOSTFIX)
LIB1TARGET = $(SLB)$/_deplmisc.lib