blob: 3e8aa252de421aad7e25d1a1fd22750867012f95 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_desktop.hxx"
#include "dp_descriptioninfoset.hxx"
#include "dp_resource.h"
#include "sal/config.h"
#include "comphelper/sequence.hxx"
#include "comphelper/seqstream.hxx"
#include "comphelper/makesequence.hxx"
#include "comphelper/processfactory.hxx"
#include "boost/optional.hpp"
#include "com/sun/star/container/XNameAccess.hpp"
#include "com/sun/star/beans/Optional.hpp"
#include "com/sun/star/beans/PropertyValue.hpp"
#include "com/sun/star/beans/XPropertySet.hpp"
#include "com/sun/star/io/SequenceInputStream.hpp"
#include "com/sun/star/lang/XMultiComponentFactory.hpp"
#include "com/sun/star/lang/Locale.hpp"
#include "com/sun/star/uno/Reference.hxx"
#include "com/sun/star/uno/RuntimeException.hpp"
#include "com/sun/star/uno/Sequence.hxx"
#include "com/sun/star/uno/XComponentContext.hpp"
#include "com/sun/star/uno/XInterface.hpp"
#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 >
{
public:
EmptyNodeList();
virtual ~EmptyNodeList();
virtual ::sal_Int32 SAL_CALL getLength() throw (css::uno::RuntimeException);
virtual css::uno::Reference< css::xml::dom::XNode > SAL_CALL
item(::sal_Int32 index) throw (css::uno::RuntimeException);
private:
EmptyNodeList(EmptyNodeList &); // not defined
void operator =(EmptyNodeList &); // not defined
};
EmptyNodeList::EmptyNodeList() {}
EmptyNodeList::~EmptyNodeList() {}
::sal_Int32 EmptyNodeList::getLength() throw (css::uno::RuntimeException) {
return 0;
}
css::uno::Reference< css::xml::dom::XNode > EmptyNodeList::item(::sal_Int32)
throw (css::uno::RuntimeException)
{
throw css::uno::RuntimeException(
::rtl::OUString(
RTL_CONSTASCII_USTRINGPARAM(
"bad EmptyNodeList com.sun.star.xml.dom.XNodeList.item call")),
static_cast< ::cppu::OWeakObject * >(this));
}
::rtl::OUString getNodeValue(
css::uno::Reference< css::xml::dom::XNode > const & node)
{
OSL_ASSERT(node.is());
try {
return node->getNodeValue();
} catch (css::xml::dom::DOMException & e) {
throw css::uno::RuntimeException(
(::rtl::OUString(
RTL_CONSTASCII_USTRINGPARAM(
"com.sun.star.xml.dom.DOMException: ")) +
e.Message),
css::uno::Reference< css::uno::XInterface >());
}
}
/**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):
m_context(context),
m_element(element)
{
css::uno::Reference< css::lang::XMultiComponentFactory > manager(
context->getServiceManager(), css::uno::UNO_QUERY_THROW);
if (m_element.is()) {
m_xpath = css::uno::Reference< css::xml::xpath::XXPathAPI >(
manager->createInstanceWithContext(
::rtl::OUString(
RTL_CONSTASCII_USTRINGPARAM(
"com.sun.star.xml.xpath.XPathAPI")),
context),
css::uno::UNO_QUERY_THROW);
m_xpath->registerNS(
::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("desc")),
element->getNamespaceURI());
m_xpath->registerNS(
::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("xlink")),
::rtl::OUString(
RTL_CONSTASCII_USTRINGPARAM("http://www.w3.org/1999/xlink")));
}
}
DescriptionInfoset::~DescriptionInfoset() {}
::boost::optional< ::rtl::OUString > DescriptionInfoset::getIdentifier() const {
return getOptionalValue(
::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("desc:identifier/@value")));
}
::rtl::OUString DescriptionInfoset::getNodeValueFromExpression(::rtl::OUString const & expression) const
{
css::uno::Reference< css::xml::dom::XNode > n;
if (m_element.is()) {
try {
n = m_xpath->selectSingleNode(m_element, expression);
} catch (css::xml::xpath::XPathException &) {
// ignore
}
}
return n.is() ? getNodeValue(n) : ::rtl::OUString();
}
void DescriptionInfoset::checkBlacklist() const
{
if (m_element.is()) {
boost::optional< OUString > id(getIdentifier());
if (!id)
return; // nothing to check
OUString currentversion(getVersion());
if (currentversion.getLength() == 0)
return; // nothing to check
css::uno::Reference< css::lang::XMultiComponentFactory > manager(
m_context->getServiceManager(), css::uno::UNO_QUERY_THROW);
css::uno::Reference< css::lang::XMultiServiceFactory> provider(
manager->createInstanceWithContext(
::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.ConfigurationProvider")), m_context),
css::uno::UNO_QUERY_THROW);
css::uno::Sequence< css::uno::Any > args = css::uno::Sequence< css::uno::Any >(1);
css::beans::PropertyValue prop;
prop.Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("nodepath"));
prop.Value <<= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/org.openoffice.Office.ExtensionDependencies/Extensions"));
args[0] <<= prop;
css::uno::Reference< css::container::XNameAccess > blacklist(
provider->createInstanceWithArguments(
::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.ConfigurationAccess")), args),
css::uno::UNO_QUERY_THROW);
// check first if a blacklist entry is available
if (blacklist.is() && blacklist->hasByName(*id)) {
css::uno::Reference< css::beans::XPropertySet > extProps(
blacklist->getByName(*id), css::uno::UNO_QUERY_THROW);
css::uno::Any anyValue = extProps->getPropertyValue(
::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Versions")));
css::uno::Sequence< ::rtl::OUString > blversions;
anyValue >>= blversions;
// check if the current version requires further dependency checks from the blacklist
if (checkBlacklistVersion(currentversion, blversions)) {
anyValue = extProps->getPropertyValue(
::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Dependencies")));
::rtl::OUString udeps;
anyValue >>= udeps;
if (udeps.getLength() == 0)
return; // nothing todo
::rtl::OString xmlDependencies = ::rtl::OUStringToOString(udeps, RTL_TEXTENCODING_UNICODE);
css::uno::Reference< css::xml::dom::XDocumentBuilder> docbuilder(
manager->createInstanceWithContext(
::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.dom.DocumentBuilder")), m_context),
css::uno::UNO_QUERY_THROW);
css::uno::Sequence< sal_Int8 > byteSeq((const sal_Int8*)xmlDependencies.getStr(), xmlDependencies.getLength());
css::uno::Reference< css::io::XInputStream> inputstream( css::io::SequenceInputStream::createStreamFromSequence(m_context, byteSeq),
css::uno::UNO_QUERY_THROW);
css::uno::Reference< css::xml::dom::XDocument > xDocument(docbuilder->parse(inputstream));
css::uno::Reference< css::xml::dom::XElement > xElement(xDocument->getDocumentElement());
css::uno::Reference< css::xml::dom::XNodeList > xDeps(xElement->getChildNodes());
sal_Int32 nLen = xDeps->getLength();
// get the parent xml document of current description info for the import
css::uno::Reference< css::xml::dom::XDocument > xCurrentDescInfo(m_element->getOwnerDocument());
// get dependency node of current description info to merge the new dependencies from the blacklist
css::uno::Reference< css::xml::dom::XNode > xCurrentDeps(
m_xpath->selectSingleNode(m_element, ::rtl::OUString(
RTL_CONSTASCII_USTRINGPARAM("desc:dependencies"))));
// if no dependency node exists, create a new one in the current description info
if (!xCurrentDeps.is()) {
css::uno::Reference< css::xml::dom::XNode > xNewDepNode(
xCurrentDescInfo->createElementNS(
::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("http://openoffice.org/extensions/description/2006")),
::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("dependencies"))), css::uno::UNO_QUERY_THROW);
m_element->appendChild(xNewDepNode);
xCurrentDeps = m_xpath->selectSingleNode(m_element, ::rtl::OUString(
RTL_CONSTASCII_USTRINGPARAM("desc:dependencies")));
}
for (sal_Int32 i=0; i<nLen; i++) {
css::uno::Reference< css::xml::dom::XNode > xNode(xDeps->item(i));
css::uno::Reference< css::xml::dom::XElement > xDep(xNode, css::uno::UNO_QUERY);
if (xDep.is()) {
// found valid blacklist dependency, import the node first and append it to the existing dependency node
css::uno::Reference< css::xml::dom::XNode > importedNode = xCurrentDescInfo->importNode(xNode, true);
xCurrentDeps->appendChild(importedNode);
}
}
}
}
}
}
bool DescriptionInfoset::checkBlacklistVersion(
::rtl::OUString currentversion,
::com::sun::star::uno::Sequence< ::rtl::OUString > const & versions) const
{
sal_Int32 nLen = versions.getLength();
for (sal_Int32 i=0; i<nLen; i++) {
if (currentversion.equals(versions[i]))
return true;
}
return false;
}
::rtl::OUString DescriptionInfoset::getVersion() const
{
return getNodeValueFromExpression( ::rtl::OUString(
RTL_CONSTASCII_USTRINGPARAM("desc:version/@value")));
}
css::uno::Sequence< ::rtl::OUString > DescriptionInfoset::getSupportedPlaforms() const
{
//When there is no description.xml then we assume that we support all platforms
if (! m_element.is())
{
return comphelper::makeSequence(
::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("all")));
}
//Check if the <platform> element was provided. If not the default is "all" platforms
css::uno::Reference< css::xml::dom::XNode > nodePlatform(
m_xpath->selectSingleNode(m_element, ::rtl::OUString(
RTL_CONSTASCII_USTRINGPARAM("desc:platform"))));
if (!nodePlatform.is())
{
return comphelper::makeSequence(
::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("all")));
}
//There is a platform element.
const ::rtl::OUString value = getNodeValueFromExpression(::rtl::OUString(
RTL_CONSTASCII_USTRINGPARAM("desc:platform/@value")));
//parse the string, it can contained multiple strings separated by commas
::std::vector< ::rtl::OUString> vec;
sal_Int32 nIndex = 0;
do
{
::rtl::OUString aToken = value.getToken( 0, ',', nIndex );
aToken = aToken.trim();
if (aToken.getLength())
vec.push_back(aToken);
}
while (nIndex >= 0);
return comphelper::containerToSequence(vec);
}
css::uno::Reference< css::xml::dom::XNodeList >
DescriptionInfoset::getDependencies() const {
if (m_element.is()) {
try {
// check the extension blacklist first and expand the dependencies if applicable
checkBlacklist();
return m_xpath->selectNodeList(m_element, ::rtl::OUString(
RTL_CONSTASCII_USTRINGPARAM("desc:dependencies/*")));
} catch (css::xml::xpath::XPathException &) {
// ignore
}
}
return new EmptyNodeList;
}
css::uno::Sequence< ::rtl::OUString >
DescriptionInfoset::getUpdateInformationUrls() const {
return getUrls(
::rtl::OUString(
RTL_CONSTASCII_USTRINGPARAM(
"desc:update-information/desc:src/@xlink:href")));
}
css::uno::Sequence< ::rtl::OUString >
DescriptionInfoset::getUpdateDownloadUrls() const
{
return getUrls(
::rtl::OUString(
RTL_CONSTASCII_USTRINGPARAM(
"desc:update-download/desc:src/@xlink:href")));
}
::rtl::OUString DescriptionInfoset::getIconURL( sal_Bool bHighContrast ) const
{
css::uno::Sequence< ::rtl::OUString > aStrList = getUrls( ::rtl::OUString(
RTL_CONSTASCII_USTRINGPARAM( "desc:icon/desc:default/@xlink:href")));
css::uno::Sequence< ::rtl::OUString > aStrListHC = getUrls( ::rtl::OUString(
RTL_CONSTASCII_USTRINGPARAM( "desc:icon/desc:high-contrast/@xlink:href")));
if ( bHighContrast && aStrListHC.hasElements() && aStrListHC[0].getLength() )
return aStrListHC[0];
if ( aStrList.hasElements() && aStrList[0].getLength() )
return aStrList[0];
return ::rtl::OUString();
}
::boost::optional< ::rtl::OUString > DescriptionInfoset::getLocalizedUpdateWebsiteURL()
const
{
bool bParentExists = false;
const ::rtl::OUString sURL (getLocalizedHREFAttrFromChild(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
"/desc:description/desc:update-website")), &bParentExists ));
if (sURL.getLength() > 0)
return ::boost::optional< ::rtl::OUString >(sURL);
else
return bParentExists ? ::boost::optional< ::rtl::OUString >(::rtl::OUString()) :
::boost::optional< ::rtl::OUString >();
}
::boost::optional< ::rtl::OUString > DescriptionInfoset::getOptionalValue(
::rtl::OUString const & expression) const
{
css::uno::Reference< css::xml::dom::XNode > n;
if (m_element.is()) {
try {
n = m_xpath->selectSingleNode(m_element, expression);
} catch (css::xml::xpath::XPathException &) {
// ignore
}
}
return n.is()
? ::boost::optional< ::rtl::OUString >(getNodeValue(n))
: ::boost::optional< ::rtl::OUString >();
}
css::uno::Sequence< ::rtl::OUString > DescriptionInfoset::getUrls(
::rtl::OUString const & expression) const
{
css::uno::Reference< css::xml::dom::XNodeList > ns;
if (m_element.is()) {
try {
ns = m_xpath->selectNodeList(m_element, expression);
} catch (css::xml::xpath::XPathException &) {
// ignore
}
}
css::uno::Sequence< ::rtl::OUString > urls(ns.is() ? ns->getLength() : 0);
for (::sal_Int32 i = 0; i < urls.getLength(); ++i) {
urls[i] = getNodeValue(ns->item(i));
}
return urls;
}
::std::pair< ::rtl::OUString, ::rtl::OUString > DescriptionInfoset::getLocalizedPublisherNameAndURL() const
{
css::uno::Reference< css::xml::dom::XNode > node =
getLocalizedChild(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("desc:publisher")));
::rtl::OUString sPublisherName;
::rtl::OUString sURL;
if (node.is())
{
const ::rtl::OUString exp1(RTL_CONSTASCII_USTRINGPARAM("text()"));
css::uno::Reference< css::xml::dom::XNode > xPathName;
try {
xPathName = m_xpath->selectSingleNode(node, exp1);
} catch (css::xml::xpath::XPathException &) {
// ignore
}
OSL_ASSERT(xPathName.is());
if (xPathName.is())
sPublisherName = xPathName->getNodeValue();
const ::rtl::OUString exp2(RTL_CONSTASCII_USTRINGPARAM("@xlink:href"));
css::uno::Reference< css::xml::dom::XNode > xURL;
try {
xURL = m_xpath->selectSingleNode(node, exp2);
} catch (css::xml::xpath::XPathException &) {
// ignore
}
OSL_ASSERT(xURL.is());
if (xURL.is())
sURL = xURL->getNodeValue();
}
return ::std::make_pair(sPublisherName, sURL);
}
::rtl::OUString DescriptionInfoset::getLocalizedReleaseNotesURL() const
{
return getLocalizedHREFAttrFromChild(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
"/desc:description/desc:release-notes")), NULL);
}
::rtl::OUString DescriptionInfoset::getLocalizedDisplayName() const
{
css::uno::Reference< css::xml::dom::XNode > node =
getLocalizedChild(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("desc:display-name")));
if (node.is())
{
const ::rtl::OUString exp(RTL_CONSTASCII_USTRINGPARAM("text()"));
css::uno::Reference< css::xml::dom::XNode > xtext;
try {
xtext = m_xpath->selectSingleNode(node, exp);
} catch (css::xml::xpath::XPathException &) {
// ignore
}
if (xtext.is())
return xtext->getNodeValue();
}
return ::rtl::OUString();
}
::rtl::OUString DescriptionInfoset::getLocalizedLicenseURL() const
{
return getLocalizedHREFAttrFromChild(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
"/desc:description/desc:registration/desc:simple-license")), NULL);
}
::boost::optional<SimpleLicenseAttributes>
DescriptionInfoset::getSimpleLicenseAttributes() const
{
//Check if the node exist
css::uno::Reference< css::xml::dom::XNode > n;
if (m_element.is()) {
try {
n = m_xpath->selectSingleNode(m_element,
::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
"/desc:description/desc:registration/desc:simple-license/@accept-by")));
} catch (css::xml::xpath::XPathException &) {
// ignore
}
if (n.is())
{
SimpleLicenseAttributes attributes;
attributes.acceptBy =
getNodeValueFromExpression(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
"/desc:description/desc:registration/desc:simple-license/@accept-by")));
::boost::optional< ::rtl::OUString > suppressOnUpdate = getOptionalValue(
::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
"/desc:description/desc:registration/desc:simple-license/@suppress-on-update")));
if (suppressOnUpdate)
attributes.suppressOnUpdate = (*suppressOnUpdate).trim().equalsIgnoreAsciiCase(
::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("true")));
else
attributes.suppressOnUpdate = false;
::boost::optional< ::rtl::OUString > suppressIfRequired = getOptionalValue(
::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
"/desc:description/desc:registration/desc:simple-license/@suppress-if-required")));
if (suppressIfRequired)
attributes.suppressIfRequired = (*suppressIfRequired).trim().equalsIgnoreAsciiCase(
::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("true")));
else
attributes.suppressIfRequired = false;
return ::boost::optional<SimpleLicenseAttributes>(attributes);
}
}
return ::boost::optional<SimpleLicenseAttributes>();
}
::rtl::OUString DescriptionInfoset::getLocalizedDescriptionURL() const
{
return getLocalizedHREFAttrFromChild(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
"/desc:description/desc:extension-description")), NULL);
}
css::uno::Reference< css::xml::dom::XNode >
DescriptionInfoset::getLocalizedChild( const ::rtl::OUString & sParent) const
{
if ( ! m_element.is() || !sParent.getLength())
return css::uno::Reference< css::xml::dom::XNode > ();
css::uno::Reference< css::xml::dom::XNode > xParent;
try {
xParent = m_xpath->selectSingleNode(m_element, sParent);
} catch (css::xml::xpath::XPathException &) {
// ignore
}
css::uno::Reference<css::xml::dom::XNode> nodeMatch;
if (xParent.is())
{
const ::rtl::OUString sLocale = getOfficeLocaleString();
nodeMatch = matchFullLocale(xParent, sLocale);
//office: en-DE, en, en-DE-altmark
if (! nodeMatch.is())
{
const css::lang::Locale officeLocale = getOfficeLocale();
nodeMatch = matchCountryAndLanguage(xParent, officeLocale);
if ( ! nodeMatch.is())
{
nodeMatch = matchLanguage(xParent, officeLocale);
if (! nodeMatch.is())
nodeMatch = getChildWithDefaultLocale(xParent);
}
}
}
return nodeMatch;
}
css::uno::Reference<css::xml::dom::XNode>
DescriptionInfoset::matchFullLocale(css::uno::Reference< css::xml::dom::XNode >
const & xParent, ::rtl::OUString const & sLocale) const
{
OSL_ASSERT(xParent.is());
const ::rtl::OUString exp1(
::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*[@lang=\""))
+ sLocale +
::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("\"]")));
try {
return m_xpath->selectSingleNode(xParent, exp1);
} catch (css::xml::xpath::XPathException &) {
// ignore
return 0;
}
}
css::uno::Reference<css::xml::dom::XNode>
DescriptionInfoset::matchCountryAndLanguage(
css::uno::Reference< css::xml::dom::XNode > const & xParent, css::lang::Locale const & officeLocale) const
{
OSL_ASSERT(xParent.is());
css::uno::Reference<css::xml::dom::XNode> nodeMatch;
if (officeLocale.Country.getLength())
{
const ::rtl::OUString sLangCountry(officeLocale.Language +
::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("-")) +
officeLocale.Country);
//first try exact match for lang-country
const ::rtl::OUString exp1(
::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*[@lang=\""))
+ sLangCountry +
::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("\"]")));
try {
nodeMatch = m_xpath->selectSingleNode(xParent, exp1);
} catch (css::xml::xpath::XPathException &) {
// ignore
}
//try to match in strings that also have a variant, for example en-US matches in
//en-US-montana
if (!nodeMatch.is())
{
const ::rtl::OUString exp2(
::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*[starts-with(@lang,\""))
+ sLangCountry +
::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("-\")]")));
try {
nodeMatch = m_xpath->selectSingleNode(xParent, exp2);
} catch (css::xml::xpath::XPathException &) {
// ignore
}
}
}
return nodeMatch;
}
css::uno::Reference<css::xml::dom::XNode>
DescriptionInfoset::matchLanguage(
css::uno::Reference< css::xml::dom::XNode > const & xParent, css::lang::Locale const & officeLocale) const
{
OSL_ASSERT(xParent.is());
css::uno::Reference<css::xml::dom::XNode> nodeMatch;
//first try exact match for lang
const ::rtl::OUString exp1(
::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*[@lang=\""))
+ officeLocale.Language
+ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("\"]")));
try {
nodeMatch = m_xpath->selectSingleNode(xParent, exp1);
} catch (css::xml::xpath::XPathException &) {
// ignore
}
//try to match in strings that also have a country and/orvariant, for example en matches in
//en-US-montana, en-US, en-montana
if (!nodeMatch.is())
{
const ::rtl::OUString exp2(
::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*[starts-with(@lang,\""))
+ officeLocale.Language
+ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("-\")]")));
try {
nodeMatch = m_xpath->selectSingleNode(xParent, exp2);
} catch (css::xml::xpath::XPathException &) {
// ignore
}
}
return nodeMatch;
}
css::uno::Reference<css::xml::dom::XNode>
DescriptionInfoset::getChildWithDefaultLocale(css::uno::Reference< css::xml::dom::XNode >
const & xParent) const
{
OSL_ASSERT(xParent.is());
if (xParent->getNodeName().equals(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("simple-license"))))
{
css::uno::Reference<css::xml::dom::XNode> nodeDefault;
try {
nodeDefault = m_xpath->selectSingleNode(xParent, ::rtl::OUString(
RTL_CONSTASCII_USTRINGPARAM("@default-license-id")));
} catch (css::xml::xpath::XPathException &) {
// ignore
}
if (nodeDefault.is())
{
//The old way
const ::rtl::OUString exp1(
::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("desc:license-text[@license-id = \""))
+ nodeDefault->getNodeValue()
+ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("\"]")));
try {
return m_xpath->selectSingleNode(xParent, exp1);
} catch (css::xml::xpath::XPathException &) {
// ignore
}
}
}
const ::rtl::OUString exp2(RTL_CONSTASCII_USTRINGPARAM("*[1]"));
try {
return m_xpath->selectSingleNode(xParent, exp2);
} catch (css::xml::xpath::XPathException &) {
// ignore
return 0;
}
}
::rtl::OUString DescriptionInfoset::getLocalizedHREFAttrFromChild(
::rtl::OUString const & sXPathParent, bool * out_bParentExists)
const
{
css::uno::Reference< css::xml::dom::XNode > node =
getLocalizedChild(sXPathParent);
::rtl::OUString sURL;
if (node.is())
{
if (out_bParentExists)
*out_bParentExists = true;
const ::rtl::OUString exp(RTL_CONSTASCII_USTRINGPARAM("@xlink:href"));
css::uno::Reference< css::xml::dom::XNode > xURL;
try {
xURL = m_xpath->selectSingleNode(node, exp);
} catch (css::xml::xpath::XPathException &) {
// ignore
}
OSL_ASSERT(xURL.is());
if (xURL.is())
sURL = xURL->getNodeValue();
}
else
{
if (out_bParentExists)
*out_bParentExists = false;
}
return sURL;
}
}