summaryrefslogtreecommitdiff
path: root/configmgr/source/xml/elementparser.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'configmgr/source/xml/elementparser.cxx')
-rw-r--r--configmgr/source/xml/elementparser.cxx585
1 files changed, 585 insertions, 0 deletions
diff --git a/configmgr/source/xml/elementparser.cxx b/configmgr/source/xml/elementparser.cxx
new file mode 100644
index 000000000000..663294a0b97c
--- /dev/null
+++ b/configmgr/source/xml/elementparser.cxx
@@ -0,0 +1,585 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: elementparser.cxx,v $
+ * $Revision: 1.16 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_configmgr.hxx"
+
+#include "elementparser.hxx"
+#include "xmlstrings.hxx"
+#include "typeconverter.hxx"
+
+#include <com/sun/star/configuration/backend/SchemaAttribute.hpp>
+#include <com/sun/star/configuration/backend/NodeAttribute.hpp>
+
+#include <rtl/ustrbuf.hxx>
+
+// -----------------------------------------------------------------------------
+
+namespace configmgr
+{
+// -----------------------------------------------------------------------------
+ namespace xml
+ {
+// -----------------------------------------------------------------------------
+ namespace uno = ::com::sun::star::uno;
+ namespace sax = ::com::sun::star::xml::sax;
+// -----------------------------------------------------------------------------
+
+static
+inline
+sal_Int16 impl_getIndexByName(uno::Reference< sax::XAttributeList > const& xAttribs, rtl::OUString const& aAttributeName)
+{
+ OSL_PRECOND( xAttribs.is(), "ERROR: NULL Attribute list");
+
+ sal_Int16 nIndex = xAttribs->getLength();
+
+ while (--nIndex >= 0)
+ {
+ if (xAttribs->getNameByIndex(nIndex).equals(aAttributeName))
+ break;
+ }
+ // nIndex == -1 if not found
+
+ return nIndex;
+}
+// -----------------------------------------------------------------------------
+static
+inline
+bool impl_maybeGetAttribute(uno::Reference< sax::XAttributeList > const& xAttribs, rtl::OUString const& aAttributeName, /* OUT */ rtl::OUString& rAttributeValue)
+{
+ OSL_PRECOND( xAttribs.is(), "ERROR: NULL Attribute list");
+
+ rtl::OUString aValue = xAttribs->getValueByName(aAttributeName);
+ if( aValue.getLength()!=0)
+ {
+ rAttributeValue = aValue;
+ return true;
+ }
+ return false;
+}
+// -----------------------------------------------------------------------------
+
+/// retrieve the (almost) complete information for an element
+ElementInfo ElementParser::parseElementInfo(rtl::OUString const& _sTag, uno::Reference< sax::XAttributeList > const& _xAttribs) const
+{
+ ElementType::Enum aType = this->getNodeType(_sTag,_xAttribs);
+
+ ElementInfo aInfo( this->getName(_sTag,_xAttribs,aType), aType );
+
+ aInfo.op = this->getOperation(_xAttribs,aType);
+ aInfo.flags = this->getNodeFlags(_xAttribs,aType);
+
+ return aInfo;
+}
+// -----------------------------------------------------------------------------
+
+ElementType::Enum ElementParser::getNodeType(rtl::OUString const& _sElementName, uno::Reference< sax::XAttributeList > const& _xAttribs) const
+{
+ { (void)_xAttribs; }
+ OSL_PRECOND( _xAttribs.is(), "ERROR: NULL Attribute list");
+
+ // todo: make this use a table, if necessary
+ ElementType::Enum eResult = ElementType::unknown;
+ if (_sElementName.equals(TAG_VALUE))
+ eResult = ElementType::value;
+
+ else if (_sElementName.equals(TAG_PROP))
+ eResult = ElementType::property;
+
+ else if (_sElementName.equals(TAG_NODE))
+ eResult = ElementType::node;
+
+ else if (_sElementName.equals(TAG_GROUP))
+ eResult = ElementType::group;
+
+ else if (_sElementName.equals(TAG_SET))
+ eResult = ElementType::set;
+
+ else if (_sElementName.equals(TAG_INSTANCE))
+ eResult = ElementType::instance;
+
+ else if (_sElementName.equals(TAG_ITEMTYPE))
+ eResult = ElementType::item_type;
+
+ else if (_sElementName.equals(TAG_IMPORT))
+ eResult = ElementType::import;
+
+ else if (_sElementName.equals(TAG_LAYER))
+ eResult = ElementType::layer;
+
+ else if (_sElementName.equals(TAG_SCHEMA))
+ eResult = ElementType::schema;
+
+ else if (_sElementName.equals(TAG_COMPONENT))
+ eResult = ElementType::component;
+
+ else if (_sElementName.equals(TAG_TEMPLATES))
+ eResult = ElementType::templates;
+
+ else if (_sElementName.equals(TAG_USES))
+ eResult = ElementType::uses;
+
+ // #109668# maintain support for old tag on load
+ else if (_sElementName.equals(DEPRECATED_TAG_LAYER))
+ {
+ logger().warning("Layer starts with invalid root tag \"oor:node\". Use \"oor:component-data\" instead.",
+ "getNodeType()","configmgr::xml::ElementParser");
+ eResult = ElementType::layer;
+ }
+
+ else
+ eResult = ElementType::other;
+
+ return eResult;
+}
+// -----------------------------------------------------------------------------
+
+/// takes the node name from either an attribute or the element name
+rtl::OUString ElementParser::getName(rtl::OUString const& _sElementName, uno::Reference< sax::XAttributeList > const& _xAttribs, ElementType::Enum _eType) const
+{
+ rtl::OUString aName;
+ rtl::OUString aPackage;
+
+ bool bNameFound = this->maybeGetAttribute(_xAttribs, ATTR_NAME, aName);
+ bool bPackage = false;
+
+ switch (_eType)
+ {
+ case ElementType::schema:
+ bPackage = this->maybeGetAttribute(_xAttribs,ATTR_PACKAGE,aPackage);
+ OSL_ENSURE(bPackage, "configmgr::xml::ElementParser: Found schema without package.");
+ break;
+
+ case ElementType::layer:
+ bPackage = this->maybeGetAttribute(_xAttribs,ATTR_PACKAGE,aPackage);
+
+ if (!bPackage) // for compatibility we still support 'oor:context'
+ {
+ bPackage = this->maybeGetAttribute(_xAttribs,ATTR_CONTEXT,aPackage);
+
+ if (bPackage)
+ {
+ // TODO: log this
+ OSL_TRACE("configmgr::xml::ElementParser: Found obsolete layer attribute "
+ "oor:context=\"%s\" in component \"%s\".\n",
+ rtl::OUStringToOString(aPackage,RTL_TEXTENCODING_ASCII_US).getStr(),
+ rtl::OUStringToOString(aName,RTL_TEXTENCODING_ASCII_US).getStr());
+ }
+ }
+
+ OSL_ENSURE(bPackage, "configmgr::xml::ElementParser: Found layer without package.");
+ break;
+
+ case ElementType::node:
+ case ElementType::set:
+ case ElementType::group:
+ case ElementType::instance:
+ case ElementType::property:
+ break;
+
+ // these have no name to speak of
+ case ElementType::value:
+ case ElementType::item_type:
+ case ElementType::import:
+ case ElementType::uses:
+ case ElementType::templates:
+ case ElementType::component:
+ OSL_ENSURE(!bNameFound, "Configuration Parser: Unexpected name attribute is ignored\n");
+ return _sElementName;
+
+ // for unknown prefer name to
+ case ElementType::unknown:
+ if (!bNameFound) return _sElementName;
+
+ bPackage = this->maybeGetAttribute(_xAttribs,ATTR_PACKAGE,aPackage);
+ break;
+
+ default:
+ if (!bNameFound) return _sElementName;
+ break;
+ }
+
+ OSL_ENSURE(aName.getLength(),"Found empty name tag on element");
+
+ if (bPackage)
+ {
+ static const sal_Unicode chPackageSep = '.';
+
+ aName = aPackage.concat(rtl::OUString(&chPackageSep,1)).concat(aName);
+ }
+ else
+ {
+ OSL_ENSURE(!this->maybeGetAttribute(_xAttribs,ATTR_PACKAGE,aPackage),
+ "configmgr::xml::ElementParser: Found unexpected 'oor:package' on inner or unknown node." );
+ }
+
+ return aName;
+}
+// -----------------------------------------------------------------------------
+
+Operation::Enum ElementParser::getOperation(uno::Reference< sax::XAttributeList > const& xAttribs,ElementType::Enum _eType) const
+{
+ rtl::OUString sOpName;
+ if ((_eType != ElementType::property) && (_eType !=ElementType::node))
+ {
+ return Operation::none;
+ }
+
+ if ( !this->maybeGetAttribute(xAttribs,ATTR_OPERATION, sOpName) )
+ return Operation::none;
+
+ if (sOpName.equals(OPERATION_MODIFY))
+ return Operation::modify;
+
+ else if (sOpName.equals(OPERATION_REPLACE))
+ return Operation::replace;
+ else if (sOpName.equals(OPERATION_FUSE))
+ return Operation::fuse;
+
+ else if (sOpName.equals(OPERATION_REMOVE))
+ return Operation::remove;
+#if 0
+ else if (sOpName.equals(OPERATION_CLEAR))
+ return Operation::clear;
+#endif
+ else
+ return Operation::unknown;
+}
+// -----------------------------------------------------------------------------
+
+
+/// retrieve the locale stored in the attribute list
+bool ElementParser::getLanguage(uno::Reference< sax::XAttributeList > const& xAttribs, rtl::OUString& _rsLanguage) const
+{
+ return this->maybeGetAttribute(xAttribs, EXT_ATTR_LANGUAGE, _rsLanguage);
+}
+// -----------------------------------------------------------------------------
+
+/// reads attributes for nodes from the attribute list
+sal_Int16 ElementParser::getNodeFlags(uno::Reference< sax::XAttributeList > const& xAttribs,ElementType::Enum _eType) const
+{
+ namespace NodeAttribute = ::com::sun::star::configuration::backend::NodeAttribute;
+ namespace SchemaAttribute = ::com::sun::star::configuration::backend::SchemaAttribute;
+
+ bool bValue;
+
+ sal_Int16 aResult = 0;
+
+ switch(_eType)
+ {
+ case ElementType::property :
+ if (this->maybeGetAttribute(xAttribs, ATTR_FLAG_NULLABLE, bValue) && ! bValue)
+ aResult |= SchemaAttribute::REQUIRED;
+ if (this->maybeGetAttribute(xAttribs, ATTR_FLAG_LOCALIZED, bValue) && bValue)
+ aResult |= SchemaAttribute::LOCALIZED;
+ if (this->maybeGetAttribute(xAttribs, ATTR_FLAG_READONLY, bValue) && bValue)
+ aResult |= NodeAttribute::READONLY;
+ if (this->maybeGetAttribute(xAttribs, ATTR_FLAG_FINALIZED, bValue) && bValue)
+ aResult |= NodeAttribute::FINALIZED;
+ break;
+
+ case ElementType::node:
+ if (this->maybeGetAttribute(xAttribs, ATTR_FLAG_FINALIZED, bValue) && bValue)
+ aResult |= NodeAttribute::FINALIZED;
+ if (this->maybeGetAttribute(xAttribs, ATTR_FLAG_MANDATORY, bValue) && bValue)
+ aResult |= NodeAttribute::MANDATORY;
+ if (this->maybeGetAttribute(xAttribs, ATTR_FLAG_READONLY, bValue) && bValue)
+ aResult |= NodeAttribute::READONLY;
+ break;
+
+ case ElementType::group:
+ case ElementType::set:
+ if (this->maybeGetAttribute(xAttribs, ATTR_FLAG_EXTENSIBLE, bValue) && bValue)
+ aResult |= SchemaAttribute::EXTENSIBLE;
+ break;
+
+ case ElementType::layer:
+ if (this->maybeGetAttribute(xAttribs, ATTR_FLAG_READONLY, bValue) && bValue)
+ aResult |= NodeAttribute::READONLY;
+ if (this->maybeGetAttribute(xAttribs, ATTR_FLAG_FINALIZED, bValue) && bValue)
+ aResult |= NodeAttribute::FINALIZED;
+ break;
+
+ default:
+ break;
+
+ }
+ return aResult;
+}
+// -----------------------------------------------------------------------------
+static
+void badValueType(Logger const & logger, sal_Char const * _pMsg, rtl::OUString const & _sType)
+{
+ rtl::OUStringBuffer sMessageBuf;
+ sMessageBuf.appendAscii( "Configuration XML parser: Bad value type attribute: " );
+ if (_pMsg) sMessageBuf.appendAscii(_pMsg);
+
+ const sal_Unicode kQuote = '"';
+ sMessageBuf.append(kQuote).append(_sType).append(kQuote);
+
+ rtl::OUString const sMessage = sMessageBuf.makeStringAndClear();
+ logger.error(sMessage);
+ throw ElementParser::BadValueType(sMessage);
+}
+// -----------------------------------------------------------------------------
+static
+inline
+sal_Bool matchNsPrefix(rtl::OUString const & _sString, rtl::OUString const & _sPrefix)
+{
+ return _sString.match(_sPrefix) &&
+ _sString.getStr()[_sPrefix.getLength()] == k_NS_SEPARATOR;
+}
+// -----------------------------------------------------------------------------
+static
+inline
+sal_Bool matchSuffix(rtl::OUString const & _sString, rtl::OUString const & _sSuffix)
+{
+ sal_Int32 nSuffixStart = _sString.getLength() - _sSuffix.getLength();
+ if (nSuffixStart < 0)
+ return false;
+
+ return _sString.match(_sSuffix,nSuffixStart);
+}
+// -----------------------------------------------------------------------------
+static
+inline
+rtl::OUString stripNsPrefix(rtl::OUString const & _sString, rtl::OUString const & _sPrefix)
+{
+ OSL_ASSERT( matchNsPrefix(_sString,_sPrefix) );
+
+ return _sString.copy(_sPrefix.getLength() + 1);
+}
+// -----------------------------------------------------------------------------
+static
+inline
+rtl::OUString stripSuffix(rtl::OUString const & _sString, rtl::OUString const & _sSuffix)
+{
+ OSL_ASSERT( matchSuffix(_sString,_sSuffix) );
+
+ sal_Int32 nSuffixStart = _sString.getLength() - _sSuffix.getLength();
+
+ return _sString.copy(0,nSuffixStart);
+}
+// -----------------------------------------------------------------------------
+static
+inline
+rtl::OUString stripTypeName(Logger const & logger, rtl::OUString const & _sString, rtl::OUString const & _sPrefix)
+{
+ if ( matchNsPrefix(_sString,_sPrefix))
+ return stripNsPrefix(_sString, _sPrefix);
+
+ badValueType(logger, "Missing expected namespace prefix on type name: ", _sString);
+
+ return _sString;
+}
+// -----------------------------------------------------------------------------
+static
+uno::Type xmlToScalarType(const rtl::OUString& _rType)
+{
+ uno::Type aRet;
+
+ if (_rType.equalsIgnoreAsciiCaseAscii(VALUETYPE_BOOLEAN))
+ aRet = ::getBooleanCppuType();
+
+ else if(_rType.equalsIgnoreAsciiCaseAscii(VALUETYPE_SHORT))
+ aRet = ::getCppuType(static_cast<sal_Int16 const*>(0));
+
+ else if(_rType.equalsIgnoreAsciiCaseAscii(VALUETYPE_INT))
+ aRet = ::getCppuType(static_cast<sal_Int32 const*>(0));
+
+ else if(_rType.equalsIgnoreAsciiCaseAscii(VALUETYPE_LONG))
+ aRet = ::getCppuType(static_cast<sal_Int64 const*>(0));
+
+ else if(_rType.equalsIgnoreAsciiCaseAscii(VALUETYPE_DOUBLE))
+ aRet = ::getCppuType(static_cast< double const*>(0));
+
+ else if(_rType.equalsIgnoreAsciiCaseAscii(VALUETYPE_STRING))
+ aRet = ::getCppuType(static_cast<rtl::OUString const*>(0));
+
+ else if(_rType.equalsIgnoreAsciiCaseAscii(VALUETYPE_BINARY))
+ aRet = ::getCppuType(static_cast<uno::Sequence<sal_Int8> const*>(0));
+
+ else if(_rType.equalsIgnoreAsciiCaseAscii(VALUETYPE_ANY))
+ aRet = ::getCppuType(static_cast<uno::Any const*>(0));
+
+ else
+ OSL_ENSURE(false,"Cannot parse: Unknown value type");
+
+ return aRet;
+}
+// -----------------------------------------------------------------------------
+uno::Type xmlToListType(const rtl::OUString& _aElementType)
+{
+ uno::Type aRet;
+
+ if (_aElementType.equalsIgnoreAsciiCaseAscii(VALUETYPE_BOOLEAN))
+ aRet = ::getCppuType(static_cast<uno::Sequence<sal_Bool> const*>(0));
+
+ else if(_aElementType.equalsIgnoreAsciiCaseAscii(VALUETYPE_SHORT))
+ aRet = ::getCppuType(static_cast<uno::Sequence<sal_Int16> const*>(0));
+
+ else if(_aElementType.equalsIgnoreAsciiCaseAscii(VALUETYPE_INT))
+ aRet = ::getCppuType(static_cast<uno::Sequence<sal_Int32> const*>(0));
+
+ else if(_aElementType.equalsIgnoreAsciiCaseAscii(VALUETYPE_LONG))
+ aRet = ::getCppuType(static_cast<uno::Sequence<sal_Int64> const*>(0));
+
+ else if(_aElementType.equalsIgnoreAsciiCaseAscii(VALUETYPE_DOUBLE))
+ aRet = ::getCppuType(static_cast<uno::Sequence<double> const*>(0));
+
+ else if(_aElementType.equalsIgnoreAsciiCaseAscii(VALUETYPE_STRING))
+ aRet = ::getCppuType(static_cast<uno::Sequence<rtl::OUString> const*>(0));
+
+ else if(_aElementType.equalsIgnoreAsciiCaseAscii(VALUETYPE_BINARY))
+ aRet = ::getCppuType(static_cast<uno::Sequence<uno::Sequence<sal_Int8> > const*>(0));
+
+ else
+ OSL_ENSURE(false,"Cannot parse: Unknown list value type");
+
+ return aRet;
+}
+// -----------------------------------------------------------------------------
+/// retrieve data type of a property,
+uno::Type ElementParser::getPropertyValueType(uno::Reference< sax::XAttributeList > const& xAttribs) const
+{
+ rtl::OUString sTypeName;
+ if (!this->maybeGetAttribute(xAttribs, ATTR_VALUETYPE, sTypeName))
+ return uno::Type(); // => VOID
+
+ uno::Type aType;
+
+ // valuetype names are either 'xs:<type>' or 'oor:<type>' or 'oor:<type>-list'
+ if (matchSuffix(sTypeName,VALUETYPE_LIST_SUFFIX))
+ {
+ rtl::OUString sBasicName = stripTypeName( mLogger, stripSuffix(sTypeName,VALUETYPE_LIST_SUFFIX), NS_PREFIX_OOR );
+
+ aType = xmlToListType(sBasicName);
+ }
+ else
+ {
+ rtl::OUString sPrefix = matchNsPrefix(sTypeName,NS_PREFIX_OOR) ? rtl::OUString( NS_PREFIX_OOR ) : rtl::OUString( NS_PREFIX_XS );
+
+ rtl::OUString sBasicName = stripTypeName( mLogger, sTypeName, sPrefix );
+
+ aType = xmlToScalarType(sBasicName);
+ }
+
+ if (aType == uno::Type())
+ badValueType(mLogger,"Unknown type name: ", sTypeName);
+
+ return aType;
+}
+// -----------------------------------------------------------------------------
+
+/// retrieve element type and associated module name of a set,
+bool ElementParser::getSetElementType(uno::Reference< sax::XAttributeList > const& xAttribs, rtl::OUString& aElementType, rtl::OUString& aElementTypeModule) const
+{
+ if (!this->maybeGetAttribute(xAttribs, ATTR_ITEMTYPE, aElementType))
+ return false;
+
+ maybeGetAttribute(xAttribs, ATTR_ITEMTYPECOMPONENT, aElementTypeModule);
+
+ return true;
+}
+// -----------------------------------------------------------------------------
+
+/// retrieve instance type and associated module name of a set,
+bool ElementParser::getInstanceType(uno::Reference< sax::XAttributeList > const& xAttribs, rtl::OUString& aElementType, rtl::OUString& aElementTypeModule) const
+{
+ if (!this->maybeGetAttribute(xAttribs, ATTR_ITEMTYPE, aElementType))
+ return false;
+
+ maybeGetAttribute(xAttribs, ATTR_ITEMTYPECOMPONENT, aElementTypeModule);
+
+ return true;
+}
+// -----------------------------------------------------------------------------
+
+/// retrieve the component for an import or uses element,
+bool ElementParser::getImportComponent(uno::Reference< sax::XAttributeList > const& xAttribs, rtl::OUString& _rsComponent) const
+{
+ return this->maybeGetAttribute(xAttribs, ATTR_COMPONENT, _rsComponent);
+}
+// -----------------------------------------------------------------------------
+
+/// reads attributes for values from the attribute list
+bool ElementParser::isNull(uno::Reference< sax::XAttributeList > const& _xAttribs) const
+{
+ bool bNull;
+ return maybeGetAttribute(_xAttribs, EXT_ATTR_NULL, bNull) && bNull;
+}
+// -----------------------------------------------------------------------------
+
+/// reads attributes for values from the attribute list
+rtl::OUString ElementParser::getSeparator(uno::Reference< sax::XAttributeList > const& _xAttribs) const
+{
+ rtl::OUString aSeparator;
+ maybeGetAttribute(_xAttribs, ATTR_VALUESEPARATOR, aSeparator);
+ return aSeparator;
+}
+// -----------------------------------------------------------------------------
+
+// low-level internal methods
+/// checks for presence of a boolean attribute and assigns its value if it exists (and is a bool)
+bool ElementParser::maybeGetAttribute(uno::Reference< sax::XAttributeList > const& xAttribs, rtl::OUString const& aAttributeName, bool& rAttributeValue) const
+{
+ rtl::OUString sAttribute;
+
+ if ( !this->maybeGetAttribute(xAttribs, aAttributeName, sAttribute) )
+ {
+ return false;
+ }
+
+ else if (sAttribute.equals(ATTR_VALUE_TRUE))
+ rAttributeValue = true; // will return true
+
+ else if (sAttribute.equals(ATTR_VALUE_FALSE))
+ rAttributeValue = false; // will return true
+
+ else
+ {
+ OSL_ENSURE(sAttribute.getLength() == 0, "Invalid text found in boolean attribute");
+ return false;
+ }
+
+ return true;
+}
+// -----------------------------------------------------------------------------
+
+/// checks for presence of an attribute and assigns its value if it exists
+bool ElementParser::maybeGetAttribute(uno::Reference< sax::XAttributeList > const& xAttribs, rtl::OUString const& aAttributeName, rtl::OUString& rAttributeValue) const
+{
+ return xAttribs.is() && impl_maybeGetAttribute(xAttribs, aAttributeName, rAttributeValue);
+}
+
+// -----------------------------------------------------------------------------
+} // namespace
+} // namespace
+