2009-05-15 14:06:56 +02:00
|
|
|
/*************************************************************************
|
|
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
|
|
*
|
|
|
|
* Copyright 2009 by Sun Microsystems, Inc.
|
|
|
|
*
|
|
|
|
* OpenOffice.org - a multi-platform office productivity suite
|
|
|
|
*
|
|
|
|
* $RCSfile: code,v $
|
|
|
|
*
|
|
|
|
* $Revision: 1.4 $
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
************************************************************************/
|
|
|
|
|
|
|
|
#include "precompiled_configmgr.hxx"
|
|
|
|
#include "sal/config.h"
|
|
|
|
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
#include "boost/noncopyable.hpp"
|
|
|
|
#include "com/sun/star/uno/Any.hxx"
|
|
|
|
#include "com/sun/star/uno/RuntimeException.hpp"
|
2009-06-03 15:57:23 +02:00
|
|
|
#include "com/sun/star/uno/Sequence.hxx"
|
2009-05-28 10:19:30 +02:00
|
|
|
#include "com/sun/star/uno/XInterface.hpp"
|
2009-05-15 14:06:56 +02:00
|
|
|
#include "comphelper/sequenceasvector.hxx"
|
|
|
|
#include "libxml/parser.h"
|
|
|
|
#include "libxml/xmlschemastypes.h"
|
2009-07-08 17:25:16 +02:00
|
|
|
#include "libxml/xmlwriter.h"
|
2009-05-15 14:06:56 +02:00
|
|
|
#include "osl/diagnose.h"
|
|
|
|
#include "osl/file.hxx"
|
|
|
|
#include "osl/mutex.hxx"
|
|
|
|
#include "osl/thread.hxx"
|
|
|
|
#include "rtl/bootstrap.hxx"
|
2009-05-19 10:49:37 +02:00
|
|
|
#include "rtl/ref.hxx"
|
2009-07-10 11:20:28 +02:00
|
|
|
#include "rtl/strbuf.hxx"
|
2009-05-15 14:06:56 +02:00
|
|
|
#include "rtl/string.h"
|
|
|
|
#include "rtl/string.hxx"
|
|
|
|
#include "rtl/textcvt.h"
|
|
|
|
#include "rtl/textenc.h"
|
|
|
|
#include "rtl/ustrbuf.hxx"
|
|
|
|
#include "rtl/ustring.h"
|
|
|
|
#include "rtl/ustring.hxx"
|
|
|
|
#include "sal/types.h"
|
2009-05-20 17:20:08 +02:00
|
|
|
#include "stl/hash_map"
|
2009-05-15 14:06:56 +02:00
|
|
|
|
|
|
|
#include "components.hxx"
|
|
|
|
#include "groupnode.hxx"
|
|
|
|
#include "localizedpropertynode.hxx"
|
2009-05-20 17:20:08 +02:00
|
|
|
#include "localizedpropertyvaluenode.hxx"
|
2009-05-15 14:06:56 +02:00
|
|
|
#include "lock.hxx"
|
|
|
|
#include "node.hxx"
|
|
|
|
#include "nodemap.hxx"
|
|
|
|
#include "propertynode.hxx"
|
|
|
|
#include "setnode.hxx"
|
|
|
|
|
|
|
|
namespace configmgr {
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
namespace css = com::sun::star;
|
|
|
|
|
2009-05-20 17:20:08 +02:00
|
|
|
typedef std::hash_map< rtl::OUString, css::uno::Any, rtl::OUStringHash >
|
|
|
|
LocalizedValues;
|
|
|
|
|
2009-07-13 14:54:09 +02:00
|
|
|
bool isRemovedValue(css::uno::Any const & value) {
|
|
|
|
// An ANY of type TYPE whose value is VOID is used within a LocalizedValues
|
|
|
|
// map as a marker for a removed localized value (in a fused xcu property
|
|
|
|
// within the registrymodifications file):
|
|
|
|
return value.getValueType().getTypeClass() == css::uno::TypeClass_TYPE;
|
|
|
|
}
|
|
|
|
|
2009-05-20 17:20:08 +02:00
|
|
|
void setValues(LocalizedPropertyNode * node, LocalizedValues const & values) {
|
|
|
|
for (LocalizedValues::const_iterator i(values.begin()); i != values.end();
|
|
|
|
++i)
|
|
|
|
{
|
2009-07-13 14:54:09 +02:00
|
|
|
OSL_ASSERT(!isRemovedValue(i->second));
|
2009-05-20 17:20:08 +02:00
|
|
|
node->getMembers().insert(
|
|
|
|
NodeMap::value_type(
|
2009-06-04 10:46:43 +02:00
|
|
|
i->first, new LocalizedPropertyValueNode(i->second)));
|
2009-05-20 17:20:08 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-05-15 14:06:56 +02:00
|
|
|
template< typename T > sal_Int32 findFirst(
|
|
|
|
rtl::OUString const & string, T sub, sal_Int32 fromIndex)
|
|
|
|
{
|
|
|
|
sal_Int32 i = string.indexOf(sub, fromIndex);
|
|
|
|
return i == -1 ? string.getLength() : i;
|
|
|
|
}
|
|
|
|
|
2009-07-08 17:25:16 +02:00
|
|
|
bool isPrefix(rtl::OUString const & prefix, rtl::OUString const & path) {
|
|
|
|
return prefix.getLength() < path.getLength() && path.match(prefix) &&
|
|
|
|
path[prefix.getLength()] == '/';
|
|
|
|
}
|
|
|
|
|
2009-07-13 14:54:09 +02:00
|
|
|
bool decodeXml(
|
|
|
|
rtl::OUString const & encoded, sal_Int32 begin, sal_Int32 end,
|
|
|
|
rtl::OUString * decoded)
|
|
|
|
{
|
|
|
|
OSL_ASSERT(
|
|
|
|
begin >= 0 && begin <= end && end <= encoded.getLength() &&
|
|
|
|
decoded != 0);
|
|
|
|
rtl::OUStringBuffer buf;
|
|
|
|
while (begin != end) {
|
|
|
|
sal_Unicode c = encoded[begin++];
|
|
|
|
if (c == '&') {
|
|
|
|
if (encoded.matchAsciiL(RTL_CONSTASCII_STRINGPARAM("amp;"), begin))
|
|
|
|
{
|
|
|
|
buf.append(sal_Unicode('&'));
|
|
|
|
begin += RTL_CONSTASCII_LENGTH("amp;");
|
|
|
|
} else if (encoded.matchAsciiL(
|
|
|
|
RTL_CONSTASCII_STRINGPARAM("quot;"), begin))
|
|
|
|
{
|
|
|
|
buf.append(sal_Unicode('"'));
|
|
|
|
begin += RTL_CONSTASCII_LENGTH("quot;");
|
|
|
|
} else if (encoded.matchAsciiL(
|
|
|
|
RTL_CONSTASCII_STRINGPARAM("apos;"), begin))
|
|
|
|
{
|
|
|
|
buf.append(sal_Unicode('\''));
|
|
|
|
begin += RTL_CONSTASCII_LENGTH("apos;");
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
OSL_ASSERT(begin <= end);
|
|
|
|
} else {
|
|
|
|
buf.append(c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*decoded = buf.makeStringAndClear();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
rtl::OUString parseLastSegment(
|
|
|
|
rtl::OUString const & path, rtl::OUString * name)
|
|
|
|
{
|
|
|
|
OSL_ASSERT(name != 0);
|
|
|
|
sal_Int32 i = path.getLength();
|
|
|
|
OSL_ASSERT(i > 0 && path[i - 1] != '/');
|
|
|
|
if (path[i - 1] == ']') {
|
|
|
|
OSL_ASSERT(i > 2 && (path[i - 2] == '\'' || (path[i - 2] == '"')));
|
|
|
|
sal_Int32 j = path.lastIndexOf(path[i - 2], i - 2);
|
|
|
|
OSL_ASSERT(j > 0);
|
|
|
|
decodeXml(path, j + 1, i - 2, name);
|
|
|
|
i = path.lastIndexOf('/', j);
|
|
|
|
} else {
|
|
|
|
i = path.lastIndexOf('/');
|
|
|
|
*name = path.copy(i + 1);
|
|
|
|
}
|
|
|
|
OSL_ASSERT(i != -1);
|
|
|
|
return path.copy(0, i);
|
|
|
|
}
|
|
|
|
|
2009-05-15 14:06:56 +02:00
|
|
|
xmlChar const * xmlString(char const * str) {
|
|
|
|
return reinterpret_cast< xmlChar const * >(str);
|
|
|
|
}
|
|
|
|
|
|
|
|
rtl::OUString fromXmlString(xmlChar const * str) {
|
|
|
|
char const * s = reinterpret_cast< char const * >(str);
|
|
|
|
return s == 0
|
|
|
|
? rtl::OUString()
|
|
|
|
: rtl::OUString(s, rtl_str_getLength(s), RTL_TEXTENCODING_UTF8);
|
|
|
|
}
|
|
|
|
|
|
|
|
rtl::OUString fromXmlString(xmlChar const * str, xmlChar const * end) {
|
|
|
|
OSL_ASSERT(str != 0 && end != 0);
|
|
|
|
return rtl::OUString(
|
|
|
|
reinterpret_cast< char const * >(str), end - str,
|
|
|
|
RTL_TEXTENCODING_UTF8);
|
|
|
|
}
|
|
|
|
|
|
|
|
struct XmlString: private boost::noncopyable {
|
2009-05-28 13:54:00 +02:00
|
|
|
xmlChar * str;
|
2009-05-15 14:06:56 +02:00
|
|
|
|
2009-05-28 13:54:00 +02:00
|
|
|
explicit XmlString(xmlChar * theStr = 0): str(theStr) {}
|
2009-05-15 14:06:56 +02:00
|
|
|
|
|
|
|
~XmlString() { xmlFree(str); }
|
2009-05-28 13:54:00 +02:00
|
|
|
|
|
|
|
XmlString & operator =(xmlChar * theStr);
|
2009-05-15 14:06:56 +02:00
|
|
|
};
|
|
|
|
|
2009-05-28 13:54:00 +02:00
|
|
|
XmlString & XmlString::operator =(xmlChar * theStr) {
|
|
|
|
OSL_ASSERT(str == 0);
|
|
|
|
str = theStr;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2009-07-02 14:21:36 +02:00
|
|
|
struct XmlParserContext: private boost::noncopyable {
|
|
|
|
xmlParserCtxtPtr context;
|
|
|
|
|
|
|
|
XmlParserContext();
|
|
|
|
|
|
|
|
~XmlParserContext() { xmlFreeParserCtxt(context); }
|
|
|
|
};
|
|
|
|
|
|
|
|
XmlParserContext::XmlParserContext(): context(xmlNewParserCtxt()) {
|
|
|
|
if (context == 0) {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM("xmlNewParserCtxt failed")),
|
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-05-15 14:06:56 +02:00
|
|
|
struct XmlDoc: private boost::noncopyable {
|
|
|
|
xmlDocPtr doc;
|
|
|
|
|
|
|
|
explicit XmlDoc(xmlDocPtr theDoc): doc(theDoc) {}
|
|
|
|
|
|
|
|
~XmlDoc() { xmlFreeDoc(doc); }
|
|
|
|
};
|
|
|
|
|
2009-07-08 17:25:16 +02:00
|
|
|
struct XmlTextWriter: private boost::noncopyable {
|
|
|
|
xmlTextWriterPtr writer;
|
|
|
|
|
|
|
|
explicit XmlTextWriter(xmlTextWriterPtr theWriter): writer(theWriter) {}
|
|
|
|
|
|
|
|
~XmlTextWriter() { xmlFreeTextWriter(writer); }
|
|
|
|
};
|
|
|
|
|
2009-05-15 14:06:56 +02:00
|
|
|
rtl::OUString fullTemplateName(
|
|
|
|
rtl::OUString const & component, rtl::OUString const & name)
|
|
|
|
{
|
2009-07-08 17:25:16 +02:00
|
|
|
OSL_ASSERT(component.indexOf(':') == -1);
|
2009-05-15 14:06:56 +02:00
|
|
|
rtl::OUStringBuffer buf(component);
|
2009-07-08 17:25:16 +02:00
|
|
|
buf.append(sal_Unicode(':'));
|
2009-05-15 14:06:56 +02:00
|
|
|
buf.append(name);
|
|
|
|
return buf.makeStringAndClear();
|
|
|
|
}
|
|
|
|
|
|
|
|
class NodeRef: public Node {
|
|
|
|
public:
|
2009-05-19 10:49:37 +02:00
|
|
|
NodeRef(
|
2009-06-04 10:46:43 +02:00
|
|
|
rtl::OUString const & templateName,
|
2009-05-28 10:19:30 +02:00
|
|
|
Components::TemplateMap const & templates):
|
2009-06-04 10:46:43 +02:00
|
|
|
templateName_(templateName), templates_(templates)
|
2009-05-28 10:19:30 +02:00
|
|
|
{}
|
2009-05-15 14:06:56 +02:00
|
|
|
|
2009-06-04 10:46:43 +02:00
|
|
|
virtual rtl::Reference< Node > clone() const
|
|
|
|
{ return new NodeRef(templateName_, templates_); }
|
2009-05-15 14:06:56 +02:00
|
|
|
|
2009-05-19 10:49:37 +02:00
|
|
|
virtual rtl::Reference< Node > getMember(rtl::OUString const &);
|
2009-05-15 14:06:56 +02:00
|
|
|
|
|
|
|
rtl::OUString getTemplateName() const { return templateName_; }
|
|
|
|
|
2009-05-28 10:19:30 +02:00
|
|
|
Components::TemplateMap const & getTemplates() const { return templates_; }
|
|
|
|
|
2009-05-15 14:06:56 +02:00
|
|
|
private:
|
2009-05-19 10:49:37 +02:00
|
|
|
virtual ~NodeRef() {}
|
|
|
|
|
2009-05-15 14:06:56 +02:00
|
|
|
rtl::OUString templateName_;
|
2009-05-28 10:19:30 +02:00
|
|
|
Components::TemplateMap const & templates_;
|
2009-05-15 14:06:56 +02:00
|
|
|
};
|
|
|
|
|
2009-05-19 10:49:37 +02:00
|
|
|
rtl::Reference< Node > NodeRef::getMember(rtl::OUString const &) {
|
2009-05-15 14:06:56 +02:00
|
|
|
throw css::uno::RuntimeException(
|
2009-06-03 15:57:23 +02:00
|
|
|
rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("unresolved node-ref")),
|
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
|
2009-07-08 17:25:16 +02:00
|
|
|
rtl::OString convertToUtf8(rtl::OUString const & text) {
|
|
|
|
rtl::OString utf8;
|
|
|
|
if (!text.convertToString(
|
|
|
|
&utf8, RTL_TEXTENCODING_UTF8,
|
|
|
|
(RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR |
|
|
|
|
RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
|
|
|
|
{
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM("cannot translate text to UTF-8")),
|
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
|
|
|
}
|
|
|
|
return utf8;
|
|
|
|
}
|
|
|
|
|
|
|
|
rtl::OString convertToFilepath(rtl::OUString const & url) {
|
2009-05-15 14:06:56 +02:00
|
|
|
rtl::OUString path1;
|
|
|
|
if (osl::FileBase::getSystemPathFromFileURL(url, path1) !=
|
|
|
|
osl::FileBase::E_None)
|
|
|
|
{
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM("cannot get system path for ")) +
|
|
|
|
url),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
rtl::OString path2;
|
|
|
|
if (!path1.convertToString(
|
|
|
|
&path2, osl_getThreadTextEncoding(),
|
|
|
|
(RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR |
|
|
|
|
RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
|
|
|
|
{
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM("cannot translate system path ")) +
|
|
|
|
path1),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
2009-07-08 17:25:16 +02:00
|
|
|
return path2;
|
|
|
|
}
|
|
|
|
|
|
|
|
xmlDocPtr parseXmlFile(rtl::OUString const & url) {
|
2009-07-02 14:21:36 +02:00
|
|
|
XmlParserContext context;
|
|
|
|
xmlDocPtr doc(
|
2009-07-08 17:25:16 +02:00
|
|
|
xmlCtxtReadFile(
|
|
|
|
context.context, convertToFilepath(url).getStr(), 0,
|
|
|
|
XML_PARSE_NOERROR));
|
2009-07-02 14:21:36 +02:00
|
|
|
//TODO: pass (external) file URL instead of filepath?
|
2009-05-15 14:06:56 +02:00
|
|
|
if (doc == 0) {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
2009-07-02 14:21:36 +02:00
|
|
|
RTL_CONSTASCII_USTRINGPARAM("xmlCtxtReadFile failed for ")) +
|
2009-05-15 14:06:56 +02:00
|
|
|
url),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
return doc;
|
|
|
|
}
|
|
|
|
|
|
|
|
xmlNodePtr skipBlank(xmlNodePtr node) {
|
|
|
|
while (node != 0 && xmlIsBlankNode(node)) {
|
|
|
|
node = node->next;
|
|
|
|
}
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isOorElement(xmlNodePtr node, char const * name) {
|
|
|
|
return node != 0 && xmlStrEqual(node->name, xmlString(name)) &&
|
|
|
|
(node->ns == 0 ||
|
|
|
|
xmlStrEqual(
|
|
|
|
node->ns->href, xmlString("http://openoffice.org/2001/registry")));
|
|
|
|
}
|
|
|
|
|
|
|
|
rtl::OUString getNameAttribute(xmlDocPtr doc, xmlNodePtr node) {
|
|
|
|
XmlString name(
|
|
|
|
xmlGetNsProp(
|
|
|
|
node, xmlString("name"),
|
|
|
|
xmlString("http://openoffice.org/2001/registry")));
|
|
|
|
if (name.str == 0) {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM("missing name attribute in ")) +
|
|
|
|
fromXmlString(doc->URL)),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
return fromXmlString(name.str);
|
|
|
|
}
|
|
|
|
|
|
|
|
enum Operation {
|
|
|
|
OPERATION_MODIFY, OPERATION_REPLACE, OPERATION_FUSE, OPERATION_REMOVE };
|
|
|
|
|
|
|
|
Operation getOperationAttribute(xmlDocPtr doc, xmlNodePtr node) {
|
|
|
|
XmlString op(
|
|
|
|
xmlGetNsProp(
|
|
|
|
node, xmlString("op"),
|
|
|
|
xmlString("http://openoffice.org/2001/registry")));
|
|
|
|
if (op.str == 0 || xmlStrEqual(op.str, xmlString("modify"))) {
|
|
|
|
return OPERATION_MODIFY;
|
|
|
|
} else if (xmlStrEqual(op.str, xmlString("replace"))) {
|
|
|
|
return OPERATION_REPLACE;
|
|
|
|
} else if (xmlStrEqual(op.str, xmlString("fuse"))) {
|
|
|
|
return OPERATION_FUSE;
|
|
|
|
} else if (xmlStrEqual(op.str, xmlString("remove"))) {
|
|
|
|
return OPERATION_REMOVE;
|
|
|
|
} else {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM("invalid op attribute in ")) +
|
|
|
|
fromXmlString(doc->URL)),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Type getTypeAttribute(xmlDocPtr doc, xmlNodePtr node) {
|
|
|
|
XmlString type(
|
|
|
|
xmlGetNsProp(
|
|
|
|
node, xmlString("type"),
|
|
|
|
xmlString("http://openoffice.org/2001/registry")));
|
|
|
|
if (type.str == 0) {
|
2009-06-03 18:02:52 +02:00
|
|
|
return TYPE_ERROR;
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
xmlChar const * p = xmlStrchr(type.str, ':');
|
|
|
|
if (p == 0) {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM("invalid type attribute ")) +
|
|
|
|
fromXmlString(doc->URL)),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
XmlString prefix(xmlStrsub(type.str, 0, p - type.str));
|
|
|
|
xmlNsPtr ns(xmlSearchNs(doc, node, prefix.str));
|
|
|
|
if (ns == 0) {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM("invalid type attribute ")) +
|
|
|
|
fromXmlString(doc->URL)),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
if (xmlStrEqual(ns->href, xmlString("http://www.w3.org/2001/XMLSchema"))) {
|
|
|
|
if (xmlStrEqual(p + 1, xmlString("boolean"))) {
|
|
|
|
return TYPE_BOOLEAN;
|
|
|
|
} else if (xmlStrEqual(p + 1, xmlString("short"))) {
|
|
|
|
return TYPE_SHORT;
|
|
|
|
} else if (xmlStrEqual(p + 1, xmlString("int"))) {
|
|
|
|
return TYPE_INT;
|
|
|
|
} else if (xmlStrEqual(p + 1, xmlString("long"))) {
|
|
|
|
return TYPE_LONG;
|
|
|
|
} else if (xmlStrEqual(p + 1, xmlString("double"))) {
|
|
|
|
return TYPE_DOUBLE;
|
|
|
|
} else if (xmlStrEqual(p + 1, xmlString("string"))) {
|
|
|
|
return TYPE_STRING;
|
|
|
|
} else if (xmlStrEqual(p + 1, xmlString("hexBinary"))) {
|
|
|
|
return TYPE_HEXBINARY;
|
|
|
|
}
|
|
|
|
} else if (xmlStrEqual(
|
|
|
|
ns->href, xmlString("http://openoffice.org/2001/registry")))
|
|
|
|
{
|
|
|
|
if (xmlStrEqual(p + 1, xmlString("any"))) {
|
|
|
|
return TYPE_ANY;
|
|
|
|
} else if (xmlStrEqual(p + 1, xmlString("boolean-list"))) {
|
|
|
|
return TYPE_BOOLEAN_LIST;
|
|
|
|
} else if (xmlStrEqual(p + 1, xmlString("short-list"))) {
|
|
|
|
return TYPE_SHORT_LIST;
|
|
|
|
} else if (xmlStrEqual(p + 1, xmlString("int-list"))) {
|
|
|
|
return TYPE_INT_LIST;
|
|
|
|
} else if (xmlStrEqual(p + 1, xmlString("long-list"))) {
|
|
|
|
return TYPE_LONG_LIST;
|
|
|
|
} else if (xmlStrEqual(p + 1, xmlString("double-list"))) {
|
|
|
|
return TYPE_DOUBLE_LIST;
|
|
|
|
} else if (xmlStrEqual(p + 1, xmlString("string-list"))) {
|
|
|
|
return TYPE_STRING_LIST;
|
|
|
|
} else if (xmlStrEqual(p + 1, xmlString("hexBinary-list"))) {
|
|
|
|
return TYPE_HEXBINARY_LIST;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM("invalid type attribute ")) +
|
|
|
|
fromXmlString(doc->URL)),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool getBooleanAttribute(
|
|
|
|
xmlDocPtr doc, xmlNodePtr node, char const * ns, char const * name,
|
|
|
|
bool deflt)
|
|
|
|
{
|
|
|
|
XmlString attr(xmlGetNsProp(node, xmlString(name), xmlString(ns)));
|
|
|
|
if (attr.str == 0) {
|
|
|
|
return deflt;
|
|
|
|
}
|
|
|
|
if (xmlStrEqual(attr.str, xmlString("true"))) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (xmlStrEqual(attr.str, xmlString("false"))) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM("bad boolean attribute value in ")) +
|
|
|
|
fromXmlString(doc->URL)),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
|
2009-05-28 13:54:00 +02:00
|
|
|
bool parseBooleanValue(
|
|
|
|
xmlChar const * text, xmlChar const * end, sal_Bool * value)
|
|
|
|
{
|
|
|
|
OSL_ASSERT(text != 0 && value != 0);
|
|
|
|
if (end == 0) {
|
|
|
|
if (xmlStrEqual(text, xmlString("true")) ||
|
|
|
|
xmlStrEqual(text, xmlString("1")))
|
|
|
|
{
|
|
|
|
*value = true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (xmlStrEqual(text, xmlString("false")) ||
|
|
|
|
xmlStrEqual(text, xmlString("0")))
|
|
|
|
{
|
|
|
|
*value = false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
int len = xmlStrlen(text);
|
|
|
|
if ((len == RTL_CONSTASCII_LENGTH("true") &&
|
|
|
|
(xmlStrncmp(text, xmlString("true"), RTL_CONSTASCII_LENGTH("true"))
|
|
|
|
== 0)) ||
|
|
|
|
(len == RTL_CONSTASCII_LENGTH("1") &&
|
|
|
|
xmlStrncmp(text, xmlString("1"), RTL_CONSTASCII_LENGTH("1")) == 0))
|
|
|
|
{
|
|
|
|
*value = true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if ((len == RTL_CONSTASCII_LENGTH("false") &&
|
|
|
|
(xmlStrncmp(
|
|
|
|
text, xmlString("false"), RTL_CONSTASCII_LENGTH("false"))
|
|
|
|
== 0)) ||
|
|
|
|
(len == RTL_CONSTASCII_LENGTH("0") &&
|
|
|
|
xmlStrncmp(text, xmlString("0"), RTL_CONSTASCII_LENGTH("0")) == 0))
|
|
|
|
{
|
|
|
|
*value = false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool parseShortValue(
|
|
|
|
xmlChar const * text, xmlChar const * end, sal_Int16 * value)
|
|
|
|
{
|
|
|
|
OSL_ASSERT(text != 0 && value != 0);
|
|
|
|
sal_Int32 n;
|
|
|
|
if (end == 0) {
|
|
|
|
n = rtl_str_toInt32(reinterpret_cast< char const * >(text), 10);
|
|
|
|
//TODO: check valid lexical representation
|
|
|
|
} else {
|
|
|
|
n = fromXmlString(text, end).toInt32();
|
|
|
|
//TODO: check valid lexical representation
|
|
|
|
}
|
|
|
|
if (n >= SAL_MIN_INT16 && n <= SAL_MAX_INT16) {
|
|
|
|
*value = static_cast< sal_Int16 >(n);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool parseIntValue(
|
|
|
|
xmlChar const * text, xmlChar const * end, sal_Int32 * value)
|
|
|
|
{
|
|
|
|
OSL_ASSERT(text != 0 && value != 0);
|
|
|
|
if (end == 0) {
|
|
|
|
*value = rtl_str_toInt32(reinterpret_cast< char const * >(text), 10);
|
|
|
|
//TODO: check valid lexical representation
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
*value = fromXmlString(text, end).toInt32();
|
|
|
|
//TODO: check valid lexical representation
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool parseLongValue(
|
|
|
|
xmlChar const * text, xmlChar const * end, sal_Int64 * value)
|
|
|
|
{
|
|
|
|
OSL_ASSERT(text != 0 && value != 0);
|
|
|
|
if (end == 0) {
|
|
|
|
*value = rtl_str_toInt64(reinterpret_cast< char const * >(text), 10);
|
|
|
|
//TODO: check valid lexical representation
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
*value = fromXmlString(text, end).toInt64();
|
|
|
|
//TODO: check valid lexical representation
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool parseDoubleValue(xmlChar const * text, xmlChar const * end, double * value)
|
|
|
|
{
|
|
|
|
OSL_ASSERT(text != 0 && value != 0);
|
|
|
|
if (end == 0) {
|
|
|
|
*value = rtl_str_toDouble(reinterpret_cast< char const * >(text));
|
|
|
|
//TODO: check valid lexical representation
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
*value = fromXmlString(text, end).toDouble();
|
|
|
|
//TODO: check valid lexical representation
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool parseStringValue(
|
|
|
|
xmlChar const * text, xmlChar const * end, rtl::OUString * value)
|
|
|
|
{
|
|
|
|
OSL_ASSERT((text != 0 || end == 0) && value != 0);
|
|
|
|
if (end == 0) {
|
|
|
|
*value = fromXmlString(text);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
*value = fromXmlString(text, end);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2009-06-03 15:57:23 +02:00
|
|
|
enum ParseResult { PARSE_END, PARSE_GOOD, PARSE_BAD };
|
|
|
|
|
|
|
|
ParseResult parseHexDigit(
|
|
|
|
xmlChar const * text, xmlChar const * end, int * value)
|
|
|
|
{
|
|
|
|
OSL_ASSERT(text != 0 && value != 0);
|
|
|
|
if (end == 0 ? *text == '\0' : text == end) {
|
|
|
|
return PARSE_END;
|
|
|
|
}
|
|
|
|
xmlChar c = *text;
|
|
|
|
if (c >= '0' && c <= '9') {
|
|
|
|
*value = c - '0';
|
|
|
|
return PARSE_GOOD;
|
|
|
|
}
|
|
|
|
if (c >= 'A' && c <= 'F') {
|
|
|
|
*value = c - 'A' + 10;
|
|
|
|
return PARSE_GOOD;
|
|
|
|
}
|
|
|
|
if (c >= 'a' && c <= 'f') {
|
|
|
|
*value = c - 'a' + 10;
|
|
|
|
return PARSE_GOOD;
|
|
|
|
}
|
|
|
|
return PARSE_BAD;
|
|
|
|
}
|
|
|
|
|
2009-05-28 13:54:00 +02:00
|
|
|
bool parseHexbinaryValue(
|
2009-06-03 15:57:23 +02:00
|
|
|
xmlChar const * text, xmlChar const * end,
|
2009-05-28 13:54:00 +02:00
|
|
|
css::uno::Sequence< sal_Int8 > * value)
|
|
|
|
{
|
2009-06-03 15:57:23 +02:00
|
|
|
OSL_ASSERT((text != 0 || end == 0) && value != 0);
|
|
|
|
comphelper::SequenceAsVector< sal_Int8 > seq;
|
|
|
|
if (text != 0) {
|
|
|
|
for (xmlChar const * p = text;;) {
|
|
|
|
int n1;
|
|
|
|
switch (parseHexDigit(p++, end, &n1)) {
|
|
|
|
case PARSE_END:
|
|
|
|
goto done;
|
|
|
|
case PARSE_GOOD:
|
|
|
|
break;
|
|
|
|
case PARSE_BAD:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
int n2;
|
|
|
|
if (parseHexDigit(p++, end, &n2) != PARSE_GOOD) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
seq.push_back(static_cast< sal_Int8 >((n1 << 4) | n2));
|
|
|
|
}
|
|
|
|
done:;
|
|
|
|
}
|
|
|
|
*value = seq.getAsConstList();
|
|
|
|
return true;
|
2009-05-28 13:54:00 +02:00
|
|
|
}
|
|
|
|
|
2009-07-10 11:20:28 +02:00
|
|
|
template< typename T > xmlChar const * parseEscapedValue(
|
|
|
|
xmlChar const * text, bool (* parse)(xmlChar const *, xmlChar const *, T *),
|
|
|
|
T * value)
|
|
|
|
{
|
|
|
|
if (*text++ != '[') {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
rtl::OStringBuffer buf;
|
|
|
|
for (;;) {
|
|
|
|
xmlChar c = *text++;
|
|
|
|
switch (c) {
|
|
|
|
case '\0':
|
|
|
|
return 0;
|
|
|
|
case ']':
|
|
|
|
goto done;
|
|
|
|
case '\\':
|
|
|
|
c = *text++;
|
|
|
|
switch (c) {
|
|
|
|
case '\\':
|
|
|
|
case ']':
|
|
|
|
buf.append(static_cast< char >(c));
|
|
|
|
break;
|
|
|
|
case 'u':
|
|
|
|
if (text[0] == '0' && text[1] == '0' &&
|
|
|
|
(text[2] == '0' || text[2] == '1') &&
|
|
|
|
((text[3] >= '0' && text[3] <= '9') ||
|
|
|
|
(text[3] >= 'A' && text[3] <= 'F') ||
|
|
|
|
(text[3] >= 'a' && text[3] <= 'f')))
|
|
|
|
{
|
|
|
|
buf.append(
|
|
|
|
static_cast< char >(
|
|
|
|
((text[2] - '0') << 4) |
|
|
|
|
(text[3] <= '9'
|
|
|
|
? text[3] - '0'
|
|
|
|
: (text[3] - (text[3] <= 'F' ? 'A' : 'a') + 10))));
|
|
|
|
text += 4;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if ((text[0] == 'F' || text[0] == 'f') &&
|
|
|
|
(text[1] == 'F' || text[1] == 'f') &&
|
|
|
|
(text[2] == 'F' || text[2] == 'f') &&
|
|
|
|
(text[3] == 'E' || text[3] == 'e' ||
|
|
|
|
text[3] == 'F' || text[3] == 'f'))
|
|
|
|
{
|
|
|
|
buf.append(static_cast< char >(0xEF));
|
|
|
|
buf.append(static_cast< char >(0xBF));
|
|
|
|
buf.append(
|
|
|
|
static_cast< char >(
|
|
|
|
0xBE + (text[3] == 'F' || text[3] == 'f' ? 1 : 0)));
|
|
|
|
text += 4;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// fall through
|
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
buf.append(static_cast< char >(c));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
done:
|
|
|
|
rtl::OString unesc(buf.makeStringAndClear());
|
|
|
|
return
|
|
|
|
(*parse)(
|
|
|
|
reinterpret_cast< xmlChar const * >(unesc.getStr()),
|
|
|
|
(reinterpret_cast< xmlChar const * >(unesc.getStr()) +
|
|
|
|
unesc.getLength()),
|
|
|
|
value)
|
|
|
|
? text : 0;
|
|
|
|
}
|
|
|
|
|
2009-05-28 13:54:00 +02:00
|
|
|
template< typename T > bool parseListValue(
|
2009-07-10 11:20:28 +02:00
|
|
|
xmlDocPtr doc, xmlNodePtr node, xmlChar const * text,
|
2009-05-28 13:54:00 +02:00
|
|
|
bool (* parse)(xmlChar const *, xmlChar const *, T *),
|
|
|
|
css::uno::Sequence< T > * value)
|
|
|
|
{
|
|
|
|
OSL_ASSERT(parse != 0 && value != 0);
|
|
|
|
comphelper::SequenceAsVector< T > seq;
|
|
|
|
if (text != 0) {
|
|
|
|
XmlString sepAttr(
|
|
|
|
xmlGetNsProp(
|
|
|
|
node, xmlString("separator"),
|
|
|
|
xmlString("http://openoffice.org/2001/registry")));
|
2009-07-10 11:20:28 +02:00
|
|
|
if (getBooleanAttribute(
|
|
|
|
doc, node, "http://openoffice.org/2001/registry", "escaped",
|
|
|
|
false))
|
|
|
|
{
|
2009-05-28 13:54:00 +02:00
|
|
|
for (;;) {
|
|
|
|
T val;
|
2009-07-10 11:20:28 +02:00
|
|
|
text = parseEscapedValue(text, parse, &val);
|
|
|
|
if (text == 0) {
|
2009-05-28 13:54:00 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
seq.push_back(val);
|
2009-07-10 11:20:28 +02:00
|
|
|
if (*text == 0) {
|
2009-05-28 13:54:00 +02:00
|
|
|
break;
|
|
|
|
}
|
2009-07-10 11:20:28 +02:00
|
|
|
if (sepAttr.str == 0) {
|
|
|
|
xmlChar const * p = text;
|
|
|
|
while (*p == ' ' || *p == '\t' || *p == '\0x0A' ||
|
|
|
|
*p == '\0x0D')
|
|
|
|
{
|
|
|
|
++p;
|
|
|
|
}
|
|
|
|
if (p == text) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
text = p;
|
|
|
|
} else {
|
|
|
|
int sepLen = xmlStrlen(sepAttr.str);
|
|
|
|
if (xmlStrncmp(text, sepAttr.str, sepLen) != 0) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
text += sepLen;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
XmlString col;
|
|
|
|
xmlChar const * p;
|
|
|
|
xmlChar const * sep;
|
|
|
|
int sepLen;
|
|
|
|
if (sepAttr.str == 0) {
|
|
|
|
col = xmlSchemaCollapseString(text);
|
|
|
|
p = col.str == 0 ? text : col.str;
|
|
|
|
sep = xmlString(" ");
|
|
|
|
sepLen = RTL_CONSTASCII_LENGTH(" ");
|
|
|
|
} else {
|
|
|
|
p = text;
|
|
|
|
sep = sepAttr.str;
|
|
|
|
sepLen = xmlStrlen(sep);
|
|
|
|
}
|
|
|
|
if (*p != '\0') {
|
|
|
|
for (;;) {
|
|
|
|
xmlChar const * q = xmlStrstr(p, sep);
|
|
|
|
T val;
|
|
|
|
if (!(*parse)(p, q, &val)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
seq.push_back(val);
|
|
|
|
if (q == 0) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
p = q + sepLen;
|
|
|
|
}
|
2009-05-28 13:54:00 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*value = seq.getAsConstList();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2009-05-15 14:06:56 +02:00
|
|
|
css::uno::Any parseValue(xmlDocPtr doc, xmlNodePtr node, Type type) {
|
|
|
|
XmlString text(xmlNodeListGetString(doc, node->xmlChildrenNode, 1));
|
|
|
|
switch (type) {
|
2009-07-13 10:31:54 +02:00
|
|
|
case TYPE_ANY:
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM("invalid value of type any in ")) +
|
|
|
|
fromXmlString(doc->URL)),
|
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
case TYPE_BOOLEAN:
|
2009-05-28 13:54:00 +02:00
|
|
|
if (text.str != 0) {
|
2009-05-15 14:06:56 +02:00
|
|
|
XmlString col(xmlSchemaCollapseString(text.str));
|
2009-05-28 13:54:00 +02:00
|
|
|
sal_Bool val;
|
|
|
|
if (parseBooleanValue(col.str == 0 ? text.str : col.str, 0, &val)) {
|
|
|
|
return css::uno::makeAny(val);
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TYPE_SHORT:
|
2009-05-28 13:54:00 +02:00
|
|
|
if (text.str != 0) {
|
2009-05-15 14:06:56 +02:00
|
|
|
XmlString col(xmlSchemaCollapseString(text.str));
|
2009-05-28 13:54:00 +02:00
|
|
|
sal_Int16 val;
|
|
|
|
if (parseShortValue(col.str == 0 ? text.str : col.str, 0, &val)) {
|
|
|
|
return css::uno::makeAny(val);
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TYPE_INT:
|
2009-05-28 13:54:00 +02:00
|
|
|
if (text.str != 0) {
|
2009-05-15 14:06:56 +02:00
|
|
|
XmlString col(xmlSchemaCollapseString(text.str));
|
2009-05-28 13:54:00 +02:00
|
|
|
sal_Int32 val;
|
|
|
|
if (parseIntValue(col.str == 0 ? text.str : col.str, 0, &val)) {
|
|
|
|
return css::uno::makeAny(val);
|
|
|
|
}
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
2009-05-28 13:54:00 +02:00
|
|
|
break;
|
2009-05-15 14:06:56 +02:00
|
|
|
case TYPE_LONG:
|
2009-05-28 13:54:00 +02:00
|
|
|
if (text.str != 0) {
|
2009-05-15 14:06:56 +02:00
|
|
|
XmlString col(xmlSchemaCollapseString(text.str));
|
2009-05-28 13:54:00 +02:00
|
|
|
sal_Int64 val;
|
|
|
|
if (parseLongValue(col.str == 0 ? text.str : col.str, 0, &val)) {
|
|
|
|
return css::uno::makeAny(val);
|
|
|
|
}
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
2009-05-28 13:54:00 +02:00
|
|
|
break;
|
2009-05-15 14:06:56 +02:00
|
|
|
case TYPE_DOUBLE:
|
2009-05-28 13:54:00 +02:00
|
|
|
if (text.str != 0) {
|
2009-05-15 14:06:56 +02:00
|
|
|
XmlString col(xmlSchemaCollapseString(text.str));
|
2009-05-28 13:54:00 +02:00
|
|
|
double val;
|
|
|
|
if (parseDoubleValue(col.str == 0 ? text.str : col.str, 0, &val)) {
|
|
|
|
return css::uno::makeAny(val);
|
|
|
|
}
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
2009-05-28 13:54:00 +02:00
|
|
|
break;
|
2009-05-15 14:06:56 +02:00
|
|
|
case TYPE_STRING:
|
2009-07-10 11:20:28 +02:00
|
|
|
if (getBooleanAttribute(
|
|
|
|
doc, node, "http://openoffice.org/2001/registry", "escaped",
|
|
|
|
false))
|
2009-05-28 13:54:00 +02:00
|
|
|
{
|
2009-07-10 11:20:28 +02:00
|
|
|
rtl::OUString val;
|
|
|
|
xmlChar const * p = parseEscapedValue(
|
|
|
|
text.str, &parseStringValue, &val);
|
|
|
|
if (p != 0 && *p == '\0') {
|
|
|
|
return css::uno::makeAny(val);
|
|
|
|
}
|
|
|
|
} else {
|
2009-05-28 13:54:00 +02:00
|
|
|
rtl::OUString val;
|
|
|
|
if (parseStringValue(text.str, 0, &val)) {
|
|
|
|
return css::uno::makeAny(val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2009-05-15 14:06:56 +02:00
|
|
|
case TYPE_HEXBINARY:
|
2009-06-03 15:57:23 +02:00
|
|
|
{
|
|
|
|
XmlString col;
|
|
|
|
if (text.str != 0) {
|
|
|
|
col = xmlSchemaCollapseString(text.str);
|
|
|
|
}
|
|
|
|
css::uno::Sequence< sal_Int8 > val;
|
|
|
|
if (parseHexbinaryValue(col.str == 0 ? text.str : col.str, 0, &val))
|
|
|
|
{
|
2009-05-28 13:54:00 +02:00
|
|
|
return css::uno::makeAny(val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2009-05-15 14:06:56 +02:00
|
|
|
case TYPE_BOOLEAN_LIST:
|
2009-05-28 13:54:00 +02:00
|
|
|
{
|
|
|
|
css::uno::Sequence< sal_Bool > val;
|
2009-07-10 11:20:28 +02:00
|
|
|
if (parseListValue(doc, node, text.str, &parseBooleanValue, &val)) {
|
2009-05-28 13:54:00 +02:00
|
|
|
return css::uno::makeAny(val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2009-05-15 14:06:56 +02:00
|
|
|
case TYPE_SHORT_LIST:
|
2009-05-28 13:54:00 +02:00
|
|
|
{
|
|
|
|
css::uno::Sequence< sal_Int16 > val;
|
2009-07-10 11:20:28 +02:00
|
|
|
if (parseListValue(doc, node, text.str, &parseShortValue, &val)) {
|
2009-05-28 13:54:00 +02:00
|
|
|
return css::uno::makeAny(val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2009-05-15 14:06:56 +02:00
|
|
|
case TYPE_INT_LIST:
|
2009-05-28 13:54:00 +02:00
|
|
|
{
|
|
|
|
css::uno::Sequence< sal_Int32 > val;
|
2009-07-10 11:20:28 +02:00
|
|
|
if (parseListValue(doc, node, text.str, &parseIntValue, &val)) {
|
2009-05-28 13:54:00 +02:00
|
|
|
return css::uno::makeAny(val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2009-05-15 14:06:56 +02:00
|
|
|
case TYPE_LONG_LIST:
|
2009-05-28 13:54:00 +02:00
|
|
|
{
|
|
|
|
css::uno::Sequence< sal_Int64 > val;
|
2009-07-10 11:20:28 +02:00
|
|
|
if (parseListValue(doc, node, text.str, &parseLongValue, &val)) {
|
2009-05-28 13:54:00 +02:00
|
|
|
return css::uno::makeAny(val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2009-05-15 14:06:56 +02:00
|
|
|
case TYPE_DOUBLE_LIST:
|
2009-05-28 13:54:00 +02:00
|
|
|
{
|
|
|
|
css::uno::Sequence< double > val;
|
2009-07-10 11:20:28 +02:00
|
|
|
if (parseListValue(doc, node, text.str, &parseDoubleValue, &val)) {
|
2009-05-28 13:54:00 +02:00
|
|
|
return css::uno::makeAny(val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2009-05-15 14:06:56 +02:00
|
|
|
case TYPE_STRING_LIST:
|
|
|
|
{
|
2009-05-28 13:54:00 +02:00
|
|
|
css::uno::Sequence< rtl::OUString > val;
|
2009-07-10 11:20:28 +02:00
|
|
|
if (parseListValue(doc, node, text.str, &parseStringValue, &val)) {
|
2009-05-28 13:54:00 +02:00
|
|
|
return css::uno::makeAny(val);
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
}
|
2009-05-28 13:54:00 +02:00
|
|
|
break;
|
2009-05-15 14:06:56 +02:00
|
|
|
case TYPE_HEXBINARY_LIST:
|
2009-05-28 13:54:00 +02:00
|
|
|
{
|
|
|
|
css::uno::Sequence< css::uno::Sequence< sal_Int8 > > val;
|
2009-07-10 11:20:28 +02:00
|
|
|
if (parseListValue(doc, node, text.str, &parseHexbinaryValue, &val))
|
|
|
|
{
|
2009-05-28 13:54:00 +02:00
|
|
|
return css::uno::makeAny(val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2009-05-15 14:06:56 +02:00
|
|
|
default:
|
|
|
|
OSL_ASSERT(false);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("invalid value in ")) +
|
|
|
|
fromXmlString(doc->URL)),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
rtl::OUString parseTemplateReference(
|
|
|
|
rtl::OUString const & componentName, xmlDocPtr doc, xmlNodePtr node,
|
|
|
|
rtl::OUString const * defaultTemplateName)
|
|
|
|
{
|
|
|
|
XmlString nodeType(
|
|
|
|
xmlGetNsProp(
|
|
|
|
node, xmlString("node-type"),
|
|
|
|
xmlString("http://openoffice.org/2001/registry")));
|
|
|
|
if (nodeType.str == 0) {
|
|
|
|
if (defaultTemplateName != 0) {
|
|
|
|
return *defaultTemplateName;
|
|
|
|
}
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"xcs: missing node-type attribute in ")) +
|
|
|
|
fromXmlString(doc->URL)),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
XmlString component(
|
|
|
|
xmlGetNsProp(
|
|
|
|
node, xmlString("component"),
|
|
|
|
xmlString("http://openoffice.org/2001/registry")));
|
|
|
|
return fullTemplateName(
|
|
|
|
(component.str == 0 ? componentName : fromXmlString(component.str)),
|
|
|
|
fromXmlString(nodeType.str));
|
|
|
|
}
|
|
|
|
|
|
|
|
void parseXcsGroupContent(
|
|
|
|
rtl::OUString const & componentName, xmlDocPtr doc, xmlNodePtr node,
|
2009-05-28 10:19:30 +02:00
|
|
|
rtl::Reference< GroupNode > const & group,
|
|
|
|
Components::TemplateMap const & templates);
|
2009-05-15 14:06:56 +02:00
|
|
|
|
2009-05-19 10:49:37 +02:00
|
|
|
rtl::Reference< Node > parseXcsGroup(
|
|
|
|
rtl::OUString const & componentName, xmlDocPtr doc, xmlNodePtr node,
|
2009-06-04 10:46:43 +02:00
|
|
|
rtl::OUString const & templateName,
|
2009-05-28 10:19:30 +02:00
|
|
|
Components::TemplateMap const & templates)
|
2009-05-15 14:06:56 +02:00
|
|
|
{
|
2009-05-19 10:49:37 +02:00
|
|
|
rtl::Reference< GroupNode > group(
|
2009-05-15 14:06:56 +02:00
|
|
|
new GroupNode(
|
|
|
|
getBooleanAttribute(
|
|
|
|
doc, node, "http://openoffice.org/2001/registry", "extensible",
|
2009-05-19 17:32:24 +02:00
|
|
|
false),
|
|
|
|
templateName));
|
2009-05-28 10:19:30 +02:00
|
|
|
parseXcsGroupContent(componentName, doc, node, group, templates);
|
2009-05-19 10:49:37 +02:00
|
|
|
return group.get();
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Node * parseXcsSet(
|
2009-05-19 10:49:37 +02:00
|
|
|
rtl::OUString const & componentName, xmlDocPtr doc, xmlNodePtr node,
|
2009-06-04 10:46:43 +02:00
|
|
|
rtl::OUString const & templateName)
|
2009-05-15 14:06:56 +02:00
|
|
|
{
|
|
|
|
xmlNodePtr p(skipBlank(node->xmlChildrenNode));
|
|
|
|
if (isOorElement(p, "info")) {
|
|
|
|
p = skipBlank(p->next);
|
|
|
|
}
|
|
|
|
std::vector< rtl::OUString > additional;
|
|
|
|
while (isOorElement(p, "item")) {
|
|
|
|
additional.push_back(parseTemplateReference(componentName, doc, p, 0));
|
|
|
|
p = skipBlank(p->next);
|
|
|
|
}
|
|
|
|
if (p != 0) {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"xcs: bad set content in ")) +
|
|
|
|
fromXmlString(doc->URL)),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
return new SetNode(
|
2009-06-04 10:46:43 +02:00
|
|
|
parseTemplateReference(componentName, doc, node, 0), additional,
|
2009-05-29 16:48:52 +02:00
|
|
|
templateName);
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void parseXcsGroupContent(
|
|
|
|
rtl::OUString const & componentName, xmlDocPtr doc, xmlNodePtr node,
|
2009-05-28 10:19:30 +02:00
|
|
|
rtl::Reference< GroupNode > const & group,
|
|
|
|
Components::TemplateMap const & templates)
|
2009-05-15 14:06:56 +02:00
|
|
|
{
|
|
|
|
xmlNodePtr p(skipBlank(node->xmlChildrenNode));
|
|
|
|
if (isOorElement(p, "info")) {
|
|
|
|
p = skipBlank(p->next);
|
|
|
|
}
|
|
|
|
for (; p != 0; p = skipBlank(p->next)) {
|
2009-05-19 10:49:37 +02:00
|
|
|
rtl::Reference< Node > member;
|
2009-05-15 14:06:56 +02:00
|
|
|
if (isOorElement(p, "prop")) {
|
|
|
|
Type type(getTypeAttribute(doc, p));
|
2009-06-03 18:02:52 +02:00
|
|
|
if (type == TYPE_ERROR) {
|
2009-05-15 14:06:56 +02:00
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"xcs: missing type attribute in ")) +
|
|
|
|
fromXmlString(doc->URL)),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
xmlNodePtr q(skipBlank(p->xmlChildrenNode));
|
|
|
|
if (isOorElement(q, "info")) {
|
|
|
|
q = skipBlank(q->next);
|
|
|
|
}
|
|
|
|
if (isOorElement(q, "constraints")) { //TODO
|
|
|
|
q = skipBlank(q->next);
|
|
|
|
}
|
|
|
|
LocalizedValues values;
|
|
|
|
if (isOorElement(q, "value")) {
|
|
|
|
values.insert(
|
|
|
|
LocalizedValues::value_type(
|
|
|
|
rtl::OUString(), parseValue(doc, q, type)));
|
|
|
|
q = skipBlank(q->next);
|
|
|
|
}
|
|
|
|
if (q != 0) {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"xcs: bad prop content in ")) +
|
|
|
|
fromXmlString(doc->URL)),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
2009-05-20 17:20:08 +02:00
|
|
|
if (getBooleanAttribute(
|
2009-05-15 14:06:56 +02:00
|
|
|
doc, p, "http://openoffice.org/2001/registry", "localized",
|
2009-05-20 17:20:08 +02:00
|
|
|
false))
|
|
|
|
{
|
|
|
|
rtl::Reference< LocalizedPropertyNode > locprop(
|
2009-05-15 14:06:56 +02:00
|
|
|
new LocalizedPropertyNode(
|
2009-06-04 10:46:43 +02:00
|
|
|
type,
|
2009-05-15 14:06:56 +02:00
|
|
|
getBooleanAttribute(
|
|
|
|
doc, p, "http://openoffice.org/2001/registry",
|
2009-05-20 17:20:08 +02:00
|
|
|
"nillable", true)));
|
|
|
|
setValues(locprop.get(), values);
|
|
|
|
member = locprop.get();
|
|
|
|
} else {
|
|
|
|
member = new PropertyNode(
|
2009-06-04 10:46:43 +02:00
|
|
|
type,
|
2009-05-20 17:20:08 +02:00
|
|
|
getBooleanAttribute(
|
|
|
|
doc, p, "http://openoffice.org/2001/registry",
|
|
|
|
"nillable", true),
|
|
|
|
values[rtl::OUString()], false);
|
|
|
|
}
|
2009-05-15 14:06:56 +02:00
|
|
|
} else if (isOorElement(p, "node-ref")) {
|
|
|
|
xmlNodePtr q(skipBlank(p->xmlChildrenNode));
|
|
|
|
if (isOorElement(q, "info")) {
|
|
|
|
q = skipBlank(q->next);
|
|
|
|
}
|
|
|
|
if (q != 0) {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"xcs: bad set content in ")) +
|
|
|
|
fromXmlString(doc->URL)),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
2009-05-19 10:49:37 +02:00
|
|
|
member = new NodeRef(
|
2009-06-04 10:46:43 +02:00
|
|
|
parseTemplateReference(componentName, doc, p, 0), templates);
|
2009-05-15 14:06:56 +02:00
|
|
|
} else if (isOorElement(p, "group")) {
|
2009-05-19 10:49:37 +02:00
|
|
|
member = parseXcsGroup(
|
2009-06-04 10:46:43 +02:00
|
|
|
componentName, doc, p, rtl::OUString(), templates);
|
2009-05-15 14:06:56 +02:00
|
|
|
} else if (isOorElement(p, "set")) {
|
2009-06-04 10:46:43 +02:00
|
|
|
member = parseXcsSet(componentName, doc, p, rtl::OUString());
|
2009-05-15 14:06:56 +02:00
|
|
|
} else {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"xcs: bad component-schema/component content in ")) +
|
|
|
|
fromXmlString(doc->URL)),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
2009-05-19 10:49:37 +02:00
|
|
|
if (!group->getMembers().insert(
|
2009-05-29 16:48:52 +02:00
|
|
|
NodeMap::value_type(getNameAttribute(doc, p), member)).
|
2009-05-19 10:49:37 +02:00
|
|
|
second)
|
2009-05-15 14:06:56 +02:00
|
|
|
{
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"xcs: multiple members with same name in ")) +
|
|
|
|
fromXmlString(doc->URL)),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
xmlNodePtr parseXcsTemplates(
|
|
|
|
rtl::OUString const & componentName, xmlDocPtr doc, xmlNodePtr node,
|
2009-05-19 10:49:37 +02:00
|
|
|
Components::TemplateMap * templates)
|
2009-05-15 14:06:56 +02:00
|
|
|
{
|
|
|
|
if (!isOorElement(node, "templates")) {
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
xmlNodePtr p(skipBlank(node->xmlChildrenNode));
|
|
|
|
if (isOorElement(p, "info")) {
|
|
|
|
p = skipBlank(p->next);
|
|
|
|
}
|
|
|
|
for (; p != 0; p = skipBlank(p->next)) {
|
2009-05-19 17:32:24 +02:00
|
|
|
rtl::OUString tmplName;
|
|
|
|
rtl::Reference< Node > tmpl;
|
2009-05-15 14:06:56 +02:00
|
|
|
if (isOorElement(p, "group")) {
|
2009-05-19 17:32:24 +02:00
|
|
|
tmplName = fullTemplateName(
|
|
|
|
componentName, getNameAttribute(doc, p));
|
2009-06-04 10:46:43 +02:00
|
|
|
tmpl = parseXcsGroup(componentName, doc, p, tmplName, *templates);
|
2009-05-15 14:06:56 +02:00
|
|
|
} else if (isOorElement(p, "set")) {
|
2009-05-19 17:32:24 +02:00
|
|
|
tmplName = fullTemplateName(
|
|
|
|
componentName, getNameAttribute(doc, p));
|
2009-06-04 10:46:43 +02:00
|
|
|
tmpl = parseXcsSet(componentName, doc, p, tmplName);
|
2009-05-15 14:06:56 +02:00
|
|
|
} else {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"xcs: bad component-schema/templates content in ")) +
|
|
|
|
fromXmlString(doc->URL)),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
2009-05-19 17:32:24 +02:00
|
|
|
if (!templates->insert(NodeMap::value_type(tmplName, tmpl)).second) {
|
2009-05-15 14:06:56 +02:00
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"xcs: multiple templates with same name in ")) +
|
|
|
|
fromXmlString(doc->URL)),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return node->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
xmlNodePtr parseXcsComponent(
|
|
|
|
xmlDocPtr doc, rtl::OUString const & component, xmlNodePtr node,
|
2009-05-28 10:19:30 +02:00
|
|
|
NodeMap * components, Components::TemplateMap const & templates)
|
2009-05-15 14:06:56 +02:00
|
|
|
{
|
|
|
|
if (!isOorElement(node, "component")) {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"xcs: bad component-schema content in ")) +
|
|
|
|
fromXmlString(doc->URL)),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
2009-06-04 10:46:43 +02:00
|
|
|
rtl::Reference< GroupNode > comp(new GroupNode(false, rtl::OUString()));
|
2009-05-28 10:19:30 +02:00
|
|
|
parseXcsGroupContent(component, doc, node, comp, templates);
|
2009-05-15 14:06:56 +02:00
|
|
|
if (!components->insert(NodeMap::value_type(component, comp.get())).second)
|
|
|
|
{
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"xcs: multiply defined component-schema in ")) +
|
|
|
|
fromXmlString(doc->URL)),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
return node->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
void parseXcsFile(
|
2009-05-19 10:49:37 +02:00
|
|
|
rtl::OUString const & url, Components::TemplateMap * templates,
|
|
|
|
NodeMap * components)
|
2009-05-15 14:06:56 +02:00
|
|
|
{
|
|
|
|
XmlDoc doc(parseXmlFile(url));
|
|
|
|
xmlNodePtr root(xmlDocGetRootElement(doc.doc));
|
|
|
|
if (root == 0) {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM("xcs: no root element in ")) +
|
|
|
|
fromXmlString(doc.doc->URL)),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
if (!xmlStrEqual(root->name, xmlString("component-schema")) ||
|
|
|
|
root->ns == 0 ||
|
|
|
|
!xmlStrEqual(
|
|
|
|
root->ns->href, xmlString("http://openoffice.org/2001/registry")))
|
|
|
|
{
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"xcs: non component-schema root element in ")) +
|
|
|
|
fromXmlString(doc.doc->URL)),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
XmlString package(
|
|
|
|
xmlGetNsProp(
|
|
|
|
root, xmlString("package"),
|
|
|
|
xmlString("http://openoffice.org/2001/registry")));
|
|
|
|
if (package.str == 0) {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"xcs: no root package attribute in ")) +
|
|
|
|
fromXmlString(doc.doc->URL)),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
rtl::OUStringBuffer buf(fromXmlString(package.str));
|
|
|
|
buf.append(sal_Unicode('.'));
|
|
|
|
buf.append(getNameAttribute(doc.doc, root));
|
|
|
|
rtl::OUString comp(buf.makeStringAndClear());
|
|
|
|
//TODO: root xml:lang attribute
|
|
|
|
xmlNodePtr p(skipBlank(root->xmlChildrenNode));
|
|
|
|
if (isOorElement(p, "info")) {
|
|
|
|
p = skipBlank(p->next);
|
|
|
|
}
|
|
|
|
while (isOorElement(p, "import")) { //TODO: process?
|
|
|
|
p = skipBlank(p->next);
|
|
|
|
}
|
|
|
|
while (isOorElement(p, "uses")) { //TODO: process?
|
|
|
|
p = skipBlank(p->next);
|
|
|
|
}
|
|
|
|
p = skipBlank(parseXcsTemplates(comp, doc.doc, p, templates));
|
2009-05-28 10:19:30 +02:00
|
|
|
p = skipBlank(parseXcsComponent(doc.doc, comp, p, components, *templates));
|
2009-05-15 14:06:56 +02:00
|
|
|
if (p != 0) {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"xcs: bad component-schema content in ")) +
|
|
|
|
fromXmlString(doc.doc->URL)),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void parseXcuNode(
|
2009-05-19 10:49:37 +02:00
|
|
|
rtl::OUString const & componentName,
|
|
|
|
Components::TemplateMap const & templates, xmlDocPtr doc,
|
2009-07-08 17:25:16 +02:00
|
|
|
xmlNodePtr xmlNode, rtl::Reference< Node > const & node,
|
|
|
|
Components * modifications, rtl::OUString const & pathPrefix)
|
2009-05-15 14:06:56 +02:00
|
|
|
{
|
2009-05-19 10:49:37 +02:00
|
|
|
if (GroupNode * group = dynamic_cast< GroupNode * >(node.get())) {
|
2009-05-15 14:06:56 +02:00
|
|
|
for (xmlNodePtr p(skipBlank(xmlNode->xmlChildrenNode)); p != 0;
|
|
|
|
p = skipBlank(p->next))
|
|
|
|
{
|
|
|
|
if (isOorElement(p, "prop")) {
|
|
|
|
rtl::OUString name(getNameAttribute(doc, p));
|
|
|
|
PropertyNode * property = 0;
|
|
|
|
LocalizedPropertyNode * localized = 0;
|
2009-05-28 10:19:30 +02:00
|
|
|
NodeMap::iterator i(
|
|
|
|
Components::resolveNode(name, &group->getMembers()));
|
2009-05-15 14:06:56 +02:00
|
|
|
if (i != group->getMembers().end()) {
|
2009-05-19 10:49:37 +02:00
|
|
|
property = dynamic_cast< PropertyNode * >(i->second.get());
|
2009-05-15 14:06:56 +02:00
|
|
|
localized = dynamic_cast< LocalizedPropertyNode * >(
|
2009-05-19 10:49:37 +02:00
|
|
|
i->second.get());
|
2009-05-15 14:06:56 +02:00
|
|
|
if (property == 0 && localized == 0) {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"xcu: inappropriate prop in ")) +
|
|
|
|
fromXmlString(doc->URL)),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
Type type(getTypeAttribute(doc, p));
|
|
|
|
if (type == TYPE_ANY) {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"xcu: invalid type attribute in ")) +
|
|
|
|
fromXmlString(doc->URL)),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
2009-07-13 14:54:09 +02:00
|
|
|
Operation op(getOperationAttribute(doc, p));
|
2009-05-15 14:06:56 +02:00
|
|
|
//TODO: oor:finalized attributes
|
|
|
|
xmlNodePtr q(skipBlank(p->xmlChildrenNode));
|
|
|
|
LocalizedValues values;
|
|
|
|
while (isOorElement(q, "value")) {
|
2009-06-03 18:02:52 +02:00
|
|
|
if (type == TYPE_ERROR) {
|
2009-05-15 14:06:56 +02:00
|
|
|
if (property != 0) {
|
|
|
|
type = property->getType();
|
|
|
|
} else if (localized != 0) {
|
|
|
|
type = localized->getType();
|
|
|
|
} else {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"xcu: missing type attribute in ")) +
|
|
|
|
fromXmlString(doc->URL)),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
if (type == TYPE_ANY) {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"xcu: missing type attribute in ")) +
|
|
|
|
fromXmlString(doc->URL)),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
bool nil = getBooleanAttribute(
|
|
|
|
doc, q, "http://www.w3.org/2001/XMLSchema-instance",
|
|
|
|
"nil", false);
|
|
|
|
if (nil &&
|
|
|
|
((property != 0 && !property->isNillable()) ||
|
|
|
|
(localized != 0 && !localized->isNillable())))
|
|
|
|
{
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"xcu: xsi:nil attribute for non-nillable"
|
|
|
|
" prop in ")) +
|
|
|
|
fromXmlString(doc->URL)),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
XmlString lang(xmlNodeGetLang(q));
|
|
|
|
if (lang.str != 0 && localized == 0) {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"xcu: xml:lang attribute for non-localized"
|
|
|
|
" prop in ")) +
|
|
|
|
fromXmlString(doc->URL)),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
2009-07-13 14:54:09 +02:00
|
|
|
bool remove;
|
|
|
|
switch (getOperationAttribute(doc, q)) {
|
|
|
|
case OPERATION_MODIFY:
|
|
|
|
remove = false;
|
|
|
|
break;
|
|
|
|
case OPERATION_REMOVE:
|
|
|
|
//TODO: disallow removing when e.g. lang=""?
|
|
|
|
if (localized != 0 && op == OPERATION_FUSE) {
|
|
|
|
remove = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// fall through
|
|
|
|
default:
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"xcu: bad op attribute for value element"
|
|
|
|
" in ")) +
|
|
|
|
fromXmlString(doc->URL)),
|
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
|
|
|
}
|
|
|
|
// For nil and removed values, any actually provided value
|
|
|
|
// is simply ignored for now:
|
2009-05-15 14:06:56 +02:00
|
|
|
if (!values.insert(
|
|
|
|
LocalizedValues::value_type(
|
2009-07-13 14:54:09 +02:00
|
|
|
(lang.str == 0
|
|
|
|
? rtl::OUString() : fromXmlString(lang.str)),
|
|
|
|
(remove
|
|
|
|
? css::uno::makeAny(
|
|
|
|
cppu::UnoType< cppu::UnoVoidType >::get())
|
|
|
|
: (nil
|
|
|
|
? css::uno::Any()
|
|
|
|
: parseValue(doc, q, type))))).
|
2009-05-15 14:06:56 +02:00
|
|
|
second)
|
|
|
|
{
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"xcu: multiple values (for same xml:lang)"
|
|
|
|
" in ")) +
|
|
|
|
fromXmlString(doc->URL)),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
q = skipBlank(q->next);
|
|
|
|
}
|
|
|
|
if (q != 0) {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"xcu: bad prop content in ")) +
|
|
|
|
fromXmlString(doc->URL)),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
if (i == group->getMembers().end()) {
|
|
|
|
if (!group->isExtensible()) {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"xcu: unknown prop name in ")) +
|
|
|
|
fromXmlString(doc->URL)),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
2009-07-13 14:54:09 +02:00
|
|
|
switch (op) {
|
2009-05-15 14:06:56 +02:00
|
|
|
case OPERATION_MODIFY:
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"xcu: invalid modify of extension property"
|
|
|
|
" in ")) +
|
|
|
|
fromXmlString(doc->URL)),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
case OPERATION_REPLACE:
|
|
|
|
case OPERATION_FUSE:
|
2009-05-19 10:49:37 +02:00
|
|
|
group->getMembers().insert(
|
|
|
|
NodeMap::value_type(
|
|
|
|
name,
|
2009-05-15 14:06:56 +02:00
|
|
|
new PropertyNode(
|
2009-07-13 10:28:10 +02:00
|
|
|
TYPE_ANY, true, values[rtl::OUString()],
|
2009-05-29 16:48:52 +02:00
|
|
|
true)));
|
2009-05-15 14:06:56 +02:00
|
|
|
break;
|
|
|
|
case OPERATION_REMOVE:
|
|
|
|
// ignore unknown (presumably extension) properties
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
2009-07-13 14:54:09 +02:00
|
|
|
switch (op) {
|
2009-05-15 14:06:56 +02:00
|
|
|
case OPERATION_MODIFY:
|
|
|
|
case OPERATION_FUSE:
|
|
|
|
if (property != 0) {
|
|
|
|
property->setValue(values[rtl::OUString()]);
|
|
|
|
} else {
|
|
|
|
for (LocalizedValues::iterator j(values.begin());
|
|
|
|
j != values.end(); ++j)
|
|
|
|
{
|
2009-07-13 14:54:09 +02:00
|
|
|
if (isRemovedValue(j->second)) {
|
|
|
|
localized->getMembers().erase(j->first);
|
2009-05-20 17:20:08 +02:00
|
|
|
} else {
|
2009-07-13 14:54:09 +02:00
|
|
|
NodeMap::iterator k(
|
|
|
|
Components::resolveNode(
|
|
|
|
j->first,
|
|
|
|
&localized->getMembers()));
|
|
|
|
if (k == localized->getMembers().end()) {
|
|
|
|
localized->getMembers().insert(
|
|
|
|
NodeMap::value_type(
|
|
|
|
j->first,
|
|
|
|
new LocalizedPropertyValueNode(
|
|
|
|
j->second)));
|
|
|
|
} else {
|
|
|
|
dynamic_cast<
|
|
|
|
LocalizedPropertyValueNode * >(
|
|
|
|
k->second.get())->
|
|
|
|
setValue(j->second);
|
|
|
|
}
|
2009-05-20 17:20:08 +02:00
|
|
|
}
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case OPERATION_REPLACE:
|
|
|
|
if (property != 0) {
|
|
|
|
property->setValue(values[rtl::OUString()]);
|
|
|
|
} else {
|
2009-05-20 17:20:08 +02:00
|
|
|
localized->getMembers().clear();
|
|
|
|
setValues(localized, values);
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case OPERATION_REMOVE:
|
|
|
|
{
|
|
|
|
if (!property->isExtension()) {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"xcu: invalid remove of"
|
|
|
|
" non-extension property in ")) +
|
|
|
|
fromXmlString(doc->URL)),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference<
|
|
|
|
css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
group->getMembers().erase(i);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2009-07-08 17:25:16 +02:00
|
|
|
if (modifications != 0) {
|
|
|
|
if (localized == 0) {
|
|
|
|
modifications->addModification(pathPrefix + name);
|
|
|
|
} else {
|
|
|
|
rtl::OUString path(
|
|
|
|
pathPrefix + name +
|
|
|
|
rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/")));
|
|
|
|
for (LocalizedValues::iterator j(values.begin());
|
|
|
|
j != values.end(); ++j)
|
|
|
|
{
|
|
|
|
modifications->addModification(
|
|
|
|
path +
|
|
|
|
Components::createSegment(
|
|
|
|
rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM("*")),
|
|
|
|
j->first));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-05-15 14:06:56 +02:00
|
|
|
} else if (isOorElement(p, "node")) {
|
|
|
|
Operation op = getOperationAttribute(doc, p);
|
2009-07-08 17:25:16 +02:00
|
|
|
if ((op != OPERATION_MODIFY && op != OPERATION_FUSE) ||
|
|
|
|
modifications != 0)
|
|
|
|
{
|
2009-05-15 14:06:56 +02:00
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
2009-07-13 10:28:10 +02:00
|
|
|
"xcu: invalid operation on group node in ")) +
|
2009-05-15 14:06:56 +02:00
|
|
|
fromXmlString(doc->URL)),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
//TODO: oor:component, oor:finalized, oor:mandatory, oor:node-type attributes
|
|
|
|
NodeMap::iterator i(
|
2009-05-28 10:19:30 +02:00
|
|
|
Components::resolveNode(
|
|
|
|
getNameAttribute(doc, p), &group->getMembers()));
|
2009-05-15 14:06:56 +02:00
|
|
|
if (i == group->getMembers().end()) {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"xcu: unknown node name in ")) +
|
|
|
|
fromXmlString(doc->URL)),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
2009-07-08 17:25:16 +02:00
|
|
|
parseXcuNode(
|
|
|
|
componentName, templates, doc, p, i->second, 0,
|
|
|
|
rtl::OUString());
|
2009-05-15 14:06:56 +02:00
|
|
|
} else {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"xcu: bad component-data or node content in ")) +
|
|
|
|
fromXmlString(doc->URL)),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
}
|
2009-05-19 10:49:37 +02:00
|
|
|
} else if (SetNode * set = dynamic_cast< SetNode * >(node.get())) {
|
2009-05-15 14:06:56 +02:00
|
|
|
for (xmlNodePtr p(skipBlank(xmlNode->xmlChildrenNode)); p != 0;
|
|
|
|
p = skipBlank(p->next))
|
|
|
|
{
|
|
|
|
if (!isOorElement(p, "node")) {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"xcu: non-node element within set node element"
|
|
|
|
" in ")) +
|
|
|
|
fromXmlString(doc->URL)),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
rtl::OUString name(getNameAttribute(doc, p));
|
|
|
|
rtl::OUString templateName(
|
|
|
|
parseTemplateReference(
|
|
|
|
componentName, doc, p, &set->getDefaultTemplateName()));
|
|
|
|
if (!set->isValidTemplate(templateName)) {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"xcu: set member node references invalid template"
|
|
|
|
" in ")) +
|
|
|
|
fromXmlString(doc->URL)),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
2009-05-19 10:49:37 +02:00
|
|
|
Components::TemplateMap::const_iterator i(
|
|
|
|
templates.find(templateName));
|
2009-05-15 14:06:56 +02:00
|
|
|
if (i == templates.end()) {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"xcu: set member node references undefined template"
|
|
|
|
" in ")) +
|
|
|
|
fromXmlString(doc->URL)),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
switch (getOperationAttribute(doc, p)) {
|
|
|
|
case OPERATION_MODIFY:
|
|
|
|
{
|
2009-05-28 10:19:30 +02:00
|
|
|
NodeMap::iterator j(
|
|
|
|
Components::resolveNode(name, &set->getMembers()));
|
2009-05-15 14:06:56 +02:00
|
|
|
if (j == set->getMembers().end()) {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"xcu: invalid modify of unknown set member"
|
|
|
|
" node in ")) +
|
|
|
|
fromXmlString(doc->URL)),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
2009-07-08 17:25:16 +02:00
|
|
|
parseXcuNode(
|
|
|
|
componentName, templates, doc, p, j->second, 0,
|
|
|
|
rtl::OUString());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case OPERATION_REPLACE:
|
|
|
|
{
|
2009-06-04 10:46:43 +02:00
|
|
|
rtl::Reference< Node > member(i->second->clone());
|
2009-07-08 17:25:16 +02:00
|
|
|
parseXcuNode(
|
|
|
|
componentName, templates, doc, p, member, 0,
|
|
|
|
rtl::OUString());
|
2009-05-28 10:19:30 +02:00
|
|
|
NodeMap::iterator j(
|
|
|
|
Components::resolveNode(name, &set->getMembers()));
|
2009-05-19 10:49:37 +02:00
|
|
|
if (j == set->getMembers().end()) {
|
2009-05-15 14:06:56 +02:00
|
|
|
set->getMembers().insert(
|
2009-05-19 10:49:37 +02:00
|
|
|
NodeMap::value_type(name, member));
|
|
|
|
} else {
|
|
|
|
j->second = member;
|
|
|
|
};
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case OPERATION_FUSE:
|
|
|
|
{
|
2009-05-28 10:19:30 +02:00
|
|
|
NodeMap::iterator j(
|
|
|
|
Components::resolveNode(name, &set->getMembers()));
|
2009-05-15 14:06:56 +02:00
|
|
|
if (j == set->getMembers().end()) {
|
2009-06-04 10:46:43 +02:00
|
|
|
rtl::Reference< Node > member(i->second->clone());
|
2009-07-08 17:25:16 +02:00
|
|
|
parseXcuNode(
|
|
|
|
componentName, templates, doc, p, member, 0,
|
|
|
|
rtl::OUString());
|
2009-05-15 14:06:56 +02:00
|
|
|
set->getMembers().insert(
|
2009-05-29 16:48:52 +02:00
|
|
|
NodeMap::value_type(name, member));
|
2009-05-15 14:06:56 +02:00
|
|
|
} else {
|
|
|
|
parseXcuNode(
|
2009-07-08 17:25:16 +02:00
|
|
|
componentName, templates, doc, p, j->second, 0,
|
|
|
|
rtl::OUString());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case OPERATION_REMOVE:
|
|
|
|
{
|
2009-05-28 10:19:30 +02:00
|
|
|
NodeMap::iterator j(
|
|
|
|
Components::resolveNode(name, &set->getMembers()));
|
2009-05-15 14:06:56 +02:00
|
|
|
// Ignore unknown members:
|
|
|
|
if (j != set->getMembers().end()) {
|
|
|
|
set->getMembers().erase(j);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2009-07-08 17:25:16 +02:00
|
|
|
if (modifications != 0) {
|
|
|
|
modifications->addModification(
|
|
|
|
pathPrefix + Components::createSegment(templateName, name));
|
|
|
|
}
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM("xcu: inappropriate node in ")) +
|
|
|
|
fromXmlString(doc->URL)),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void parseXcuFile(
|
2009-05-19 10:49:37 +02:00
|
|
|
rtl::OUString const & url, Components::TemplateMap * templates,
|
|
|
|
NodeMap * components)
|
2009-05-15 14:06:56 +02:00
|
|
|
{
|
|
|
|
XmlDoc doc(parseXmlFile(url));
|
|
|
|
xmlNodePtr root(xmlDocGetRootElement(doc.doc));
|
|
|
|
if (root == 0) {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM("xcu: no root element in ")) +
|
|
|
|
fromXmlString(doc.doc->URL)),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
if (!xmlStrEqual(root->name, xmlString("component-data")) ||
|
|
|
|
root->ns == 0 ||
|
|
|
|
!xmlStrEqual(
|
|
|
|
root->ns->href, xmlString("http://openoffice.org/2001/registry")))
|
|
|
|
{
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"xcu: non component-data root element in ")) +
|
|
|
|
fromXmlString(doc.doc->URL)),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
XmlString package(
|
|
|
|
xmlGetNsProp(
|
|
|
|
root, xmlString("package"),
|
|
|
|
xmlString("http://openoffice.org/2001/registry")));
|
|
|
|
if (package.str == 0) {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"xcu: no root package attribute in ")) +
|
|
|
|
fromXmlString(doc.doc->URL)),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
rtl::OUStringBuffer buf(fromXmlString(package.str));
|
|
|
|
buf.append(sal_Unicode('.'));
|
|
|
|
buf.append(getNameAttribute(doc.doc, root));
|
|
|
|
rtl::OUString comp(buf.makeStringAndClear());
|
|
|
|
//TODO: root oor:finalized, oor:op attributes
|
2009-05-28 10:19:30 +02:00
|
|
|
NodeMap::iterator i(Components::resolveNode(comp, components));
|
2009-05-15 14:06:56 +02:00
|
|
|
if (i == components->end()) {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"xcu: unknown component-data name in ")) +
|
|
|
|
fromXmlString(doc.doc->URL)),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
2009-07-08 17:25:16 +02:00
|
|
|
parseXcuNode(
|
|
|
|
comp, *templates, doc.doc, root, i->second, 0, rtl::OUString());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void parseFiles(
|
|
|
|
rtl::OUString const & extension,
|
2009-05-19 10:49:37 +02:00
|
|
|
void (* parseFile)(
|
|
|
|
rtl::OUString const &, Components::TemplateMap *, NodeMap *),
|
|
|
|
rtl::OUString const & url, Components::TemplateMap * templates,
|
|
|
|
NodeMap * components, bool recursive)
|
2009-05-15 14:06:56 +02:00
|
|
|
{
|
|
|
|
osl::Directory dir(url);
|
|
|
|
switch (dir.open()) {
|
|
|
|
case osl::FileBase::E_None:
|
|
|
|
break;
|
|
|
|
case osl::FileBase::E_NOENT:
|
|
|
|
if (!recursive) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// fall through
|
|
|
|
default:
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM("cannot open directory ")) +
|
|
|
|
url),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
for (;;) {
|
|
|
|
osl::DirectoryItem i;
|
|
|
|
osl::FileBase::RC rc = dir.getNextItem(i, SAL_MAX_UINT32);
|
|
|
|
if (rc == osl::FileBase::E_NOENT) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (rc != osl::FileBase::E_None) {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM("cannot iterate directory ")) +
|
|
|
|
url),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
osl::FileStatus stat(
|
|
|
|
FileStatusMask_Type | FileStatusMask_FileName |
|
|
|
|
FileStatusMask_FileURL);
|
|
|
|
if (i.getFileStatus(stat) != osl::FileBase::E_None) {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM("cannot stat in directory ")) +
|
|
|
|
url),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
if (stat.getFileType() == osl::FileStatus::Directory) { //TODO: symlinks
|
|
|
|
parseFiles(
|
|
|
|
extension, parseFile, stat.getFileURL(), templates, components,
|
|
|
|
true);
|
|
|
|
} else {
|
|
|
|
rtl::OUString file(stat.getFileName());
|
|
|
|
if (file.getLength() >= extension.getLength() &&
|
|
|
|
file.match(extension, file.getLength() - extension.getLength()))
|
|
|
|
{
|
|
|
|
(*parseFile)(stat.getFileURL(), templates, components);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void parseXcsXcuLayer(
|
2009-05-19 10:49:37 +02:00
|
|
|
rtl::OUString const & url, Components::TemplateMap * templates,
|
|
|
|
NodeMap * components)
|
2009-05-15 14:06:56 +02:00
|
|
|
{
|
|
|
|
parseFiles(
|
|
|
|
rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".xcs")), &parseXcsFile,
|
|
|
|
url + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/schema")),
|
|
|
|
templates, components, false);
|
|
|
|
parseFiles(
|
|
|
|
rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".xcu")), &parseXcuFile,
|
|
|
|
url + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/data")), templates,
|
|
|
|
components, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
void parseModuleLayer(
|
2009-05-19 10:49:37 +02:00
|
|
|
rtl::OUString const & url, Components::TemplateMap * templates,
|
|
|
|
NodeMap * components)
|
2009-05-15 14:06:56 +02:00
|
|
|
{
|
|
|
|
parseFiles(
|
|
|
|
rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".xcu")), &parseXcuFile, url,
|
|
|
|
templates, components, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
void parseResLayer(
|
2009-05-19 10:49:37 +02:00
|
|
|
rtl::OUString const & url, Components::TemplateMap * templates,
|
|
|
|
NodeMap * components)
|
2009-05-15 14:06:56 +02:00
|
|
|
{
|
|
|
|
parseFiles(
|
|
|
|
rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".xcu")), &parseXcuFile, url,
|
|
|
|
templates, components, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
void parseSystemLayer() {
|
|
|
|
//TODO
|
|
|
|
}
|
|
|
|
|
2009-07-10 11:20:28 +02:00
|
|
|
void writeBooleanValue(xmlTextWriterPtr writer, sal_Bool const & value) {
|
|
|
|
xmlTextWriterWriteString(
|
|
|
|
writer, xmlString(value ? "true" : "false"));
|
|
|
|
}
|
|
|
|
|
|
|
|
void writeShortValue(xmlTextWriterPtr writer, sal_Int16 const & value) {
|
|
|
|
xmlTextWriterWriteString(
|
|
|
|
writer,
|
|
|
|
xmlString(
|
|
|
|
convertToUtf8(rtl::OUString::valueOf(sal_Int32(value))).getStr()));
|
|
|
|
}
|
|
|
|
|
|
|
|
void writeIntValue(xmlTextWriterPtr writer, sal_Int32 const & value) {
|
|
|
|
xmlTextWriterWriteString(
|
|
|
|
writer,
|
|
|
|
xmlString(convertToUtf8(rtl::OUString::valueOf(value)).getStr()));
|
|
|
|
}
|
|
|
|
|
|
|
|
void writeLongValue(xmlTextWriterPtr writer, sal_Int64 const & value) {
|
|
|
|
xmlTextWriterWriteString(
|
|
|
|
writer,
|
|
|
|
xmlString(convertToUtf8(rtl::OUString::valueOf(value)).getStr()));
|
|
|
|
}
|
|
|
|
|
|
|
|
void writeDoubleValue(xmlTextWriterPtr writer, double const & value) {
|
|
|
|
xmlTextWriterWriteString(
|
|
|
|
writer,
|
|
|
|
xmlString(convertToUtf8(rtl::OUString::valueOf(value)).getStr()));
|
|
|
|
}
|
|
|
|
|
|
|
|
void writeStringValue(xmlTextWriterPtr writer, rtl::OUString const & value) {
|
|
|
|
rtl::OUStringBuffer buf;
|
|
|
|
buf.append(sal_Unicode('['));
|
|
|
|
for (sal_Int32 i = 0; i < value.getLength(); ++i) {
|
|
|
|
sal_Unicode c = value[i];
|
|
|
|
if (c <= 0x001F || c == 0xFFFE || c == 0xFFFF) {
|
|
|
|
static sal_Unicode const hexDigit[16] = {
|
|
|
|
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C',
|
|
|
|
'D', 'E', 'F' };
|
|
|
|
buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("\\u"));
|
|
|
|
buf.append(hexDigit[(c >> 12) & 0xF]);
|
|
|
|
buf.append(hexDigit[(c >> 8) & 0xF]);
|
|
|
|
buf.append(hexDigit[(c >> 4) & 0xF]);
|
|
|
|
buf.append(hexDigit[c & 0xF]);
|
|
|
|
} else {
|
|
|
|
if (c == '\\' || c == ']') {
|
|
|
|
buf.append(sal_Unicode('\\'));
|
|
|
|
}
|
|
|
|
buf.append(c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
buf.append(sal_Unicode(']'));
|
|
|
|
xmlTextWriterWriteString(
|
|
|
|
writer, xmlString(convertToUtf8(buf.makeStringAndClear()).getStr()));
|
|
|
|
}
|
|
|
|
|
|
|
|
void writeHexbinaryValue(
|
|
|
|
xmlTextWriterPtr writer, css::uno::Sequence< sal_Int8 > const & value)
|
|
|
|
{
|
|
|
|
rtl::OStringBuffer buf;
|
|
|
|
buf.append('[');
|
|
|
|
for (sal_Int32 i = 0; i < value.getLength(); ++i) {
|
|
|
|
static char const hexDigit[16] = {
|
|
|
|
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C',
|
|
|
|
'D', 'E', 'F' };
|
|
|
|
buf.append(hexDigit[(value[i] >> 4) & 0xF]);
|
|
|
|
buf.append(hexDigit[value[i] & 0xF]);
|
|
|
|
}
|
|
|
|
buf.append(']');
|
|
|
|
xmlTextWriterWriteString(
|
|
|
|
writer, xmlString(buf.makeStringAndClear().getStr()));
|
|
|
|
}
|
|
|
|
|
|
|
|
template< typename T > void writeListValue(
|
|
|
|
xmlTextWriterPtr writer, void (* write)(xmlTextWriterPtr, T const &),
|
|
|
|
css::uno::Any const & value)
|
|
|
|
{
|
|
|
|
css::uno::Sequence< T > val;
|
|
|
|
value >>= val;
|
|
|
|
for (sal_Int32 i = 0; i < val.getLength(); ++i) {
|
|
|
|
if (i != 0) {
|
|
|
|
xmlTextWriterWriteString(writer, xmlString(" "));
|
|
|
|
}
|
|
|
|
(*write)(writer, val[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-07-08 17:25:16 +02:00
|
|
|
void writeNode(
|
|
|
|
xmlTextWriterPtr writer, rtl::OUString const & name,
|
|
|
|
rtl::Reference< Node > const & node)
|
|
|
|
{
|
|
|
|
if (PropertyNode * prop = dynamic_cast< PropertyNode * >(node.get())) {
|
|
|
|
xmlTextWriterStartElementNS(
|
|
|
|
writer, xmlString("oor"), xmlString("prop"),
|
|
|
|
xmlString("http://openoffice.org/2001/registry"));
|
|
|
|
xmlTextWriterWriteAttributeNS(
|
|
|
|
writer, xmlString("oor"), xmlString("name"),
|
|
|
|
xmlString("http://openoffice.org/2001/registry"),
|
|
|
|
xmlString(convertToUtf8(name).getStr()));
|
|
|
|
xmlTextWriterWriteAttributeNS(
|
|
|
|
writer, xmlString("oor"), xmlString("op"),
|
|
|
|
xmlString("http://openoffice.org/2001/registry"),
|
|
|
|
xmlString("fuse"));
|
2009-07-10 11:20:28 +02:00
|
|
|
Type type = prop->getType();
|
|
|
|
if (type == TYPE_ANY) {
|
|
|
|
type = mapType(prop->getValue());
|
2009-07-13 10:28:10 +02:00
|
|
|
static char const * const typeNames[] = {
|
2009-07-13 10:31:54 +02:00
|
|
|
0, 0, 0, // TYPE_ERROR, TYPE_NIL, TYPE_ANY
|
2009-07-13 10:28:10 +02:00
|
|
|
"xs:boolean", // TYPE_BOOLEAN
|
|
|
|
"xs:short", // TYPE_SHORT
|
|
|
|
"xs:int", // TYPE_INT
|
|
|
|
"xs:long", // TYPE_LONG
|
|
|
|
"xs:double", // TYPE_DOUBLE
|
|
|
|
"xs:string", // TYPE_STRING
|
|
|
|
"xs:hexBinary", // TYPE_HEXBINARY
|
|
|
|
"oor:boolean-list", // TYPE_BOOLEAN_LIST
|
|
|
|
"oor:short-list", // TYPE_SHORT_LIST
|
|
|
|
"oor:int-list", // TYPE_INT_LIST
|
|
|
|
"oor:long-list", // TYPE_LONG_LIST
|
|
|
|
"oor:double-list", // TYPE_DOUBLE_LIST
|
|
|
|
"oor:string-list", // TYPE_STRING_LIST
|
|
|
|
"oor:hexBinary-list" }; // TYPE_HEXBINARY_LIST
|
|
|
|
xmlTextWriterWriteAttributeNS(
|
|
|
|
writer, xmlString("oor"), xmlString("type"),
|
|
|
|
xmlString("http://openoffice.org/2001/registry"),
|
|
|
|
xmlString(typeNames[type]));
|
2009-07-10 11:20:28 +02:00
|
|
|
}
|
2009-07-13 10:28:10 +02:00
|
|
|
xmlTextWriterStartElementNS(
|
|
|
|
writer, xmlString("oor"), xmlString("value"),
|
|
|
|
xmlString("http://openoffice.org/2001/registry"));
|
2009-07-10 11:20:28 +02:00
|
|
|
switch (type) {
|
|
|
|
case TYPE_NIL:
|
2009-07-08 17:25:16 +02:00
|
|
|
xmlTextWriterWriteAttributeNS(
|
|
|
|
writer, xmlString("xsi"), xmlString("nil"),
|
|
|
|
xmlString("http://www.w3.org/2001/XMLSchema-instance"),
|
|
|
|
xmlString("true"));
|
|
|
|
break;
|
2009-07-10 11:20:28 +02:00
|
|
|
case TYPE_BOOLEAN:
|
2009-07-08 17:25:16 +02:00
|
|
|
{
|
|
|
|
bool val;
|
2009-07-10 11:20:28 +02:00
|
|
|
prop->getValue() >>= val;
|
|
|
|
writeBooleanValue(writer, val);
|
2009-07-08 17:25:16 +02:00
|
|
|
}
|
|
|
|
break;
|
2009-07-10 11:20:28 +02:00
|
|
|
case TYPE_SHORT:
|
|
|
|
{
|
|
|
|
sal_Int16 val;
|
|
|
|
prop->getValue() >>= val;
|
|
|
|
writeShortValue(writer, val);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TYPE_INT:
|
|
|
|
{
|
|
|
|
sal_Int32 val;
|
|
|
|
prop->getValue() >>= val;
|
|
|
|
writeIntValue(writer, val);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TYPE_LONG:
|
2009-07-08 17:25:16 +02:00
|
|
|
{
|
|
|
|
sal_Int64 val;
|
2009-07-10 11:20:28 +02:00
|
|
|
prop->getValue() >>= val;
|
|
|
|
writeLongValue(writer, val);
|
2009-07-08 17:25:16 +02:00
|
|
|
}
|
|
|
|
break;
|
2009-07-10 11:20:28 +02:00
|
|
|
case TYPE_DOUBLE:
|
2009-07-08 17:25:16 +02:00
|
|
|
{
|
2009-07-10 11:20:28 +02:00
|
|
|
double val;
|
|
|
|
prop->getValue() >>= val;
|
|
|
|
writeDoubleValue(writer, val);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TYPE_STRING:
|
|
|
|
{
|
|
|
|
xmlTextWriterWriteAttributeNS(
|
|
|
|
writer, xmlString("oor"), xmlString("escaped"),
|
|
|
|
xmlString("http://openoffice.org/2001/registry"),
|
|
|
|
xmlString("true"));
|
2009-07-08 17:25:16 +02:00
|
|
|
rtl::OUString val;
|
2009-07-10 11:20:28 +02:00
|
|
|
prop->getValue() >>= val;
|
|
|
|
writeStringValue(writer, val);
|
2009-07-08 17:25:16 +02:00
|
|
|
}
|
|
|
|
break;
|
2009-07-10 11:20:28 +02:00
|
|
|
case TYPE_HEXBINARY:
|
|
|
|
{
|
|
|
|
// Written in escaped form to be able to share
|
|
|
|
// writeHexbinaryValue with the TYPE_HEXBINARY_LIST case (see
|
|
|
|
// there):
|
|
|
|
xmlTextWriterWriteAttributeNS(
|
|
|
|
writer, xmlString("oor"), xmlString("escaped"),
|
|
|
|
xmlString("http://openoffice.org/2001/registry"),
|
|
|
|
xmlString("true"));
|
|
|
|
css::uno::Sequence< sal_Int8 > val;
|
|
|
|
prop->getValue() >>= val;
|
|
|
|
writeHexbinaryValue(writer, val);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TYPE_BOOLEAN_LIST:
|
|
|
|
writeListValue(writer, &writeBooleanValue, prop->getValue());
|
|
|
|
break;
|
|
|
|
case TYPE_SHORT_LIST:
|
|
|
|
writeListValue(writer, &writeShortValue, prop->getValue());
|
|
|
|
break;
|
|
|
|
case TYPE_INT_LIST:
|
|
|
|
writeListValue(writer, &writeIntValue, prop->getValue());
|
|
|
|
break;
|
|
|
|
case TYPE_LONG_LIST:
|
|
|
|
writeListValue(writer, &writeLongValue, prop->getValue());
|
|
|
|
break;
|
|
|
|
case TYPE_DOUBLE_LIST:
|
|
|
|
writeListValue(writer, &writeDoubleValue, prop->getValue());
|
|
|
|
break;
|
|
|
|
case TYPE_STRING_LIST:
|
|
|
|
xmlTextWriterWriteAttributeNS(
|
|
|
|
writer, xmlString("oor"), xmlString("escaped"),
|
|
|
|
xmlString("http://openoffice.org/2001/registry"),
|
|
|
|
xmlString("true"));
|
|
|
|
writeListValue(writer, &writeStringValue, prop->getValue());
|
|
|
|
break;
|
|
|
|
case TYPE_HEXBINARY_LIST:
|
|
|
|
// Written in escaped form to distinguish an empty list from a list
|
|
|
|
// with one empty hexbinary element:
|
|
|
|
xmlTextWriterWriteAttributeNS(
|
|
|
|
writer, xmlString("oor"), xmlString("escaped"),
|
|
|
|
xmlString("http://openoffice.org/2001/registry"),
|
|
|
|
xmlString("true"));
|
|
|
|
writeListValue(writer, &writeHexbinaryValue, prop->getValue());
|
|
|
|
break;
|
|
|
|
default: // TYPE_ERROR, TYPE_ANY
|
2009-07-08 17:25:16 +02:00
|
|
|
OSL_ASSERT(false);
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM("this cannot happen")),
|
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
|
|
|
}
|
|
|
|
xmlTextWriterEndElement(writer);
|
|
|
|
xmlTextWriterEndElement(writer);
|
|
|
|
} else if (GroupNode * group = dynamic_cast< GroupNode * >(node.get())) {
|
|
|
|
xmlTextWriterStartElementNS(
|
|
|
|
writer, xmlString("oor"), xmlString("node"),
|
|
|
|
xmlString("http://openoffice.org/2001/registry"));
|
|
|
|
xmlTextWriterWriteAttributeNS(
|
|
|
|
writer, xmlString("oor"), xmlString("name"),
|
|
|
|
xmlString("http://openoffice.org/2001/registry"),
|
|
|
|
xmlString(convertToUtf8(name).getStr()));
|
|
|
|
if (group->getTemplateName().getLength() != 0) { // set member
|
|
|
|
xmlTextWriterWriteAttributeNS(
|
|
|
|
writer, xmlString("oor"), xmlString("op"),
|
|
|
|
xmlString("http://openoffice.org/2001/registry"),
|
|
|
|
xmlString("replace"));
|
|
|
|
}
|
|
|
|
for (NodeMap::iterator i(group->getMembers().begin());
|
|
|
|
i != group->getMembers().end(); ++i)
|
|
|
|
{
|
|
|
|
writeNode(writer, i->first, i->second);
|
|
|
|
}
|
|
|
|
xmlTextWriterEndElement(writer);
|
|
|
|
} else {
|
|
|
|
if(true)abort();*(char*)0=0;throw 0;//TODO
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Components & Components::singleton() {
|
|
|
|
static Components * c = new Components(); // leaks
|
|
|
|
return *c;
|
|
|
|
}
|
|
|
|
|
2009-05-20 17:20:08 +02:00
|
|
|
bool Components::allLocales(rtl::OUString const & locale) {
|
|
|
|
return locale.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("*"));
|
|
|
|
}
|
|
|
|
|
2009-07-08 17:25:16 +02:00
|
|
|
rtl::OUString Components::createSegment(
|
|
|
|
rtl::OUString const & templateName, rtl::OUString const & name)
|
|
|
|
{
|
2009-07-13 17:15:58 +02:00
|
|
|
if (templateName.getLength() == 0) {
|
|
|
|
return name;
|
|
|
|
}
|
2009-07-08 17:25:16 +02:00
|
|
|
rtl::OUStringBuffer buf(templateName);
|
|
|
|
//TODO: verify template name contains no bad chars?
|
|
|
|
buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("['"));
|
|
|
|
for (sal_Int32 i = 0; i < name.getLength(); ++i) {
|
|
|
|
sal_Unicode c = name[i];
|
|
|
|
switch (c) {
|
|
|
|
case '&':
|
|
|
|
buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("&"));
|
|
|
|
break;
|
|
|
|
case '"':
|
|
|
|
buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("""));
|
|
|
|
break;
|
|
|
|
case '\'':
|
|
|
|
buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("'"));
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
buf.append(c);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("']"));
|
|
|
|
return buf.makeStringAndClear();
|
|
|
|
}
|
|
|
|
|
2009-07-13 10:28:10 +02:00
|
|
|
sal_Int32 Components::parseSegment(
|
|
|
|
rtl::OUString const & path, sal_Int32 index, rtl::OUString * name,
|
|
|
|
bool * setElement, rtl::OUString * templateName)
|
2009-05-15 14:06:56 +02:00
|
|
|
{
|
2009-07-13 10:28:10 +02:00
|
|
|
OSL_ASSERT(
|
|
|
|
index >= 0 && index <= path.getLength() && name != 0 &&
|
|
|
|
setElement != 0);
|
|
|
|
sal_Int32 i = index;
|
|
|
|
while (i < path.getLength() && path[i] != '/' && path[i] != '[') {
|
|
|
|
++i;
|
|
|
|
}
|
|
|
|
if (i == path.getLength() || path[i] == '/') {
|
|
|
|
*name = path.copy(index, i - index);
|
2009-05-15 14:06:56 +02:00
|
|
|
*setElement = false;
|
2009-07-13 10:28:10 +02:00
|
|
|
return i;
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
if (templateName != 0) {
|
2009-07-13 10:28:10 +02:00
|
|
|
if (i - index == 1 && path[index] == '*') {
|
2009-05-15 14:06:56 +02:00
|
|
|
*templateName = rtl::OUString();
|
2009-07-13 10:28:10 +02:00
|
|
|
} else {
|
|
|
|
*templateName = path.copy(index, i - index);
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
}
|
2009-07-13 10:28:10 +02:00
|
|
|
if (++i == path.getLength()) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
sal_Unicode del = path[i++];
|
|
|
|
if (del != '\'' && del != '"') {
|
|
|
|
return -1;
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
2009-07-13 14:54:09 +02:00
|
|
|
sal_Int32 j = path.indexOf(del, i);
|
|
|
|
if (j == -1 || j + 1 == path.getLength() || path[j + 1] != ']' ||
|
|
|
|
!decodeXml(path, i, j, name))
|
|
|
|
{
|
2009-07-13 10:28:10 +02:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
*setElement = true;
|
2009-07-13 14:54:09 +02:00
|
|
|
return j + 2;
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
|
2009-05-28 10:19:30 +02:00
|
|
|
NodeMap::iterator Components::resolveNode(
|
|
|
|
rtl::OUString const & name, NodeMap * map)
|
|
|
|
{
|
|
|
|
OSL_ASSERT(map != 0);
|
|
|
|
NodeMap::iterator i(map->find(name));
|
2009-05-28 13:54:00 +02:00
|
|
|
if (i != map->end()) {
|
|
|
|
if (NodeRef * ref = dynamic_cast< NodeRef * >(i->second.get())) {
|
|
|
|
NodeMap::const_iterator j(
|
|
|
|
ref->getTemplates().find(ref->getTemplateName()));
|
|
|
|
if (j == ref->getTemplates().end()) {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM("unknown node-ref ")) +
|
|
|
|
ref->getTemplateName()),
|
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
|
|
|
}
|
2009-06-04 10:46:43 +02:00
|
|
|
i->second = j->second->clone();
|
2009-05-28 10:19:30 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
2009-05-29 16:48:52 +02:00
|
|
|
rtl::Reference< Node > Components::resolvePath(
|
2009-07-02 14:21:36 +02:00
|
|
|
rtl::OUString const & path, rtl::OUString * firstSegment,
|
2009-07-13 17:15:58 +02:00
|
|
|
rtl::OUString * lastSegment, rtl::OUString * canonicalPath)
|
2009-05-29 16:48:52 +02:00
|
|
|
{
|
2009-05-20 17:20:08 +02:00
|
|
|
if (path.getLength() == 0 || path[0] != '/') {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("bad path ")) + path, 0);
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
2009-05-20 17:20:08 +02:00
|
|
|
rtl::OUString seg;
|
|
|
|
bool setElement;
|
2009-07-13 10:28:10 +02:00
|
|
|
sal_Int32 n = parseSegment(path, 1, &seg, &setElement, 0);
|
|
|
|
if (n == -1 || setElement)
|
2009-05-20 17:20:08 +02:00
|
|
|
{
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("bad path ")) + path, 0);
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
2009-07-02 14:21:36 +02:00
|
|
|
if (firstSegment != 0) {
|
|
|
|
*firstSegment = seg;
|
|
|
|
}
|
2009-07-13 17:15:58 +02:00
|
|
|
rtl::OUStringBuffer canonic;
|
|
|
|
if (canonicalPath != 0) {
|
|
|
|
canonic.append(sal_Unicode('/'));
|
|
|
|
canonic.append(seg);
|
|
|
|
}
|
2009-07-02 14:21:36 +02:00
|
|
|
NodeMap::iterator i(resolveNode(seg, &components_));
|
2009-05-20 17:20:08 +02:00
|
|
|
rtl::Reference< Node > p(i == components_.end() ? 0 : i->second);
|
2009-05-19 10:49:37 +02:00
|
|
|
while (p != 0 && n != path.getLength()) {
|
2009-07-13 10:28:10 +02:00
|
|
|
if (path[n++] != '/') {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("bad path ")) + path,
|
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
|
|
|
}
|
|
|
|
if (n == path.getLength()) {
|
|
|
|
break; // for backwards compatibility, ignore a final slash
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
rtl::OUString templateName;
|
2009-07-13 10:28:10 +02:00
|
|
|
n = parseSegment(path, n, &seg, &setElement, &templateName);
|
|
|
|
if (n == -1) {
|
2009-05-20 13:33:52 +02:00
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("bad path ")) + path,
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-20 13:33:52 +02:00
|
|
|
}
|
2009-05-15 14:06:56 +02:00
|
|
|
if (setElement) {
|
2009-05-19 10:49:37 +02:00
|
|
|
SetNode * set = dynamic_cast< SetNode * >(p.get());
|
2009-05-15 14:06:56 +02:00
|
|
|
if (set == 0 ||
|
|
|
|
(templateName.getLength() != 0 &&
|
|
|
|
!set->isValidTemplate(templateName)))
|
|
|
|
{
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("bad path ")) +
|
|
|
|
path),
|
2009-06-03 15:57:23 +02:00
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
2009-05-19 10:49:37 +02:00
|
|
|
p = set->getMember(seg);
|
|
|
|
if (templateName.getLength() != 0 && p != 0) {
|
2009-06-03 15:57:23 +02:00
|
|
|
rtl::OUString name;
|
2009-06-04 14:38:04 +02:00
|
|
|
if (GroupNode * mg = dynamic_cast< GroupNode * >(p.get())) {
|
|
|
|
name = mg->getTemplateName();
|
|
|
|
} else if (SetNode * ms = dynamic_cast< SetNode * >(p.get())) {
|
|
|
|
name = ms->getTemplateName();
|
2009-06-03 15:57:23 +02:00
|
|
|
} else {
|
|
|
|
OSL_ASSERT(false);
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM("this cannot happen")),
|
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
|
|
|
}
|
|
|
|
OSL_ASSERT(name.getLength() != 0);
|
|
|
|
if (templateName != name) {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM("bad path ")) +
|
|
|
|
path),
|
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
|
|
|
}
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// For backwards compatibility, allow set members to be accessed
|
|
|
|
// with simple path segments, like group members:
|
2009-05-19 10:49:37 +02:00
|
|
|
p = p->getMember(seg);
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
2009-07-13 17:15:58 +02:00
|
|
|
if (p != 0 && canonicalPath != 0) {
|
|
|
|
canonic.append(sal_Unicode('/'));
|
|
|
|
canonic.append(createSegment(p->getTemplateName(), seg));
|
|
|
|
}
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
2009-07-13 17:15:58 +02:00
|
|
|
if (p != 0) {
|
|
|
|
if (lastSegment != 0) {
|
|
|
|
*lastSegment = seg;
|
|
|
|
}
|
|
|
|
if (canonicalPath != 0) {
|
|
|
|
*canonicalPath = canonic.makeStringAndClear();
|
|
|
|
}
|
2009-07-02 14:21:36 +02:00
|
|
|
}
|
2009-05-19 10:49:37 +02:00
|
|
|
return p;
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
|
2009-05-19 10:49:37 +02:00
|
|
|
rtl::Reference< Node > Components::getTemplate(rtl::OUString const & fullName)
|
|
|
|
const
|
|
|
|
{
|
2009-05-15 18:00:17 +02:00
|
|
|
NodeMap::const_iterator i(templates_.find(fullName));
|
|
|
|
return i == templates_.end() ? 0 : i->second;
|
|
|
|
}
|
|
|
|
|
2009-07-08 17:25:16 +02:00
|
|
|
void Components::addModification(rtl::OUString const & path) {
|
|
|
|
//TODO
|
|
|
|
for (Modifications::iterator i(modifications_.begin());
|
|
|
|
i != modifications_.end();)
|
|
|
|
{
|
|
|
|
if (path == *i || isPrefix(*i, path)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (isPrefix(path, *i)) {
|
|
|
|
modifications_.erase(i++);
|
|
|
|
} else {
|
|
|
|
++i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
modifications_.push_back(path);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Components::writeModifications() {
|
|
|
|
rtl::OUString url(getModificationFileUrl());
|
|
|
|
XmlTextWriter writer(
|
|
|
|
xmlNewTextWriterFilename(convertToFilepath(url).getStr(), 0));
|
|
|
|
if (writer.writer == 0) {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("cannot write ")) + url,
|
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
|
|
|
}
|
|
|
|
xmlTextWriterSetIndent(writer.writer, 1);
|
|
|
|
//TODO: more readable, but potentially slower?
|
|
|
|
xmlTextWriterStartDocument(writer.writer, 0, 0, 0);
|
|
|
|
xmlTextWriterStartElement(writer.writer, xmlString("modifications"));
|
2009-07-13 10:28:10 +02:00
|
|
|
xmlTextWriterWriteAttribute(
|
|
|
|
writer.writer, xmlString("xmlns:xs"),
|
|
|
|
xmlString("http://www.w3.org/2001/XMLSchema"));
|
2009-07-13 14:54:09 +02:00
|
|
|
//TODO: Do not write back information about those removed items that did not
|
|
|
|
// come from the .xcs/.xcu files, anyway (but had been added dynamically
|
|
|
|
// instead):
|
2009-07-08 17:25:16 +02:00
|
|
|
for (Modifications::iterator i(modifications_.begin());
|
|
|
|
i != modifications_.end(); ++i)
|
|
|
|
{
|
|
|
|
xmlTextWriterStartElement(writer.writer, xmlString("item"));
|
|
|
|
rtl::OUString name;
|
2009-07-13 14:54:09 +02:00
|
|
|
rtl::OUString parentPath(parseLastSegment(*i, &name));
|
2009-07-13 17:15:58 +02:00
|
|
|
rtl::Reference< Node > node(resolvePath(*i, 0, 0, 0));
|
2009-07-08 17:25:16 +02:00
|
|
|
if (node.is()) {
|
2009-07-13 14:54:09 +02:00
|
|
|
xmlTextWriterWriteAttribute(
|
|
|
|
writer.writer, xmlString("path"),
|
|
|
|
xmlString(convertToUtf8(parentPath).getStr()));
|
2009-07-08 17:25:16 +02:00
|
|
|
writeNode(writer.writer, name, node);
|
|
|
|
} else {
|
2009-07-13 17:15:58 +02:00
|
|
|
rtl::Reference< Node > parent(resolvePath(parentPath, 0, 0, 0));
|
2009-07-13 14:54:09 +02:00
|
|
|
if (dynamic_cast< LocalizedPropertyNode * >(parent.get()) != 0) {
|
|
|
|
rtl::OUString parentName;
|
|
|
|
rtl::OUString grandparentPath(
|
|
|
|
parseLastSegment(parentPath, &parentName));
|
|
|
|
xmlTextWriterWriteAttribute(
|
|
|
|
writer.writer, xmlString("path"),
|
|
|
|
xmlString(convertToUtf8(grandparentPath).getStr()));
|
|
|
|
xmlTextWriterStartElementNS(
|
|
|
|
writer.writer, xmlString("oor"), xmlString("prop"),
|
|
|
|
xmlString("http://openoffice.org/2001/registry"));
|
|
|
|
xmlTextWriterWriteAttributeNS(
|
|
|
|
writer.writer, xmlString("oor"), xmlString("name"),
|
|
|
|
xmlString("http://openoffice.org/2001/registry"),
|
|
|
|
xmlString(convertToUtf8(parentName).getStr()));
|
|
|
|
xmlTextWriterWriteAttributeNS(
|
|
|
|
writer.writer, xmlString("oor"), xmlString("op"),
|
|
|
|
xmlString("http://openoffice.org/2001/registry"),
|
|
|
|
xmlString("fuse"));
|
|
|
|
xmlTextWriterStartElementNS(
|
|
|
|
writer.writer, xmlString("oor"), xmlString("value"),
|
|
|
|
xmlString("http://openoffice.org/2001/registry"));
|
|
|
|
xmlTextWriterWriteAttribute(
|
|
|
|
writer.writer, xmlString("xml:lang"),
|
|
|
|
xmlString(convertToUtf8(name).getStr()));
|
|
|
|
xmlTextWriterWriteAttributeNS(
|
|
|
|
writer.writer, xmlString("oor"), xmlString("op"),
|
|
|
|
xmlString("http://openoffice.org/2001/registry"),
|
|
|
|
xmlString("remove"));
|
|
|
|
xmlTextWriterEndElement(writer.writer);
|
|
|
|
xmlTextWriterEndElement(writer.writer);
|
|
|
|
} else if (dynamic_cast< GroupNode * >(parent.get()) != 0) {
|
|
|
|
OSL_ASSERT(
|
|
|
|
dynamic_cast< GroupNode * >(parent.get())->isExtensible());
|
|
|
|
xmlTextWriterWriteAttribute(
|
|
|
|
writer.writer, xmlString("path"),
|
|
|
|
xmlString(convertToUtf8(parentPath).getStr()));
|
|
|
|
xmlTextWriterStartElementNS(
|
|
|
|
writer.writer, xmlString("oor"), xmlString("prop"),
|
|
|
|
xmlString("http://openoffice.org/2001/registry"));
|
|
|
|
xmlTextWriterWriteAttributeNS(
|
|
|
|
writer.writer, xmlString("oor"), xmlString("name"),
|
|
|
|
xmlString("http://openoffice.org/2001/registry"),
|
|
|
|
xmlString(convertToUtf8(name).getStr()));
|
|
|
|
xmlTextWriterWriteAttributeNS(
|
|
|
|
writer.writer, xmlString("oor"), xmlString("op"),
|
|
|
|
xmlString("http://openoffice.org/2001/registry"),
|
|
|
|
xmlString("remove"));
|
|
|
|
xmlTextWriterEndElement(writer.writer);
|
|
|
|
} else {
|
|
|
|
OSL_ASSERT(dynamic_cast< SetNode * >(parent.get()) != 0);
|
|
|
|
xmlTextWriterWriteAttribute(
|
|
|
|
writer.writer, xmlString("path"),
|
|
|
|
xmlString(convertToUtf8(parentPath).getStr()));
|
|
|
|
xmlTextWriterStartElementNS(
|
|
|
|
writer.writer, xmlString("oor"), xmlString("node"),
|
|
|
|
xmlString("http://openoffice.org/2001/registry"));
|
|
|
|
xmlTextWriterWriteAttributeNS(
|
|
|
|
writer.writer, xmlString("oor"), xmlString("name"),
|
|
|
|
xmlString("http://openoffice.org/2001/registry"),
|
|
|
|
xmlString(convertToUtf8(name).getStr()));
|
|
|
|
xmlTextWriterWriteAttributeNS(
|
|
|
|
writer.writer, xmlString("oor"), xmlString("op"),
|
|
|
|
xmlString("http://openoffice.org/2001/registry"),
|
|
|
|
xmlString("remove"));
|
|
|
|
xmlTextWriterEndElement(writer.writer);
|
|
|
|
}
|
2009-07-08 17:25:16 +02:00
|
|
|
}
|
|
|
|
xmlTextWriterEndElement(writer.writer);
|
|
|
|
}
|
2009-07-13 14:54:09 +02:00
|
|
|
if (xmlTextWriterEndDocument(writer.writer) == -1) { //TODO: check all -1?
|
2009-07-08 17:25:16 +02:00
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("cannot write ")) + url,
|
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-05-15 14:06:56 +02:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
rtl::OUString expand(rtl::OUString const & str) {
|
|
|
|
rtl::OUString s(str);
|
|
|
|
rtl::Bootstrap::expandMacros(s); //TODO: detect failure
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Components::Components() {
|
|
|
|
parseXcsXcuLayer(
|
|
|
|
expand(
|
|
|
|
rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM("$OOO_BASE_DIR/share/registry"))),
|
|
|
|
&templates_, &components_);
|
|
|
|
parseModuleLayer(
|
|
|
|
expand(
|
|
|
|
rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"$OOO_BASE_DIR/share/registry/modules"))),
|
|
|
|
&templates_, &components_);
|
|
|
|
parseResLayer(
|
|
|
|
expand(
|
|
|
|
rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM("$OOO_BASE_DIR/share/registry"))),
|
|
|
|
&templates_, &components_);
|
|
|
|
parseXcsXcuLayer(
|
|
|
|
expand(
|
|
|
|
rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM("$BRAND_BASE_DIR/share/registry"))),
|
|
|
|
&templates_, &components_);
|
|
|
|
parseModuleLayer(
|
|
|
|
expand(
|
|
|
|
rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"$BRAND_BASE_DIR/share/registry/modules"))),
|
|
|
|
&templates_, &components_);
|
|
|
|
parseXcsXcuLayer(
|
|
|
|
expand(
|
|
|
|
rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"${$OOO_BASE_DIR/program/unorc:UNO_SHARED_PACKAGES_CACHE}/"
|
|
|
|
"registry/com.sun.star.comp.deployment.configuration."
|
|
|
|
"PackageRegistryBackend/registry"))),
|
|
|
|
&templates_, &components_);
|
|
|
|
parseSystemLayer();
|
|
|
|
parseXcsXcuLayer(
|
|
|
|
expand(
|
|
|
|
rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"${$OOO_BASE_DIR/program/unorc:UNO_USER_PACKAGES_CACHE}/"
|
|
|
|
"registry/com.sun.star.comp.deployment.configuration."
|
|
|
|
"PackageRegistryBackend/registry"))),
|
|
|
|
&templates_, &components_);
|
|
|
|
parseXcsXcuLayer(
|
|
|
|
expand(
|
|
|
|
rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"${$BRAND_BASE_DIR/program/bootstraprc:UserInstallation}/"
|
|
|
|
"user/registry"))),
|
|
|
|
&templates_, &components_);
|
2009-07-08 17:25:16 +02:00
|
|
|
parseModificationLayer();
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Components::~Components() {}
|
|
|
|
|
2009-07-08 17:25:16 +02:00
|
|
|
rtl::OUString Components::getModificationFileUrl() const {
|
|
|
|
return expand(
|
|
|
|
rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"${$BRAND_BASE_DIR/program/bootstraprc:UserInstallation}/user/"
|
|
|
|
"registrymodifications")));
|
|
|
|
}
|
|
|
|
|
|
|
|
void Components::parseModificationLayer() {
|
|
|
|
rtl::OUString url(getModificationFileUrl());
|
2009-07-02 14:21:36 +02:00
|
|
|
osl::DirectoryItem di;
|
|
|
|
switch (osl::DirectoryItem::get(url, di)) {
|
|
|
|
case osl::FileBase::E_None:
|
|
|
|
break;
|
|
|
|
case osl::FileBase::E_NOENT:
|
|
|
|
return;
|
|
|
|
default:
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("cannot stat ")) + url,
|
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
|
|
|
}
|
|
|
|
XmlDoc doc(parseXmlFile(url)); //TODO: atomic check for existence
|
|
|
|
xmlNodePtr root(xmlDocGetRootElement(doc.doc));
|
|
|
|
if (root == 0) {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("no root element in ")) +
|
|
|
|
fromXmlString(doc.doc->URL)),
|
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
|
|
|
}
|
|
|
|
if (!xmlStrEqual(root->name, xmlString("modifications")) || root->ns != 0) {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"non modifications root element in ")) +
|
|
|
|
fromXmlString(doc.doc->URL)),
|
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
|
|
|
}
|
|
|
|
for (xmlNodePtr p(skipBlank(root->xmlChildrenNode)); p != 0;
|
|
|
|
p = skipBlank(p->next))
|
|
|
|
{
|
2009-07-08 17:25:16 +02:00
|
|
|
if (xmlStrEqual(p->name, xmlString("item")) && p->ns == 0) {
|
2009-07-02 14:21:36 +02:00
|
|
|
XmlString path(xmlGetNoNsProp(p, xmlString("path")));
|
|
|
|
if (path.str == 0) {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"missing path attribute in ")) +
|
|
|
|
fromXmlString(doc.doc->URL)),
|
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
|
|
|
}
|
|
|
|
rtl::OUString componentName;
|
2009-07-13 17:15:58 +02:00
|
|
|
rtl::OUString canonicalPath;
|
2009-07-02 14:21:36 +02:00
|
|
|
rtl::Reference< Node > node(
|
2009-07-13 17:15:58 +02:00
|
|
|
resolvePath(
|
|
|
|
fromXmlString(path.str), &componentName, 0,
|
|
|
|
&canonicalPath));
|
2009-07-02 14:21:36 +02:00
|
|
|
if (!node.is()) {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"nonexisting path attribute in ")) +
|
|
|
|
fromXmlString(doc.doc->URL)),
|
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
|
|
|
}
|
2009-07-08 17:25:16 +02:00
|
|
|
parseXcuNode(
|
|
|
|
componentName, templates_, doc.doc, p, node, this,
|
2009-07-13 17:15:58 +02:00
|
|
|
(canonicalPath +
|
2009-07-08 17:25:16 +02:00
|
|
|
rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/"))));
|
2009-07-02 14:21:36 +02:00
|
|
|
} else {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("bad content in ")) +
|
|
|
|
fromXmlString(doc.doc->URL)),
|
|
|
|
css::uno::Reference< css::uno::XInterface >());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|