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"
|
|
|
|
#include "comphelper/sequenceasvector.hxx"
|
|
|
|
#include "libxml/parser.h"
|
|
|
|
#include "libxml/xmlschemastypes.h"
|
|
|
|
#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-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;
|
|
|
|
|
|
|
|
void setValues(LocalizedPropertyNode * node, LocalizedValues const & values) {
|
|
|
|
for (LocalizedValues::const_iterator i(values.begin()); i != values.end();
|
|
|
|
++i)
|
|
|
|
{
|
|
|
|
node->getMembers().insert(
|
|
|
|
NodeMap::value_type(
|
|
|
|
i->first,
|
|
|
|
new LocalizedPropertyValueNode(
|
|
|
|
node, i->first, i->second)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
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 {
|
|
|
|
xmlChar * const str;
|
|
|
|
|
|
|
|
explicit XmlString(xmlChar * theStr): str(theStr) {}
|
|
|
|
|
|
|
|
~XmlString() { xmlFree(str); }
|
|
|
|
};
|
|
|
|
|
|
|
|
struct XmlDoc: private boost::noncopyable {
|
|
|
|
xmlDocPtr doc;
|
|
|
|
|
|
|
|
explicit XmlDoc(xmlDocPtr theDoc): doc(theDoc) {}
|
|
|
|
|
|
|
|
~XmlDoc() { xmlFreeDoc(doc); }
|
|
|
|
};
|
|
|
|
|
|
|
|
rtl::OUString fullTemplateName(
|
|
|
|
rtl::OUString const & component, rtl::OUString const & name)
|
|
|
|
{
|
|
|
|
OSL_ASSERT(component.indexOf('/') == -1);
|
|
|
|
rtl::OUStringBuffer buf(component);
|
|
|
|
buf.append(sal_Unicode('/'));
|
|
|
|
buf.append(name);
|
|
|
|
return buf.makeStringAndClear();
|
|
|
|
}
|
|
|
|
|
|
|
|
class NodeRef: public Node {
|
|
|
|
public:
|
2009-05-19 10:49:37 +02:00
|
|
|
NodeRef(
|
|
|
|
Node * parent, rtl::OUString const & name,
|
|
|
|
rtl::OUString const & templateName):
|
|
|
|
Node(parent, name), templateName_(templateName) {}
|
2009-05-15 14:06:56 +02:00
|
|
|
|
2009-05-19 10:49:37 +02:00
|
|
|
virtual rtl::Reference< Node > clone(
|
|
|
|
Node * parent, rtl::OUString const & name) const
|
|
|
|
{ return new NodeRef(parent, name, templateName_); }
|
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_; }
|
|
|
|
|
|
|
|
private:
|
2009-05-19 10:49:37 +02:00
|
|
|
virtual ~NodeRef() {}
|
|
|
|
|
2009-05-15 14:06:56 +02:00
|
|
|
rtl::OUString templateName_;
|
|
|
|
};
|
|
|
|
|
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(
|
|
|
|
rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM("unresolved node-ref ")) + name_,
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
|
2009-05-19 10:49:37 +02:00
|
|
|
void resolveNodeRef(
|
|
|
|
Components::TemplateMap const & templates, NodeMap::iterator it)
|
|
|
|
{
|
|
|
|
if (NodeRef * p = dynamic_cast< NodeRef * >(it->second.get())) {
|
2009-05-15 14:06:56 +02:00
|
|
|
NodeMap::const_iterator i(templates.find(p->getTemplateName()));
|
|
|
|
if (i == templates.end()) {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM("unknown node-ref ")) +
|
|
|
|
p->getTemplateName()),
|
|
|
|
0);
|
|
|
|
}
|
2009-05-19 10:49:37 +02:00
|
|
|
rtl::Reference< Node > removed(p);
|
|
|
|
it->second = i->second->clone(p->getParent(), p->getName());
|
|
|
|
removed->unbind(); // must not throw
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
xmlDocPtr parseXmlFile(rtl::OUString const & url) {
|
|
|
|
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),
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
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),
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
xmlDocPtr doc(xmlParseFile(path2.getStr()));
|
|
|
|
if (doc == 0) {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM("xmlParseFile failed for ")) +
|
|
|
|
url),
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
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)),
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
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)),
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Type getTypeAttribute(xmlDocPtr doc, xmlNodePtr node) {
|
|
|
|
XmlString type(
|
|
|
|
xmlGetNsProp(
|
|
|
|
node, xmlString("type"),
|
|
|
|
xmlString("http://openoffice.org/2001/registry")));
|
|
|
|
if (type.str == 0) {
|
|
|
|
return TYPE_NONE;
|
|
|
|
}
|
|
|
|
xmlChar const * p = xmlStrchr(type.str, ':');
|
|
|
|
if (p == 0) {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM("invalid type attribute ")) +
|
|
|
|
fromXmlString(doc->URL)),
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
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)),
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
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)),
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
|
|
|
|
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)),
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
|
|
|
|
css::uno::Any parseValue(xmlDocPtr doc, xmlNodePtr node, Type type) {
|
|
|
|
XmlString text(xmlNodeListGetString(doc, node->xmlChildrenNode, 1));
|
|
|
|
switch (type) {
|
|
|
|
case TYPE_BOOLEAN:
|
|
|
|
{
|
|
|
|
XmlString col(xmlSchemaCollapseString(text.str));
|
|
|
|
xmlChar * p = col.str == 0 ? text.str : col.str;
|
|
|
|
if (xmlStrEqual(p, xmlString("true")) ||
|
|
|
|
xmlStrEqual(p, xmlString("1")))
|
|
|
|
{
|
|
|
|
return css::uno::makeAny(true);
|
|
|
|
} else if (xmlStrEqual(p, xmlString("false")) ||
|
|
|
|
xmlStrEqual(p, xmlString("0")))
|
|
|
|
{
|
|
|
|
return css::uno::makeAny(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TYPE_SHORT:
|
|
|
|
{
|
|
|
|
XmlString col(xmlSchemaCollapseString(text.str));
|
|
|
|
sal_Int64 n = rtl_str_toInt64(
|
|
|
|
reinterpret_cast< char * >(col.str == 0 ? text.str : col.str),
|
|
|
|
10); //TODO: check valid lexical representation
|
|
|
|
if (n >= SAL_MIN_INT16 && n <= SAL_MAX_INT16) {
|
|
|
|
return css::uno::makeAny(static_cast< sal_Int16 >(n));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TYPE_INT:
|
|
|
|
{
|
|
|
|
XmlString col(xmlSchemaCollapseString(text.str));
|
|
|
|
return css::uno::makeAny(
|
|
|
|
rtl_str_toInt32(
|
|
|
|
reinterpret_cast< char * >(
|
|
|
|
col.str == 0 ? text.str : col.str),
|
|
|
|
10)); //TODO: check valid lexical representation
|
|
|
|
}
|
|
|
|
case TYPE_LONG:
|
|
|
|
{
|
|
|
|
XmlString col(xmlSchemaCollapseString(text.str));
|
|
|
|
return css::uno::makeAny(
|
|
|
|
rtl_str_toInt64(
|
|
|
|
reinterpret_cast< char * >(
|
|
|
|
col.str == 0 ? text.str : col.str),
|
|
|
|
10)); //TODO: check valid lexical representation
|
|
|
|
}
|
|
|
|
case TYPE_DOUBLE:
|
|
|
|
{
|
|
|
|
XmlString col(xmlSchemaCollapseString(text.str));
|
|
|
|
return css::uno::makeAny(
|
|
|
|
rtl_str_toDouble(
|
|
|
|
reinterpret_cast< char * >(
|
|
|
|
col.str == 0 ? text.str : col.str)));
|
|
|
|
//TODO: check valid lexical representation
|
|
|
|
}
|
|
|
|
case TYPE_STRING:
|
|
|
|
return css::uno::makeAny(fromXmlString(text.str));
|
|
|
|
case TYPE_HEXBINARY:
|
|
|
|
//TODO
|
|
|
|
case TYPE_ANY:
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM("invalid value of type any in ")) +
|
|
|
|
fromXmlString(doc->URL)),
|
|
|
|
0);
|
|
|
|
case TYPE_BOOLEAN_LIST:
|
|
|
|
//TODO
|
|
|
|
case TYPE_SHORT_LIST:
|
|
|
|
//TODO
|
|
|
|
case TYPE_INT_LIST:
|
|
|
|
//TODO
|
|
|
|
case TYPE_LONG_LIST:
|
|
|
|
//TODO
|
|
|
|
case TYPE_DOUBLE_LIST:
|
|
|
|
//TODO
|
|
|
|
case TYPE_STRING_LIST:
|
|
|
|
{
|
|
|
|
XmlString sep(
|
|
|
|
xmlGetNsProp(
|
|
|
|
node, xmlString("separator"),
|
|
|
|
xmlString("http://openoffice.org/2001/registry")));
|
|
|
|
comphelper::SequenceAsVector< rtl::OUString > seq;
|
|
|
|
if (sep.str == 0) {
|
|
|
|
XmlString col(xmlSchemaCollapseString(text.str));
|
|
|
|
xmlChar const * p = col.str == 0 ? text.str : col.str;
|
|
|
|
if (*p != '\0') {
|
|
|
|
for (;;) {
|
|
|
|
xmlChar const * q = xmlStrchr(p, ' ');
|
|
|
|
if (q == 0) {
|
|
|
|
seq.push_back(fromXmlString(p));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
seq.push_back(fromXmlString(p, q));
|
|
|
|
p = q + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (*text.str != '\0') {
|
|
|
|
//XXX There is no way to encode a string-list that contains the
|
|
|
|
// empty string as its only element.
|
|
|
|
//TODO: use xmlStrstr
|
|
|
|
rtl::OUString text2(fromXmlString(text.str));
|
|
|
|
rtl::OUString sep2(fromXmlString(sep.str));
|
|
|
|
for (sal_Int32 i = 0;;) {
|
|
|
|
sal_Int32 j = findFirst(text2, sep2, i);
|
|
|
|
seq.push_back(text2.copy(i, j - i));
|
|
|
|
if (j == text2.getLength()) {
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
i = j + sep2.getLength();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return css::uno::makeAny(seq.getAsConstList());
|
|
|
|
}
|
|
|
|
case TYPE_HEXBINARY_LIST:
|
|
|
|
//TODO
|
|
|
|
default:
|
|
|
|
OSL_ASSERT(false);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("invalid value in ")) +
|
|
|
|
fromXmlString(doc->URL)),
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
|
|
|
|
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)),
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
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-19 10:49:37 +02:00
|
|
|
rtl::Reference< GroupNode > const & group);
|
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-05-19 17:32:24 +02:00
|
|
|
Node * parent, rtl::OUString const & name,
|
|
|
|
rtl::OUString const & templateName)
|
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(
|
2009-05-19 10:49:37 +02:00
|
|
|
parent, name,
|
2009-05-15 14:06:56 +02:00
|
|
|
getBooleanAttribute(
|
|
|
|
doc, node, "http://openoffice.org/2001/registry", "extensible",
|
2009-05-19 17:32:24 +02:00
|
|
|
false),
|
|
|
|
templateName));
|
2009-05-19 10:49:37 +02:00
|
|
|
parseXcsGroupContent(componentName, doc, node, group);
|
|
|
|
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-05-19 17:32:24 +02:00
|
|
|
Node * parent, rtl::OUString const & name,
|
|
|
|
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)),
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
return new SetNode(
|
2009-05-19 10:49:37 +02:00
|
|
|
parent, name, parseTemplateReference(componentName, doc, node, 0),
|
2009-05-19 17:32:24 +02:00
|
|
|
additional, templateName);
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void parseXcsGroupContent(
|
|
|
|
rtl::OUString const & componentName, xmlDocPtr doc, xmlNodePtr node,
|
2009-05-19 10:49:37 +02:00
|
|
|
rtl::Reference< GroupNode > const & group)
|
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));
|
|
|
|
if (type == TYPE_NONE) {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"xcs: missing type attribute in ")) +
|
|
|
|
fromXmlString(doc->URL)),
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
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)),
|
|
|
|
0);
|
|
|
|
}
|
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-05-19 10:49:37 +02:00
|
|
|
group.get(), getNameAttribute(doc, p), 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(
|
|
|
|
group.get(), getNameAttribute(doc, p), type,
|
|
|
|
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)),
|
|
|
|
0);
|
|
|
|
}
|
2009-05-19 10:49:37 +02:00
|
|
|
member = new NodeRef(
|
|
|
|
group.get(), getNameAttribute(doc, p),
|
|
|
|
parseTemplateReference(componentName, doc, p, 0));
|
2009-05-15 14:06:56 +02:00
|
|
|
} else if (isOorElement(p, "group")) {
|
2009-05-19 10:49:37 +02:00
|
|
|
member = parseXcsGroup(
|
2009-05-19 17:32:24 +02:00
|
|
|
componentName, doc, p, group.get(), getNameAttribute(doc, p),
|
|
|
|
rtl::OUString());
|
2009-05-15 14:06:56 +02:00
|
|
|
} else if (isOorElement(p, "set")) {
|
2009-05-19 10:49:37 +02:00
|
|
|
member = parseXcsSet(
|
2009-05-19 17:32:24 +02:00
|
|
|
componentName, doc, p, group.get(), getNameAttribute(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)),
|
|
|
|
0);
|
|
|
|
}
|
2009-05-19 10:49:37 +02:00
|
|
|
if (!group->getMembers().insert(
|
|
|
|
NodeMap::value_type(member->getName(), member)).
|
|
|
|
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)),
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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));
|
|
|
|
tmpl = parseXcsGroup(
|
|
|
|
componentName, doc, p, 0, rtl::OUString(), tmplName);
|
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));
|
|
|
|
tmpl = parseXcsSet(
|
|
|
|
componentName, doc, p, 0, rtl::OUString(), 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)),
|
|
|
|
0);
|
|
|
|
}
|
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)),
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return node->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
xmlNodePtr parseXcsComponent(
|
|
|
|
xmlDocPtr doc, rtl::OUString const & component, xmlNodePtr node,
|
|
|
|
NodeMap * components)
|
|
|
|
{
|
|
|
|
if (!isOorElement(node, "component")) {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"xcs: bad component-schema content in ")) +
|
|
|
|
fromXmlString(doc->URL)),
|
|
|
|
0);
|
|
|
|
}
|
2009-05-19 17:32:24 +02:00
|
|
|
rtl::Reference< GroupNode > comp(
|
|
|
|
new GroupNode(0, component, false, rtl::OUString()));
|
2009-05-19 10:49:37 +02:00
|
|
|
parseXcsGroupContent(component, doc, node, comp);
|
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)),
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
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)),
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
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)),
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
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)),
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
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));
|
|
|
|
p = skipBlank(parseXcsComponent(doc.doc, comp, p, components));
|
|
|
|
if (p != 0) {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"xcs: bad component-schema content in ")) +
|
|
|
|
fromXmlString(doc.doc->URL)),
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void parseXcuNode(
|
2009-05-19 10:49:37 +02:00
|
|
|
rtl::OUString const & componentName,
|
|
|
|
Components::TemplateMap const & templates, xmlDocPtr doc,
|
|
|
|
xmlNodePtr xmlNode, rtl::Reference< Node > const & node)
|
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;
|
|
|
|
NodeMap::iterator i(group->getMembers().find(name));
|
|
|
|
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)),
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
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)),
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
//TODO: oor:finalized attributes
|
|
|
|
xmlNodePtr q(skipBlank(p->xmlChildrenNode));
|
|
|
|
LocalizedValues values;
|
|
|
|
while (isOorElement(q, "value")) {
|
|
|
|
if (type == TYPE_NONE) {
|
|
|
|
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)),
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
if (type == TYPE_ANY) {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"xcu: missing type attribute in ")) +
|
|
|
|
fromXmlString(doc->URL)),
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
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)),
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
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)),
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
// For nil values, any actually provided value is simply
|
|
|
|
// ignored for now:
|
|
|
|
if (!values.insert(
|
|
|
|
LocalizedValues::value_type(
|
|
|
|
lang.str == 0
|
|
|
|
? rtl::OUString() : fromXmlString(lang.str),
|
|
|
|
nil ? com::sun::star::uno::Any()
|
|
|
|
: parseValue(doc, q, type))).
|
|
|
|
second)
|
|
|
|
{
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"xcu: multiple values (for same xml:lang)"
|
|
|
|
" in ")) +
|
|
|
|
fromXmlString(doc->URL)),
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
q = skipBlank(q->next);
|
|
|
|
}
|
|
|
|
if (q != 0) {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"xcu: bad prop content in ")) +
|
|
|
|
fromXmlString(doc->URL)),
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
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)),
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
switch (getOperationAttribute(doc, p)) {
|
|
|
|
case OPERATION_MODIFY:
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"xcu: invalid modify of extension property"
|
|
|
|
" in ")) +
|
|
|
|
fromXmlString(doc->URL)),
|
|
|
|
0);
|
|
|
|
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-05-19 10:49:37 +02:00
|
|
|
group, name, type, true,
|
|
|
|
values[rtl::OUString()], true)));
|
2009-05-15 14:06:56 +02:00
|
|
|
break;
|
|
|
|
case OPERATION_REMOVE:
|
|
|
|
// ignore unknown (presumably extension) properties
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
switch (getOperationAttribute(doc, p)) {
|
|
|
|
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-05-20 17:20:08 +02:00
|
|
|
NodeMap::iterator k(
|
|
|
|
localized->getMembers().find(j->first));
|
|
|
|
if (k == localized->getMembers().end()) {
|
|
|
|
localized->getMembers().insert(
|
|
|
|
NodeMap::value_type(
|
|
|
|
j->first,
|
|
|
|
new LocalizedPropertyValueNode(
|
|
|
|
localized, j->first,
|
|
|
|
j->second)));
|
|
|
|
} else {
|
|
|
|
dynamic_cast<
|
|
|
|
LocalizedPropertyValueNode * >(
|
|
|
|
k->second.get())->
|
|
|
|
setValue(j->second);
|
|
|
|
}
|
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)),
|
|
|
|
0);
|
|
|
|
}
|
2009-05-19 10:49:37 +02:00
|
|
|
rtl::Reference< Node > removed(i->second);
|
2009-05-15 14:06:56 +02:00
|
|
|
group->getMembers().erase(i);
|
2009-05-19 10:49:37 +02:00
|
|
|
removed->unbind(); // must not throw
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (isOorElement(p, "node")) {
|
|
|
|
Operation op = getOperationAttribute(doc, p);
|
|
|
|
if (op != OPERATION_MODIFY && op != OPERATION_FUSE) {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"xcu: invalid operation on group node in")) +
|
|
|
|
fromXmlString(doc->URL)),
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
//TODO: oor:component, oor:finalized, oor:mandatory, oor:node-type attributes
|
|
|
|
NodeMap::iterator i(
|
|
|
|
group->getMembers().find(getNameAttribute(doc, p)));
|
|
|
|
if (i == group->getMembers().end()) {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"xcu: unknown node name in ")) +
|
|
|
|
fromXmlString(doc->URL)),
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
resolveNodeRef(templates, i);
|
|
|
|
parseXcuNode(componentName, templates, doc, p, i->second);
|
|
|
|
} else {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"xcu: bad component-data or node content in ")) +
|
|
|
|
fromXmlString(doc->URL)),
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
}
|
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)),
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
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)),
|
|
|
|
0);
|
|
|
|
}
|
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)),
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
switch (getOperationAttribute(doc, p)) {
|
|
|
|
case OPERATION_MODIFY:
|
|
|
|
{
|
|
|
|
NodeMap::iterator j(set->getMembers().find(name));
|
|
|
|
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)),
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
parseXcuNode(componentName, templates, doc, p, j->second);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case OPERATION_REPLACE:
|
|
|
|
{
|
2009-05-19 10:49:37 +02:00
|
|
|
rtl::Reference< Node > member(
|
|
|
|
i->second->clone(group, name));
|
|
|
|
parseXcuNode(componentName, templates, doc, p, member);
|
|
|
|
NodeMap::iterator j(set->getMembers().find(name));
|
|
|
|
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 {
|
|
|
|
rtl::Reference< Node > removed(j->second);
|
|
|
|
j->second = member;
|
|
|
|
removed->unbind(); // must not throw
|
|
|
|
};
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case OPERATION_FUSE:
|
|
|
|
{
|
|
|
|
NodeMap::iterator j(set->getMembers().find(name));
|
|
|
|
if (j == set->getMembers().end()) {
|
2009-05-19 10:49:37 +02:00
|
|
|
rtl::Reference< Node > member(
|
|
|
|
i->second->clone(group, name));
|
|
|
|
parseXcuNode(componentName, templates, doc, p, member);
|
2009-05-15 14:06:56 +02:00
|
|
|
set->getMembers().insert(
|
|
|
|
NodeMap::value_type(
|
2009-05-19 10:49:37 +02:00
|
|
|
member->getName(), member));
|
2009-05-15 14:06:56 +02:00
|
|
|
} else {
|
|
|
|
parseXcuNode(
|
|
|
|
componentName, templates, doc, p, j->second);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case OPERATION_REMOVE:
|
|
|
|
{
|
|
|
|
NodeMap::iterator j(set->getMembers().find(name));
|
|
|
|
// Ignore unknown members:
|
|
|
|
if (j != set->getMembers().end()) {
|
2009-05-19 10:49:37 +02:00
|
|
|
rtl::Reference< Node > removed(j->second);
|
2009-05-15 14:06:56 +02:00
|
|
|
set->getMembers().erase(j);
|
2009-05-19 10:49:37 +02:00
|
|
|
removed->unbind(); // must not throw
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM("xcu: inappropriate node in ")) +
|
|
|
|
fromXmlString(doc->URL)),
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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)),
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
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)),
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
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)),
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
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
|
|
|
|
NodeMap::iterator i(components->find(comp));
|
|
|
|
if (i == components->end()) {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
(rtl::OUString(
|
|
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"xcu: unknown component-data name in ")) +
|
|
|
|
fromXmlString(doc.doc->URL)),
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
resolveNodeRef(*templates, i);
|
|
|
|
parseXcuNode(comp, *templates, doc.doc, root, i->second);
|
|
|
|
}
|
|
|
|
|
|
|
|
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),
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
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),
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
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),
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
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-05-20 13:33:52 +02:00
|
|
|
bool Components::parseSegment(
|
|
|
|
rtl::OUString const & segment, rtl::OUString * name, bool * setElement,
|
2009-05-15 14:06:56 +02:00
|
|
|
rtl::OUString * templateName)
|
|
|
|
{
|
2009-05-20 13:33:52 +02:00
|
|
|
OSL_ASSERT(name != 0 && setElement != 0);
|
2009-05-15 14:06:56 +02:00
|
|
|
sal_Int32 i = segment.indexOf('[');
|
|
|
|
if (i == -1) {
|
2009-05-20 13:33:52 +02:00
|
|
|
*name = segment;
|
2009-05-15 14:06:56 +02:00
|
|
|
*setElement = false;
|
2009-05-20 13:33:52 +02:00
|
|
|
return true;
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
*setElement = true;
|
|
|
|
if (templateName != 0) {
|
|
|
|
// For backwards compatibility, treat an empty template name the same
|
|
|
|
// as "*".
|
|
|
|
*templateName = segment.copy(0, i);
|
|
|
|
if (templateName->equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("*"))) {
|
|
|
|
*templateName = rtl::OUString();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (segment[segment.getLength() - 1] != ']' ||
|
|
|
|
(segment[i + 1] != '\'' && segment[i + 1] != '"') ||
|
|
|
|
segment.getLength() - 2 <= i + 1 ||
|
|
|
|
segment[segment.getLength() - 2] != segment[i + 1])
|
|
|
|
{
|
2009-05-20 13:33:52 +02:00
|
|
|
return false;
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
rtl::OUStringBuffer buf;
|
|
|
|
i += 2;
|
|
|
|
while (i < segment.getLength() - 2) {
|
|
|
|
sal_Unicode c = segment[i];
|
|
|
|
if (c == '&') {
|
|
|
|
if (segment.matchAsciiL(RTL_CONSTASCII_STRINGPARAM("amp;"), i + 1))
|
|
|
|
{
|
|
|
|
buf.append(sal_Unicode('&'));
|
|
|
|
i += RTL_CONSTASCII_LENGTH("&");
|
|
|
|
} else if (segment.matchAsciiL(
|
|
|
|
RTL_CONSTASCII_STRINGPARAM("quot;"), i + 1))
|
|
|
|
{
|
|
|
|
buf.append(sal_Unicode('"'));
|
|
|
|
i += RTL_CONSTASCII_LENGTH(""");
|
|
|
|
} else if (segment.matchAsciiL(
|
|
|
|
RTL_CONSTASCII_STRINGPARAM("apos;"), i + 1))
|
|
|
|
{
|
|
|
|
buf.append(sal_Unicode('\''));
|
|
|
|
i += RTL_CONSTASCII_LENGTH("'");
|
|
|
|
} else {
|
2009-05-20 13:33:52 +02:00
|
|
|
return false;
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
buf.append(c);
|
|
|
|
++i;
|
|
|
|
}
|
|
|
|
}
|
2009-05-20 13:33:52 +02:00
|
|
|
*name = buf.makeStringAndClear();
|
|
|
|
return true;
|
2009-05-15 14:06:56 +02:00
|
|
|
}
|
|
|
|
|
2009-05-20 17:20:08 +02:00
|
|
|
rtl::Reference< Node > Components::resolvePath(rtl::OUString const & path) {
|
|
|
|
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
|
|
|
sal_Int32 n = findFirst(path, '/', 1);
|
|
|
|
rtl::OUString seg;
|
|
|
|
bool setElement;
|
|
|
|
if (!parseSegment(path.copy(1, n - 1), &seg, &setElement, 0) || setElement)
|
|
|
|
{
|
|
|
|
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
|
|
|
NodeMap::iterator i(components_.find(path.copy(1, n - 1)));
|
|
|
|
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-05-15 14:06:56 +02:00
|
|
|
sal_Int32 n1 = findFirst(path, '/', n + 1);
|
|
|
|
rtl::OUString segment(path.copy(n + 1, n1 - (n + 1)));
|
|
|
|
// For backwards compatibility, ignore a final slash:
|
|
|
|
if (segment.getLength() == 0 && n1 == path.getLength()) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
rtl::OUString templateName;
|
2009-05-20 13:33:52 +02:00
|
|
|
if (!parseSegment(segment, &seg, &setElement, &templateName)) {
|
|
|
|
throw css::uno::RuntimeException(
|
|
|
|
rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("bad path ")) + path,
|
|
|
|
0);
|
|
|
|
}
|
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),
|
|
|
|
0);
|
|
|
|
}
|
2009-05-19 10:49:37 +02:00
|
|
|
p = set->getMember(seg);
|
|
|
|
if (templateName.getLength() != 0 && p != 0) {
|
2009-05-15 14:06:56 +02:00
|
|
|
//TODO: check match
|
|
|
|
}
|
|
|
|
} 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
|
|
|
}
|
|
|
|
n = n1;
|
|
|
|
}
|
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-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_);
|
|
|
|
}
|
|
|
|
|
|
|
|
Components::~Components() {}
|
|
|
|
|
|
|
|
}
|