summaryrefslogtreecommitdiff
path: root/configmgr/source/xml/basicparser.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'configmgr/source/xml/basicparser.cxx')
-rw-r--r--configmgr/source/xml/basicparser.cxx462
1 files changed, 462 insertions, 0 deletions
diff --git a/configmgr/source/xml/basicparser.cxx b/configmgr/source/xml/basicparser.cxx
new file mode 100644
index 000000000000..517a5d7090d6
--- /dev/null
+++ b/configmgr/source/xml/basicparser.cxx
@@ -0,0 +1,462 @@
+/*************************************************************************
+ *
+ * $RCSfile: basicparser.cxx,v $
+ *
+ * $Revision: 1.1 $
+ *
+ * last change: $Author: jb $ $Date: 2002-05-16 11:00:28 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library 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 for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2002 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include "basicparser.hxx"
+
+#ifndef _COM_SUN_STAR_XML_SAX_SAXEXCEPTION_HPP_
+#include <com/sun/star/xml/sax/SAXException.hpp>
+#endif
+
+#ifndef CONFIGMGR_XML_VALUECONVERTER_HXX
+#include "valueconverter.hxx"
+#endif
+// -----------------------------------------------------------------------------
+
+namespace configmgr
+{
+// -----------------------------------------------------------------------------
+ namespace xml
+ {
+// -----------------------------------------------------------------------------
+ namespace uno = ::com::sun::star::uno;
+ namespace sax = ::com::sun::star::xml::sax;
+// -----------------------------------------------------------------------------
+
+namespace
+{
+ typedef uno::Reference< script::XTypeConverter > TypeConverter;
+
+ static inline
+ uno::Reference< uno::XInterface > createTCV(BasicParser::ServiceFactory const & _xSvcFactory)
+ {
+ OSL_ENSURE(_xSvcFactory.is(),"Cannot create Parser without a ServiceManager");
+
+ static const rtl::OUString k_sTCVService(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.script.Converter"));
+
+ return TypeConverter::query(_xSvcFactory->createInstance(k_sTCVService));
+ }
+
+ static inline
+ TypeConverter asTCV(uno::Reference< uno::XInterface > const & _xTCV)
+ {
+ OSL_ASSERT(TypeConverter::query(_xTCV).get() == _xTCV.get());
+ return static_cast< script::XTypeConverter * >(_xTCV.get());
+ }
+}
+// -----------------------------------------------------------------------------
+
+struct BasicParser::ValueData : ValueConverter
+{
+ OUString content;
+ OUString locale;
+ bool isLocalized;
+
+ ValueData(uno::Type const& _aType, TypeConverter const & _xTCV)
+ : ValueConverter(_aType, _xTCV)
+ , content()
+ , locale()
+ , isLocalized(false)
+ {
+ }
+
+ uno::Any convertToAny() const
+ {
+ return ValueConverter::convertToAny(this->content);
+ }
+
+ void setLocalized(OUString const & _aLocale)
+ {
+ isLocalized = true;
+ locale = _aLocale;
+ }
+};
+// -----------------------------------------------------------------------------
+
+BasicParser::BasicParser(ServiceFactory const & _xSvcFactory)
+: m_xTypeConverter( createTCV(_xSvcFactory) )
+, m_xLocator(NULL)
+, m_aDataParser()
+, m_aNodes()
+, m_aValueType()
+, m_pValueData(NULL)
+, m_nSkipLevels(0)
+, m_bEmpty()
+{
+ if (!m_xTypeConverter.is())
+ throw uno::RuntimeException();
+}
+// -----------------------------------------------------------------------------
+
+BasicParser::~BasicParser()
+{
+ delete m_pValueData;
+}
+// -----------------------------------------------------------------------------
+
+void SAL_CALL BasicParser::startDocument( )
+ throw (sax::SAXException, uno::RuntimeException)
+{
+ m_aDataParser.reset();
+ m_aValueType = uno::Type();
+ m_nSkipLevels = 0;
+
+ delete m_pValueData, m_pValueData = NULL;
+
+ while (!m_aNodes.empty()) m_aNodes.pop();
+
+ m_bEmpty = true;
+}
+// -----------------------------------------------------------------------------
+
+void SAL_CALL BasicParser::endDocument( ) throw (sax::SAXException, uno::RuntimeException)
+{
+ if (!m_aNodes.empty() || isSkipping() || isInValueData())
+ raiseParseException( "Configuration XML Parser - Invalid XML: Unexpected end of document" );
+
+ m_xLocator.clear();
+}
+// -----------------------------------------------------------------------------
+
+void SAL_CALL BasicParser::characters( const OUString& aChars )
+ throw (sax::SAXException, uno::RuntimeException)
+{
+ if (isInValueData())
+ {
+ m_pValueData->content += aChars;
+ }
+#ifdef CONFIG_XMLPARSER_VALIDATE_WHITESPACE
+ else
+ OSL_ENSURE( isSkipping() || aChars.trim().getLength() == 0, "Unexpected text content in configuration XML");
+#endif
+}
+// -----------------------------------------------------------------------------
+
+void SAL_CALL BasicParser::ignorableWhitespace( const OUString& aWhitespaces )
+ throw (sax::SAXException, uno::RuntimeException)
+{
+ if (isInValueData())
+ {
+ OSL_ENSURE(false, "Configuration XML: Unexpected ignorable (!) whitespace instruction in value data");
+ if (!m_pValueData->isNull())
+ m_pValueData->content += aWhitespaces;
+ }
+#ifdef CONFIG_XMLPARSER_VALIDATE_WHITESPACE
+ else
+ OSL_ENSURE( aChars.trim().getLength() == 0, "Unexpected non-space content in ignorable whitespace");
+#endif
+}
+// -----------------------------------------------------------------------------
+
+void SAL_CALL BasicParser::processingInstruction( const OUString& aTarget, const OUString& aData )
+ throw (sax::SAXException, uno::RuntimeException)
+{
+ OSL_ENSURE(false, "Unexpected processing instruction in Configuration XML");
+}
+// -----------------------------------------------------------------------------
+
+void SAL_CALL BasicParser::setDocumentLocator( const uno::Reference< sax::XLocator >& xLocator )
+ throw (sax::SAXException, uno::RuntimeException)
+{
+ m_xLocator = xLocator;
+}
+// -----------------------------------------------------------------------------
+
+void BasicParser::startNode( ElementInfo const & aInfo, const uno::Reference< sax::XAttributeList >& xAttribs )
+{
+ OSL_ENSURE( !isSkipping(), "While skipping, call startSkipping() instead of startNode()");
+ OSL_ENSURE( aInfo.type != ElementType::property, "For properties, call startProperty() instead of startNode()");
+
+ if (isInProperty())
+ raiseParseException( "Configuration XML Parser - Invalid Data: Cannot have a node nested in a property" );
+
+ m_aNodes.push(aInfo);
+ m_bEmpty = (aInfo.flags != 0) || (aInfo.op > Operation::modify);
+
+ OSL_POSTCOND( isInNode(), "Could not start a node ");
+}
+// -----------------------------------------------------------------------------
+
+void BasicParser::endNode( )
+{
+ OSL_ENSURE( !isSkipping(), "While skipping, honor wasSkipping() instead of calling endNode()");
+ OSL_ENSURE( !isInProperty(), "For properties, call endProperty() instead of endNode()" );
+
+ ensureInNode();
+
+ m_aNodes.pop();
+ m_bEmpty = false;
+}
+// -----------------------------------------------------------------------------
+
+void BasicParser::ensureInNode( )
+{
+ if (!isInNode())
+ raiseParseException("Unexpected endElement without matching startElement");
+}
+// -----------------------------------------------------------------------------
+
+bool BasicParser::isInNode( )
+{
+ return ! m_aNodes.empty();
+}
+// -----------------------------------------------------------------------------
+
+bool BasicParser::isEmptyNode( )
+{
+ return m_bEmpty;
+}
+// -----------------------------------------------------------------------------
+
+ElementInfo const & BasicParser::getActiveNodeInfo( )
+{
+ ensureInNode();
+
+ return m_aNodes.top();
+}
+// -----------------------------------------------------------------------------
+
+void BasicParser::startProperty( ElementInfo const & aInfo, const uno::Reference< sax::XAttributeList >& xAttribs )
+{
+ OSL_ENSURE( !isSkipping(), "While skipping, call startSkipping() instead of startProperty()");
+ OSL_ENSURE( aInfo.type == ElementType::property, "For non-property nodes, call startNode() instead of startProperty()");
+
+ if (isInProperty())
+ raiseParseException( "Configuration XML Parser - Invalid Data: Properties may not nest" );
+
+ m_aValueType = getDataParser().getPropertyValueType(xAttribs);
+
+ if (m_aValueType == uno::Type())
+ raiseParseException( "Configuration XML Parser - Invalid Data: Property without a type" );
+
+ m_aNodes.push(aInfo);
+ m_bEmpty = true;
+
+ OSL_POSTCOND( isInProperty(), "Could not get data to start a property" );
+ OSL_POSTCOND( isInUnhandledProperty(), "Could not mark property as unhandled");
+}
+// -----------------------------------------------------------------------------
+
+void BasicParser::endProperty( )
+{
+ OSL_ENSURE( !isSkipping(), "While skipping, honor wasSkipping() instead of calling endProperty()");
+ OSL_ENSURE( isInProperty(), "For non-property nodes, call endNode() instead of endProperty()" );
+
+ ensureInNode();
+
+ m_aNodes.pop();
+ m_bEmpty = false;
+
+ m_aValueType = uno::Type();
+
+ OSL_POSTCOND( !isInProperty(), "Could not get mark end of property" );
+}
+// -----------------------------------------------------------------------------
+
+uno::Type BasicParser::getActivePropertyType()
+{
+ return m_aValueType;
+}
+// -----------------------------------------------------------------------------
+
+bool BasicParser::isInProperty()
+{
+ return m_aValueType.getTypeClass() != uno::TypeClass_VOID;
+}
+// -----------------------------------------------------------------------------
+
+bool BasicParser::isInUnhandledProperty()
+{
+ return m_bEmpty && m_aValueType.getTypeClass() != uno::TypeClass_VOID;
+}
+// -----------------------------------------------------------------------------
+
+void BasicParser::startValueData(const uno::Reference< sax::XAttributeList >& xAttribs)
+{
+ if (!isInProperty())
+ raiseParseException( "Configuration XML Parser - Invalid Data: A value may occur only within a property" );
+
+ if (m_aValueType.getTypeClass() == uno::TypeClass_ANY)
+ raiseParseException( "Configuration XML Parser - Invalid Data: Cannot have values for properties of type 'Any'" );
+
+ if (isInValueData())
+ raiseParseException( "Configuration XML Parser - Invalid Data: Unexpected element while parsing value data" );
+
+ m_pValueData = new ValueData(m_aValueType, asTCV(m_xTypeConverter));
+
+ m_pValueData->setIsNull( getDataParser().isNull(xAttribs) );
+
+ OUString aLocale;
+ if ( getDataParser().getLanguage(xAttribs,aLocale) )
+ m_pValueData->setLocalized( aLocale );
+
+ if (!m_pValueData->isNull() && m_pValueData->isList())
+ m_pValueData->setSeparator( getDataParser().getSeparator(xAttribs) );
+
+ else
+ OSL_ENSURE(getDataParser().getSeparator(xAttribs).getLength() == 0,
+ "Warning: Spurious oor:separator on value that is not a list (or null)");
+}
+// -----------------------------------------------------------------------------
+
+bool BasicParser::isInValueData()
+{
+ return m_pValueData != NULL;
+}
+// -----------------------------------------------------------------------------
+
+bool BasicParser::isValueDataLocalized()
+{
+ OSL_ENSURE(isInValueData(), "There is no value data that could be localized");
+
+ return m_pValueData && m_pValueData->isLocalized;
+}
+// -----------------------------------------------------------------------------
+
+OUString BasicParser::getValueDataLocale()
+{
+ OSL_ENSURE(isValueDataLocalized(), "There is no value data or it is not localized");
+
+ return m_pValueData->locale;
+}
+// -----------------------------------------------------------------------------
+
+uno::Any BasicParser::getCurrentValue()
+{
+ OSL_ASSERT( isInValueData() );
+
+ return m_pValueData->convertToAny();
+}
+// -----------------------------------------------------------------------------
+
+/// end collecting data for a value
+void BasicParser::endValueData()
+{
+ OSL_ASSERT( isInValueData() );
+
+ delete m_pValueData, m_pValueData = NULL;
+ m_bEmpty = false;
+
+ OSL_POSTCOND( !isInValueData(), "Could not end value data tag" );
+ OSL_POSTCOND( !isInUnhandledProperty(), "Could not mark property as handled" );
+}
+// -----------------------------------------------------------------------------
+
+void BasicParser::startSkipping( const OUString& aName, const uno::Reference< sax::XAttributeList >& xAttribs )
+{
+ m_aNodes.push( ElementInfo(aName) );
+ ++m_nSkipLevels;
+}
+// -----------------------------------------------------------------------------
+
+bool BasicParser::wasSkipping( const OUString& aName )
+{
+ if (m_nSkipLevels == 0) return false;
+
+ if (m_aNodes.empty())
+ raiseParseException( "Configuration XML Parser - Invalid XML: Unexpected end of element (while skipping data)" );
+
+ if (aName != m_aNodes.top().name)
+ raiseParseException( "Configuration XML Parser - Invalid XML: End tag does not match start tag (while skipping data)" );
+
+ --m_nSkipLevels;
+ m_aNodes.pop();
+
+ return true;
+}
+// -----------------------------------------------------------------------------
+
+bool BasicParser::isSkipping( )
+{
+ return m_nSkipLevels != 0;
+}
+// -----------------------------------------------------------------------------
+
+void BasicParser::raiseParseException( uno::Any const & _aTargetException, sal_Char const * _pMsg )
+ CFG_THROW2 (sax::SAXException, uno::RuntimeException)
+{
+ if (_pMsg == 0) _pMsg = "Configuration XML Parser: Invalid Data: ";
+
+ OUString sMessage = OUString::createFromAscii(_pMsg);
+
+ uno::Exception aEx;
+ if (_aTargetException >>= aEx)
+ sMessage += aEx.Message;
+
+ throw sax::SAXException( sMessage, *this, _aTargetException );
+}
+// -----------------------------------------------------------------------------
+
+void BasicParser::raiseParseException( sal_Char const * _pMsg )
+ CFG_THROW2 (sax::SAXException, uno::RuntimeException)
+{
+ if (_pMsg == 0) _pMsg = "Configuration XML Parser: Invalid XML";
+
+ OUString const sMessage = OUString::createFromAscii(_pMsg);
+
+ throw sax::SAXException( sMessage, *this, uno::Any() );
+}
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+ } // namespace
+
+// -----------------------------------------------------------------------------
+} // namespace
+