diff options
author | Ivo Hinkelmann <ihi@openoffice.org> | 2011-02-28 18:27:24 +0100 |
---|---|---|
committer | Ivo Hinkelmann <ihi@openoffice.org> | 2011-02-28 18:27:24 +0100 |
commit | f54c23ce694b60a80303c53fb590003b2056a911 (patch) | |
tree | 8fac381cff66ce7e3dcf0948a38939ceb7045bcc /unoxml | |
parent | CWS-TOOLING: integrate CWS sw34bf03 (diff) | |
parent | xmlfix3: argh, another unhandled exception... (diff) | |
download | core-f54c23ce694b60a80303c53fb590003b2056a911.tar.gz core-f54c23ce694b60a80303c53fb590003b2056a911.zip |
CWS-TOOLING: integrate CWS xmlfix3
Diffstat (limited to 'unoxml')
78 files changed, 6828 insertions, 2123 deletions
diff --git a/unoxml/JunitTest_unordf_complex.mk b/unoxml/JunitTest_unordf_complex.mk new file mode 100644 index 000000000000..7637eef13a82 --- /dev/null +++ b/unoxml/JunitTest_unordf_complex.mk @@ -0,0 +1,52 @@ +#************************************************************************* +# +# 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 +# +# 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. +# +#************************************************************************* + +$(eval $(call gb_JunitTest_JunitTest,unordf_complex)) + +$(eval $(call gb_JunitTest_set_defs,unordf_complex,\ + $$(DEFS) \ + -Dorg.openoffice.test.arg.tdoc=$(SRCDIR)/unoxml/qa/complex/unoxml/testdocuments \ +)) + +$(eval $(call gb_JunitTest_add_jars,unordf_complex,\ + $(OUTDIR)/bin/OOoRunner.jar \ + $(OUTDIR)/bin/ridl.jar \ + $(OUTDIR)/bin/test.jar \ + $(OUTDIR)/bin/unoil.jar \ + $(OUTDIR)/bin/jurt.jar \ +)) + +$(eval $(call gb_JunitTest_add_sourcefiles,unordf_complex,\ + unoxml/qa/complex/unoxml/RDFRepositoryTest \ + unoxml/qa/complex/unoxml/TestDocument \ +)) + +$(eval $(call gb_JunitTest_add_classes,unordf_complex,\ + complex.unoxml.RDFRepositoryTest \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/unoxml/JunitTest_unoxml_complex.mk b/unoxml/JunitTest_unoxml_complex.mk new file mode 100644 index 000000000000..09eaa32e7bbe --- /dev/null +++ b/unoxml/JunitTest_unoxml_complex.mk @@ -0,0 +1,52 @@ +#************************************************************************* +# +# 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 +# +# 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. +# +#************************************************************************* + +$(eval $(call gb_JunitTest_JunitTest,unoxml_complex)) + +$(eval $(call gb_JunitTest_set_defs,unoxml_complex,\ + $$(DEFS) \ + -Dorg.openoffice.test.arg.tdoc=$(SRCDIR)/unoxml/qa/complex/unoxml/testdocuments \ +)) + +$(eval $(call gb_JunitTest_add_jars,unoxml_complex,\ + $(OUTDIR)/bin/OOoRunner.jar \ + $(OUTDIR)/bin/ridl.jar \ + $(OUTDIR)/bin/test.jar \ + $(OUTDIR)/bin/unoil.jar \ + $(OUTDIR)/bin/jurt.jar \ +)) + +$(eval $(call gb_JunitTest_add_sourcefiles,unoxml_complex,\ + unoxml/qa/complex/unoxml/DOMTest \ + unoxml/qa/complex/unoxml/TestDocument \ +)) + +$(eval $(call gb_JunitTest_add_classes,unoxml_complex,\ + complex.unoxml.DOMTest \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/unoxml/Library_unordf.mk b/unoxml/Library_unordf.mk new file mode 100644 index 000000000000..79123c6a359c --- /dev/null +++ b/unoxml/Library_unordf.mk @@ -0,0 +1,74 @@ +#************************************************************************* +# +# 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 +# +# 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. +# +#************************************************************************* + +$(eval $(call gb_Library_Library,unordf)) + +$(eval $(call gb_Library_set_componentfile,unordf,unoxml/source/rdf/unordf)) + +$(eval $(call gb_Library_set_include,unordf,\ + $$(INCLUDE) \ + -I$(OUTDIR)/inc/offuh \ +)) + +$(eval $(call gb_Library_set_defs,unordf,\ + $$(DEFS) \ +)) + +$(eval $(call gb_Library_add_linked_libs,unordf,\ + cppuhelper \ + cppu \ + sal \ + stl \ + rdf \ + xslt \ + $(gb_STDLIBS) \ +)) + +$(eval $(call gb_Library_add_exception_objects,unordf,\ + unoxml/source/rdf/CBlankNode \ + unoxml/source/rdf/CURI \ + unoxml/source/rdf/CLiteral \ + unoxml/source/rdf/librdf_repository \ + unoxml/source/rdf/librdf_services \ +)) + +ifeq ($(SYSTEM_REDLAND),YES) +$(eval $(call gb_Library_set_cxxflags,unordf,\ + $$(CXXFLAGS) \ + -DSYSTEM_REDLAND $$(REDLAND_CFLAGS) \ +)) +endif + +ifeq ($(SYSTEM_LIBXSLT),YES) +$(eval $(call gb_Library_set_cxxflags,unordf,\ + $$(CXXFLAGS) \ + $$(LIBXSLT_CFLAGS) \ +)) +endif + +# vim: set noet sw=4 ts=4: + diff --git a/unoxml/Library_unoxml.mk b/unoxml/Library_unoxml.mk new file mode 100644 index 000000000000..517c8a8462c0 --- /dev/null +++ b/unoxml/Library_unoxml.mk @@ -0,0 +1,96 @@ +#************************************************************************* +# +# 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 +# +# 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. +# +#************************************************************************* + +$(eval $(call gb_Library_Library,unoxml)) + +$(eval $(call gb_Library_set_componentfile,unoxml,unoxml/source/service/unoxml)) + +$(eval $(call gb_Library_set_include,unoxml,\ + $$(INCLUDE) \ + -I$(OUTDIR)/inc/offuh \ +)) + +$(eval $(call gb_Library_set_defs,unoxml,\ + $$(DEFS) \ +)) + +$(eval $(call gb_Library_add_linked_libs,unoxml,\ + ucbhelper \ + sax \ + comphelper \ + cppuhelper \ + cppu \ + sal \ + stl \ + xml2 \ + $(gb_STDLIBS) \ +)) + +$(eval $(call gb_Library_add_exception_objects,unoxml,\ + unoxml/source/dom/node \ + unoxml/source/dom/document \ + unoxml/source/dom/element \ + unoxml/source/dom/attr \ + unoxml/source/dom/cdatasection \ + unoxml/source/dom/characterdata \ + unoxml/source/dom/comment \ + unoxml/source/dom/documentbuilder \ + unoxml/source/dom/documentfragment \ + unoxml/source/dom/documenttype \ + unoxml/source/dom/entity \ + unoxml/source/dom/entityreference \ + unoxml/source/dom/notation \ + unoxml/source/dom/processinginstruction \ + unoxml/source/dom/text \ + unoxml/source/dom/domimplementation \ + unoxml/source/dom/elementlist \ + unoxml/source/dom/childlist \ + unoxml/source/dom/notationsmap \ + unoxml/source/dom/entitiesmap \ + unoxml/source/dom/attributesmap \ + unoxml/source/dom/saxbuilder \ + unoxml/source/xpath/xpathobject \ + unoxml/source/xpath/nodelist \ + unoxml/source/xpath/xpathapi \ + unoxml/source/events/event \ + unoxml/source/events/eventdispatcher \ + unoxml/source/events/mutationevent \ + unoxml/source/events/uievent \ + unoxml/source/events/mouseevent \ + unoxml/source/events/testlistener \ + unoxml/source/service/services \ +)) + +ifeq ($(SYSTEM_LIBXML),YES) +$(eval $(call gb_Library_set_cxxflags,unoxml,\ + $$(CXXFLAGS) \ + -DSYSTEM_LIBXML $$(LIBXML_CFLAGS) \ +)) +endif + +# vim: set noet sw=4 ts=4: + diff --git a/unoxml/qa/complex/unoxml/makefile.mk b/unoxml/Makefile index 136d23a9a232..c898975e5277 100644 --- a/unoxml/qa/complex/unoxml/makefile.mk +++ b/unoxml/Makefile @@ -1,7 +1,7 @@ #************************************************************************* # # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# +# # Copyright 2000, 2010 Oracle and/or its affiliates. # # OpenOffice.org - a multi-platform office productivity suite @@ -23,37 +23,16 @@ # <http://www.openoffice.org/license.html> # for a copy of the LGPLv3 License. # -#***********************************************************************/ - -.IF "$(OOO_SUBSEQUENT_TESTS)" == "" -nothing .PHONY: -.ELSE - -PRJ = ../../.. -PRJNAME = unoxml -TARGET = qa_complex_unoxml - -.IF "$(OOO_JUNIT_JAR)" != "" -PACKAGE = complex/unoxml -JAVATESTFILES = \ - RDFRepositoryTest.java - -JAVAFILES = $(JAVATESTFILES) \ - TestDocument.java - -JARFILES = OOoRunner.jar ridl.jar test.jar unoil.jar jurt.jar -EXTRAJARFILES = $(OOO_JUNIT_JAR) - -# Sample how to debug -# JAVAIFLAGS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,address=9003,suspend=y -.END - -.INCLUDE: settings.mk -.INCLUDE: target.mk -.INCLUDE: installationtest.mk +#************************************************************************* -ALLTAR : javatest +ifeq ($(strip $(SOLARENV)),) +$(error No environment set!) +endif -.END +gb_PARTIALBUILD := T +GBUILDDIR := $(SOLARENV)/gbuild +include $(GBUILDDIR)/gbuild.mk +$(eval $(call gb_Module_make_global_targets,$(shell ls $(dir $(realpath $(firstword $(MAKEFILE_LIST))))/Module*.mk))) +# vim: set noet sw=4 ts=4: diff --git a/unoxml/source/events/makefile.mk b/unoxml/Module_unoxml.mk index 2ec7489e1a8d..5050d0701f3f 100644 --- a/unoxml/source/events/makefile.mk +++ b/unoxml/Module_unoxml.mk @@ -1,8 +1,8 @@ #************************************************************************* # # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# Copyright 2009 by Sun Microsystems, Inc. # # OpenOffice.org - a multi-platform office productivity suite # @@ -14,43 +14,27 @@ # # 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 +# 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 +# version 3 along with OpenOffice.org. If not, see # <http://www.openoffice.org/license.html> # for a copy of the LGPLv3 License. # #************************************************************************* -PRJ=../.. - -PRJNAME=unoxml -TARGET=eventsimpl -ENABLE_EXCEPTIONS=TRUE - -# --- Settings ----------------------------------------------------- - -.INCLUDE : settings.mk - -.IF "$(SYSTEM_LIBXML)" == "YES" -CFLAGS+=-DSYSTEM_LIBXML $(LIBXML_CFLAGS) -.ENDIF - -# --- Files -------------------------------------------------------- - -SLOFILES =\ - $(SLO)$/event.obj \ - $(SLO)$/eventdispatcher.obj \ - $(SLO)$/mutationevent.obj \ - $(SLO)$/uievent.obj \ - $(SLO)$/mouseevent.obj \ - $(SLO)$/testlistener.obj - -# --- Targets ------------------------------------------------------ +$(eval $(call gb_Module_Module,unoxml)) -.INCLUDE : target.mk +$(eval $(call gb_Module_add_targets,unoxml,\ + Library_unoxml \ + Library_unordf \ +)) +$(eval $(call gb_Module_add_subsequentcheck_targets,unoxml,\ + JunitTest_unoxml_complex \ + JunitTest_unordf_complex \ +)) +# vim: set noet sw=4 ts=4: diff --git a/unoxml/prj/build.lst b/unoxml/prj/build.lst index 4da29cb9d669..02f0482d76f8 100644 --- a/unoxml/prj/build.lst +++ b/unoxml/prj/build.lst @@ -1,8 +1,2 @@ -ux unoxml : offuh cppuhelper LIBXML2:libxml2 LIBXSLT:libxslt REDLAND:redland tools NULL -ux unoxml\source\dom nmake - all ux_dom NULL -ux unoxml\source\xpath nmake - all ux_xpath ux_dom NULL -ux unoxml\source\events nmake - all ux_events ux_dom NULL -ux unoxml\source\service nmake - all ux_service ux_dom ux_xpath ux_events NULL -ux unoxml\source\rdf nmake - all ux_librdf NULL - -ux unoxml\qa\complex\unoxml nmake - all ux_complex ux_librdf NULL +ux unoxml : offuh cppuhelper LIBXML2:libxml2 LIBXSLT:libxslt REDLAND:redland sax comphelper ucbhelper NULL +ux unoxml\prj nmake - all ux_prj NULL diff --git a/unoxml/prj/d.lst b/unoxml/prj/d.lst index 4fcedbdba7a2..e69de29bb2d1 100644 --- a/unoxml/prj/d.lst +++ b/unoxml/prj/d.lst @@ -1,5 +0,0 @@ -..\%__SRC%\lib\lib*.so %_DEST%\lib%_EXT%\lib*.so -..\%__SRC%\lib\lib*.dylib %_DEST%\lib%_EXT%\lib*.dylib -..\%__SRC%\bin\*.dll %_DEST%\bin%_EXT%\*.dll -..\%__SRC%\misc\unordf.component %_DEST%\xml%_EXT%\unordf.component -..\%__SRC%\misc\unoxml.component %_DEST%\xml%_EXT%\unoxml.component diff --git a/unoxml/source/xpath/makefile.mk b/unoxml/prj/makefile.mk index 7b1ccdae742b..5ebed8a45c4a 100644 --- a/unoxml/source/xpath/makefile.mk +++ b/unoxml/prj/makefile.mk @@ -1,7 +1,7 @@ #************************************************************************* # # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# +# # Copyright 2000, 2010 Oracle and/or its affiliates. # # OpenOffice.org - a multi-platform office productivity suite @@ -25,28 +25,16 @@ # #************************************************************************* -PRJ=../.. - -PRJNAME=unoxml -TARGET=xpathimpl -ENABLE_EXCEPTIONS=TRUE +PRJ=.. +TARGET=prj -# --- Settings ----------------------------------------------------- +.INCLUDE : settings.mk -.INCLUDE : settings.mk - -.IF "$(SYSTEM_LIBXML)" == "YES" -CFLAGS+=-DSYSTEM_LIBXML $(LIBXML_CFLAGS) +.IF "$(VERBOSE)"!="" +VERBOSEFLAG := +.ELSE +VERBOSEFLAG := -s .ENDIF -# --- Files -------------------------------------------------------- - -SLOFILES = \ - $(SLO)$/xpathobject.obj \ - $(SLO)$/nodelist.obj \ - $(SLO)$/xpathapi.obj - -# --- Targets ------------------------------------------------------ - -.INCLUDE : target.mk - +all: + cd $(PRJ) && $(GNUMAKE) $(VERBOSEFLAG) -r -j$(MAXPROCESS) $(gb_MAKETARGET) diff --git a/unoxml/qa/complex/unoxml/DOMTest.java b/unoxml/qa/complex/unoxml/DOMTest.java new file mode 100644 index 000000000000..e7efad8ab5a7 --- /dev/null +++ b/unoxml/qa/complex/unoxml/DOMTest.java @@ -0,0 +1,2986 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +package complex.unoxml; + +import lib.TestParameters; +import helper.StreamSimulator; + +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XComponentContext; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.beans.XPropertySet; +import com.sun.star.io.XInputStream; +import com.sun.star.xml.dom.*; +import static com.sun.star.xml.dom.DOMExceptionType.*; +import static com.sun.star.xml.dom.NodeType.*; +import com.sun.star.xml.dom.events.*; +import com.sun.star.xml.xpath.*; +import static com.sun.star.xml.xpath.XPathObjectType.*; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.openoffice.test.OfficeConnection; +import static org.junit.Assert.*; + +/** + * Test for com.sun.star.xml.dom.*, com.sun.star.xml.xpath.* + */ +public class DOMTest +{ + private static final OfficeConnection connection = new OfficeConnection(); + + // setup and close connections + @BeforeClass public static void setUpConnection() throws Exception { + System.out.println("setUpConnection()"); + connection.setUp(); + } + + @AfterClass public static void tearDownConnection() + throws InterruptedException, com.sun.star.uno.Exception + { + System.out.println("tearDownConnection()"); + connection.tearDown(); + } + + XComponentContext m_xContext; + XMultiServiceFactory m_xMSF; + TestParameters m_params; + + @Before public void before() throws Exception + { + final XMultiServiceFactory xMSF = UnoRuntime.queryInterface( + XMultiServiceFactory.class, + connection.getComponentContext().getServiceManager()); + assertNotNull("could not create MultiServiceFactory.", xMSF); + m_params = new TestParameters(); + m_params.put("ServiceFactory", xMSF); + XPropertySet xPropertySet = + UnoRuntime.queryInterface(XPropertySet.class, xMSF); + m_xContext = UnoRuntime.queryInterface(XComponentContext.class, + xPropertySet.getPropertyValue("DefaultContext")); + assertNotNull("could not get component context.", m_xContext); + m_xMSF = xMSF; + } + + @Test public void testXSAXDocumentBuilder() throws Exception + { + XSAXDocumentBuilder xSAXBuilder = + UnoRuntime.queryInterface(XSAXDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.SAXDocumentBuilder")); + //FIXME TODO + } + + @Test public void testXDocumentBuilder() throws Exception + { + XDocumentBuilder xBuilder = + UnoRuntime.queryInterface(XDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.DocumentBuilder")); + + XDOMImplementation xDomImpl = xBuilder.getDOMImplementation(); +//FIXME fails assertNotNull("getDOMImplementation", xDomImpl); + + xBuilder.isNamespaceAware(); + xBuilder.isValidating(); + + { + XDocument xDoc = xBuilder.newDocument(); + assertNotNull("newDocument", xDoc); + } + + try { + xBuilder.parse(null); + fail("XDocumentBuilder.parse(null)"); + } catch (Exception e) { /* expected */ } + { + XInputStream xIn = new StreamSimulator( + TestDocument.getUrl("example.rdf"), true, m_params); + XDocument xDoc = xBuilder.parse(xIn); + assertNotNull("XDocumentBuilder.parse", xDoc); + } + try { + xBuilder.parseURI(""); + fail("XDocumentBuilder.parseURI(\"\")"); + } catch (Exception e) { /* expected */ } + { + XDocument xDoc = + xBuilder.parseURI(TestDocument.getUrl("example.rdf")); + assertNotNull("XDocumentBuilder.parseURI", xDoc); + } + + xBuilder.setEntityResolver(null); + /* FIXME TODO + XEntityResolver xER; + xBuilder.setEntityResolver(xER); + */ + + xBuilder.setErrorHandler(null); + /* FIXME TODO + XErrorHandler xEH; + xBuilder.setErrorHandler(xEH); + */ + } + + @Test public void testXDocument() throws Exception + { + XDocumentBuilder xBuilder = + UnoRuntime.queryInterface(XDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.DocumentBuilder")); + XDocument xDoc = xBuilder.newDocument(); + + /* FIXME + try { + xDoc.createAttribute("&"); + fail("XDocument.createAttribute"); + } catch (DOMException e) { + assertTrue("XDocument.createAttribute", + INVALID_CHARACTER_ERR == e.Code); + }*/ + { + XAttr xAttr = xDoc.createAttribute("foo"); + assertNotNull("XDocument.createAttribute", xAttr); + assertEquals("XDocument.createAttribute", + "foo", xAttr.getNodeName()); + } + + String ns = "http://example.com/"; + /* FIXME + try { + xDoc.createAttributeNS(ns, "&"); + fail("XDocument.createAttributeNS"); + } catch (DOMException e) { + assertTrue("XDocument.createAttributeNS", + INVALID_CHARACTER_ERR == e.Code); + } + */ + { + XAttr xAttr = xDoc.createAttributeNS(ns, "e:foo"); + assertNotNull("XDocument.createAttributeNS", xAttr); + assertEquals("XDocument.createAttributeNS", "foo", + xAttr.getNodeName()); + } + + XCDATASection xCDS = xDoc.createCDATASection("foo"); + assertNotNull("XDocument.createCDATASection", xCDS); + + XComment xComment = xDoc.createComment("foo"); + assertNotNull("XDocument.createComment", xComment); + + XDocumentFragment xDF = xDoc.createDocumentFragment(); + assertNotNull("XDocument.createDocumentFragment", xDF); + + /* FIXME + try { + xDoc.createElement("&"); + fail("XDocument.createElement(\"&\")"); + } catch (DOMException e) { + assertTrue("XDocument.createElement(\"&\")", + INVALID_CHARACTER_ERR == e.Code); + } + */ + XElement xElemFoo = xDoc.createElement("foo"); + assertNotNull("XDocument.createElement(\"foo\")", xElemFoo); + assertEquals("XDocument.createElement(\"foo\")", + "foo", xElemFoo.getNodeName()); + + /* FIXME + try { + xDoc.createElementNS(ns, "&"); + fail("XDocument.createElementNS(\"&\")"); + } catch (DOMException e) { + assertTrue("XDocument.createElementNS(\"&\")", + INVALID_CHARACTER_ERR == e.Code); + } + */ + XElement xElemFooNs = xDoc.createElementNS(ns, "foo"); + assertNotNull("XDocument.createElementNS(\"foo\")", xElemFooNs); + assertEquals("XDocument.createElementNS(\"foo\")", + "foo", xElemFooNs.getNodeName()); + + XEntityReference xER = xDoc.createEntityReference("foo"); + assertNotNull("XDocument.createEntityReference", xER); + + XProcessingInstruction xPI = + xDoc.createProcessingInstruction("foo", "bar"); + assertNotNull("XDocument.createProcessingInstruction", xPI); + + XText xText = xDoc.createTextNode("foo"); + assertNotNull("XDocument.createTextNode", xText); + + XDocumentType xDT = xDoc.getDoctype(); + assertNull("XDocument.getDoctype", xDT); + + { + XElement xDE = xDoc.getDocumentElement(); + assertNull("XDocument.getDocumentElement", xDE); + } + { + XElement xById = xDoc.getElementById("foo"); + assertNull("XDocument.getDocumentElement", xById); + } + + { + XNodeList xNodeList = xDoc.getElementsByTagName("foo"); + assertNotNull("XDocument.getElementsByTagName", xNodeList); + assertTrue("XDocument.getElementsByTagName", + 0 == xNodeList.getLength()); + } + + { + XNodeList xNodeList = xDoc.getElementsByTagNameNS(ns, "foo"); + assertNotNull("XDocument.getElementsByTagNameNS", xNodeList); + assertTrue("XDocument.getElementsByTagNameNS", + 0 == xNodeList.getLength()); + } + + XDOMImplementation xDOMImpl = xDoc.getImplementation(); + assertNotNull("XDocument.getImplementation", xDOMImpl); + + { + XNode xRet = xElemFooNs.appendChild(xElemFoo); + assertEquals("XElement.appendChild(xElemFoo)", xElemFoo, xRet); + } + { + XNode xRet = xDoc.appendChild(xElemFooNs); + assertTrue("XDocument.appendChild(xElemFooNs)", + xElemFooNs.equals(xRet)); + } + + XElement xDE = xDoc.getDocumentElement(); + assertNotNull("XDocument.getDocumentElement", xDE); + assertEquals("XDocument.getDocumentElement", xElemFooNs, xDE); + + { + XNodeList xNodeList = xDoc.getElementsByTagName("foo"); + assertNotNull("XDocument.getElementsByTagName", xNodeList); + assertTrue("XDocument.getElementsByTagName", + 2 == xNodeList.getLength()); + assertEquals("XDocument.getElementsByTagNameNS", + xElemFooNs, xNodeList.item(0)); + assertEquals("XDocument.getElementsByTagName", + xElemFoo, xNodeList.item(1)); + } + + { + XNodeList xNodeList = xDoc.getElementsByTagNameNS(ns, "foo"); + assertNotNull("XDocument.getElementsByTagNameNS", xNodeList); + assertTrue("XDocument.getElementsByTagNameNS", + 1 == xNodeList.getLength()); + assertEquals("XDocument.getElementsByTagNameNS", + xElemFooNs, xNodeList.item(0)); + } + + xElemFoo.setAttributeNS("http://www.w3.org/XML/1998/namespace", + "xml:id", "bar"); + + XElement xById = xDoc.getElementById("bar"); + assertNotNull("XDocument.getDocumentElement", xById); + assertEquals("XDocument.getDocumentElement", xElemFoo, xById); + + try { + xDoc.importNode(null, false); + fail("XDocument.importNode(null)"); + } catch (Exception e) { /* expected */ } + { + XNode xImported = xDoc.importNode(xElemFoo, false); + assertNotNull("XDocument.importNode()", xImported); + assertEquals("XDocument.importNode()", xElemFoo, xImported); + } + { + MockAttr xMockAttrBar = new MockAttr("bar", "blah"); + MockAttr xMockAttrBaz = new MockAttr("baz", "quux"); + MockElement xMockElemFoo = new MockElement("foo", + new MockAttr[] { xMockAttrBar, xMockAttrBaz }); + MockElement xMockElemBar = new MockElement("bar", + new MockAttr[] { }); + MockElement xMockElemRoot = + new MockElement("root", new MockAttr[] { }); + MockDoc xMockDoc = new MockDoc(); + xMockDoc.init(new MockNode[] { xMockElemRoot }); + xMockElemRoot.init(xMockDoc, xMockDoc, null, null, + new MockNode[] { xMockElemFoo, xMockElemBar }); + xMockElemFoo.init(xMockDoc, xMockElemRoot, null, xMockElemBar, + new MockNode[] { }); + xMockElemBar.init(xMockDoc, xMockElemRoot, xMockElemFoo, null, + new MockNode[] { }); + + { + XNode xImported = xDoc.importNode(xMockElemRoot, false); + assertNotNull("XDocument.importNode(false)", xImported); + XElement xE = + UnoRuntime.queryInterface(XElement.class, xImported); + assertNotNull("XDocument.importNode(false)", xE); + assertEquals("XDocument.importNode(false)", + "root", xE.getLocalName()); + assertFalse("XDocument.importNode(false)", xE.hasAttributes()); + assertFalse("XDocument.importNode(false)", xE.hasChildNodes()); + } + + { + XNode xImported = xDoc.importNode(xMockElemRoot, true); + assertNotNull("XDocument.importNode(true)", xImported); + XElement xImpRoot = + UnoRuntime.queryInterface(XElement.class, xImported); + assertNotNull("XDocument.importNode(true)", xImpRoot); + assertEquals("XDocument.importNode(true)", + "root", xImpRoot.getLocalName()); + assertFalse("XDocument.importNode(true)", + xImpRoot.hasAttributes()); + assertTrue("XDocument.importNode(true)", + xImpRoot.hasChildNodes()); + assertEquals("XDocument.importNode(true)", + "root", xImpRoot.getNodeName()); + + XNode xImpFooN = xImpRoot.getFirstChild(); + assertNotNull("XDocument.importNode(true)", xImpFooN); + XElement xImpFoo = + UnoRuntime.queryInterface(XElement.class, xImpFooN); + assertNotNull("XDocument.importNode(true)", xImpFoo); + assertTrue("XDocument.importNode(true)", + xImpFoo.hasAttributes()); + assertFalse("XDocument.importNode(true)", + xImpFoo.hasChildNodes()); + assertEquals("XDocument.importNode(true)", + "foo", xImpFoo.getNodeName()); + assertEquals("XDocument.importNode(true)", + "blah", xImpFoo.getAttribute("bar")); + assertEquals("XDocument.importNode(true)", + "quux", xImpFoo.getAttribute("baz")); + XNode xImpBarN = xImpFooN.getNextSibling(); + assertNotNull("XDocument.importNode(true)", xImpBarN); + XElement xImpBar = + UnoRuntime.queryInterface(XElement.class, xImpBarN); + assertNotNull("XDocument.importNode(true)", xImpBar); + assertFalse("XDocument.importNode(true)", + xImpBar.hasAttributes()); + assertFalse("XDocument.importNode(true)", + xImpBar.hasChildNodes()); + assertEquals("XDocument.importNode(true)", + "bar", xImpBar.getNodeName()); + assertNull("XDocument.importNode(true)", + xImpBar.getNextSibling()); + } + } + + // XNode //////////////////////////////////////////////////// + + { + XNode xDocCloneN = xDoc.cloneNode(false); + assertNotNull("XDocument.cloneNode(false)", xDocCloneN); + XDocument xDocClone = + UnoRuntime.queryInterface(XDocument.class, xDocCloneN); + assertNotNull("XDocument.cloneNode(false)", xDocClone); + assertFalse("XDocument.cloneNode(false)", + xDocClone.hasChildNodes()); + assertNull("XDocument.cloneNode(false)", xDocClone.getFirstChild()); + assertNull("XDocument.cloneNode(false)", + xDocClone.getDocumentElement()); + } + { + XNode xDocCloneN = xDoc.cloneNode(true); + assertNotNull("XDocument.cloneNode(true)", xDocCloneN); + XDocument xDocClone = + UnoRuntime.queryInterface(XDocument.class, xDocCloneN); + assertNotNull("XDocument.cloneNode(true)", xDocClone); + assertTrue("XDocument.cloneNode(true)", xDocClone.hasChildNodes()); + assertNotNull("XDocument.cloneNode(true)", + xDocClone.getFirstChild()); + XElement xE = xDocClone.getDocumentElement(); + assertNotNull("XDocument.cloneNode(true)", xE); + assertFalse("XDocument.cloneNode(true)", xElemFooNs.equals(xE)); + assertEquals("XDocument.cloneNode(true)", "foo", xE.getLocalName()); + assertEquals("XDocument.cloneNode(true)", ns, xE.getNamespaceURI()); + } + + assertNull("XDocument.getAttributes()", xDoc.getAttributes()); + + { + XNodeList xChildren = xDoc.getChildNodes(); + assertTrue("XDocument.getChildNodes()", 1 == xChildren.getLength()); + assertEquals("XDocument.getChildNodes()", + xElemFooNs, xChildren.item(0)); + + XNode xFirst = xDoc.getFirstChild(); + assertEquals("XDocument.getFirstChild()", xElemFooNs, xFirst); + XNode xLast = xDoc.getLastChild(); + assertEquals("XDocument.getLastChild()", xElemFooNs, xLast); + } + + assertEquals("XDocument.getLocalName()", "", xDoc.getLocalName()); + + assertEquals("XDocument.getNamespaceURI()", "", xDoc.getNamespaceURI()); + + assertNull("XDocument.getNextSibling()", xDoc.getNextSibling()); + + assertEquals("XDocument.getNodeName()", + "#document", xDoc.getNodeName()); + + assertTrue("XDocument.getNodeType()", + DOCUMENT_NODE == xDoc.getNodeType()); + + assertEquals("XDocument.getNodeValue()", "", xDoc.getNodeValue()); + + assertEquals("XDocument.getOwnerDocument()", + xDoc, xDoc.getOwnerDocument()); + + assertNull("XDocument.getParentNode()", xDoc.getParentNode()); + + assertEquals("XDocument.getPrefix()", "", xDoc.getPrefix()); + + assertNull("XDocument.getPreviousSibling()", xDoc.getPreviousSibling()); + + assertFalse("XDocument.hasAttributes()", xDoc.hasAttributes()); + + assertTrue("XDocument.hasChildNodes()", xDoc.hasChildNodes()); + + assertFalse("XDocument.isSupported()", + xDoc.isSupported("frobnication", "v99.33.0.0.0.1")); + + xDoc.normalize(); + + try { + xDoc.setNodeValue("42"); + fail("XDocument.setNodeValue()"); + } catch (DOMException e) { + assertTrue("XDocument.setNodeValue()", + NO_MODIFICATION_ALLOWED_ERR == e.Code); + } + + try { + xDoc.setPrefix("foo"); + fail("XDocument.setPrefix()"); + } catch (DOMException e) { + assertTrue("XDocument.setPrefix()", + NO_MODIFICATION_ALLOWED_ERR == e.Code); + } + + try { + xDoc.appendChild(null); + fail("XDocument.appendChild(null)"); + } catch (Exception e) { /* expected */ } + + + try { + xDoc.insertBefore(null, xText); + fail("XDocument.insertBefore(null,)"); + } catch (Exception e) { /* expected */ } + try { + xDoc.insertBefore(xText, null); + fail("XDocument.insertBefore(, null)"); + } catch (Exception e) { /* expected */ } + try { + xDoc.insertBefore(xText, xText); + fail("XDocument.insertBefore(x, x)"); + } catch (DOMException e) { + assertTrue("XDocument.insertBefore(x, x)", + HIERARCHY_REQUEST_ERR == e.Code); + } + + { + XNode xRet = xDoc.insertBefore(xComment, xElemFooNs); + assertEquals("XDocument.insertBefore(xComment, xElemFooNs)", + xRet, xElemFooNs); // why does this return the old node? + assertEquals("XDocument.insertBefore(xComment, xElemFooNs)", + xComment, xDoc.getFirstChild()); + assertEquals("XDocument.insertBefore(xComment, xElemFooNs)", + xDoc, xComment.getParentNode()); + assertEquals("XDocument.insertBefore(xCommnet, xElemFooNs)", + xElemFooNs, xDoc.getLastChild()); + } + + try { + xDoc.replaceChild(null, xText); + fail("XDocument.replaceChild(null, )"); + } catch (Exception e) { /* expected */ } + try { + xDoc.replaceChild(xText, null); + fail("XDocument.replaceChild(, null)"); + } catch (Exception e) { /* expected */ } + try { + xDoc.replaceChild(xElemFoo, xElemFoo); // not child + fail("XDocument.replaceChild(xElemFoo, xElemFoo)"); + } catch (DOMException e) { + assertTrue("XDocument.replaceChild(xElemFoo, xElemFoo)", + HIERARCHY_REQUEST_ERR == e.Code); + } + try { + xDoc.replaceChild(xElemFooNs, xElemFooNs); // child + assertFalse("XDocument.replaceChild(xElemFooNs, xElemFooNs)", + false); + } catch (DOMException e) { + assertTrue("XDocument.replaceChild(xElemFooNs, xElemFooNs)", + HIERARCHY_REQUEST_ERR == e.Code); + } + XNode xReplaced = xDoc.replaceChild(xPI, xComment); + assertEquals("XDocument.replaceChild(xPI, xComment)", + xReplaced, xComment); + assertEquals("XDocument.replaceChild(xPI, xComment)", + xPI, xDoc.getFirstChild()); + assertEquals("XDocument.replaceChild(xPI, xComment)", + xElemFooNs, xDoc.getLastChild()); + + try { + xDoc.removeChild(null); + fail("XDocument.removeChild(null)"); + } catch (Exception e) { /* expected */ } + try { + xDoc.removeChild(xElemFoo); + fail("XDocument.removeChild()"); + } catch (DOMException e) { + assertTrue("XDocument.removeChild()", + HIERARCHY_REQUEST_ERR == e.Code); + } + + XNode xRemoved = xDoc.removeChild(xPI); + assertEquals("XDocument.removeChild(xPI)", xRemoved, xPI); + assertTrue("XDocument.removeChild(xPI)", xDoc.hasChildNodes()); + assertEquals("XDocument.removeChild(xPI)", + xElemFooNs, xDoc.getFirstChild()); + assertEquals("XDocument.removeChild(xPI)", + xElemFooNs, xDoc.getLastChild()); + } + + @Test public void testXDocumentFragment() throws Exception + { + XDocumentBuilder xBuilder = + UnoRuntime.queryInterface(XDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.DocumentBuilder")); + XDocument xDoc = xBuilder.newDocument(); + + XDocumentFragment xDF = xDoc.createDocumentFragment(); + assertNotNull("XDocument.createDocumentFragment", xDF); + + XElement xElemFoo = xDoc.createElement("foo"); + assertNotNull("XDocument.createElement", xElemFoo); + + xDF.appendChild(xElemFoo); + + // XNode //////////////////////////////////////////////////// + + XText xText = xDoc.createTextNode("foo"); + XComment xComment = xDoc.createComment("foo"); + + { + XNode xDFCloneN = xDF.cloneNode(false); + assertNotNull("XDocumentFragment.cloneNode(false)", xDFCloneN); + XDocumentFragment xDFClone = + UnoRuntime.queryInterface(XDocumentFragment.class, xDFCloneN); + assertNotNull("XDocumentFragment.cloneNode(false)", xDFClone); + assertFalse("XDocumentFragment.cloneNode(false)", + xDFClone.hasChildNodes()); + assertNull("XDocumentFragment.cloneNode(false)", + xDFClone.getFirstChild()); + } + { + XNode xDFCloneN = xDF.cloneNode(true); + assertNotNull("XDocumentFragment.cloneNode(true)", xDFCloneN); + XDocumentFragment xDFClone = + UnoRuntime.queryInterface(XDocumentFragment.class, xDFCloneN); + assertNotNull("XDocumentFragment.cloneNode(true)", xDFClone); + assertTrue("XDocumentFragment.cloneNode(true)", + xDFClone.hasChildNodes()); + XNode xChild = xDFClone.getFirstChild(); + assertNotNull("XDocumentFragment.cloneNode(true)", xChild); + XElement xE = UnoRuntime.queryInterface(XElement.class, xChild); + assertFalse("XDocumentFragment.cloneNode(true)", + xElemFoo.equals(xE)); + assertEquals("XDocumentFragment.cloneNode(true)", + "foo", xE.getLocalName()); + } + + assertNull("XDocumentFragment.getAttributes()", xDF.getAttributes()); + + { + XNodeList xChildren = xDF.getChildNodes(); + assertTrue("XDocumentFragment.getChildNodes()", + 1 == xChildren.getLength()); + assertEquals("XDocumentFragment.getChildNodes()", + xElemFoo, xChildren.item(0)); + + XNode xFirst = xDF.getFirstChild(); + assertEquals("XDocumentFragment.getFirstChild()", + xElemFoo, xFirst); + XNode xLast = xDF.getLastChild(); + assertEquals("XDocumentFragment.getLastChild()", xElemFoo, xLast); + } + + assertEquals("XDocumentFragment.getLocalName()", + "", xDF.getLocalName()); + + assertEquals("XDocumentFragment.getNamespaceURI()", + "", xDF.getNamespaceURI()); + + assertNull("XDocumentFragment.getNextSibling()", xDF.getNextSibling()); + + assertEquals("XDocumentFragment.getNodeName()", + "#document-fragment", xDF.getNodeName()); + + assertTrue("XDocumentFragment.getNodeType()", + DOCUMENT_FRAGMENT_NODE == xDF.getNodeType()); + + assertEquals("XDocumentFragment.getNodeValue()", + "", xDF.getNodeValue()); + + assertEquals("XDocumentFragment.getOwnerDocument()", + xDoc, xDF.getOwnerDocument()); + + assertNull("XDocumentFragment.getParentNode()", xDF.getParentNode()); + + assertEquals("XDocumentFragment.getPrefix()", "", xDF.getPrefix()); + + assertNull("XDocumentFragment.getPreviousSibling()", + xDF.getPreviousSibling()); + + assertFalse("XDocumentFragment.hasAttributes()", xDF.hasAttributes()); + + assertTrue("XDocumentFragment.hasChildNodes()", xDF.hasChildNodes()); + + assertFalse("XDocumentFragment.isSupported()", + xDF.isSupported("frobnication", "v99.33.0.0.0.1")); + + xDF.normalize(); + + try { + xDF.setNodeValue("42"); + fail("XDocumentFragment.setNodeValue()"); + } catch (DOMException e) { + assertTrue("XDocumentFragment.setNodeValue()", + NO_MODIFICATION_ALLOWED_ERR == e.Code); + } + + try { + xDF.setPrefix("foo"); + fail("XDocumentFragment.setPrefix()"); + } catch (DOMException e) { + assertTrue("XDocumentFragment.setPrefix()", + NO_MODIFICATION_ALLOWED_ERR == e.Code); + } + + try { + xDF.appendChild(null); + fail("XDocumentFragment.appendChild(null)"); + } catch (Exception e) { /* expected */ } + + + try { + xDF.insertBefore(null, xText); + fail("XDocumentFragment.insertBefore(null,)"); + } catch (Exception e) { /* expected */ } + try { + xDF.insertBefore(xText, null); + fail("XDocumentFragment.insertBefore(, null)"); + } catch (Exception e) { /* expected */ } + try { + xDF.insertBefore(xText, xText); + fail("XDocumentFragment.insertBefore(x, x)"); + } catch (DOMException e) { + assertTrue("XDocumentFragment.insertBefore(x, x)", + HIERARCHY_REQUEST_ERR == e.Code); + } + + { + XNode xRet = xDF.insertBefore(xComment, xElemFoo); + assertEquals("XDocumentFragment.insertBefore(xComment, xElemFoo)", + xRet, xElemFoo); // why does this return the old node? + assertEquals("XDocumentFragment.insertBefore(xComment, xElemFoo)", + xComment, xDF.getFirstChild()); + assertEquals("XDocumentFragment.insertBefore(xComment, xElemFoo)", + xDF, xComment.getParentNode()); + assertEquals("XDocumentFragment.insertBefore(xCommnet, xElemFoo)", + xElemFoo, xDF.getLastChild()); + } + + try { + xDF.replaceChild(null, xText); + fail("XDocumentFragment.replaceChild(null, )"); + } catch (Exception e) { /* expected */ } + try { + xDF.replaceChild(xText, null); + fail("XDocumentFragment.replaceChild(, null)"); + } catch (Exception e) { /* expected */ } + try { + xDF.replaceChild(xElemFoo, xElemFoo); // not child + fail("XDocumentFragment.replaceChild(xElemFoo, xElemFoo)"); + } catch (DOMException e) { + assertTrue("XDocumentFragment.replaceChild(xElemFoo, xElemFoo)", + HIERARCHY_REQUEST_ERR == e.Code); + } + try { + xDF.replaceChild(xElemFoo, xElemFoo); // child + assertFalse("XDocumentFragment.replaceChild(xElemFoo, xElemFoo)", + false); + } catch (DOMException e) { + assertTrue("XDocumentFragment.replaceChild(xElemFoo, xElemFoo)", + HIERARCHY_REQUEST_ERR == e.Code); + } + XNode xReplaced = xDF.replaceChild(xText, xComment); + assertEquals("XDocumentFragment.replaceChild(xText, xComment)", + xReplaced, xComment); + assertEquals("XDocumentFragment.replaceChild(xText, xComment)", + xText, xDF.getFirstChild()); + assertEquals("XDocumentFragment.replaceChild(xText, xComment)", + xElemFoo, xDF.getLastChild()); + + try { + xDF.removeChild(null); + fail("XDocumentFragment.removeChild(null)"); + } catch (Exception e) { /* expected */ } + try { + xDF.removeChild(xComment); + fail("XDocumentFragment.removeChild()"); + } catch (DOMException e) { + assertTrue("XDocumentFragment.removeChild()", + HIERARCHY_REQUEST_ERR == e.Code); + } + + XNode xRemoved = xDF.removeChild(xText); + assertEquals("XDocumentFragment.removeChild(xText)", xRemoved, xText); + assertTrue("XDocumentFragment.removeChild(xText)", xDF.hasChildNodes()); + assertEquals("XDocumentFragment.removeChild(xText)", + xElemFoo, xDF.getFirstChild()); + assertEquals("XDocumentFragment.removeChild(xText)", + xElemFoo, xDF.getLastChild()); + } + + @Test public void testXElement() throws Exception + { + XDocumentBuilder xBuilder = + UnoRuntime.queryInterface(XDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.DocumentBuilder")); + XDocument xDoc = xBuilder.newDocument(); + + String ns = "http://example.com/"; + + XElement xElemFoo = xDoc.createElement("foo"); + assertNotNull("XDocument.createElement(\"foo\")", xElemFoo); + + XElement xElemFooNs = xDoc.createElementNS(ns, "e:foo"); + assertNotNull("XDocument.createElementNs(\"foo\")", xElemFooNs); + + assertEquals("XElement.getTagName", "foo", xElemFoo.getTagName()); + + { + XNodeList xNodeList = xElemFoo.getElementsByTagName("bar"); + assertNotNull("XElement.getElementsByTagName", xNodeList); + assertTrue("XElement.getElementsByTagName", + 0 == xNodeList.getLength()); + } + + { + XNodeList xNodeList = xElemFoo.getElementsByTagNameNS(ns, "bar"); + assertNotNull("XElement.getElementsByTagNameNS", xNodeList); + assertTrue("XElement.getElementsByTagNameNS", + 0 == xNodeList.getLength()); + } + + xElemFoo.appendChild(xElemFooNs); + + { + XNodeList xNodeList = xElemFoo.getElementsByTagName("foo"); + assertNotNull("XElement.getElementsByTagName", xNodeList); + assertTrue("XElement.getElementsByTagName", + 2 == xNodeList.getLength()); + assertEquals("XElement.getElementsByTagName", + xElemFoo, xNodeList.item(0)); + assertEquals("XElement.getElementsByTagName", + xElemFooNs, xNodeList.item(1)); + } + { + XNodeList xNodeList = xElemFoo.getElementsByTagNameNS(ns, "foo"); + assertNotNull("XElement.getElementsByTagNameNS", xNodeList); + assertTrue("XElement.getElementsByTagNameNS", + 1 == xNodeList.getLength()); + assertEquals("XElement.getElementsByTagNameNS", + xElemFooNs, xNodeList.item(0)); + } + + { + String ret = xElemFoo.getAttribute("foo"); + assertEquals("XElement.getAttribute", "", ret); + } + { + String ret = xElemFoo.getAttributeNS(ns, "foo"); + assertEquals("XElement.getAttributeNS", "", ret); + } + { + XNode xAttr = xElemFoo.getAttributeNode("foo"); + assertNull("XElement.getAttributeNode", xAttr); + } + { + XNode xAttr = xElemFoo.getAttributeNodeNS(ns, "foo"); + assertNull("XElement.getAttributeNodeNS", xAttr); + } + assertFalse("XElement.hasAttribute", xElemFoo.hasAttribute("foo")); + assertFalse("XElement.hasAttributeNS", + xElemFoo.hasAttributeNS(ns, "foo")); + + // surprisingly this does not throw? + xElemFoo.removeAttribute("foo"); + xElemFoo.removeAttributeNS(ns, "foo"); + + XAttr xAttr = xDoc.createAttribute("foo"); + XAttr xAttrNs = xDoc.createAttributeNS(ns, "foo"); + + try { + xElemFoo.removeAttributeNode(null); + fail("XElement.removeAttributeNode(null)"); + } catch (Exception e) { /* expected */ } + + try { + xElemFoo.removeAttributeNode(xAttr); + fail("XElement.removeAttributeNode(xAttr)"); + } catch (DOMException e) { + assertTrue("XElement.removeAttributeNode(xAttr)", + HIERARCHY_REQUEST_ERR == e.Code); + } + + /* FIXME + try { + xElemFoo.setAttribute("&", "foo"); + fail("XElement.setAttribute(\"&\")"); + } catch (DOMException e) { + assertTrue("XElement.setAttribute(\"&\")", + INVALID_CHARACTER_ERR == e.Code); + } + try { + xElemFoo.setAttributeNS(ns, "&", "foo"); + fail("XElement.setAttributeNS(\"&\")"); + } catch (DOMException e) { + assertTrue("XElement.setAttributeNS(\"&\")", + INVALID_CHARACTER_ERR == e.Code); + } + */ + + XAttr xAttrSet = xElemFoo.setAttributeNode(xAttr); + assertEquals("XElement.setAttributeNode(xAttr)", + xAttrSet, xElemFoo.getAttributeNode("foo")); + assertEquals("XElement.setAttributeNode(xAttr)", + xElemFoo, xAttrSet.getOwnerElement()); + try { + xElemFooNs.setAttributeNode(xAttrSet); + fail("XElement.setAttributeNode(xAttrSet)"); + } catch (DOMException e) { + assertTrue("XElement.setAttributeNode(xAttrSet)", + INUSE_ATTRIBUTE_ERR == e.Code); + } + + XAttr xAttrNsSet = xElemFooNs.setAttributeNodeNS(xAttrNs); + assertEquals("XElement.setAttributeNodeNS(xAttr)", + xAttrNsSet, xElemFooNs.getAttributeNodeNS(ns, "foo")); + assertEquals("XElement.setAttributeNodeNS(xAttrNs)", + xElemFooNs, xAttrNsSet.getOwnerElement()); + try { + xElemFooNs.setAttributeNodeNS(xAttrNsSet); + fail("XElement.setAttributeNodeNS(xAttrNsSet)"); + } catch (DOMException e) { + assertTrue("XElement.setAttributeNodeNS(xAttrNsSet)", + INUSE_ATTRIBUTE_ERR == e.Code); + } + + XAttr xAttrRemoved = xElemFoo.removeAttributeNode(xAttrSet); + assertNotNull("XElement.removeAttributeNode(xAttrSet)", xAttrRemoved); + assertEquals("XElement.removeAttributeNode(xAttrSet)", + "foo", xAttrRemoved.getName()); + assertNull("XElement.removeAttributeNode(xAttrSet)", + xAttrRemoved.getOwnerElement()); + + XAttr xAttrNsRemoved = xElemFooNs.removeAttributeNode(xAttrNsSet); + assertNotNull("XElement.removeAttributeNode(xAttrNsSet)", + xAttrNsRemoved); + assertEquals("XElement.removeAttributeNode(xAttrNsSet)", + "foo", xAttrNsRemoved.getName()); + assertNull("XElement.removeAttributeNode(xAttrNsSet)", + xAttrNsRemoved.getOwnerElement()); + + + xElemFoo.setAttribute("foo", "bar"); + assertEquals("XElement.setAttribute()", + "bar", xElemFoo.getAttribute("foo")); + + xElemFooNs.setAttributeNS(ns, "foo", "bar"); + assertEquals("XElement.setAttributeNS()", + "bar", xElemFooNs.getAttributeNS(ns, "foo")); + + xElemFoo.removeAttribute("foo"); + assertNull("XElement.removeAttribute", + xElemFoo.getAttributeNode("foo")); + + xElemFooNs.removeAttributeNS(ns, "foo"); + assertNull("XElement.removeAttributeNS", + xElemFooNs.getAttributeNodeNS(ns, "foo")); + + // XNode //////////////////////////////////////////////////// + + XText xText = xDoc.createTextNode("foo"); + XComment xComment = xDoc.createComment("foo"); + + { + XNamedNodeMap xAttrMap = xElemFoo.getAttributes(); + assertNotNull("XElement.getAttributes", xAttrMap); + assertTrue("XElement.getAttributes", 0 == xAttrMap.getLength()); + assertFalse("XElement.hasAttributes()", xElemFoo.hasAttributes()); + } + + xElemFooNs.setAttribute("foo", "bar"); + xElemFoo.setAttributeNS(ns, "foo", "bar"); + + { + XNamedNodeMap xAttrMap = xElemFoo.getAttributes(); + assertNotNull("XElement.getAttributes", xAttrMap); + assertTrue("XElement.getAttributes", 1 == xAttrMap.getLength()); + XNode xAttr_ = xAttrMap.getNamedItemNS(ns, "foo"); + assertNotNull("XElement.getAttributes", xAttr_); + } + { + XNamedNodeMap xAttrMap = xElemFooNs.getAttributes(); + assertNotNull("XElement.getAttributes", xAttrMap); + assertTrue("XElement.getAttributes", 1 == xAttrMap.getLength()); + XNode xAttr_ = xAttrMap.getNamedItem("foo"); + assertNotNull("XElement.getAttributes", xAttr_); + } + + { + XNode xElemFooCloneN = xElemFoo.cloneNode(false); + assertNotNull("XElement.cloneNode(false)", xElemFooCloneN); + XElement xElemFooClone = + UnoRuntime.queryInterface(XElement.class, xElemFooCloneN); + assertNotNull("XElement.cloneNode(false)", xElemFooClone); + assertFalse("XElement.cloneNode(false)", + xElemFooClone.hasChildNodes()); + assertNull("XElement.cloneNode(false)", + xElemFooClone.getFirstChild()); + } + { + XNode xElemFooCloneN = xElemFoo.cloneNode(true); + assertNotNull("XElement.cloneNode(true)", xElemFooCloneN); + XElement xElemFooClone = + UnoRuntime.queryInterface(XElement.class, xElemFooCloneN); + assertNotNull("XElement.cloneNode(true)", xElemFooClone); + assertTrue("XElement.cloneNode(true)", + xElemFooClone.hasChildNodes()); + assertTrue("XElement.cloneNode(true)", + xElemFooClone.hasAttributeNS(ns, "foo")); + XNode xChild = xElemFooClone.getFirstChild(); + assertNotNull("XElement.cloneNode(true)", xChild); + XElement xElemFooNsClone = + UnoRuntime.queryInterface(XElement.class, xChild); + assertNotNull("XElement.cloneNode(true)", xElemFooNsClone); + assertEquals("XElement.cloneNode(true)", "foo", + xElemFooNsClone.getLocalName()); + assertEquals("XElement.cloneNode(true)", ns, + xElemFooNsClone.getNamespaceURI()); + assertTrue("XElement.cloneNode(true)", + xElemFooNsClone.hasAttribute("foo")); + } + + { + XNodeList xChildren = xElemFoo.getChildNodes(); + assertTrue("XElement.getChildNodes()", 1 == xChildren.getLength()); + assertEquals("XElement.getChildNodes()", + xElemFooNs, xChildren.item(0)); + + XNode xFirst = xElemFoo.getFirstChild(); + assertEquals("XDocument.getFirstChild()", xElemFooNs, xFirst); + XNode xLast = xElemFoo.getLastChild(); + assertEquals("XDocument.getLastChild()", xElemFooNs, xLast); + } + + assertEquals("XElement.getLocalName()", "foo", xElemFoo.getLocalName()); + assertEquals("XElement.getLocalName()", "foo", + xElemFooNs.getLocalName()); + + assertEquals("XElement.getNamespaceURI()", "", + xElemFoo.getNamespaceURI()); + assertEquals("XElement.getNamespaceURI()", ns, + xElemFooNs.getNamespaceURI()); + + assertNull("XElement.getNextSibling()", xElemFoo.getNextSibling()); + + assertEquals("XElement.getNodeName()", "foo", xElemFoo.getNodeName()); + assertEquals("XElement.getNodeName()", "foo", + xElemFooNs.getNodeName()); + + assertTrue("XElement.getNodeType()", + ELEMENT_NODE == xElemFoo.getNodeType()); + + assertEquals("XElement.getNodeValue()", "", xElemFoo.getNodeValue()); + + assertEquals("XElement.getOwnerDocument()", + xDoc, xElemFoo.getOwnerDocument()); + + assertNull("XElement.getParentNode()", xElemFoo.getParentNode()); + assertEquals("XElement.getParentNode()", + xElemFoo, xElemFooNs.getParentNode()); + + assertEquals("XElement.getPrefix()", "", xElemFoo.getPrefix()); + assertEquals("XElement.getPrefix()", "e", xElemFooNs.getPrefix()); + + assertNull("XElement.getPreviousSibling()", + xElemFoo.getPreviousSibling()); + + assertTrue("XElement.hasAttributes()", xElemFoo.hasAttributes()); + + assertTrue("XElement.hasChildNodes()", xElemFoo.hasChildNodes()); + assertFalse("XElement.hasChildNodes()", xElemFooNs.hasChildNodes()); + + assertFalse("XElement.isSupported()", + xElemFoo.isSupported("frobnication", "v99.33.0.0.0.1")); + + xElemFoo.normalize(); + + try { + xElemFoo.setNodeValue("42"); + fail("XElement.setNodeValue()"); + } catch (DOMException e) { + assertTrue("XElement.setNodeValue()", + NO_MODIFICATION_ALLOWED_ERR == e.Code); + } + + xElemFooNs.setPrefix("f"); + assertEquals("XElement.getPrefix()", "f", xElemFooNs.getPrefix()); + + try { + xElemFoo.appendChild(null); + fail("XElement.appendChild(null)"); + } catch (Exception e) { /* expected */ } + + try { + xElemFoo.insertBefore(null, xText); + fail("XElemFoo.insertBefore(null,)"); + } catch (Exception e) { /* expected */ } + try { + xElemFoo.insertBefore(xText, null); + fail("XElemFoo.insertBefore(, null)"); + } catch (Exception e) { /* expected */ } + try { + xElemFoo.insertBefore(xText, xText); + fail("XElement.insertBefore(x, x)"); + } catch (DOMException e) { + assertTrue("XDocument.insertBefore(x, x)", + HIERARCHY_REQUEST_ERR == e.Code); + } + + { + XNode xRet = xElemFoo.insertBefore(xText, xElemFooNs); + assertEquals("XElement.insertBefore(xText, xElemFooNs)", + xRet, xElemFooNs); // why does this return the old node? + assertEquals("XElement.insertBefore(xText, xElemFooNs)", + xText, xElemFoo.getFirstChild()); + assertEquals("XElement.insertBefore(xText, xElemFooNs)", + xElemFoo, xText.getParentNode()); + assertEquals("XElement.insertBefore(xText, xElemFooNs)", + xElemFooNs, xElemFoo.getLastChild()); + } + + try { + xElemFoo.replaceChild(null, xText); + fail("XElement.replaceChild(null, )"); + } catch (Exception e) { /* expected */ } + try { + xElemFoo.replaceChild(xText, null); + fail("XElement.replaceChild(, null)"); + } catch (Exception e) { /* expected */ } + try { + xElemFoo.replaceChild(xElemFoo, xElemFoo); // not child + fail("XElement.replaceChild(xElemFoo, xElemFoo)"); + } catch (DOMException e) { + assertTrue("XElement.replaceChild(xElemFoo, xElemFoo)", + HIERARCHY_REQUEST_ERR == e.Code); + } + try { + xElemFoo.replaceChild(xElemFooNs, xElemFooNs); // child + assertFalse("XElement.replaceChild(xElemFooNs, xElemFooNs)", + false); + } catch (DOMException e) { + assertTrue("XElement.replaceChild(xElemFooNs, xElemFooNs)", + HIERARCHY_REQUEST_ERR == e.Code); + } + XNode xReplaced = xElemFoo.replaceChild(xComment, xText); + assertEquals("XElement.replaceChild(xComment, xText)", + xReplaced, xText); + assertEquals("XElement.replaceChild(xComment, xText)", + xComment, xElemFoo.getFirstChild()); + assertEquals("XElement.replaceChild(xComment, xText)", + xElemFooNs, xElemFoo.getLastChild()); + + try { + xElemFoo.removeChild(null); + fail("XElement.removeChild(null)"); + } catch (Exception e) { /* expected */ } + try { + xElemFoo.removeChild(xElemFoo); + fail("XElement.removeChild()"); + } catch (DOMException e) { + assertTrue("XElement.removeChild()", + HIERARCHY_REQUEST_ERR == e.Code); + } + + XNode xRemoved = xElemFoo.removeChild(xComment); + assertEquals("XElement.removeChild(xComment)", xRemoved, xComment); + assertTrue("XElement.removeChild(xComment)", xElemFoo.hasChildNodes()); + assertEquals("XElement.removeChild(xComment)", + xElemFooNs, xElemFoo.getFirstChild()); + assertEquals("XElement.removeChild(xComment)", + xElemFooNs, xElemFoo.getLastChild()); + } + + @Test public void testXAttr() throws Exception + { + XDocumentBuilder xBuilder = + UnoRuntime.queryInterface(XDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.DocumentBuilder")); + XDocument xDoc = xBuilder.newDocument(); + + String ns = "http://example.com/"; + + XAttr xAttr = xDoc.createAttribute("foo"); + assertNotNull("XDocument.createAttribute", xAttr); + + XAttr xAttrNs = xDoc.createAttributeNS(ns, "e:foo"); + assertNotNull("XDocument.createAttribute", xAttr); + + assertTrue("XAttr.getSpecified", xAttr.getSpecified()); + + assertEquals("XAttr.getName()", "foo", xAttr.getName()); + + assertNull("XAttr.getOwnerElement()", xAttr.getOwnerElement()); + + XElement xElemFoo = xDoc.createElement("foo"); + XNode xInserted = xElemFoo.appendChild(xAttr); + XAttr xAttrIns = + UnoRuntime.queryInterface(XAttr.class, xInserted); + assertNotNull(xAttrIns); + assertEquals("XAttr.getOwnerElement()", + xElemFoo, xAttrIns.getOwnerElement()); + + assertEquals("XAttr.getValue()", "", xAttr.getValue()); + + xAttr.setValue("bar"); + assertEquals("XAttr.setValue()", "bar", xAttr.getValue()); + + // XNode //////////////////////////////////////////////////// + + { + XNode xAttrCloneN = xAttr.cloneNode(false); + assertNotNull("XAttr.cloneNode(false)", xAttrCloneN); + XAttr xAttrClone = + UnoRuntime.queryInterface(XAttr.class, xAttrCloneN); + assertNotNull("XAttr.cloneNode(false)", xAttrClone); + // actually the children are copied even if bDeep=false + // does that make sense for attributes? + /* + assertFalse("XAttr.cloneNode(false)", xAttrClone.hasChildNodes()); + assertNull("XAttr.cloneNode(false)", xAttrClone.getFirstChild()); + */ + assertTrue("XAttr.cloneNode(true)", xAttrClone.hasChildNodes()); + XNode xChild = xAttrClone.getFirstChild(); + assertNotNull("XAttr.cloneNode(true)", xChild); + XText xText = UnoRuntime.queryInterface(XText.class, xChild); + assertNotNull("XAttr.cloneNode(true)", xText); + assertEquals("XAttr.cloneNode(true)", "bar", xText.getNodeValue()); + } + { + XNode xAttrCloneN = xAttr.cloneNode(true); + assertNotNull("XAttr.cloneNode(true)", xAttrCloneN); + XAttr xAttrClone = + UnoRuntime.queryInterface(XAttr.class, xAttrCloneN); + assertNotNull("XAttr.cloneNode(true)", xAttrClone); + assertTrue("XAttr.cloneNode(true)", xAttrClone.hasChildNodes()); + XNode xChild = xAttrClone.getFirstChild(); + assertNotNull("XAttr.cloneNode(true)", xChild); + XText xText = UnoRuntime.queryInterface(XText.class, xChild); + assertNotNull("XAttr.cloneNode(true)", xText); + assertEquals("XAttr.cloneNode(true)", "bar", xText.getNodeValue()); + } + + assertNull("XAttr.getAttributes()", xAttr.getAttributes()); + + { + XNodeList xChildren = xAttr.getChildNodes(); + assertTrue("XAttr.getChildNodes()", 1 == xChildren.getLength()); + XNode xChild = xChildren.item(0); + assertNotNull("XAttr.getChildNodes()", xChild); + XText xText = UnoRuntime.queryInterface(XText.class, xChild); + assertNotNull("XAttr.getChildNodes()", xText); + + XNode xFirst = xAttr.getFirstChild(); + assertEquals("XAttr.getFirstChild()", xText, xFirst); + XNode xLast = xAttr.getLastChild(); + assertEquals("XAttr.getLastChild()", xText, xLast); + } + + assertEquals("XAttr.getLocalName()", "foo", xAttr.getLocalName()); + assertEquals("XAttr.getLocalName()", "foo", xAttrNs.getLocalName()); + + assertEquals("XAttr.getNamespaceURI()", "", xAttr.getNamespaceURI()); + assertEquals("XAttr.getNamespaceURI()", ns, xAttrNs.getNamespaceURI()); + + assertNull("XAttr.getNextSibling()", xAttr.getNextSibling()); + + assertEquals("XAttr.getNodeName()", "foo", xAttr.getNodeName()); + assertEquals("XAttr.getNodeName()", "foo", xAttrNs.getNodeName()); + + assertTrue("XAttr.getNodeType()", + ATTRIBUTE_NODE == xAttr.getNodeType()); + + assertEquals("XAttr.getNodeValue()", "bar", xAttr.getNodeValue()); + assertEquals("XAttr.getNodeValue()", "", xAttrNs.getNodeValue()); + + assertEquals("XAttr.getOwnerDocument()", + xDoc, xDoc.getOwnerDocument()); + + assertNull("XAttr.getParentNode()", xAttr.getParentNode()); + + assertEquals("XAttr.getPrefix()", "", xAttr.getPrefix()); + assertEquals("XAttr.getPrefix()", "e", xAttrNs.getPrefix()); + + assertNull("XAttr.getPreviousSibling()", xAttr.getPreviousSibling()); + + assertFalse("XAttr.hasAttributes()", xAttr.hasAttributes()); + + assertTrue("XAttr.hasChildNodes()", xAttr.hasChildNodes()); + + assertFalse("XAttr.isSupported()", + xAttr.isSupported("frobnication", "v99.33.0.0.0.1")); + + xAttr.normalize(); + + xAttr.setNodeValue("42"); + assertEquals("XAttr.setNodeValue()", "42", xAttr.getNodeValue()); + + xAttrNs.setPrefix("f"); + assertEquals("XAttr.setPrefix()", "f", xAttrNs.getPrefix()); + + XText xText = xDoc.createTextNode("baz"); + XText xTextNew = xDoc.createTextNode("quux"); + + try { + xAttr.appendChild(null); + fail("XAttr.appendChild(null)"); + } catch (Exception e) { /* expected */ } + + try { + xAttr.insertBefore(null, xText); + fail("XAttr.insertBefore(null,)"); + } catch (Exception e) { /* expected */ } + try { + xAttr.insertBefore(xText, null); + fail("XAttr.insertBefore(, null)"); + } catch (Exception e) { /* expected */ } + try { + xAttr.insertBefore(xText, xText); + fail("XAttr.insertBefore(x, x)"); + } catch (DOMException e) { + assertTrue("XAttr.insertBefore(x, x)", + HIERARCHY_REQUEST_ERR == e.Code); + } + + XNode xChild = xAttr.getFirstChild(); + assertNotNull(xChild); + + { + XNode xRet = xAttr.insertBefore(xText, xChild); + assertEquals("XAttr.insertBefore(xText, xChild)", + xRet, xChild); // why does this return the old node? + assertEquals("XAttr.insertBefore(xText, xChild)", + xText, xAttr.getFirstChild()); + assertEquals("XAttr.insertBefore(xText, xChild)", + xAttr, xText.getParentNode()); + assertEquals("XAttr.insertBefore(xText, xChild)", + xChild, xAttr.getLastChild()); + } + + try { + xAttr.replaceChild(null, xText); + fail("XAttr.replaceChild(null, )"); + } catch (Exception e) { /* expected */ } + try { + xAttr.replaceChild(xText, null); + fail("XAttr.replaceChild(, null)"); + } catch (Exception e) { /* expected */ } + try { + xAttr.replaceChild(xAttrNs, xAttrNs); // not child + fail("XAttr.replaceChild(xAttrNs, xAttrNs)"); + } catch (DOMException e) { + assertTrue("XAttr.replaceChild(xAttrNs, xAttrNs)", + HIERARCHY_REQUEST_ERR == e.Code); + } + try { + xAttr.replaceChild(xChild, xChild); // child + assertFalse("XAttr.replaceChild(xChild, xChild)", + false); + } catch (DOMException e) { + assertTrue("XAttr.replaceChild(xChild, xChild)", + HIERARCHY_REQUEST_ERR == e.Code); + } + XNode xReplaced = xAttr.replaceChild(xTextNew, xChild); + assertEquals("XAttr.replaceChild(xTextNew, xChild)", xChild, xReplaced); + assertEquals("XAttr.replaceChild(xTextNew, xChild)", + xText, xAttr.getFirstChild()); + assertEquals("XAttr.replaceChild(xTextNew, xChild)", + xTextNew, xAttr.getLastChild()); + + try { + xAttr.removeChild(null); + fail("XAttr.removeChild(null)"); + } catch (Exception e) { /* expected */ } + try { + xAttr.removeChild(xAttrNs); + fail("XAttr.removeChild()"); + } catch (DOMException e) { + assertTrue("XAttr.removeChild()", HIERARCHY_REQUEST_ERR == e.Code); + } + + XNode xRemoved = xAttr.removeChild(xTextNew); + assertEquals("XAttr.removeChild(xText)", xRemoved, xTextNew); + assertTrue("XAttr.removeChild(xText)", xAttr.hasChildNodes()); + assertEquals("XAttr.removeChild(xText)", + xText, xAttr.getFirstChild()); + assertEquals("XAttr.removeChild(xText)", + xText, xAttr.getLastChild()); + } + + @Test public void testXText() throws Exception + { + XDocumentBuilder xBuilder = + UnoRuntime.queryInterface(XDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.DocumentBuilder")); + XDocument xDoc = xBuilder.newDocument(); + + XText xText = xDoc.createTextNode("foobar"); + assertNotNull(xText); + + assertEquals("XText.getData", "foobar", xText.getData()); + assertEquals("XText.getLength", 6, xText.getLength()); + + /* FIXME + try { + xText.splitText(9999); + fail("XText.splitText(9999)"); + } catch (DOMException e) { + assertTrue("XText.splitText(9999)", INDEX_SIZE_ERR == e.Code); + } + + { + XText xTextBar = xText.splitText(2); + assertNotNull("XText.splitText", xTextBar); + assertEquals("XText.splitText", "foo", xText.getData()); + assertEquals("XText.splitText", "bar", xTextBar.getData()); + } + */ + xText.setData("foo"); + + xText.appendData("baz"); + assertEquals("XText.appendData", "foobaz", xText.getData()); + + try { + xText.deleteData(999,999); + fail("XText.deleteData(999,999)"); + } catch (DOMException e) { + assertTrue("XText.deleteData(999,999)", INDEX_SIZE_ERR == e.Code); + } + xText.deleteData(0, 3); + assertEquals("XText.deleteData", "baz", xText.getData()); + + try { + xText.insertData(999,"blah"); + fail("XText.insertData(999,\"blah\")"); + } catch (DOMException e) { + assertTrue("XText.insertData(999,\"blah\")", + INDEX_SIZE_ERR == e.Code); + } + xText.insertData(1, "arb"); + assertEquals("XText.insertData", "barbaz", xText.getData()); + + try { + xText.replaceData(999,999,"x"); + fail("XText.replaceData(999,999,\"x\")"); + } catch (DOMException e) { + assertTrue("XText.replaceData(999,999,\"x\")", + INDEX_SIZE_ERR == e.Code); + } + xText.replaceData(3, 3, "foo"); + assertEquals("XText.replaceData", "barfoo", xText.getData()); + + xText.setData("quux"); + assertEquals("XText.setData", "quux", xText.getData()); + + try { + xText.subStringData(999,999); + fail("XText.subStringData(999,999)"); + } catch (DOMException e) { + assertTrue("XText.subStringData(999,999)", + INDEX_SIZE_ERR == e.Code); + } + assertEquals("XText.subStringData", "x", xText.subStringData(3, 1)); + + // XNode //////////////////////////////////////////////////// + + { + XNode xTextCloneN = xText.cloneNode(false); + assertNotNull("XText.cloneNode(false)", xTextCloneN); + XText xTextClone = + UnoRuntime.queryInterface(XText.class, xTextCloneN); + assertNotNull("XText.cloneNode(false)", xTextClone); + assertFalse("XText.cloneNode(false)", + xTextClone.hasChildNodes()); + } + { + XNode xTextCloneN = xText.cloneNode(true); + assertNotNull("XText.cloneNode(true)", xTextCloneN); + XText xTextClone = + UnoRuntime.queryInterface(XText.class, xTextCloneN); + assertNotNull("XText.cloneNode(true)", xTextClone); + assertFalse("XText.cloneNode(true)", xTextClone.hasChildNodes()); + } + + assertNull("XText.getAttributes()", xText.getAttributes()); + + { + XNodeList xChildren = xText.getChildNodes(); + assertTrue("XText.getChildNodes()", 0 == xChildren.getLength()); + } + + assertEquals("XText.getLocalName()", "", xText.getLocalName()); + + assertEquals("XText.getNamespaceURI()", "", xText.getNamespaceURI()); + + assertNull("XText.getNextSibling()", xText.getNextSibling()); + + assertEquals("XText.getNodeName()", "#text", xText.getNodeName()); + + assertTrue("XText.getNodeType()", + TEXT_NODE == xText.getNodeType()); + + assertEquals("XText.getNodeValue()", "quux", xText.getNodeValue()); + + assertEquals("XText.getOwnerDocument()", + xDoc, xText.getOwnerDocument()); + + assertNull("XText.getParentNode()", xText.getParentNode()); + + assertEquals("XText.getPrefix()", "", xText.getPrefix()); + + assertNull("XText.getPreviousSibling()", xText.getPreviousSibling()); + + assertFalse("XText.hasAttributes()", xText.hasAttributes()); + + assertFalse("XText.hasChildNodes()", xText.hasChildNodes()); + + assertFalse("XText.isSupported()", + xText.isSupported("frobnication", "v99.33.0.0.0.1")); + + xText.normalize(); + + xText.setNodeValue("42"); + assertEquals("XText.setNodeValue()", "42", xText.getNodeValue()); + + try { + xText.setPrefix("foo"); + fail("XText.setPrefix()"); + } catch (DOMException e) { + assertTrue("XText.setPrefix()", + NO_MODIFICATION_ALLOWED_ERR == e.Code); + } + + XText xText2 = xDoc.createTextNode("foobar"); + XText xText3 = xDoc.createTextNode("foobar"); + + try { + xText.appendChild(null); + fail("XText.appendChild(null)"); + } catch (Exception e) { /* expected */ } + try { + xText.appendChild(xText2); + fail("XText.appendChild(xText2)"); + } catch (DOMException e) { + assertTrue("XText.appendChild(xText2)", + HIERARCHY_REQUEST_ERR == e.Code); + } + + try { + xText.insertBefore(xText2, xText3); + fail("XText.insertBefore"); + } catch (Exception e) { /* expected */ } + + try { + xText.replaceChild(xText2, xText3); + fail("XText.insertBefore"); + } catch (Exception e) { /* expected */ } + + try { + xText.removeChild(null); + fail("XText.removeChild(null)"); + } catch (Exception e) { /* expected */ } + + try { + xText.removeChild(xText2); + fail("XText.removeChild"); + } catch (DOMException e) { + assertTrue("XText.removeChild", HIERARCHY_REQUEST_ERR == e.Code); + } + } + + @Test public void testXCDataSection() throws Exception + { + XDocumentBuilder xBuilder = + UnoRuntime.queryInterface(XDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.DocumentBuilder")); + XDocument xDoc = xBuilder.newDocument(); + + XCDATASection xCDS = xDoc.createCDATASection("foobar"); + assertNotNull(xCDS); + + assertEquals("XCDATASection.getData", "foobar", xCDS.getData()); + assertEquals("XCDATASection.getLength", 6, xCDS.getLength()); + + /* FIXME + try { + xCDS.splitText(9999); + fail("XCDATASection.splitText(9999)"); + } catch (DOMException e) { + assertTrue("XCDATASection.splitText(9999)", + INDEX_SIZE_ERR == e.Code); + } + + { + XCDATASection xCDSBar = xCDS.splitText(2); + assertNotNull("XCDATASection.splitText", xCDSBar); + assertEquals("XCDATASection.splitText", "foo", xCDS.getData()); + assertEquals("XCDATASection.splitText", "bar", xCDSBar.getData()); + } + */ + xCDS.setData("foo"); + + xCDS.appendData("baz"); + assertEquals("XCDATASection.appendData", "foobaz", xCDS.getData()); + + try { + xCDS.deleteData(999,999); + fail("XCDATASection.deleteData(999,999)"); + } catch (DOMException e) { + assertTrue("XCDATASection.deleteData(999,999)", + INDEX_SIZE_ERR == e.Code); + } + xCDS.deleteData(0, 3); + assertEquals("XCDATASection.deleteData", "baz", xCDS.getData()); + + try { + xCDS.insertData(999,"blah"); + fail("XCDATASection.insertData(999,\"blah\")"); + } catch (DOMException e) { + assertTrue("XCDATASection.insertData(999,\"blah\")", + INDEX_SIZE_ERR == e.Code); + } + xCDS.insertData(1, "arb"); + assertEquals("XCDATASection.insertData", "barbaz", xCDS.getData()); + + try { + xCDS.replaceData(999,999,"x"); + fail("XCDATASection.replaceData(999,999,\"x\")"); + } catch (DOMException e) { + assertTrue("XCDATASection.replaceData(999,999,\"x\")", + INDEX_SIZE_ERR == e.Code); + } + xCDS.replaceData(3, 3, "foo"); + assertEquals("XCDATASection.replaceData", "barfoo", xCDS.getData()); + + xCDS.setData("quux"); + assertEquals("XCDATASection.setData", "quux", xCDS.getData()); + + try { + xCDS.subStringData(999,999); + fail("XCDATASection.subStringData(999,999)"); + } catch (DOMException e) { + assertTrue("XCDATASection.subStringData(999,999)", + INDEX_SIZE_ERR == e.Code); + } + assertEquals("XCDATASection.subStringData", "x", + xCDS.subStringData(3, 1)); + + // XNode //////////////////////////////////////////////////// + + { + XNode xCDSCloneN = xCDS.cloneNode(false); + assertNotNull("XCDATASection.cloneNode(false)", xCDSCloneN); + XCDATASection xCDSClone = + UnoRuntime.queryInterface(XCDATASection.class, xCDSCloneN); + assertNotNull("XCDATASection.cloneNode(false)", xCDSClone); + assertFalse("XCDATASection.cloneNode(false)", + xCDSClone.hasChildNodes()); + } + { + XNode xCDSCloneN = xCDS.cloneNode(true); + assertNotNull("XCDATASection.cloneNode(true)", xCDSCloneN); + XCDATASection xCDSClone = + UnoRuntime.queryInterface(XCDATASection.class, xCDSCloneN); + assertNotNull("XCDATASection.cloneNode(true)", xCDSClone); + assertFalse("XCDATASection.cloneNode(true)", + xCDSClone.hasChildNodes()); + } + + assertNull("XCDATASection.getAttributes()", xCDS.getAttributes()); + + { + XNodeList xChildren = xCDS.getChildNodes(); + assertTrue("XCDATASection.getChildNodes()", + 0 == xChildren.getLength()); + } + + assertEquals("XCDATASection.getLocalName()", "", xCDS.getLocalName()); + + assertEquals("XCDATASection.getNamespaceURI()", "", + xCDS.getNamespaceURI()); + + assertNull("XCDATASection.getNextSibling()", xCDS.getNextSibling()); + + assertEquals("XCDATASection.getNodeName()", "#cdata-section", + xCDS.getNodeName()); + + assertTrue("XCDATASection.getNodeType()", + CDATA_SECTION_NODE == xCDS.getNodeType()); + + assertEquals("XCDATASection.getNodeValue()", "quux", + xCDS.getNodeValue()); + + assertEquals("XCDATASection.getOwnerDocument()", + xDoc, xCDS.getOwnerDocument()); + + assertNull("XCDATASection.getParentNode()", xCDS.getParentNode()); + + assertEquals("XCDATASection.getPrefix()", "", xCDS.getPrefix()); + + assertNull("XCDATASection.getPreviousSibling()", + xCDS.getPreviousSibling()); + + assertFalse("XCDATASection.hasAttributes()", xCDS.hasAttributes()); + + assertFalse("XCDATASection.hasChildNodes()", xCDS.hasChildNodes()); + + assertFalse("XCDATASection.isSupported()", + xCDS.isSupported("frobnication", "v99.33.0.0.0.1")); + + xCDS.normalize(); + + xCDS.setNodeValue("42"); + assertEquals("XCDATASection.setNodeValue()", "42", xCDS.getNodeValue()); + + try { + xCDS.setPrefix("foo"); + fail("XCDATASection.setPrefix()"); + } catch (DOMException e) { + assertTrue("XCDATASection.setPrefix()", + NO_MODIFICATION_ALLOWED_ERR == e.Code); + } + + XCDATASection xCDS2 = xDoc.createCDATASection("foobar"); + XCDATASection xCDS3 = xDoc.createCDATASection("foobar"); + + try { + xCDS.appendChild(null); + fail("XCDATASection.appendChild(null)"); + } catch (Exception e) { /* expected */ } + try { + xCDS.appendChild(xCDS2); + fail("XCDATASection.appendChild(xCDS2)"); + } catch (DOMException e) { + assertTrue("XCDATASection.appendChild(xCDS2)", + HIERARCHY_REQUEST_ERR == e.Code); + } + + try { + xCDS.insertBefore(xCDS2, xCDS3); + fail("XCDATASection.insertBefore"); + } catch (Exception e) { /* expected */ } + + try { + xCDS.replaceChild(xCDS2, xCDS3); + fail("XCDATASection.insertBefore"); + } catch (Exception e) { /* expected */ } + + try { + xCDS.removeChild(null); + fail("XCDATASection.removeChild(null)"); + } catch (Exception e) { /* expected */ } + + try { + xCDS.removeChild(xCDS2); + fail("XCDATASection.removeChild"); + } catch (DOMException e) { + assertTrue("XCDATASection.removeChild", + HIERARCHY_REQUEST_ERR == e.Code); + } + + } + + @Test public void testXComment() throws Exception + { + XDocumentBuilder xBuilder = + UnoRuntime.queryInterface(XDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.DocumentBuilder")); + XDocument xDoc = xBuilder.newDocument(); + + XComment xComment = xDoc.createComment("foo"); + assertNotNull(xComment); + + assertEquals("XComment.getData", "foo", xComment.getData()); + assertEquals("XComment.getLength", 3, xComment.getLength()); + + xComment.appendData("baz"); + assertEquals("XComment.appendData", "foobaz", xComment.getData()); + + try { + xComment.deleteData(999,999); + fail("XComment.deleteData(999,999)"); + } catch (DOMException e) { + assertTrue("XComment.deleteData(999,999)", + INDEX_SIZE_ERR == e.Code); + } + xComment.deleteData(0, 3); + assertEquals("XComment.deleteData", "baz", xComment.getData()); + + try { + xComment.insertData(999,"blah"); + fail("XComment.insertData(999,\"blah\")"); + } catch (DOMException e) { + assertTrue("XComment.insertData(999,\"blah\")", + INDEX_SIZE_ERR == e.Code); + } + xComment.insertData(1, "arb"); + assertEquals("XComment.insertData", "barbaz", xComment.getData()); + + try { + xComment.replaceData(999,999,"x"); + fail("XComment.replaceData(999,999,\"x\")"); + } catch (DOMException e) { + assertTrue("XComment.replaceData(999,999,\"x\")", + INDEX_SIZE_ERR == e.Code); + } + xComment.replaceData(3, 3, "foo"); + assertEquals("XComment.replaceData", "barfoo", xComment.getData()); + + xComment.setData("quux"); + assertEquals("XComment.setData", "quux", xComment.getData()); + + try { + xComment.subStringData(999,999); + fail("XComment.subStringData(999,999)"); + } catch (DOMException e) { + assertTrue("XComment.subStringData(999,999)", + INDEX_SIZE_ERR == e.Code); + } + assertEquals("XComment.subStringData", "x", + xComment.subStringData(3, 1)); + + // XNode //////////////////////////////////////////////////// + + { + XNode xCommentCloneN = xComment.cloneNode(false); + assertNotNull("XComment.cloneNode(false)", xCommentCloneN); + XComment xCommentClone = + UnoRuntime.queryInterface(XComment.class, xCommentCloneN); + assertNotNull("XComment.cloneNode(false)", xCommentClone); + assertFalse("XComment.cloneNode(false)", + xCommentClone.hasChildNodes()); + } + { + XNode xCommentCloneN = xComment.cloneNode(true); + assertNotNull("XComment.cloneNode(true)", xCommentCloneN); + XComment xCommentClone = + UnoRuntime.queryInterface(XComment.class, xCommentCloneN); + assertNotNull("XComment.cloneNode(true)", xCommentClone); + assertFalse("XComment.cloneNode(true)", + xCommentClone.hasChildNodes()); + } + + assertNull("XComment.getAttributes()", xComment.getAttributes()); + + { + XNodeList xChildren = xComment.getChildNodes(); + assertTrue("XComment.getChildNodes()", 0 == xChildren.getLength()); + } + + assertEquals("XComment.getLocalName()", "", xComment.getLocalName()); + + assertEquals("XComment.getNamespaceURI()", "", + xComment.getNamespaceURI()); + + assertNull("XComment.getNextSibling()", xComment.getNextSibling()); + + assertEquals("XComment.getNodeName()", "#comment", + xComment.getNodeName()); + + assertTrue("XComment.getNodeType()", + COMMENT_NODE == xComment.getNodeType()); + + assertEquals("XComment.getNodeValue()", "quux", + xComment.getNodeValue()); + + assertEquals("XComment.getOwnerDocument()", + xDoc, xComment.getOwnerDocument()); + + assertNull("XComment.getParentNode()", xComment.getParentNode()); + + assertEquals("XComment.getPrefix()", "", xComment.getPrefix()); + + assertNull("XComment.getPreviousSibling()", + xComment.getPreviousSibling()); + + assertFalse("XComment.hasAttributes()", xComment.hasAttributes()); + + assertFalse("XComment.hasChildNodes()", xComment.hasChildNodes()); + + assertFalse("XComment.isSupported()", + xComment.isSupported("frobnication", "v99.33.0.0.0.1")); + + xComment.normalize(); + + xComment.setNodeValue("42"); + assertEquals("XComment.setNodeValue()", "42", xComment.getNodeValue()); + + try { + xComment.setPrefix("foo"); + fail("XComment.setPrefix()"); + } catch (DOMException e) { + assertTrue("XComment.setPrefix()", + NO_MODIFICATION_ALLOWED_ERR == e.Code); + } + + XComment xComment2 = xDoc.createComment("foobar"); + XComment xComment3 = xDoc.createComment("foobar"); + + try { + xComment.appendChild(null); + fail("XComment.appendChild(null)"); + } catch (Exception e) { /* expected */ } + try { + xComment.appendChild(xComment2); + fail("XComment.appendChild(xComment2)"); + } catch (DOMException e) { + assertTrue("XComment.appendChild(xComment2)", + HIERARCHY_REQUEST_ERR == e.Code); + } + + try { + xComment.insertBefore(xComment2, xComment3); + fail("XComment.insertBefore"); + } catch (Exception e) { /* expected */ } + + try { + xComment.replaceChild(xComment2, xComment3); + fail("XComment.insertBefore"); + } catch (Exception e) { /* expected */ } + + try { + xComment.removeChild(null); + fail("XComment.removeChild(null)"); + } catch (Exception e) { /* expected */ } + + try { + xComment.removeChild(xComment2); + fail("XComment.removeChild"); + } catch (DOMException e) { + assertTrue("XComment.removeChild", HIERARCHY_REQUEST_ERR == e.Code); + } + } + + @Test public void testXEntityReference() throws Exception + { + XDocumentBuilder xBuilder = + UnoRuntime.queryInterface(XDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.DocumentBuilder")); + XDocument xDoc = xBuilder.newDocument(); + + XEntityReference xER = xDoc.createEntityReference("foobar"); + assertNotNull(xER); + + XEntityReference xERChild = xDoc.createEntityReference("baz"); + assertNotNull(xERChild); + + xER.appendChild(xERChild); + + // XNode //////////////////////////////////////////////////// + + XText xText = xDoc.createTextNode("foo"); + XComment xComment = xDoc.createComment("foo"); + + { + XNode xERCloneN = xER.cloneNode(false); + assertNotNull("XEntityReference.cloneNode(false)", xERCloneN); + XEntityReference xERClone = + UnoRuntime.queryInterface(XEntityReference.class, xERCloneN); + assertNotNull("XEntityReference.cloneNode(false)", xERClone); + assertFalse("XEntityReference.cloneNode(false)", + xERClone.hasChildNodes()); + assertNull("XEntityReference.cloneNode(false)", + xERClone.getFirstChild()); + } + { + XNode xERCloneN = xER.cloneNode(true); + assertNotNull("XEntityReference.cloneNode(true)", xERCloneN); + XEntityReference xERClone = + UnoRuntime.queryInterface(XEntityReference.class, xERCloneN); + assertNotNull("XEntityReference.cloneNode(true)", xERClone); + /* FIXME this is actually in libxml2: children are not copied + assertTrue("XEntityReference.cloneNode(true)", + xERClone.hasChildNodes()); + XNode xChild = xERClone.getFirstChild(); + assertNotNull("XEntityReference.cloneNode(true)", xChild); + XEntityReference xChildER = + UnoRuntime.queryInterface(XEntityReference.class, xChild); + assertNotNull("XEntityReference.cloneNode(true)", xChildER); + assertFalse("XEntityReference.cloneNode(true)", + xChildER.equals(xERChild)); + assertEquals("XEntityReference.cloneNode(true)", + "baz", xChildER.getLocalName()); + */ + } + + assertNull("XEntityReference.getAttributes()", xER.getAttributes()); + + { + XNodeList xChildren = xER.getChildNodes(); + assertTrue("XEntityReference.getChildNodes()", + 1 == xChildren.getLength()); + assertEquals("XEntityReference.getChildNodes()", + xERChild, xChildren.item(0)); + + XNode xFirst = xER.getFirstChild(); + assertEquals("XEntityReference.getFirstChild()", + xERChild, xFirst); + XNode xLast = xER.getLastChild(); + assertEquals("XEntityReference.getLastChild()", xERChild, xLast); + } + + assertEquals("XEntityReference.getLocalName()", "", xER.getLocalName()); + + assertEquals("XEntityReference.getNamespaceURI()", "", + xER.getNamespaceURI()); + + assertNull("XEntityReference.getNextSibling()", xER.getNextSibling()); + + assertEquals("XEntityReference.getNodeName()", + "foobar", xER.getNodeName()); + + assertTrue("XEntityReference.getNodeType()", + ENTITY_REFERENCE_NODE == xER.getNodeType()); + + assertEquals("XEntityReference.getNodeValue()", "", xER.getNodeValue()); + + assertEquals("XEntityReference.getOwnerDocument()", + xDoc, xER.getOwnerDocument()); + + assertNull("XEntityReference.getParentNode()", xER.getParentNode()); + + assertEquals("XEntityReference.getPrefix()", "", xER.getPrefix()); + + assertNull("XEntityReference.getPreviousSibling()", + xER.getPreviousSibling()); + + assertFalse("XEntityReference.hasAttributes()", xER.hasAttributes()); + + assertTrue("XEntityReference.hasChildNodes()", xER.hasChildNodes()); + + assertFalse("XEntityReference.isSupported()", + xER.isSupported("frobnication", "v99.33.0.0.0.1")); + + xER.normalize(); + + try { + xER.setNodeValue("42"); + fail("XEntityReference.setNodeValue()"); + } catch (DOMException e) { + assertTrue("XEntityReference.setNodeValue()", + NO_MODIFICATION_ALLOWED_ERR == e.Code); + } + + try { + xER.setPrefix("foo"); + fail("XEntityReference.setPrefix()"); + } catch (DOMException e) { + assertTrue("XEntityReference.setPrefix()", + NO_MODIFICATION_ALLOWED_ERR == e.Code); + } + + try { + xER.appendChild(null); + fail("XEntityReference.appendChild(null)"); + } catch (Exception e) { /* expected */ } + + try { + xER.insertBefore(null, xText); + fail("XEntityReference.insertBefore(null,)"); + } catch (Exception e) { /* expected */ } + try { + xER.insertBefore(xText, null); + fail("XEntityReference.insertBefore(, null)"); + } catch (Exception e) { /* expected */ } + try { + xER.insertBefore(xText, xText); + fail("XEntityReference.insertBefore(x, x)"); + } catch (DOMException e) { + assertTrue("XEntityReference.insertBefore(x, x)", + HIERARCHY_REQUEST_ERR == e.Code); + } + + { + XNode xRet = xER.insertBefore(xComment, xERChild); + assertEquals("XEntityReference.insertBefore(xComment, xERChild)", + xRet, xERChild); // why does this return the old node? + assertEquals("XEntityReference.insertBefore(xComment, xERChild)", + xComment, xER.getFirstChild()); + assertEquals("XEntityReference.insertBefore(xComment, xERChild)", + xER, xComment.getParentNode()); + assertEquals("XEntityReference.insertBefore(xCommnet, xERChild)", + xERChild, xER.getLastChild()); + } + + try { + xER.replaceChild(null, xText); + fail("XEntityReference.replaceChild(null, )"); + } catch (Exception e) { /* expected */ } + try { + xER.replaceChild(xText, null); + fail("XEntityReference.replaceChild(, null)"); + } catch (Exception e) { /* expected */ } + try { + xER.replaceChild(xText, xText); // not child + fail("XEntityReference.replaceChild(xElemFoo, xElemFoo)"); + } catch (DOMException e) { + assertTrue("XEntityReference.replaceChild(xElemFoo, xElemFoo)", + HIERARCHY_REQUEST_ERR == e.Code); + } + try { + xER.replaceChild(xERChild, xERChild); // child + assertFalse("XEntityReference.replaceChild(xERChild, xERChild)", + false); + } catch (DOMException e) { + assertTrue("XEntityReference.replaceChild(xERChild, xERChild)", + HIERARCHY_REQUEST_ERR == e.Code); + } + XNode xReplaced = xER.replaceChild(xText, xComment); + assertEquals("XEntityReference.replaceChild(xText, xComment)", + xReplaced, xComment); + assertEquals("XEntityReference.replaceChild(xText, xComment)", + xText, xER.getFirstChild()); + assertEquals("XEntityReference.replaceChild(xText, xComment)", + xERChild, xER.getLastChild()); + + try { + xER.removeChild(null); + fail("XEntityReference.removeChild(null)"); + } catch (Exception e) { /* expected */ } + try { + xER.removeChild(xER); + fail("XEntityReference.removeChild()"); + } catch (DOMException e) { + assertTrue("XEntityReference.removeChild()", + HIERARCHY_REQUEST_ERR == e.Code); + } + + XNode xRemoved = xER.removeChild(xText); + assertEquals("XEntityReference.removeChild(xText)", xRemoved, xText); + assertTrue("XEntityReference.removeChild(xText)", xER.hasChildNodes()); + assertEquals("XEntityReference.removeChild(xText)", + xERChild, xER.getFirstChild()); + assertEquals("XEntityReference.removeChild(xText)", + xERChild, xER.getLastChild()); + } + + @Test public void testXProcessingInstruction() throws Exception + { + XDocumentBuilder xBuilder = + UnoRuntime.queryInterface(XDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.DocumentBuilder")); + XDocument xDoc = xBuilder.newDocument(); + + XProcessingInstruction xPI = + xDoc.createProcessingInstruction("foo", "bar"); + assertNotNull(xPI); + + assertEquals("XProcessingInstruction.getTarget", + "foo", xPI.getTarget()); + + assertEquals("XProcessingInstruction.getData", "bar", xPI.getData()); + + xPI.setData("baz"); + assertEquals("XProcessingInstruction.setData", "baz", xPI.getData()); + + // XNode //////////////////////////////////////////////////// + + { + XNode xPICloneN = xPI.cloneNode(false); + assertNotNull("XProcessingInstruction.cloneNode(false)", xPICloneN); + XProcessingInstruction xPIClone = UnoRuntime.queryInterface( + XProcessingInstruction.class, xPICloneN); + assertNotNull("XProcessingInstruction.cloneNode(false)", xPIClone); + assertFalse("XProcessingInstruction.cloneNode(false)", + xPIClone.hasChildNodes()); + } + { + XNode xPICloneN = xPI.cloneNode(true); + assertNotNull("XProcessingInstruction.cloneNode(true)", xPICloneN); + XProcessingInstruction xPIClone = UnoRuntime.queryInterface( + XProcessingInstruction.class, xPICloneN); + assertNotNull("XProcessingInstruction.cloneNode(true)", xPIClone); + assertFalse("XProcessingInstruction.cloneNode(true)", + xPIClone.hasChildNodes()); + } + + assertNull("XProcessingInstruction.getAttributes()", + xPI.getAttributes()); + + { + XNodeList xChildren = xPI.getChildNodes(); + assertTrue("XProcessingInstruction.getChildNodes()", + 0 == xChildren.getLength()); + } + + assertEquals("XProcessingInstruction.getLocalName()", + "", xPI.getLocalName()); + + assertEquals("XProcessingInstruction.getNamespaceURI()", + "", xPI.getNamespaceURI()); + + assertNull("XProcessingInstruction.getNextSibling()", + xPI.getNextSibling()); + + assertEquals("XProcessingInstruction.getNodeName()", + "foo", xPI.getNodeName()); + + assertTrue("XProcessingInstruction.getNodeType()", + PROCESSING_INSTRUCTION_NODE == xPI.getNodeType()); + + assertEquals("XProcessingInstruction.getNodeValue()", + "baz", xPI.getNodeValue()); + + assertEquals("XProcessingInstruction.getOwnerDocument()", + xDoc, xPI.getOwnerDocument()); + + assertNull("XProcessingInstruction.getParentNode()", + xPI.getParentNode()); + + assertEquals("XProcessingInstruction.getPrefix()", "", xPI.getPrefix()); + + assertNull("XProcessingInstruction.getPreviousSibling()", + xPI.getPreviousSibling()); + + assertFalse("XProcessingInstruction.hasAttributes()", + xPI.hasAttributes()); + + assertFalse("XProcessingInstruction.hasChildNodes()", + xPI.hasChildNodes()); + + assertFalse("XProcessingInstruction.isSupported()", + xPI.isSupported("frobnication", "v99.33.0.0.0.1")); + + xPI.normalize(); + + xPI.setNodeValue("42"); + assertEquals("XProcessingInstruction.setNodeValue()", + "42", xPI.getNodeValue()); + + try { + xPI.setPrefix("foo"); + fail("XProcessingInstruction.setPrefix()"); + } catch (DOMException e) { + assertTrue("XProcessingInstruction.setPrefix()", + NO_MODIFICATION_ALLOWED_ERR == e.Code); + } + + XText xText2 = xDoc.createTextNode("foobar"); + XText xText3 = xDoc.createTextNode("foobar"); + + try { + xPI.appendChild(null); + fail("XProcessingInstruction.appendChild(null)"); + } catch (Exception e) { /* expected */ } + try { + xPI.appendChild(xText2); + fail("XProcessingInstruction.appendChild(xText2)"); + } catch (DOMException e) { + assertTrue("XProcessingInstruction.appendChild(xText2)", + HIERARCHY_REQUEST_ERR == e.Code); + } + + try { + xPI.insertBefore(xText2, xText3); + fail("XProcessingInstruction.insertBefore"); + } catch (Exception e) { /* expected */ } + + try { + xPI.replaceChild(xText2, xText3); + fail("XProcessingInstruction.insertBefore"); + } catch (Exception e) { /* expected */ } + + try { + xPI.removeChild(null); + fail("XProcessingInstruction.removeChild(null)"); + } catch (Exception e) { /* expected */ } + + try { + xPI.removeChild(xText2); + fail("XProcessingInstruction.removeChild"); + } catch (DOMException e) { + assertTrue("XProcessingInstruction.removeChild", + HIERARCHY_REQUEST_ERR == e.Code); + } + } + + /* + @Test public void testXEntity() throws Exception + { + XEntity xEntity = FIXME how to get at this shy creature? + } + */ + + /* + @Test public void testXNotation() throws Exception + { + XNotation xNotation = FIXME how to create? + } + */ + + /* + @Test public void testXDocumentType() throws Exception + { + XDocumentType xDT = FIXME how to create? + } + */ + + @Test public void testXNodeList_ChildList() throws Exception + { + XDocumentBuilder xBuilder = + UnoRuntime.queryInterface(XDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.DocumentBuilder")); + XDocument xDoc = xBuilder.newDocument(); + + XElement xRoot = xDoc.createElement("root"); + XElement xFoo = xDoc.createElement("foo"); + XElement xBar = xDoc.createElement("bar"); + XElement xBaz = xDoc.createElement("baz"); + + xDoc.appendChild(xRoot); + + XNodeList xChildList = xRoot.getChildNodes(); + assertNotNull(xChildList); + assertSame("ChildList.getLength()", 0, xChildList.getLength()); + + try { + xChildList.item(4); + } catch (Exception e) { /* expected */ } + + xRoot.appendChild(xFoo); + assertSame("ChildList.getLength()", 1, xChildList.getLength()); + assertEquals("ChildList.item", xFoo, xChildList.item(0)); + + xRoot.appendChild(xBar); + assertSame("ChildList.getLength()", 2, xChildList.getLength()); + assertEquals("ChildList.item", xFoo, xChildList.item(0)); + assertEquals("ChildList.item", xBar, xChildList.item(1)); + + xRoot.appendChild(xBaz); + assertSame("ChildList.getLength()", 3, xChildList.getLength()); + assertEquals("ChildList.item", xFoo, xChildList.item(0)); + assertEquals("ChildList.item", xBar, xChildList.item(1)); + assertEquals("ChildList.item", xBaz, xChildList.item(2)); + + xRoot.removeChild(xBar); + assertSame("ChildList.getLength()", 2, xChildList.getLength()); + assertEquals("ChildList.item", xFoo, xChildList.item(0)); + assertEquals("ChildList.item", xBaz, xChildList.item(1)); + } + + @Test public void testXNodeList_ElementList() throws Exception + { + XDocumentBuilder xBuilder = + UnoRuntime.queryInterface(XDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.DocumentBuilder")); + XDocument xDoc = xBuilder.newDocument(); + + XElement xRoot = xDoc.createElement("root"); + XElement xBar = xDoc.createElement("bar"); + XElement xFoo1 = xDoc.createElement("foo"); + XElement xFoo2 = xDoc.createElement("foo"); + XElement xFoo3 = xDoc.createElement("foo"); + + xDoc.appendChild(xRoot); + + XNodeList xElementList = xRoot.getElementsByTagName("foo"); + assertNotNull(xElementList); + assertSame("ElementList.getLength()", 0, xElementList.getLength()); + + try { + xElementList.item(4); + } catch (Exception e) { /* expected */ } + + xRoot.appendChild(xFoo1); + assertSame("ElementList.getLength()", 1, xElementList.getLength()); + assertEquals("ElementList.item", xFoo1, xElementList.item(0)); + + xFoo1.appendChild(xBar); + assertSame("ElementList.getLength()", 1, xElementList.getLength()); + assertEquals("ElementList.item", xFoo1, xElementList.item(0)); + + xRoot.appendChild(xFoo3); + assertSame("ElementList.getLength()", 2, xElementList.getLength()); + assertEquals("ElementList.item", xFoo1, xElementList.item(0)); + assertEquals("ElementList.item", xFoo3, xElementList.item(1)); + + xBar.appendChild(xFoo2); + assertSame("ElementList.getLength()", 3, xElementList.getLength()); + assertEquals("ElementList.item", xFoo1, xElementList.item(0)); + assertEquals("ElementList.item", xFoo2, xElementList.item(1)); + assertEquals("ElementList.item", xFoo3, xElementList.item(2)); + + xRoot.removeChild(xFoo1); + assertSame("ElementList.getLength()", 1, xElementList.getLength()); + assertEquals("ElementList.item", xFoo3, xElementList.item(0)); + } + + @Test public void testXNamedNodeMap_AttributesMap() throws Exception + { + XDocumentBuilder xBuilder = + UnoRuntime.queryInterface(XDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.DocumentBuilder")); + XDocument xDoc = xBuilder.newDocument(); + + String ns = "http://example.com/"; + + XElement xElem = xDoc.createElement("foo"); + + XNamedNodeMap xAttributes = xElem.getAttributes(); + assertNotNull(xAttributes); + assertSame("AttributesMap.getLength()", 0, xAttributes.getLength()); + + try { + xAttributes.item(4); + } catch (Exception e) { /* expected */ } + + xElem.setAttribute("bar", "42"); + XAttr xAttrBar = xElem.getAttributeNode("bar"); + assertSame("AttributesMap.getLength()", 1, xAttributes.getLength()); + assertEquals("AttributesMap.item", xAttrBar, xAttributes.item(0)); + assertEquals("AttributesMap.getNamedItem", + xAttrBar, xAttributes.getNamedItem("bar")); + + xElem.setAttributeNS(ns, "n:bar", "43"); + XAttr xAttrBarNs = xElem.getAttributeNodeNS(ns, "bar"); + assertSame("AttributesMap.getLength()", 2, xAttributes.getLength()); + assertEquals("AttributesMap.item", xAttrBar, xAttributes.item(0)); + assertEquals("AttributesMap.item", xAttrBarNs, xAttributes.item(1)); + assertEquals("AttributesMap.getNamedItem", + xAttrBar, xAttributes.getNamedItem("bar")); + assertEquals("AttributesMap.getNamedItemNS", + xAttrBarNs, xAttributes.getNamedItemNS(ns, "bar")); + + XNode xAttrBarNsRem = xAttributes.removeNamedItemNS(ns, "bar"); + assertSame("AttributesMap.getLength()", 1, xAttributes.getLength()); + assertEquals("AttributesMap.removeNamedItemNS", + xAttrBar, xAttributes.item(0)); + assertEquals("AttributesMap.removeNamedItemNS", + xAttrBar, xAttributes.getNamedItem("bar")); + assertNull("AttributesMap.removeNamedItemNS", + xAttrBarNsRem.getParentNode()); + + XNode xAttrBarRem = xAttributes.removeNamedItem("bar"); + assertSame("AttributesMap.getLength()", 0, xAttributes.getLength()); + assertNull("AttributesMap.removeNamedItem", + xAttrBarRem.getParentNode()); + + XNode xAttrBarSetN = xAttributes.setNamedItem(xAttrBarRem); + assertNotNull("AttributesMap.setNamedItem", xAttrBarSetN); + XAttr xAttrBarSet = + UnoRuntime.queryInterface(XAttr.class, xAttrBarSetN); + assertNotNull("AttributesMap.setNamedItem", xAttrBarSet); + assertEquals("AttributesMap.setNamedItem", + xAttrBarSet, xAttributes.getNamedItem("bar")); + + XNode xAttrBarNsSetN = xAttributes.setNamedItemNS(xAttrBarNsRem); + assertNotNull("AttributesMap.setNamedItemNS", xAttrBarNsSetN); + XAttr xAttrBarNsSet = + UnoRuntime.queryInterface(XAttr.class, xAttrBarNsSetN); + assertNotNull("AttributesMap.setNamedItemNS", xAttrBarNsSet); + assertEquals("AttributesMap.setNamedItemNS", + xAttrBarNsSet, xAttributes.getNamedItemNS(ns, "bar")); + assertSame("AttributesMap.getLength()", 2, xAttributes.getLength()); + } + + /* + @Test public void testXNamedNodeMap_EntitiesMap() throws Exception + { + XNamedNodeMap xEntities = FIXME + } + */ + + /* + @Test public void testXNamedNodeMap_NotationsMap() throws Exception + { + XNamedNodeMap xNotations = FIXME + } + */ + + @Test public void testXXPathAPI() throws Exception + { + XXPathAPI xXPathAPI = + UnoRuntime.queryInterface(XXPathAPI.class, + m_xMSF.createInstance("com.sun.star.xml.xpath.XPathAPI")); + XDocumentBuilder xBuilder = + UnoRuntime.queryInterface(XDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.DocumentBuilder")); + + String ns = "http://example.com/"; + + XDocument xDoc = xBuilder.newDocument(); + + XElement xRoot = xDoc.createElement("root"); + + XElement xFoo1 = xDoc.createElement("foo"); + XElement xFoo2 = xDoc.createElement("foo"); + XElement xFooNs = xDoc.createElementNS(ns, "ns:foo"); + XElement xBar = xDoc.createElement("bar"); + + xDoc.appendChild(xRoot); + xRoot.appendChild(xFoo1); + xFoo1.appendChild(xBar); + xBar.appendChild(xFoo2); + xRoot.appendChild(xFooNs); + + try { + xXPathAPI.eval(xRoot, "~/-$+&#_"); + fail("XXPathAPI.eval"); + } catch (XPathException e) { /* expected */ } + try { + xXPathAPI.evalNS(xRoot, "~/-$+&#_", xRoot); + fail("XXPathAPI.evalNS"); + } catch (XPathException e) { /* expected */ } + try { + xXPathAPI.selectNodeList(xRoot, "~/-$+&#_"); + fail("XXPathAPI.selectNodeList"); + } catch (XPathException e) { /* expected */ } + try { + xXPathAPI.selectNodeListNS(xRoot, "~/-$+&#_", xRoot); + fail("XXPathAPI.selectNodeListNS"); + } catch (XPathException e) { /* expected */ } + try { + xXPathAPI.selectSingleNode(xRoot, "~/-$+&#_"); + fail("XXPathAPI.selectSingleNode"); + } catch (XPathException e) { /* expected */ } + try { + xXPathAPI.selectSingleNodeNS(xRoot, "~/-$+&#_", xRoot); + fail("XXPathAPI.selectSingleNodeNS"); + } catch (XPathException e) { /* expected */ } + try { + xXPathAPI.eval(null, "child::foo"); + fail("XXPathAPI.eval(null)"); + } catch (Exception e) { /* expected */ } + try { + xXPathAPI.evalNS(null, "child::foo", xRoot); + fail("XXPathAPI.evalNS(null)"); + } catch (Exception e) { /* expected */ } + try { + xXPathAPI.selectNodeList(null, "child::foo"); + fail("XXPathAPI.selectNodeList(null)"); + } catch (Exception e) { /* expected */ } + try { + xXPathAPI.selectNodeListNS(null, "child::foo", xRoot); + fail("XXPathAPI.selectNodeListNS(null)"); + } catch (Exception e) { /* expected */ } + try { + xXPathAPI.selectSingleNode(null, "child::foo"); + fail("XXPathAPI.selectSingleNode(null)"); + } catch (Exception e) { /* expected */ } + try { + xXPathAPI.selectSingleNodeNS(null, "child::foo", xRoot); + fail("XXPathAPI.selectSingleNodeNS(null)"); + } catch (Exception e) { /* expected */ } + + { + XXPathObject xResult = xXPathAPI.eval(xRoot, "count(child::foo)"); + assertNotNull("XXPathAPI.eval", xResult); + assertEquals("XXPathAPI.eval", + XPATH_NUMBER, xResult.getObjectType()); + assertEquals("XXPathAPI.eval", 1, xResult.getLong()); + } + { + XXPathObject xResult = + xXPathAPI.evalNS(xRoot, "count(//ns:foo)", xFooNs); + assertNotNull("XXPathAPI.evalNS", xResult); + assertEquals("XXPathAPI.evalNS", + XPATH_NUMBER, xResult.getObjectType()); + assertEquals("XXPathAPI.evalNS", 1, xResult.getLong()); + } + { + XNodeList xResult = xXPathAPI.selectNodeList(xRoot, "child::foo"); + assertNotNull("XXPathAPI.selectNodeList", xResult); + assertEquals("XXPathAPI.selectNodeList", 1, xResult.getLength()); + assertEquals("XXPathAPI.selectNodeList", xFoo1, xResult.item(0)); + } + { + XNodeList xResult = + xXPathAPI.selectNodeListNS(xRoot, ".//ns:foo", xFooNs); + assertNotNull("XXPathAPI.selectNodeListNS", xResult); + assertEquals("XXPathAPI.selectNodeListNS", 1, xResult.getLength()); + assertEquals("XXPathAPI.selectNodeListNS", xFooNs, xResult.item(0)); + } + { + XNode xResult = xXPathAPI.selectSingleNode(xBar, "child::foo"); + assertNotNull("XXPathAPI.selectSingleNode", xResult); + assertEquals("XXPathAPI.selectSingleNode", xFoo2, xResult); + } + { + XNode xResult = + xXPathAPI.selectSingleNodeNS(xFoo2, "//ns:foo", xFooNs); + assertNotNull("XXPathAPI.selectSingleNodeNS", xResult); + assertEquals("XXPathAPI.selectSingleNodeNS", xFooNs, xResult); + } + + try { + XNode xResult = xXPathAPI.selectSingleNode(xDoc, "//pre:foo"); + fail("XXPathAPI.selectSingleNode"); + } catch (XPathException e) { /* expected */ } + xXPathAPI.registerNS("pre", ns); + { + XNode xResult = xXPathAPI.selectSingleNode(xDoc, "//pre:foo"); + assertNotNull("XXPathAPI.registerNS", xResult); + assertEquals("XXPathAPI.registerNS", xFooNs, xResult); + } + + xXPathAPI.unregisterNS("pre", ns); + try { + XNode xResult = xXPathAPI.selectSingleNode(xDoc, "//pre:foo"); + fail("XXPathAPI.unregisterNS"); + } catch (XPathException e) { /* expected */ } + + /* FIXME + registerExtension(""); + registerExtensionInstance(xExtension); + */ + } + + @Test public void testXXPathObject() throws Exception + { + XXPathAPI xXPathAPI = + UnoRuntime.queryInterface(XXPathAPI.class, + m_xMSF.createInstance("com.sun.star.xml.xpath.XPathAPI")); + XDocumentBuilder xBuilder = + UnoRuntime.queryInterface(XDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.DocumentBuilder")); + + String ns = "http://example.com/"; + + XDocument xDoc = xBuilder.newDocument(); + + XElement xRoot = xDoc.createElement("root"); + + XElement xFoo1 = xDoc.createElement("foo"); + XElement xFoo2 = xDoc.createElement("foo"); + XElement xFooNs = xDoc.createElementNS(ns, "ns:foo"); + XElement xBar = xDoc.createElement("bar"); + + xDoc.appendChild(xRoot); + xRoot.appendChild(xFoo1); + xFoo1.appendChild(xBar); + xBar.appendChild(xFoo2); + xRoot.appendChild(xFooNs); + + { + XXPathObject xResult = xXPathAPI.eval(xRoot, "count(//foo)"); + assertNotNull("XXPathAPI.eval", xResult); + assertEquals("XXPathObject.getObjectType", + XPATH_NUMBER, xResult.getObjectType()); + assertEquals("XXPathObject.getByte", 2, xResult.getByte()); + assertEquals("XXPathObject.getShort", 2, xResult.getShort()); + assertEquals("XXPathObject.getLong", 2, xResult.getLong()); + assertEquals("XXPathObject.getHyper", 2, xResult.getHyper()); + assertEquals("XXPathObject.getFloat", 2.0, xResult.getFloat(), 0.0); + assertEquals("XXPathObject.getDouble", + 2.0, xResult.getDouble(), 0.0); + assertEquals("XXPathObject.getString", "2", xResult.getString()); + } + { + XXPathObject xResult = xXPathAPI.eval(xRoot, "count(//foo) = 2"); + assertNotNull("XXPathAPI.eval", xResult); + assertEquals("XXPathObject.getObjectType", + XPATH_BOOLEAN, xResult.getObjectType()); + assertEquals("XXPathObject.getBoolean", true, xResult.getBoolean()); + assertEquals("XXPathObject.getString", "true", xResult.getString()); + } + { + XXPathObject xResult = xXPathAPI.eval(xRoot, "count(//foo) = 2"); + assertNotNull("XXPathAPI.eval", xResult); + assertEquals("XXPathObject.getObjectType", + XPATH_BOOLEAN, xResult.getObjectType()); + assertEquals("XXPathObject.getBoolean", true, xResult.getBoolean()); + assertEquals("XXPathObject.getString", "true", xResult.getString()); + } + { + XXPathObject xResult = xXPathAPI.eval(xRoot, "local-name(foo)"); + assertNotNull("XXPathAPI.eval", xResult); + assertEquals("XXPathObject.getObjectType", + XPATH_STRING, xResult.getObjectType()); + assertEquals("XXPathObject.getString", "foo", xResult.getString()); + } + { + XXPathObject xResult = xXPathAPI.eval(xRoot, "//foo"); + assertNotNull("XXPathAPI.eval", xResult); + assertEquals("XXPathObject.getObjectType", + XPATH_NODESET, xResult.getObjectType()); + assertNotNull("XXPathObject.getNodeList", xResult.getNodeList()); + } + } + + @Test public void testXNodeList_NodeList() throws Exception + { + XXPathAPI xXPathAPI = + UnoRuntime.queryInterface(XXPathAPI.class, + m_xMSF.createInstance("com.sun.star.xml.xpath.XPathAPI")); + XDocumentBuilder xBuilder = + UnoRuntime.queryInterface(XDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.DocumentBuilder")); + + String ns = "http://example.com/"; + + XDocument xDoc = xBuilder.newDocument(); + + XElement xRoot = xDoc.createElement("root"); + + XElement xFoo1 = xDoc.createElement("foo"); + XElement xFoo2 = xDoc.createElement("foo"); + XElement xFooNs = xDoc.createElementNS(ns, "ns:foo"); + XElement xBar = xDoc.createElement("bar"); + + xDoc.appendChild(xRoot); + xRoot.appendChild(xFoo1); + xFoo1.appendChild(xBar); + xBar.appendChild(xFoo2); + xRoot.appendChild(xFooNs); + + { + XXPathObject xResult = xXPathAPI.eval(xRoot, "//foo"); + assertNotNull("XXPathAPI.eval", xResult); + assertEquals("XXPathObject.getObjectType", + XPATH_NODESET, xResult.getObjectType()); + XNodeList xNodeList = xResult.getNodeList(); + assertNotNull("XXPathObject.getNodeList", xNodeList); + assertEquals("NodeList.getLength", 2, xNodeList.getLength()); + assertEquals("NodeList.item", xFoo1, xNodeList.item(0)); + assertEquals("NodeList.item", xFoo2, xNodeList.item(1)); + } + } + + + // just for importNode... + abstract class MockNode implements XNode + { + MockDoc m_document; + MockNode m_parent; + MockNode m_prev; + MockNode m_next; + MockNode[] m_children; + String m_localname; + +// MockNode() { ; } + void init(MockDoc doc, MockNode parent, MockNode prev, MockNode next, + MockNode[] children) + { + m_document = doc; + m_parent = parent; m_prev = prev; m_next = next; + m_children = children; + } + + public XNode appendChild(XNode c) throws DOMException { + fail("MockNode.appendChild called?"); + return null; + } + public XNode cloneNode(boolean b) { + fail("MockNode.cloneNode called?"); + return null; + } + public XNamedNodeMap getAttributes() { + fail("MockNode.getAttributes not implemented"); + return null; + } + public XNodeList getChildNodes() { + fail("MockNode.getChildList not implemented"); + return null; + } + public XNode getFirstChild() { + return (m_children.length != 0) ? m_children[0] : null; + } + public XNode getLastChild() { + return (m_children.length != 0) + ? m_children[m_children.length-1] : null; + } + public String getLocalName() { return m_localname; } + public String getNamespaceURI() { return ""; } + public XNode getNextSibling() { return m_next; } + public String getNodeName() { return m_localname; } +// NodeType getNodeType() { return m_type; } + public String getNodeValue() throws DOMException { return ""; } + public XDocument getOwnerDocument() { return m_document; } + public XNode getParentNode() { return m_parent; } + public String getPrefix() { return ""; } + public XNode getPreviousSibling() { return m_prev; } + public boolean hasAttributes() { return false; } + public boolean hasChildNodes() { return m_children.length != 0; } + public XNode insertBefore(XNode c, XNode r) throws DOMException { + fail("MockNode.insertBefore called?"); + return null; + } + public boolean isSupported(String a, String b) { return false; } + public void normalize() { + fail("MockNode.normalize called?"); + } + public XNode removeChild(XNode c) throws DOMException { + fail("MockNode.removeChild called?"); + return null; + } + public XNode replaceChild(XNode c, XNode o) throws DOMException { + fail("MockNode.replaceChild called?"); + return null; + } + public void setNodeValue(String v) throws DOMException { + fail("MockNode.setNodeValue called?"); + } + public void setPrefix(String p) throws DOMException { + fail("MockNode.setPrefix called?"); + } + } + class MockDoc extends MockNode implements XDocument + { +// MockDoc() { } + void init(MockNode[] children) { + super.init(this, null, null, null, children); + } + + public NodeType getNodeType() { return DOCUMENT_NODE; } + + public XAttr createAttribute(String n) throws DOMException { + fail("MockNode.createAttribute called?"); + return null; + } + public XAttr createAttributeNS(String n, String q) throws DOMException { + fail("MockNode.createAttributeNS called?"); + return null; + } + public XCDATASection createCDATASection(String s) throws DOMException { + fail("MockNode.createCDATASection called?"); + return null; + } + public XComment createComment(String s) { + fail("MockNode.createCDATASection called?"); + return null; + } + public XDocumentFragment createDocumentFragment() { + fail("MockNode.createDocumentFragment called?"); + return null; + } + public XElement createElement(String n) { + fail("MockNode.createElement called?"); + return null; + } + public XElement createElementNS(String n, String q) { + fail("MockNode.createElementNS called?"); + return null; + } + public XEntityReference createEntityReference(String n) + throws DOMException { + fail("MockNode.createEntityReference called?"); + return null; + } + public XProcessingInstruction createProcessingInstruction(String t, + String d) throws DOMException { + fail("MockNode.createEntityReference called?"); + return null; + } + public XText createTextNode(String d) { + fail("MockNode.createTextNode called?"); + return null; + } + public XDocumentType getDoctype() { + fail("MockNode.getDoctype called?"); + return null; + } + public XElement getDocumentElement() { + fail("MockNode.getDocumentElement called?"); + return null; + } + public XElement getElementById(String id) { + fail("MockNode.getElementById called?"); + return null; + } + public XNodeList getElementsByTagName(String n) { + fail("MockNode.getElementsByTagName called?"); + return null; + } + public XNodeList getElementsByTagNameNS(String n, String q) { + fail("MockNode.getElementsByTagNameNS called?"); + return null; + } + public XDOMImplementation getImplementation() { + fail("MockNode.getImplementation called?"); + return null; + } + public XNode importNode(XNode i, boolean b) throws DOMException { + fail("MockNode.importNode called?"); + return null; + } + } + class MockNodeMap implements XNamedNodeMap + { + MockAttr[] m_attributes; + + MockNodeMap(MockAttr[] attrs) { m_attributes = attrs; } + + public int getLength() { return m_attributes.length; } + public XNode getNamedItem(String name) { + fail("MockNodeMap.getNamedItem not implemented"); + return null; + } + public XNode getNamedItemNS(String n, String l) { + fail("MockNodeMap.getNamedItemNS not implemented"); + return null; + } + public XNode item(int index) { + return m_attributes[index]; + } + public XNode removeNamedItem(String n) throws DOMException { + fail("MockNodeMap.removeNamedItem called?"); + return null; + } + public XNode removeNamedItemNS(String n, String l) throws DOMException { + fail("MockNodeMap.removeNamedItemNS called?"); + return null; + } + public XNode setNamedItem(XNode n) throws DOMException { + fail("MockNodeMap.setNamedItem called?"); + return null; + } + public XNode setNamedItemNS(XNode n) throws DOMException { + fail("MockNodeMap.setNamedItemNS called?"); + return null; + } + } + class MockElement extends MockNode implements XElement + { + MockAttr[] m_attributes; + + MockElement(String name, MockAttr[] attrs) { + m_localname = name; m_attributes = attrs; + } + + public NodeType getNodeType() { return ELEMENT_NODE; } + public XNamedNodeMap getAttributes() { + return new MockNodeMap(m_attributes); + } + public boolean hasAttributes() { return m_attributes.length != 0; } + + public String getAttribute(String n) { + fail("MockNode.getAttribute not implemented"); + return null; + } + public XAttr getAttributeNode(String n) { + fail("MockNode.getAttributeNode not implemented"); + return null; + } + public XAttr getAttributeNodeNS(String n, String l) { + fail("MockNode.getAttributeNodeNS not implemented"); + return null; + } + public String getAttributeNS(String n, String q) { + fail("MockNode.getAttributeNS not implemented"); + return null; + } + public XNodeList getElementsByTagName(String n) { + fail("MockNode.getElementsByTagName called?"); + return null; + } + public XNodeList getElementsByTagNameNS(String n, String l) { + fail("MockNode.getElementsByTagNameNS called?"); + return null; + } + public String getTagName() { + return getLocalName(); + } + public boolean hasAttribute(String n) { + fail("MockNode.hasAttribute not implemented"); + return false; + } + public boolean hasAttributeNS(String n, String l) { + fail("MockNode.hasAttributeNS not implemented"); + return false; + } + public void removeAttribute(String n) throws DOMException { + fail("MockNode.removeAttribute called?"); + } + public XAttr removeAttributeNode(XAttr o) throws DOMException { + fail("MockNode.removeAttributeNode called?"); + return null; + } + public void removeAttributeNS(String n, String l) throws DOMException { + fail("MockNode.removeAttributeNS called?"); + } + public void setAttribute(String n, String v) throws DOMException { + fail("MockNode.setAttribute called?"); + } + public XAttr setAttributeNode(XAttr n) throws DOMException { + fail("MockNode.setAttributeNode called?"); + return null; + } + public XAttr setAttributeNodeNS(XAttr n) throws DOMException { + fail("MockNode.setAttributeNodeNS called?"); + return null; + } + public void setAttributeNS(String n, String q, String v) + throws DOMException { + fail("MockNode.setAttributeNS called?"); + } + } + class MockAttr extends MockNode implements XAttr + { + String m_value; + + MockAttr(String name, String value) { + m_localname = name; m_value = value; + } + + public NodeType getNodeType() { return ATTRIBUTE_NODE; } + + public String getName() { return m_localname; } + public XElement getOwnerElement() { return (XElement) m_parent; } + public boolean getSpecified() { return true; } + public String getValue() { return m_value; } + public void setValue(String v) { + fail("MockNode.setValue called?"); + } + } +} + diff --git a/unoxml/qa/complex/unoxml/TestDocument.java b/unoxml/qa/complex/unoxml/TestDocument.java index bce9510e4d94..d64431f21741 100644 --- a/unoxml/qa/complex/unoxml/TestDocument.java +++ b/unoxml/qa/complex/unoxml/TestDocument.java @@ -29,10 +29,11 @@ package complex.unoxml; import java.io.File; import org.openoffice.test.OfficeFileUrl; +import org.openoffice.test.Argument; final class TestDocument { public static String getUrl(String name) { - return OfficeFileUrl.getAbsolute(new File("testdocuments", name)); + return OfficeFileUrl.getAbsolute(new File(Argument.get("tdoc"), name)); } private TestDocument() {} diff --git a/unoxml/source/dom/attr.cxx b/unoxml/source/dom/attr.cxx index a1773a7db99f..8851c3ada86b 100644 --- a/unoxml/source/dom/attr.cxx +++ b/unoxml/source/dom/attr.cxx @@ -25,18 +25,60 @@ * ************************************************************************/ -#include "attr.hxx" -#include "element.hxx" -#include <com/sun/star/xml/dom/DOMException.hdl> +#include <attr.hxx> + #include <string.h> +#include <boost/shared_ptr.hpp> + +#include <com/sun/star/xml/dom/DOMException.hdl> +#include <com/sun/star/xml/dom/events/XMutationEvent.hpp> + +#include <document.hxx> + + namespace DOM { - CAttr::CAttr(const xmlAttrPtr pAttr) + CAttr::CAttr(CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlAttrPtr const pAttr) + : CAttr_Base(rDocument, rMutex, + NodeType_ATTRIBUTE_NODE, reinterpret_cast<xmlNodePtr>(pAttr)) + , m_aAttrPtr(pAttr) + { + } + + xmlNsPtr CAttr::GetNamespace(xmlNodePtr const pNode) + { + if (!m_pNamespace.get()) { + return 0; + } + xmlChar const*const pUri(reinterpret_cast<xmlChar const*>( + m_pNamespace->first.getStr())); + xmlChar const*const pPrefix(reinterpret_cast<xmlChar const*>( + m_pNamespace->second.getStr())); + xmlNsPtr pNs = xmlSearchNs(pNode->doc, pNode, pPrefix); + if (pNs && (0 != xmlStrcmp(pNs->href, pUri))) { + return pNs; + } + pNs = xmlNewNs(pNode, pUri, pPrefix); + if (pNs) { + return pNs; + } + pNs = xmlSearchNsByHref(pNode->doc, pNode, pUri); + // if (!pNs) hmm... now what? throw? + if (!pNs) { OSL_TRACE("CAtttr: cannot create namespace"); } + return pNs; + } + + bool CAttr::IsChildTypeAllowed(NodeType const nodeType) { - m_aAttrPtr = pAttr; - m_aNodeType = NodeType_ATTRIBUTE_NODE; - init_node((xmlNodePtr)pAttr); + switch (nodeType) { + case NodeType_TEXT_NODE: + case NodeType_ENTITY_REFERENCE_NODE: + return true; + default: + return false; + } } OUString SAL_CALL CAttr::getNodeName() @@ -61,11 +103,13 @@ namespace DOM */ OUString SAL_CALL CAttr::getName() throw (RuntimeException) { - OUString aName; - if (m_aAttrPtr != NULL) - { - aName = OUString((char*)m_aAttrPtr->name, strlen((char*)m_aAttrPtr->name), RTL_TEXTENCODING_UTF8); + ::osl::MutexGuard const g(m_rMutex); + + if ((0 == m_aNodePtr) || (0 == m_aAttrPtr)) { + return ::rtl::OUString(); } + OUString const aName((char*)m_aAttrPtr->name, + strlen((char*)m_aAttrPtr->name), RTL_TEXTENCODING_UTF8); return aName; } @@ -76,12 +120,19 @@ namespace DOM Reference< XElement > SAL_CALL CAttr::getOwnerElement() throw (RuntimeException) { - Reference< XElement > aElement; - if (m_aAttrPtr != NULL && m_aAttrPtr->parent != NULL) - { - aElement = Reference< XElement >(static_cast< CElement* >(CNode::get(m_aAttrPtr->parent))); + ::osl::MutexGuard const g(m_rMutex); + + if ((0 == m_aNodePtr) || (0 == m_aAttrPtr)) { + return 0; + } + if (0 == m_aAttrPtr->parent) { + return 0; } - return aElement; + Reference< XElement > const xRet( + static_cast< XNode* >(GetOwnerDocument().GetCNode( + m_aAttrPtr->parent).get()), + UNO_QUERY_THROW); + return xRet; } /** @@ -91,8 +142,9 @@ namespace DOM sal_Bool SAL_CALL CAttr::getSpecified() throw (RuntimeException) { - // XXX what is this supposed do exactly? - return sal_False; + // FIXME if this DOM implemenatation supported DTDs it would need + // to check that this attribute is not default or something + return sal_True; } /** @@ -101,13 +153,19 @@ namespace DOM OUString SAL_CALL CAttr::getValue() throw (RuntimeException) { - OUString aName; - if (m_aAttrPtr != NULL && m_aAttrPtr->children != NULL) - { - aName = OUString((char*)m_aAttrPtr->children->content, strlen((char*)m_aAttrPtr->children->content), - RTL_TEXTENCODING_UTF8); + ::osl::MutexGuard const g(m_rMutex); + + if ((0 == m_aNodePtr) || (0 == m_aAttrPtr)) { + return ::rtl::OUString(); } - return aName; + if (0 == m_aAttrPtr->children) { + return ::rtl::OUString(); + } + char const*const pContent((m_aAttrPtr->children) + ? reinterpret_cast<char const*>(m_aAttrPtr->children->content) + : ""); + OUString const ret(pContent, strlen(pContent), RTL_TEXTENCODING_UTF8); + return ret; } /** @@ -116,6 +174,12 @@ namespace DOM void SAL_CALL CAttr::setValue(const OUString& value) throw (RuntimeException, DOMException) { + ::osl::ClearableMutexGuard guard(m_rMutex); + + if ((0 == m_aNodePtr) || (0 == m_aAttrPtr)) { + return; + } + // remember old value (for mutation event) OUString sOldValue = getValue(); @@ -125,8 +189,11 @@ namespace DOM // this does not work if the attribute was created anew // xmlNodePtr pNode = m_aAttrPtr->parent; // xmlSetProp(pNode, m_aAttrPtr->name, xValue); - xmlChar *buffer = xmlEncodeEntitiesReentrant(m_aAttrPtr->doc, xValue); - m_aAttrPtr->children = xmlStringGetNodeList(m_aAttrPtr->doc, buffer); + ::boost::shared_ptr<xmlChar const> const buffer( + xmlEncodeEntitiesReentrant(m_aAttrPtr->doc, xValue), xmlFree); + xmlFreeNodeList(m_aAttrPtr->children); + m_aAttrPtr->children = + xmlStringGetNodeList(m_aAttrPtr->doc, buffer.get()); xmlNodePtr tmp = m_aAttrPtr->children; while (tmp != NULL) { tmp->parent = (xmlNodePtr) m_aNodePtr; @@ -145,9 +212,60 @@ namespace DOM sEventName, sal_True, sal_False, Reference<XNode>( static_cast<XAttr*>( this ) ), sOldValue, value, getName(), AttrChangeType_MODIFICATION ); + + guard.clear(); // release mutex before calling event handlers + dispatchEvent(Reference< XEvent >(event, UNO_QUERY)); dispatchSubtreeModified(); - xmlFree(buffer); } + void SAL_CALL CAttr::setPrefix(const OUString& prefix) + throw (RuntimeException, DOMException) + { + ::osl::MutexGuard const g(m_rMutex); + + if (!m_aNodePtr) { return; } + + if (m_pNamespace.get()) { + OSL_ASSERT(!m_aNodePtr->parent); + m_pNamespace->second = + OUStringToOString(prefix, RTL_TEXTENCODING_UTF8); + } else { + CNode::setPrefix(prefix); + } + } + + OUString SAL_CALL CAttr::getPrefix() + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + if (!m_aNodePtr) { return ::rtl::OUString(); } + + if (m_pNamespace.get()) { + OSL_ASSERT(!m_aNodePtr->parent); + OUString const ret(::rtl::OStringToOUString( + m_pNamespace->second, RTL_TEXTENCODING_UTF8)); + return ret; + } else { + return CNode::getPrefix(); + } + } + + OUString SAL_CALL CAttr::getNamespaceURI() + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + if (!m_aNodePtr) { return ::rtl::OUString(); } + + if (m_pNamespace.get()) { + OSL_ASSERT(!m_aNodePtr->parent); + OUString const ret(::rtl::OStringToOUString( + m_pNamespace->first, RTL_TEXTENCODING_UTF8)); + return ret; + } else { + return CNode::getNamespaceURI(); + } + } } diff --git a/unoxml/source/dom/attr.hxx b/unoxml/source/dom/attr.hxx index b79927b46037..824f042a2b85 100644 --- a/unoxml/source/dom/attr.hxx +++ b/unoxml/source/dom/attr.hxx @@ -25,16 +25,20 @@ * ************************************************************************/ -#ifndef _ATTR_HXX -#define _ATTR_HXX +#ifndef DOM_ATTR_HXX +#define DOM_ATTR_HXX + +#include <memory> + +#include <libxml/tree.h> #include <cppuhelper/implbase1.hxx> + #include <com/sun/star/uno/Reference.h> -#include <com/sun/star/uno/Exception.hpp> #include <com/sun/star/xml/dom/XNode.hpp> #include <com/sun/star/xml/dom/XAttr.hpp> -#include "node.hxx" -#include <libxml/tree.h> + +#include <node.hxx> using ::rtl::OUString; using namespace com::sun::star::uno; @@ -42,17 +46,30 @@ using namespace com::sun::star::xml::dom; namespace DOM { - class CAttr : public cppu::ImplInheritanceHelper1< CNode, XAttr > + typedef ::std::pair< ::rtl::OString, ::rtl::OString > stringpair_t; + + typedef ::cppu::ImplInheritanceHelper1< CNode, XAttr > CAttr_Base; + + class CAttr + : public CAttr_Base { - friend class CNode; - friend class CElement; + private: + friend class CDocument; + private: xmlAttrPtr m_aAttrPtr; + ::std::auto_ptr< stringpair_t > m_pNamespace; protected: - CAttr(const xmlAttrPtr aAttrPtr); + CAttr(CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlAttrPtr const pAttr); public: + /// return the libxml namespace corresponding to m_pNamespace on pNode + xmlNsPtr GetNamespace(xmlNodePtr const pNode); + + virtual bool IsChildTypeAllowed(NodeType const nodeType); + /** Returns the name of this attribute. */ @@ -122,10 +139,7 @@ namespace DOM return CNode::getLastChild(); } virtual OUString SAL_CALL getNamespaceURI() - throw (RuntimeException) - { - return CNode::getNamespaceURI(); - } + throw (RuntimeException); virtual Reference< XNode > SAL_CALL getNextSibling() throw (RuntimeException) { @@ -147,10 +161,7 @@ namespace DOM return CNode::getParentNode(); } virtual OUString SAL_CALL getPrefix() - throw (RuntimeException) - { - return CNode::getPrefix(); - } + throw (RuntimeException); virtual Reference< XNode > SAL_CALL getPreviousSibling() throw (RuntimeException) { @@ -199,10 +210,7 @@ namespace DOM return setValue(nodeValue); } virtual void SAL_CALL setPrefix(const OUString& prefix) - throw (RuntimeException, DOMException) - { - return CNode::setPrefix(prefix); - } + throw (RuntimeException, DOMException); }; } diff --git a/unoxml/source/dom/attributesmap.cxx b/unoxml/source/dom/attributesmap.cxx index c411365cf1b0..3cec81767d9e 100644 --- a/unoxml/source/dom/attributesmap.cxx +++ b/unoxml/source/dom/attributesmap.cxx @@ -25,13 +25,20 @@ * ************************************************************************/ -#include "attributesmap.hxx" +#include <attributesmap.hxx> + #include <string.h> +#include <element.hxx> +#include <document.hxx> + + namespace DOM { - CAttributesMap::CAttributesMap(const CElement* aElement) - : m_pElement(aElement) + CAttributesMap::CAttributesMap(::rtl::Reference<CElement> const& pElement, + ::osl::Mutex & rMutex) + : m_pElement(pElement) + , m_rMutex(rMutex) { } @@ -40,8 +47,10 @@ namespace DOM */ sal_Int32 SAL_CALL CAttributesMap::getLength() throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + sal_Int32 count = 0; - xmlNodePtr pNode = m_pElement->m_aNodePtr; + xmlNodePtr pNode = m_pElement->GetNodePtr(); if (pNode != NULL) { xmlAttrPtr cur = pNode->properties; @@ -52,16 +61,18 @@ namespace DOM } } return count; - } /** Retrieves a node specified by local name */ - Reference< XNode > SAL_CALL CAttributesMap::getNamedItem(const OUString& name) throw (RuntimeException) + Reference< XNode > SAL_CALL + CAttributesMap::getNamedItem(OUString const& name) throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + Reference< XNode > aNode; - xmlNodePtr pNode = m_pElement->m_aNodePtr; + xmlNodePtr pNode = m_pElement->GetNodePtr(); if (pNode != NULL) { OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8); @@ -71,7 +82,9 @@ namespace DOM { if( strcmp((char*)xName, (char*)cur->name) == 0) { - aNode = Reference< XNode >(static_cast<CNode*>(CNode::get((xmlNodePtr)cur))); + aNode = Reference< XNode >( + m_pElement->GetOwnerDocument().GetCNode( + reinterpret_cast<xmlNodePtr>(cur)).get() ); break; } cur = cur->next; @@ -83,24 +96,32 @@ namespace DOM /** Retrieves a node specified by local name and namespace URI. */ - Reference< XNode > SAL_CALL CAttributesMap::getNamedItemNS(const OUString& namespaceURI,const OUString& localName) throw (RuntimeException) + Reference< XNode > SAL_CALL + CAttributesMap::getNamedItemNS( + OUString const& namespaceURI, OUString const& localName) + throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + Reference< XNode > aNode; - xmlNodePtr pNode = m_pElement->m_aNodePtr; + xmlNodePtr pNode = m_pElement->GetNodePtr(); if (pNode != NULL) { OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8); xmlChar* xName = (xmlChar*)o1.getStr(); OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8); - xmlChar* xNs = (xmlChar*)o1.getStr(); - xmlNsPtr pNs = xmlSearchNs(pNode->doc, pNode, xNs); + xmlChar const*const xNs = + reinterpret_cast<xmlChar const*>(o2.getStr()); + xmlNsPtr const pNs = xmlSearchNsByHref(pNode->doc, pNode, xNs); xmlAttrPtr cur = pNode->properties; while (cur != NULL && pNs != NULL) { if( strcmp((char*)xName, (char*)cur->name) == 0 && cur->ns == pNs) { - aNode = Reference< XNode >(static_cast< CNode* >(CNode::get((xmlNodePtr)cur))); + aNode = Reference< XNode >( + m_pElement->GetOwnerDocument().GetCNode( + reinterpret_cast<xmlNodePtr>(cur)).get() ); break; } cur = cur->next; @@ -112,10 +133,13 @@ namespace DOM /** Returns the indexth item in the map. */ - Reference< XNode > SAL_CALL CAttributesMap::item(sal_Int32 index) throw (RuntimeException) + Reference< XNode > SAL_CALL + CAttributesMap::item(sal_Int32 index) throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + Reference< XNode > aNode; - xmlNodePtr pNode = m_pElement->m_aNodePtr; + xmlNodePtr pNode = m_pElement->GetNodePtr(); if (pNode != NULL) { xmlAttrPtr cur = pNode->properties; @@ -124,7 +148,9 @@ namespace DOM { if (count == index) { - aNode = Reference< XNode >(static_cast< CNode* >(CNode::get((xmlNodePtr)cur))); + aNode = Reference< XNode >( + m_pElement->GetOwnerDocument().GetCNode( + reinterpret_cast<xmlNodePtr>(cur)).get() ); break; } count++; @@ -132,80 +158,87 @@ namespace DOM } } return aNode; - } /** Removes a node specified by name. */ - Reference< XNode > SAL_CALL CAttributesMap::removeNamedItem(const OUString& name) throw (RuntimeException) + Reference< XNode > SAL_CALL + CAttributesMap::removeNamedItem(OUString const& name) + throw (RuntimeException) { - Reference< XNode > aNode; - xmlNodePtr pNode = m_pElement->m_aNodePtr; - if (pNode != NULL) - { - OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8); - xmlChar* xName = (xmlChar*)o1.getStr(); - xmlAttrPtr cur = pNode->properties; - while (cur != NULL) - { - if( strcmp((char*)xName, (char*)cur->name) == 0) - { - aNode = Reference< XNode >(static_cast< CNode* >(CNode::get((xmlNodePtr)cur))); - xmlUnlinkNode((xmlNodePtr)cur); - break; - } - cur = cur->next; - } + // no MutexGuard needed: m_pElement is const + Reference< XAttr > const xAttr(m_pElement->getAttributeNode(name)); + if (!xAttr.is()) { + throw DOMException(OUString(RTL_CONSTASCII_USTRINGPARAM( + "CAttributesMap::removeNamedItem: no such attribute")), + static_cast<OWeakObject*>(this), + DOMExceptionType_NOT_FOUND_ERR); } - return aNode; + Reference< XNode > const xRet( + m_pElement->removeAttributeNode(xAttr), UNO_QUERY); + return xRet; } /** // Removes a node specified by local name and namespace URI. */ - Reference< XNode > SAL_CALL CAttributesMap::removeNamedItemNS(const OUString& namespaceURI, const OUString& localName) throw (RuntimeException) + Reference< XNode > SAL_CALL + CAttributesMap::removeNamedItemNS( + OUString const& namespaceURI, OUString const& localName) + throw (RuntimeException) { - Reference< XNode > aNode; - xmlNodePtr pNode = m_pElement->m_aNodePtr; - if (pNode != NULL) - { - OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8); - xmlChar* xName = (xmlChar*)o1.getStr(); - OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8); - xmlChar* xNs = (xmlChar*)o1.getStr(); - xmlNsPtr pNs = xmlSearchNs(pNode->doc, pNode, xNs); - xmlAttrPtr cur = pNode->properties; - while (cur != NULL && pNs != NULL) - { - if( strcmp((char*)xName, (char*)cur->name) == 0 && - cur->ns == pNs) - { - aNode = Reference< XNode >(static_cast< CNode* >(CNode::get((xmlNodePtr)cur))); - xmlUnlinkNode((xmlNodePtr)cur); - break; - } - cur = cur->next; - } + // no MutexGuard needed: m_pElement is const + Reference< XAttr > const xAttr( + m_pElement->getAttributeNodeNS(namespaceURI, localName)); + if (!xAttr.is()) { + throw DOMException(OUString(RTL_CONSTASCII_USTRINGPARAM( + "CAttributesMap::removeNamedItemNS: no such attribute")), + static_cast<OWeakObject*>(this), + DOMExceptionType_NOT_FOUND_ERR); } - return aNode; + Reference< XNode > const xRet( + m_pElement->removeAttributeNode(xAttr), UNO_QUERY); + return xRet; } /** // Adds a node using its nodeName attribute. */ - Reference< XNode > SAL_CALL CAttributesMap::setNamedItem(const Reference< XNode >& arg) throw (RuntimeException) + Reference< XNode > SAL_CALL + CAttributesMap::setNamedItem(Reference< XNode > const& xNode) + throw (RuntimeException) { - return arg; - // return Reference< XNode >(); + Reference< XAttr > const xAttr(xNode, UNO_QUERY); + if (!xNode.is()) { + throw DOMException(OUString(RTL_CONSTASCII_USTRINGPARAM( + "CAttributesMap::setNamedItem: XAttr argument expected")), + static_cast<OWeakObject*>(this), + DOMExceptionType_HIERARCHY_REQUEST_ERR); + } + // no MutexGuard needed: m_pElement is const + Reference< XNode > const xRet( + m_pElement->setAttributeNode(xAttr), UNO_QUERY); + return xRet; } /** Adds a node using its namespaceURI and localName. */ - Reference< XNode > SAL_CALL CAttributesMap::setNamedItemNS(const Reference< XNode >& arg) throw (RuntimeException) + Reference< XNode > SAL_CALL + CAttributesMap::setNamedItemNS(Reference< XNode > const& xNode) + throw (RuntimeException) { - return arg; - // return Reference< XNode >(); + Reference< XAttr > const xAttr(xNode, UNO_QUERY); + if (!xNode.is()) { + throw DOMException(OUString(RTL_CONSTASCII_USTRINGPARAM( + "CAttributesMap::setNamedItemNS: XAttr argument expected")), + static_cast<OWeakObject*>(this), + DOMExceptionType_HIERARCHY_REQUEST_ERR); + } + // no MutexGuard needed: m_pElement is const + Reference< XNode > const xRet( + m_pElement->setAttributeNodeNS(xAttr), UNO_QUERY); + return xRet; } } diff --git a/unoxml/source/dom/attributesmap.hxx b/unoxml/source/dom/attributesmap.hxx index d19b517251a0..b987349c9194 100644 --- a/unoxml/source/dom/attributesmap.hxx +++ b/unoxml/source/dom/attributesmap.hxx @@ -25,19 +25,18 @@ * ************************************************************************/ -#ifndef _ATTRIBUTESMAP_HXX -#define _ATTRIBUTESMAP_HXX +#ifndef DOM_ATTRIBUTESMAP_HXX +#define DOM_ATTRIBUTESMAP_HXX -#include <map> #include <sal/types.h> -#include <cppuhelper/implbase1.hxx> +#include <rtl/ref.hxx> + #include <com/sun/star/uno/Reference.h> -#include <com/sun/star/uno/Exception.hpp> #include <com/sun/star/xml/dom/XNode.hpp> #include <com/sun/star/xml/dom/XNamedNodeMap.hpp> -#include "node.hxx" -#include "element.hxx" -#include "attr.hxx" + +#include <cppuhelper/implbase1.hxx> + using ::rtl::OUString; using namespace com::sun::star::uno; @@ -45,12 +44,18 @@ using namespace com::sun::star::xml::dom; namespace DOM { - class CAttributesMap : public cppu::WeakImplHelper1< XNamedNodeMap > + class CElement; + + class CAttributesMap + : public cppu::WeakImplHelper1< XNamedNodeMap > { private: - const CElement* m_pElement; + ::rtl::Reference<CElement> const m_pElement; + ::osl::Mutex & m_rMutex; + public: - CAttributesMap(const CElement* aDocType); + CAttributesMap(::rtl::Reference<CElement> const& pElement, + ::osl::Mutex & rMutex); /** The number of nodes in this map. @@ -60,37 +65,49 @@ namespace DOM /** Retrieves a node specified by local name */ - virtual Reference< XNode > SAL_CALL getNamedItem(const OUString& name) throw (RuntimeException); + virtual Reference< XNode > SAL_CALL getNamedItem(OUString const& name) + throw (RuntimeException); /** Retrieves a node specified by local name and namespace URI. */ - virtual Reference< XNode > SAL_CALL getNamedItemNS(const OUString& namespaceURI, const OUString& localName) throw (RuntimeException); + virtual Reference< XNode > SAL_CALL getNamedItemNS( + OUString const& namespaceURI, OUString const& localName) + throw (RuntimeException); /** Returns the indexth item in the map. */ - virtual Reference< XNode > SAL_CALL item(sal_Int32 index) throw (RuntimeException); + virtual Reference< XNode > SAL_CALL item(sal_Int32 index) + throw (RuntimeException); /** Removes a node specified by name. */ - virtual Reference< XNode > SAL_CALL removeNamedItem(const OUString& name) throw (RuntimeException); + virtual Reference< XNode > SAL_CALL + removeNamedItem(OUString const& name) + throw (RuntimeException); /** // Removes a node specified by local name and namespace URI. */ - virtual Reference< XNode > SAL_CALL removeNamedItemNS(const OUString& namespaceURI, const OUString& localName) throw (RuntimeException); + virtual Reference< XNode > SAL_CALL removeNamedItemNS( + OUString const& namespaceURI, OUString const& localName) + throw (RuntimeException); /** // Adds a node using its nodeName attribute. */ - virtual Reference< XNode > SAL_CALL setNamedItem(const Reference< XNode >& arg) throw (RuntimeException); + virtual Reference< XNode > SAL_CALL + setNamedItem(Reference< XNode > const& arg) + throw (RuntimeException); /** Adds a node using its namespaceURI and localName. */ - virtual Reference< XNode > SAL_CALL setNamedItemNS(const Reference< XNode >& arg) throw (RuntimeException); + virtual Reference< XNode > SAL_CALL + setNamedItemNS(Reference< XNode > const& arg) + throw (RuntimeException); }; } diff --git a/unoxml/source/dom/cdatasection.cxx b/unoxml/source/dom/cdatasection.cxx index 7c775484770c..6f8035a793b3 100644 --- a/unoxml/source/dom/cdatasection.cxx +++ b/unoxml/source/dom/cdatasection.cxx @@ -25,20 +25,22 @@ * ************************************************************************/ -#include "cdatasection.hxx" +#include <cdatasection.hxx> #include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp> namespace DOM { - CCDATASection::CCDATASection(const xmlNodePtr aNodePtr) + CCDATASection::CCDATASection( + CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlNodePtr const pNode) + : CCDATASection_Base(rDocument, rMutex, + NodeType_CDATA_SECTION_NODE, pNode) { - m_aNodeType = NodeType_CDATA_SECTION_NODE; - init_text(aNodePtr); } - void SAL_CALL CCDATASection::saxify( - const Reference< XDocumentHandler >& i_xHandler) { + void CCDATASection::saxify(const Reference< XDocumentHandler >& i_xHandler) + { if (!i_xHandler.is()) throw RuntimeException(); Reference< XExtendedDocumentHandler > xExtended(i_xHandler, UNO_QUERY); if (xExtended.is()) { diff --git a/unoxml/source/dom/cdatasection.hxx b/unoxml/source/dom/cdatasection.hxx index 400b2a6a02d3..d809ef7e7f76 100644 --- a/unoxml/source/dom/cdatasection.hxx +++ b/unoxml/source/dom/cdatasection.hxx @@ -25,14 +25,14 @@ * ************************************************************************/ -#ifndef _CDATASECTION_HXX -#define _CDATASECTION_HXX +#ifndef DOM_CDATASECTION_HXX +#define DOM_CDATASECTION_HXX #include <com/sun/star/uno/Reference.h> -#include <com/sun/star/uno/Exception.hpp> #include <com/sun/star/xml/dom/XCDATASection.hpp> -#include "text.hxx" +#include <text.hxx> + using ::rtl::OUString; using namespace com::sun::star::uno; @@ -40,16 +40,21 @@ using namespace com::sun::star::xml::dom; namespace DOM { - class CCDATASection : public cppu::ImplInheritanceHelper1< CText, XCDATASection > + typedef ::cppu::ImplInheritanceHelper1< CText, XCDATASection > + CCDATASection_Base; + + class CCDATASection + : public CCDATASection_Base { - friend class CNode; + friend class CDocument; + protected: - CCDATASection(const xmlNodePtr aNodePtr); + CCDATASection(CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlNodePtr const pNode); public: - virtual void SAL_CALL saxify( - const Reference< XDocumentHandler >& i_xHandler); + virtual void saxify(const Reference< XDocumentHandler >& i_xHandler); virtual Reference< XText > SAL_CALL splitText(sal_Int32 offset) throw (RuntimeException) @@ -215,7 +220,7 @@ namespace DOM virtual void SAL_CALL setNodeValue(const OUString& nodeValue) throw (RuntimeException, DOMException) { - return CNode::setNodeValue(nodeValue); + return CText::setNodeValue(nodeValue); } virtual void SAL_CALL setPrefix(const OUString& prefix) throw (RuntimeException, DOMException) diff --git a/unoxml/source/dom/characterdata.cxx b/unoxml/source/dom/characterdata.cxx index 8a8407678272..6cd3d9f2c1d5 100644 --- a/unoxml/source/dom/characterdata.cxx +++ b/unoxml/source/dom/characterdata.cxx @@ -25,18 +25,29 @@ * ************************************************************************/ +#include <characterdata.hxx> + +#include <string.h> + +#include <boost/shared_ptr.hpp> + #include <com/sun/star/xml/dom/events/XDocumentEvent.hpp> -#include "characterdata.hxx" + #include "../events/mutationevent.hxx" -#include <string.h> + namespace DOM { - CCharacterData::CCharacterData() - {} + CCharacterData::CCharacterData( + CDocument const& rDocument, ::osl::Mutex const& rMutex, + NodeType const& reNodeType, xmlNodePtr const& rpNode) + : CCharacterData_Base(rDocument, rMutex, reNodeType, rpNode) + { + } - void CCharacterData::_dispatchEvent(const OUString& prevValue, const OUString& newValue) + void CCharacterData::dispatchEvent_Impl( + OUString const& prevValue, OUString const& newValue) { Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY); Reference< XMutationEvent > event(docevent->createEvent( @@ -49,23 +60,22 @@ namespace DOM dispatchSubtreeModified(); } - void CCharacterData::init_characterdata(const xmlNodePtr aNodePtr) - { - init_node(aNodePtr); - } - /** Append the string to the end of the character data of the node. */ void SAL_CALL CCharacterData::appendData(const OUString& arg) throw (RuntimeException, DOMException) { + ::osl::ClearableMutexGuard guard(m_rMutex); + if (m_aNodePtr != NULL) { OUString oldValue((char*)m_aNodePtr->content, strlen((char*)m_aNodePtr->content), RTL_TEXTENCODING_UTF8); xmlNodeAddContent(m_aNodePtr, (const xmlChar*)(OUStringToOString(arg, RTL_TEXTENCODING_UTF8).getStr())); OUString newValue((char*)m_aNodePtr->content, strlen((char*)m_aNodePtr->content), RTL_TEXTENCODING_UTF8); - _dispatchEvent(oldValue, newValue); + + guard.clear(); // release mutex before calling event handlers + dispatchEvent_Impl(oldValue, newValue); } } @@ -75,10 +85,14 @@ namespace DOM void SAL_CALL CCharacterData::deleteData(sal_Int32 offset, sal_Int32 count) throw (RuntimeException, DOMException) { + ::osl::ClearableMutexGuard guard(m_rMutex); + if (m_aNodePtr != NULL) { // get current data - OString aData((const sal_Char*)xmlNodeGetContent(m_aNodePtr)); + ::boost::shared_ptr<xmlChar const> const pContent( + xmlNodeGetContent(m_aNodePtr), xmlFree); + OString aData(reinterpret_cast<sal_Char const*>(pContent.get())); OUString tmp(aData, aData.getLength(), RTL_TEXTENCODING_UTF8); if (offset > tmp.getLength() || offset < 0 || count < 0) { DOMException e; @@ -93,8 +107,9 @@ namespace DOM OUString oldValue((char*)m_aNodePtr->content, strlen((char*)m_aNodePtr->content), RTL_TEXTENCODING_UTF8); xmlNodeSetContent(m_aNodePtr, (const xmlChar*)(OUStringToOString(tmp2, RTL_TEXTENCODING_UTF8).getStr())); OUString newValue((char*)m_aNodePtr->content, strlen((char*)m_aNodePtr->content), RTL_TEXTENCODING_UTF8); - _dispatchEvent(oldValue, newValue); + guard.clear(); // release mutex before calling event handlers + dispatchEvent_Impl(oldValue, newValue); } } @@ -104,6 +119,8 @@ namespace DOM */ OUString SAL_CALL CCharacterData::getData() throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + OUString aData; if (m_aNodePtr != NULL) { @@ -120,8 +137,10 @@ namespace DOM The number of 16-bit units that are available through data and the substringData method below. */ - sal_Int32 CCharacterData::getLength() throw (RuntimeException) + sal_Int32 SAL_CALL CCharacterData::getLength() throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + sal_Int32 length = 0; if (m_aNodePtr != NULL) { @@ -137,10 +156,14 @@ namespace DOM void SAL_CALL CCharacterData::insertData(sal_Int32 offset, const OUString& arg) throw (RuntimeException, DOMException) { + ::osl::ClearableMutexGuard guard(m_rMutex); + if (m_aNodePtr != NULL) { // get current data - OString aData((const sal_Char*)xmlNodeGetContent(m_aNodePtr)); + ::boost::shared_ptr<xmlChar const> const pContent( + xmlNodeGetContent(m_aNodePtr), xmlFree); + OString aData(reinterpret_cast<sal_Char const*>(pContent.get())); OUString tmp(aData, aData.getLength(), RTL_TEXTENCODING_UTF8); if (offset > tmp.getLength() || offset < 0) { DOMException e; @@ -154,8 +177,9 @@ namespace DOM OUString oldValue((char*)m_aNodePtr->content, strlen((char*)m_aNodePtr->content), RTL_TEXTENCODING_UTF8); xmlNodeSetContent(m_aNodePtr, (const xmlChar*)(OUStringToOString(tmp2, RTL_TEXTENCODING_UTF8).getStr())); OUString newValue((char*)m_aNodePtr->content, strlen((char*)m_aNodePtr->content), RTL_TEXTENCODING_UTF8); - _dispatchEvent(oldValue, newValue); + guard.clear(); // release mutex before calling event handlers + dispatchEvent_Impl(oldValue, newValue); } } @@ -167,10 +191,14 @@ namespace DOM void SAL_CALL CCharacterData::replaceData(sal_Int32 offset, sal_Int32 count, const OUString& arg) throw (RuntimeException, DOMException) { + ::osl::ClearableMutexGuard guard(m_rMutex); + if (m_aNodePtr != NULL) { // get current data - OString aData((const sal_Char*)xmlNodeGetContent(m_aNodePtr)); + ::boost::shared_ptr<xmlChar const> const pContent( + xmlNodeGetContent(m_aNodePtr), xmlFree); + OString aData(reinterpret_cast<sal_Char const*>(pContent.get())); OUString tmp(aData, aData.getLength(), RTL_TEXTENCODING_UTF8); if (offset > tmp.getLength() || offset < 0 || count < 0){ DOMException e; @@ -186,7 +214,9 @@ namespace DOM OUString oldValue((char*)m_aNodePtr->content, strlen((char*)m_aNodePtr->content), RTL_TEXTENCODING_UTF8); xmlNodeSetContent(m_aNodePtr, (const xmlChar*)(OUStringToOString(tmp2, RTL_TEXTENCODING_UTF8).getStr())); OUString newValue((char*)m_aNodePtr->content, strlen((char*)m_aNodePtr->content), RTL_TEXTENCODING_UTF8); - _dispatchEvent(oldValue, newValue); + + guard.clear(); // release mutex before calling event handlers + dispatchEvent_Impl(oldValue, newValue); } } @@ -196,13 +226,16 @@ namespace DOM void SAL_CALL CCharacterData::setData(const OUString& data) throw (RuntimeException, DOMException) { + ::osl::ClearableMutexGuard guard(m_rMutex); + if (m_aNodePtr != NULL) { OUString oldValue((char*)m_aNodePtr->content, strlen((char*)m_aNodePtr->content), RTL_TEXTENCODING_UTF8); xmlNodeSetContent(m_aNodePtr, (const xmlChar*)(OUStringToOString(data, RTL_TEXTENCODING_UTF8).getStr())); OUString newValue((char*)m_aNodePtr->content, strlen((char*)m_aNodePtr->content), RTL_TEXTENCODING_UTF8); - _dispatchEvent(oldValue, newValue); + guard.clear(); // release mutex before calling event handlers + dispatchEvent_Impl(oldValue, newValue); } } @@ -212,11 +245,15 @@ namespace DOM OUString SAL_CALL CCharacterData::subStringData(sal_Int32 offset, sal_Int32 count) throw (RuntimeException, DOMException) { + ::osl::MutexGuard const g(m_rMutex); + OUString aStr; if (m_aNodePtr != NULL) { // get current data - OString aData((const sal_Char*)xmlNodeGetContent(m_aNodePtr)); + ::boost::shared_ptr<xmlChar const> const pContent( + xmlNodeGetContent(m_aNodePtr), xmlFree); + OString aData(reinterpret_cast<sal_Char const*>(pContent.get())); OUString tmp(aData, aData.getLength(), RTL_TEXTENCODING_UTF8); if (offset > tmp.getLength() || offset < 0 || count < 0) { DOMException e; diff --git a/unoxml/source/dom/characterdata.hxx b/unoxml/source/dom/characterdata.hxx index 4ff1da570f7c..9639108f1e85 100644 --- a/unoxml/source/dom/characterdata.hxx +++ b/unoxml/source/dom/characterdata.hxx @@ -25,19 +25,21 @@ * ************************************************************************/ -#ifndef _CHARACTERDATA_HXX -#define _CHARACTERDATA_HXX +#ifndef DOM_CHARACTERDATA_HXX +#define DOM_CHARACTERDATA_HXX + +#include <libxml/tree.h> #include <sal/types.h> + #include <cppuhelper/implbase1.hxx> + #include <com/sun/star/uno/Reference.h> -#include <com/sun/star/uno/Exception.hpp> #include <com/sun/star/xml/dom/XNode.hpp> #include <com/sun/star/xml/dom/XCharacterData.hpp> -#include <com/sun/star/xml/dom/XElement.hpp> -#include <com/sun/star/xml/dom/XDOMImplementation.hpp> -#include <libxml/tree.h> -#include "node.hxx" + +#include <node.hxx> + using ::rtl::OUString; using namespace com::sun::star::uno; @@ -45,14 +47,19 @@ using namespace com::sun::star::xml::dom; namespace DOM { - class CCharacterData : public cppu::ImplInheritanceHelper1< CNode, XCharacterData > - { + typedef ::cppu::ImplInheritanceHelper1< CNode, XCharacterData > + CCharacterData_Base; + class CCharacterData + : public CCharacterData_Base + { protected: - CCharacterData(); - void init_characterdata(const xmlNodePtr aNodePtr); - void _dispatchEvent(const OUString& prevValue, const OUString& newValue); + CCharacterData(CDocument const& rDocument, ::osl::Mutex const& rMutex, + NodeType const& reNodeType, xmlNodePtr const& rpNode); + + void dispatchEvent_Impl( + OUString const& prevValue, OUString const& newValue); public: /** diff --git a/unoxml/source/dom/childlist.cxx b/unoxml/source/dom/childlist.cxx index aaa6e157225d..3c80c664204e 100644 --- a/unoxml/source/dom/childlist.cxx +++ b/unoxml/source/dom/childlist.cxx @@ -25,11 +25,20 @@ * ************************************************************************/ -#include "childlist.hxx" +#include <childlist.hxx> + +#include <libxml/tree.h> + +#include <node.hxx> +#include <document.hxx> + + namespace DOM { - CChildList::CChildList(const CNode* base) - : m_pNode(base->m_aNodePtr) + CChildList::CChildList(::rtl::Reference<CNode> const& pBase, + ::osl::Mutex & rMutex) + : m_pNode(pBase) + , m_rMutex(rMutex) { } @@ -38,10 +47,15 @@ namespace DOM */ sal_Int32 SAL_CALL CChildList::getLength() throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + sal_Int32 length = 0; if (m_pNode != NULL) { - xmlNodePtr cur = m_pNode->children; + xmlNodePtr cur = m_pNode->GetNodePtr(); + if (0 != cur) { + cur = cur->children; + } while (cur != NULL) { length++; @@ -54,19 +68,26 @@ namespace DOM /** Returns the indexth item in the collection. */ - Reference< XNode > SAL_CALL CChildList::item(sal_Int32 index) throw (RuntimeException) + Reference< XNode > SAL_CALL CChildList::item(sal_Int32 index) + throw (RuntimeException) { - Reference< XNode >aNode; + ::osl::MutexGuard const g(m_rMutex); + if (m_pNode != NULL) { - xmlNodePtr cur = m_pNode->children; + xmlNodePtr cur = m_pNode->GetNodePtr(); + if (0 != cur) { + cur = cur->children; + } while (cur != NULL) { - if (index-- == 0) - aNode = Reference< XNode >(CNode::get(cur)); + if (index-- == 0) { + return Reference< XNode >( + m_pNode->GetOwnerDocument().GetCNode(cur).get()); + } cur = cur->next; } } - return aNode; + return 0; } } diff --git a/unoxml/source/dom/childlist.hxx b/unoxml/source/dom/childlist.hxx index 89b73ff2e113..f23617e49806 100644 --- a/unoxml/source/dom/childlist.hxx +++ b/unoxml/source/dom/childlist.hxx @@ -25,18 +25,18 @@ * ************************************************************************/ -#ifndef _CHILDLIST_HXX -#define _CHILDLIST_HXX +#ifndef DOM_CHILDLIST_HXX +#define DOM_CHILDLIST_HXX -#include <map> #include <sal/types.h> -#include <cppuhelper/implbase1.hxx> +#include <rtl/ref.hxx> + #include <com/sun/star/uno/Reference.h> -#include <com/sun/star/uno/Exception.hpp> #include <com/sun/star/xml/dom/XNode.hpp> #include <com/sun/star/xml/dom/XNodeList.hpp> -#include "node.hxx" -#include "libxml/tree.h" + +#include <cppuhelper/implbase1.hxx> + using ::rtl::OUString; using namespace com::sun::star::uno; @@ -44,12 +44,19 @@ using namespace com::sun::star::xml::dom; namespace DOM { - class CChildList : public cppu::WeakImplHelper1< XNodeList > + class CNode; + + class CChildList + : public cppu::WeakImplHelper1< XNodeList > { private: - const xmlNodePtr m_pNode; + ::rtl::Reference<CNode> const m_pNode; + ::osl::Mutex & m_rMutex; + public: - CChildList(const CNode* base); + CChildList(::rtl::Reference<CNode> const& pBase, + ::osl::Mutex & rMutex); + /** The number of nodes in the list. */ @@ -57,7 +64,8 @@ namespace DOM /** Returns the indexth item in the collection. */ - virtual Reference< XNode > SAL_CALL item(sal_Int32 index) throw (RuntimeException); + virtual Reference< XNode > SAL_CALL item(sal_Int32 index) + throw (RuntimeException); }; } diff --git a/unoxml/source/dom/comment.cxx b/unoxml/source/dom/comment.cxx index f0f14a2d944a..d1ea6d83e3e9 100644 --- a/unoxml/source/dom/comment.cxx +++ b/unoxml/source/dom/comment.cxx @@ -25,19 +25,20 @@ * ************************************************************************/ -#include "comment.hxx" +#include <comment.hxx> #include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp> + namespace DOM { - CComment::CComment(const xmlNodePtr aNodePtr) + CComment::CComment(CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlNodePtr const pNode) + : CComment_Base(rDocument, rMutex, NodeType_COMMENT_NODE, pNode) { - m_aNodeType = NodeType_COMMENT_NODE; - init_node(aNodePtr); } - void SAL_CALL CComment::saxify( + void CComment::saxify( const Reference< XDocumentHandler >& i_xHandler) { if (!i_xHandler.is()) throw RuntimeException(); Reference< XExtendedDocumentHandler > xExtended(i_xHandler, UNO_QUERY); diff --git a/unoxml/source/dom/comment.hxx b/unoxml/source/dom/comment.hxx index 196c7460399e..0aed0cf6a09b 100644 --- a/unoxml/source/dom/comment.hxx +++ b/unoxml/source/dom/comment.hxx @@ -25,13 +25,14 @@ * ************************************************************************/ -#ifndef _COMMENT_HXX -#define _COMMENT_HXX +#ifndef DOM_COMMENT_HXX +#define DOM_COMMENT_HXX #include <com/sun/star/uno/Reference.h> -#include <com/sun/star/uno/Exception.hpp> #include <com/sun/star/xml/dom/XComment.hpp> -#include "characterdata.hxx" + +#include <characterdata.hxx> + using ::rtl::OUString; using namespace com::sun::star::uno; @@ -39,16 +40,22 @@ using namespace com::sun::star::xml::dom; namespace DOM { - class CComment : public cppu::ImplInheritanceHelper1< CCharacterData, XComment > + typedef ::cppu::ImplInheritanceHelper1< CCharacterData, XComment > + CComment_Base; + + class CComment + : public CComment_Base { - friend class CNode; + private: + friend class CDocument; + protected: - CComment(const xmlNodePtr aNodePtr); + CComment(CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlNodePtr const pNode); public: - virtual void SAL_CALL saxify( - const Reference< XDocumentHandler >& i_xHandler); + virtual void saxify(const Reference< XDocumentHandler >& i_xHandler); // --- delegations for XCharacterData virtual void SAL_CALL appendData(const OUString& arg) diff --git a/unoxml/source/dom/document.cxx b/unoxml/source/dom/document.cxx index fcd43832adf0..14d72555157a 100644 --- a/unoxml/source/dom/document.cxx +++ b/unoxml/source/dom/document.cxx @@ -40,11 +40,14 @@ #include "documenttype.hxx" #include "elementlist.hxx" #include "domimplementation.hxx" +#include <entity.hxx> +#include <notation.hxx> #include "../events/event.hxx" #include "../events/mutationevent.hxx" #include "../events/uievent.hxx" #include "../events/mouseevent.hxx" +#include "../events/eventdispatcher.hxx" #include <string.h> @@ -53,52 +56,287 @@ namespace DOM { + static xmlNodePtr lcl_getDocumentType(xmlDocPtr const i_pDocument) + { + // find the doc type + xmlNodePtr cur = i_pDocument->children; + while (cur != NULL) + { + if ((cur->type == XML_DOCUMENT_TYPE_NODE) || + (cur->type == XML_DTD_NODE)) { + return cur; + } + } + return 0; + } + + /// get the pointer to the root element node of the document + static xmlNodePtr lcl_getDocumentRootPtr(xmlDocPtr const i_pDocument) + { + // find the document element + xmlNodePtr cur = i_pDocument->children; + while (cur != NULL) + { + if (cur->type == XML_ELEMENT_NODE) + break; + cur = cur->next; + } + return cur; + } + + CDocument::CDocument(xmlDocPtr const pDoc) + : CDocument_Base(*this, m_Mutex, + NodeType_DOCUMENT_NODE, reinterpret_cast<xmlNodePtr>(pDoc)) + , m_aDocPtr(pDoc) + , m_streamListeners() + , m_pEventDispatcher(new events::CEventDispatcher()) + { + } + + ::rtl::Reference<CDocument> CDocument::CreateCDocument(xmlDocPtr const pDoc) + { + ::rtl::Reference<CDocument> const xDoc(new CDocument(pDoc)); + // add the doc itself to its nodemap! + xDoc->m_NodeMap.insert( + nodemap_t::value_type(reinterpret_cast<xmlNodePtr>(pDoc), + ::std::make_pair( + WeakReference<XNode>(static_cast<XDocument*>(xDoc.get())), + xDoc.get()))); + return xDoc; + } + CDocument::~CDocument() { + ::osl::MutexGuard const g(m_Mutex); +#ifdef DBG_UTIL + // node map must be empty now, otherwise CDocument must not die! + for (nodemap_t::iterator i = m_NodeMap.begin(); + i != m_NodeMap.end(); ++i) + { + Reference<XNode> const xNode(i->second.first); + OSL_ENSURE(!xNode.is(), + "CDocument::~CDocument(): ERROR: live node in document node map!"); + } +#endif xmlFreeDoc(m_aDocPtr); } - CDocument::CDocument(xmlDocPtr aDocPtr): - m_aDocPtr(aDocPtr), - m_streamListeners() + + events::CEventDispatcher & CDocument::GetEventDispatcher() { - // init node base - m_aNodeType = NodeType_DOCUMENT_NODE; - init_node((xmlNodePtr)m_aDocPtr); + return *m_pEventDispatcher; } - void SAL_CALL CDocument::saxify( - const Reference< XDocumentHandler >& i_xHandler) { + ::rtl::Reference< CElement > CDocument::GetDocumentElement() + { + xmlNodePtr const pNode = lcl_getDocumentRootPtr(m_aDocPtr); + ::rtl::Reference< CElement > const xRet( + dynamic_cast<CElement*>(GetCNode(pNode).get())); + return xRet; + } + + void + CDocument::RemoveCNode(xmlNodePtr const pNode, CNode const*const pCNode) + { + nodemap_t::iterator const i = m_NodeMap.find(pNode); + if (i != m_NodeMap.end()) { + // #i113681# consider this scenario: + // T1 calls ~CNode + // T2 calls getCNode: lookup will find i->second->first invalid + // so a new CNode is created and inserted + // T1 calls removeCNode: i->second->second now points to a + // different CNode instance! + // + // check that the CNode is the right one + CNode *const pCurrent = i->second.second; + if (pCurrent == pCNode) { + m_NodeMap.erase(i); + } + } + } + + /** NB: this is the CNode factory. + it is the only place where CNodes may be instantiated. + all CNodes must be registered at the m_NodeMap. + */ + ::rtl::Reference<CNode> + CDocument::GetCNode(xmlNodePtr const pNode, bool const bCreate) + { + if (0 == pNode) { + return 0; + } + //check whether there is already an instance for this node + nodemap_t::const_iterator const i = m_NodeMap.find(pNode); + if (i != m_NodeMap.end()) { + // #i113681# check that the CNode is still alive + uno::Reference<XNode> const xNode(i->second.first); + if (xNode.is()) + { + ::rtl::Reference<CNode> ret(i->second.second); + OSL_ASSERT(ret.is()); + return ret; + } + } + + if (!bCreate) { return 0; } + + // there is not yet an instance wrapping this node, + // create it and store it in the map + + ::rtl::Reference<CNode> pCNode; + switch (pNode->type) + { + case XML_ELEMENT_NODE: + // m_aNodeType = NodeType::ELEMENT_NODE; + pCNode = static_cast< CNode* >( + new CElement(*this, m_Mutex, pNode)); + break; + case XML_TEXT_NODE: + // m_aNodeType = NodeType::TEXT_NODE; + pCNode = static_cast< CNode* >( + new CText(*this, m_Mutex, pNode)); + break; + case XML_CDATA_SECTION_NODE: + // m_aNodeType = NodeType::CDATA_SECTION_NODE; + pCNode = static_cast< CNode* >( + new CCDATASection(*this, m_Mutex, pNode)); + break; + case XML_ENTITY_REF_NODE: + // m_aNodeType = NodeType::ENTITY_REFERENCE_NODE; + pCNode = static_cast< CNode* >( + new CEntityReference(*this, m_Mutex, pNode)); + break; + case XML_ENTITY_NODE: + // m_aNodeType = NodeType::ENTITY_NODE; + pCNode = static_cast< CNode* >(new CEntity(*this, m_Mutex, + reinterpret_cast<xmlEntityPtr>(pNode))); + break; + case XML_PI_NODE: + // m_aNodeType = NodeType::PROCESSING_INSTRUCTION_NODE; + pCNode = static_cast< CNode* >( + new CProcessingInstruction(*this, m_Mutex, pNode)); + break; + case XML_COMMENT_NODE: + // m_aNodeType = NodeType::COMMENT_NODE; + pCNode = static_cast< CNode* >( + new CComment(*this, m_Mutex, pNode)); + break; + case XML_DOCUMENT_NODE: + // m_aNodeType = NodeType::DOCUMENT_NODE; + OSL_ENSURE(false, "CDocument::GetCNode is not supposed to" + " create a CDocument!!!"); + pCNode = static_cast< CNode* >(new CDocument( + reinterpret_cast<xmlDocPtr>(pNode))); + break; + case XML_DOCUMENT_TYPE_NODE: + case XML_DTD_NODE: + // m_aNodeType = NodeType::DOCUMENT_TYPE_NODE; + pCNode = static_cast< CNode* >(new CDocumentType(*this, m_Mutex, + reinterpret_cast<xmlDtdPtr>(pNode))); + break; + case XML_DOCUMENT_FRAG_NODE: + // m_aNodeType = NodeType::DOCUMENT_FRAGMENT_NODE; + pCNode = static_cast< CNode* >( + new CDocumentFragment(*this, m_Mutex, pNode)); + break; + case XML_NOTATION_NODE: + // m_aNodeType = NodeType::NOTATION_NODE; + pCNode = static_cast< CNode* >(new CNotation(*this, m_Mutex, + reinterpret_cast<xmlNotationPtr>(pNode))); + break; + case XML_ATTRIBUTE_NODE: + // m_aNodeType = NodeType::ATTRIBUTE_NODE; + pCNode = static_cast< CNode* >(new CAttr(*this, m_Mutex, + reinterpret_cast<xmlAttrPtr>(pNode))); + break; + // unsupported node types + case XML_HTML_DOCUMENT_NODE: + case XML_ELEMENT_DECL: + case XML_ATTRIBUTE_DECL: + case XML_ENTITY_DECL: + case XML_NAMESPACE_DECL: + default: + break; + } + + if (pCNode != 0) { + bool const bInserted = m_NodeMap.insert( + nodemap_t::value_type(pNode, + ::std::make_pair(WeakReference<XNode>(pCNode.get()), + pCNode.get())) + ).second; + OSL_ASSERT(bInserted); + if (!bInserted) { + // if insertion failed, delete new instance and return null + return 0; + } + } + + OSL_ENSURE(pCNode.is(), "no node produced during CDocument::GetCNode!"); + return pCNode; + } + + + CDocument & CDocument::GetOwnerDocument() + { + return *this; + } + + void CDocument::saxify(const Reference< XDocumentHandler >& i_xHandler) + { i_xHandler->startDocument(); for (xmlNodePtr pChild = m_aNodePtr->children; pChild != 0; pChild = pChild->next) { - CNode * pNode = CNode::get(pChild); + ::rtl::Reference<CNode> const pNode = GetCNode(pChild); OSL_ENSURE(pNode != 0, "CNode::get returned 0"); pNode->saxify(i_xHandler); } i_xHandler->endDocument(); } - void SAL_CALL CDocument::fastSaxify( Context& rContext ) { + void CDocument::fastSaxify( Context& rContext ) + { rContext.mxDocHandler->startDocument(); for (xmlNodePtr pChild = m_aNodePtr->children; pChild != 0; pChild = pChild->next) { - CNode * pNode = CNode::get(pChild); + ::rtl::Reference<CNode> const pNode = GetCNode(pChild); OSL_ENSURE(pNode != 0, "CNode::get returned 0"); pNode->fastSaxify(rContext); } rContext.mxDocHandler->endDocument(); } + bool CDocument::IsChildTypeAllowed(NodeType const nodeType) + { + switch (nodeType) { + case NodeType_PROCESSING_INSTRUCTION_NODE: + case NodeType_COMMENT_NODE: + return true; + case NodeType_ELEMENT_NODE: + // there may be only one! + return 0 == lcl_getDocumentRootPtr(m_aDocPtr); + case NodeType_DOCUMENT_TYPE_NODE: + // there may be only one! + return 0 == lcl_getDocumentType(m_aDocPtr); + default: + return false; + } + } + + void SAL_CALL CDocument::addListener(const Reference< XStreamListener >& aListener ) throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); + m_streamListeners.insert(aListener); } void SAL_CALL CDocument::removeListener(const Reference< XStreamListener >& aListener ) throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); + m_streamListeners.erase(aListener); } @@ -134,30 +372,42 @@ namespace DOM void SAL_CALL CDocument::start() throw (RuntimeException) { - if (! m_rOutputStream.is()) return; + listenerlist_t streamListeners; + { + ::osl::MutexGuard const g(m_Mutex); + + if (! m_rOutputStream.is()) { throw RuntimeException(); } + streamListeners = m_streamListeners; + } - // notify listners about start - listenerlist_t::const_iterator iter1 = m_streamListeners.begin(); - while (iter1 != m_streamListeners.end()) { + // notify listeners about start + listenerlist_t::const_iterator iter1 = streamListeners.begin(); + while (iter1 != streamListeners.end()) { Reference< XStreamListener > aListener = *iter1; aListener->started(); iter1++; } - // setup libxml IO and write data to output stream - IOContext ioctx = {m_rOutputStream, false}; - xmlOutputBufferPtr pOut = xmlOutputBufferCreateIO( - writeCallback, closeCallback, &ioctx, NULL); - xmlSaveFileTo(pOut, m_aNodePtr->doc, NULL); + { + ::osl::MutexGuard const g(m_Mutex); + + // check again! could have been reset... + if (! m_rOutputStream.is()) { throw RuntimeException(); } + + // setup libxml IO and write data to output stream + IOContext ioctx = {m_rOutputStream, false}; + xmlOutputBufferPtr pOut = xmlOutputBufferCreateIO( + writeCallback, closeCallback, &ioctx, NULL); + xmlSaveFileTo(pOut, m_aNodePtr->doc, NULL); + } // call listeners - listenerlist_t::const_iterator iter2 = m_streamListeners.begin(); - while (iter2 != m_streamListeners.end()) { + listenerlist_t::const_iterator iter2 = streamListeners.begin(); + while (iter2 != streamListeners.end()) { Reference< XStreamListener > aListener = *iter2; aListener->closed(); iter2++; } - } void SAL_CALL CDocument::terminate() @@ -169,11 +419,15 @@ namespace DOM void SAL_CALL CDocument::setOutputStream( const Reference< XOutputStream >& aStream ) throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); + m_rOutputStream = aStream; } Reference< XOutputStream > SAL_CALL CDocument::getOutputStream() throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); + return m_rOutputStream; } @@ -181,10 +435,16 @@ namespace DOM Reference< XAttr > SAL_CALL CDocument::createAttribute(const OUString& name) throw (RuntimeException, DOMException) { + ::osl::MutexGuard const g(m_Mutex); + OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8); xmlChar *xName = (xmlChar*)o1.getStr(); - return Reference< XAttr >(static_cast< CAttr* >( - CNode::get((xmlNodePtr)xmlNewDocProp(m_aDocPtr, xName, NULL)))); + xmlAttrPtr const pAttr = xmlNewDocProp(m_aDocPtr, xName, NULL); + ::rtl::Reference< CAttr > const pCAttr( + dynamic_cast< CAttr* >(GetCNode( + reinterpret_cast<xmlNodePtr>(pAttr)).get())); + pCAttr->m_bUnlinked = true; + return pCAttr.get(); }; // Creates an attribute of the given qualified name and namespace URI. @@ -192,73 +452,96 @@ namespace DOM const OUString& ns, const OUString& qname) throw (RuntimeException, DOMException) { + ::osl::MutexGuard const g(m_Mutex); // libxml does not allow a NS definition to be attached to an // attribute node - which is a good thing, since namespaces are // only defined as parts of element nodes - // thus, we create a temporary element node which carries the ns definition - // and is removed/merged as soon as the attribute gets append to it's - // actual parent + // thus the namespace data is stored in CAttr::m_pNamespace sal_Int32 i = qname.indexOf(':'); OString oPrefix, oName, oUri; - xmlChar *xPrefix, *xName, *xUri; if (i != -1) { oPrefix = OUStringToOString(qname.copy(0, i), RTL_TEXTENCODING_UTF8); - xPrefix = (xmlChar*)oPrefix.getStr(); oName = OUStringToOString(qname.copy(i+1, qname.getLength()-i-1), RTL_TEXTENCODING_UTF8); } else { - xPrefix = (xmlChar*)""; oName = OUStringToOString(qname, RTL_TEXTENCODING_UTF8); } - xName = (xmlChar*)oName.getStr(); oUri = OUStringToOString(ns, RTL_TEXTENCODING_UTF8); - xUri = (xmlChar*)oUri.getStr(); + xmlAttrPtr const pAttr = xmlNewDocProp(m_aDocPtr, + reinterpret_cast<xmlChar const*>(oName.getStr()), 0); + ::rtl::Reference< CAttr > const pCAttr( + dynamic_cast< CAttr* >(GetCNode( + reinterpret_cast<xmlNodePtr>(pAttr)).get())); + if (!pCAttr.is()) { throw RuntimeException(); } + // store the namespace data! + pCAttr->m_pNamespace.reset( new stringpair_t(oUri, oPrefix) ); + pCAttr->m_bUnlinked = true; - // create the carrier node - xmlNodePtr pNode = xmlNewDocNode(m_aDocPtr, NULL, (xmlChar*)"__private", NULL); - xmlNsPtr pNs = xmlNewNs(pNode, xUri, xPrefix); - xmlAttrPtr pAttr = xmlNewNsProp(pNode, pNs, xName, NULL); - return Reference< XAttr >(static_cast< CAttr* >(CNode::get((xmlNodePtr)pAttr))); + return pCAttr.get(); }; // Creates a CDATASection node whose value is the specified string. Reference< XCDATASection > SAL_CALL CDocument::createCDATASection(const OUString& data) throw (RuntimeException) { - xmlChar *xData = (xmlChar*)OUStringToOString(data, RTL_TEXTENCODING_UTF8).getStr(); - xmlNodePtr pText = xmlNewCDataBlock(m_aDocPtr, xData, strlen((char*)xData)); - return Reference< XCDATASection >(static_cast< CCDATASection* >(CNode::get(pText))); + ::osl::MutexGuard const g(m_Mutex); + + OString const oData( + ::rtl::OUStringToOString(data, RTL_TEXTENCODING_UTF8)); + xmlChar const*const pData = + reinterpret_cast<xmlChar const*>(oData.getStr()); + xmlNodePtr const pText = + xmlNewCDataBlock(m_aDocPtr, pData, strlen(oData.getStr())); + Reference< XCDATASection > const xRet( + static_cast< XNode* >(GetCNode(pText).get()), + UNO_QUERY_THROW); + return xRet; } // Creates a Comment node given the specified string. Reference< XComment > SAL_CALL CDocument::createComment(const OUString& data) throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); + OString o1 = OUStringToOString(data, RTL_TEXTENCODING_UTF8); xmlChar *xData = (xmlChar*)o1.getStr(); xmlNodePtr pComment = xmlNewDocComment(m_aDocPtr, xData); - return Reference< XComment >(static_cast< CComment* >(CNode::get(pComment))); + Reference< XComment > const xRet( + static_cast< XNode* >(GetCNode(pComment).get()), + UNO_QUERY_THROW); + return xRet; } //Creates an empty DocumentFragment object. Reference< XDocumentFragment > SAL_CALL CDocument::createDocumentFragment() throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); + xmlNodePtr pFrag = xmlNewDocFragment(m_aDocPtr); - return Reference< XDocumentFragment >(static_cast< CDocumentFragment* >(CNode::get(pFrag))); + Reference< XDocumentFragment > const xRet( + static_cast< XNode* >(GetCNode(pFrag).get()), + UNO_QUERY_THROW); + return xRet; } // Creates an element of the type specified. Reference< XElement > SAL_CALL CDocument::createElement(const OUString& tagName) throw (RuntimeException, DOMException) { + ::osl::MutexGuard const g(m_Mutex); + OString o1 = OUStringToOString(tagName, RTL_TEXTENCODING_UTF8); xmlChar *xName = (xmlChar*)o1.getStr(); - xmlNodePtr aNodePtr = xmlNewDocNode(m_aDocPtr, NULL, xName, NULL); - return Reference< XElement >(static_cast< CElement* >(CNode::get(aNodePtr))); + xmlNodePtr const pNode = xmlNewDocNode(m_aDocPtr, NULL, xName, NULL); + Reference< XElement > const xRet( + static_cast< XNode* >(GetCNode(pNode).get()), + UNO_QUERY_THROW); + return xRet; } // Creates an element of the given qualified name and namespace URI. @@ -266,6 +549,8 @@ namespace DOM const OUString& ns, const OUString& qname) throw (RuntimeException, DOMException) { + ::osl::MutexGuard const g(m_Mutex); + sal_Int32 i = qname.indexOf(':'); if (ns.getLength() == 0) throw RuntimeException(); xmlChar *xPrefix; @@ -287,20 +572,28 @@ namespace DOM // xmlNsPtr aNsPtr = xmlNewReconciledNs? // xmlNsPtr aNsPtr = xmlNewGlobalNs? - xmlNodePtr aNodePtr = xmlNewDocNode(m_aDocPtr, NULL, xName, NULL); - xmlNsPtr pNs = xmlNewNs(aNodePtr, xUri, xPrefix); - xmlSetNs(aNodePtr, pNs); - return Reference< XElement >(static_cast< CElement* >(CNode::get(aNodePtr))); + xmlNodePtr const pNode = xmlNewDocNode(m_aDocPtr, NULL, xName, NULL); + xmlNsPtr const pNs = xmlNewNs(pNode, xUri, xPrefix); + xmlSetNs(pNode, pNs); + Reference< XElement > const xRet( + static_cast< XNode* >(GetCNode(pNode).get()), + UNO_QUERY_THROW); + return xRet; } //Creates an EntityReference object. Reference< XEntityReference > SAL_CALL CDocument::createEntityReference(const OUString& name) throw (RuntimeException, DOMException) { + ::osl::MutexGuard const g(m_Mutex); + OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8); xmlChar *xName = (xmlChar*)o1.getStr(); - xmlNodePtr aNodePtr = xmlNewReference(m_aDocPtr, xName); - return Reference< XEntityReference >(static_cast< CEntityReference* >(CNode::get(aNodePtr))); + xmlNodePtr const pNode = xmlNewReference(m_aDocPtr, xName); + Reference< XEntityReference > const xRet( + static_cast< XNode* >(GetCNode(pNode).get()), + UNO_QUERY_THROW); + return xRet; } // Creates a ProcessingInstruction node given the specified name and @@ -309,23 +602,33 @@ namespace DOM const OUString& target, const OUString& data) throw (RuntimeException, DOMException) { + ::osl::MutexGuard const g(m_Mutex); + OString o1 = OUStringToOString(target, RTL_TEXTENCODING_UTF8); xmlChar *xTarget = (xmlChar*)o1.getStr(); OString o2 = OUStringToOString(data, RTL_TEXTENCODING_UTF8); xmlChar *xData = (xmlChar*)o2.getStr(); - xmlNodePtr aNodePtr = xmlNewPI(xTarget, xData); - aNodePtr->doc = m_aDocPtr; - return Reference< XProcessingInstruction >(static_cast< CProcessingInstruction* >(CNode::get(aNodePtr))); + xmlNodePtr const pNode = xmlNewDocPI(m_aDocPtr, xTarget, xData); + pNode->doc = m_aDocPtr; + Reference< XProcessingInstruction > const xRet( + static_cast< XNode* >(GetCNode(pNode).get()), + UNO_QUERY_THROW); + return xRet; } // Creates a Text node given the specified string. Reference< XText > SAL_CALL CDocument::createTextNode(const OUString& data) throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); + OString o1 = OUStringToOString(data, RTL_TEXTENCODING_UTF8); xmlChar *xData = (xmlChar*)o1.getStr(); - xmlNodePtr aNodePtr = xmlNewDocText(m_aDocPtr, xData); - return Reference< XText >(static_cast< CText* >(CNode::get(aNodePtr))); + xmlNodePtr const pNode = xmlNewDocText(m_aDocPtr, xData); + Reference< XText > const xRet( + static_cast< XNode* >(GetCNode(pNode).get()), + UNO_QUERY_THROW); + return xRet; } // The Document Type Declaration (see DocumentType) associated with this @@ -333,27 +636,13 @@ namespace DOM Reference< XDocumentType > SAL_CALL CDocument::getDoctype() throw (RuntimeException) { - // find the doc type - xmlNodePtr cur = m_aDocPtr->children; - while (cur != NULL) - { - if (cur->type == XML_DOCUMENT_TYPE_NODE || cur->type == XML_DTD_NODE) - break; - } - return Reference< XDocumentType >(static_cast< CDocumentType* >(CNode::get(cur))); - } + ::osl::MutexGuard const g(m_Mutex); - /// get the pointer to the root element node of the document - static xmlNodePtr SAL_CALL _getDocumentRootPtr(xmlDocPtr i_pDocument) { - // find the document element - xmlNodePtr cur = i_pDocument->children; - while (cur != NULL) - { - if (cur->type == XML_ELEMENT_NODE) - break; - cur = cur->next; - } - return cur; + xmlNodePtr const pDocType(lcl_getDocumentType(m_aDocPtr)); + Reference< XDocumentType > const xRet( + static_cast< XNode* >(GetCNode(pDocType).get()), + UNO_QUERY); + return xRet; } // This is a convenience attribute that allows direct access to the child @@ -361,13 +650,19 @@ namespace DOM Reference< XElement > SAL_CALL CDocument::getDocumentElement() throw (RuntimeException) { - xmlNodePtr cur = _getDocumentRootPtr(m_aDocPtr); - return Reference< XElement >(static_cast< CElement* >(CNode::get(cur))); + ::osl::MutexGuard const g(m_Mutex); + + xmlNodePtr const pNode = lcl_getDocumentRootPtr(m_aDocPtr); + if (!pNode) { return 0; } + Reference< XElement > const xRet( + static_cast< XNode* >(GetCNode(pNode).get()), + UNO_QUERY); + return xRet; } - static xmlNodePtr _search_element_by_id(const xmlNodePtr cur, const xmlChar* id) + static xmlNodePtr + lcl_search_element_by_id(const xmlNodePtr cur, const xmlChar* id) { - if (cur == NULL) return NULL; // look in current node @@ -384,175 +679,195 @@ namespace DOM } } // look in children - xmlNodePtr result = _search_element_by_id(cur->children, id); + xmlNodePtr result = lcl_search_element_by_id(cur->children, id); if (result != NULL) return result; - result = _search_element_by_id(cur->next, id); + result = lcl_search_element_by_id(cur->next, id); return result; } // Returns the Element whose ID is given by elementId. - Reference< XElement > SAL_CALL CDocument::getElementById(const OUString& elementId) + Reference< XElement > SAL_CALL + CDocument::getElementById(const OUString& elementId) throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); + // search the tree for an element with the given ID OString o1 = OUStringToOString(elementId, RTL_TEXTENCODING_UTF8); xmlChar *xId = (xmlChar*)o1.getStr(); - xmlNodePtr pStart = CNode::getNodePtr(getDocumentElement().get()); - xmlNodePtr aNodePtr = _search_element_by_id(pStart, xId); - return Reference< XElement >(static_cast< CElement* >(CNode::get(aNodePtr))); + xmlNodePtr const pStart = lcl_getDocumentRootPtr(m_aDocPtr); + if (!pStart) { return 0; } + xmlNodePtr const pNode = lcl_search_element_by_id(pStart, xId); + Reference< XElement > const xRet( + static_cast< XNode* >(GetCNode(pNode).get()), + UNO_QUERY); + return xRet; } - Reference< XNodeList > SAL_CALL CDocument::getElementsByTagName(const OUString& tagname) + Reference< XNodeList > SAL_CALL + CDocument::getElementsByTagName(OUString const& rTagname) throw (RuntimeException) { - // build a list - return Reference< XNodeList >( - new CElementList(static_cast< CElement* >( - this->getDocumentElement().get()), tagname)); + ::osl::MutexGuard const g(m_Mutex); + + Reference< XNodeList > const xRet( + new CElementList(this->GetDocumentElement(), m_Mutex, rTagname)); + return xRet; } Reference< XNodeList > SAL_CALL CDocument::getElementsByTagNameNS( - const OUString& namespaceURI, const OUString& localName) + OUString const& rNamespaceURI, OUString const& rLocalName) throw (RuntimeException) { - return Reference< XNodeList >( - new CElementList(static_cast< CElement* >( - this->getDocumentElement().get()), namespaceURI, localName)); + ::osl::MutexGuard const g(m_Mutex); + + Reference< XNodeList > const xRet( + new CElementList(this->GetDocumentElement(), m_Mutex, + rLocalName, &rNamespaceURI)); + return xRet; } Reference< XDOMImplementation > SAL_CALL CDocument::getImplementation() throw (RuntimeException) { - // XXX + // does not need mutex currently return Reference< XDOMImplementation >(CDOMImplementation::get()); } - // helper function to recall import for siblings - static Reference< XNode > _import_siblings ( - const Reference< XNode > aNode, const Reference< XNode> parent, CDocument* pTarget) + // helper function to recursively import siblings + static void lcl_ImportSiblings( + Reference< XDocument > const& xTargetDocument, + Reference< XNode > const& xTargetParent, + Reference< XNode > const& xChild) { - Reference< XNode > sibling = aNode; - Reference< XNode > tmp; - Reference< XNode > firstImported; - while (sibling.is()) + Reference< XNode > xSibling = xChild; + while (xSibling.is()) { - tmp = pTarget->importNode(sibling, sal_True); - parent->appendChild(tmp); - if (!firstImported.is()) - firstImported = tmp; - sibling = sibling->getNextSibling(); + Reference< XNode > const xTmp( + xTargetDocument->importNode(xSibling, sal_True)); + xTargetParent->appendChild(xTmp); + xSibling = xSibling->getNextSibling(); } - return firstImported; } - Reference< XNode > SAL_CALL CDocument::importNode( - const Reference< XNode >& importedNode, sal_Bool deep) - throw (RuntimeException, DOMException) + static Reference< XNode > + lcl_ImportNode( Reference< XDocument > const& xDocument, + Reference< XNode > const& xImportedNode, sal_Bool deep) { - // this node could be from another memory model - // only use uno interfaces to access is!!! - - // allready in doc? - if ( importedNode->getOwnerDocument() == - Reference< XDocument>(static_cast< CDocument* >(CNode::get((xmlNodePtr)m_aDocPtr)))) - return importedNode; - - Reference< XNode > aNode; - NodeType aNodeType = importedNode->getNodeType(); + Reference< XNode > xNode; + NodeType aNodeType = xImportedNode->getNodeType(); switch (aNodeType) { case NodeType_ATTRIBUTE_NODE: { - Reference< XAttr > attr(importedNode, UNO_QUERY); - Reference< XAttr > newAttr = createAttribute(attr->getName()); - newAttr->setValue(attr->getValue()); - aNode.set(newAttr, UNO_QUERY); + Reference< XAttr > const xAttr(xImportedNode, UNO_QUERY_THROW); + Reference< XAttr > const xNew = + xDocument->createAttribute(xAttr->getName()); + xNew->setValue(xAttr->getValue()); + xNode.set(xNew, UNO_QUERY); break; } case NodeType_CDATA_SECTION_NODE: { - Reference< XCDATASection > cdata(importedNode, UNO_QUERY); - Reference< XCDATASection > newCdata = createCDATASection(cdata->getData()); - aNode.set(newCdata, UNO_QUERY); + Reference< XCDATASection > const xCData(xImportedNode, + UNO_QUERY_THROW); + Reference< XCDATASection > const xNewCData = + xDocument->createCDATASection(xCData->getData()); + xNode.set(xNewCData, UNO_QUERY); break; } case NodeType_COMMENT_NODE: { - Reference< XComment > comment(importedNode, UNO_QUERY); - Reference< XComment > newComment = createComment(comment->getData()); - aNode.set(newComment, UNO_QUERY); + Reference< XComment > const xComment(xImportedNode, + UNO_QUERY_THROW); + Reference< XComment > const xNewComment = + xDocument->createComment(xComment->getData()); + xNode.set(xNewComment, UNO_QUERY); break; } case NodeType_DOCUMENT_FRAGMENT_NODE: { - Reference< XDocumentFragment > frag(importedNode, UNO_QUERY); - Reference< XDocumentFragment > newFrag = createDocumentFragment(); - aNode.set(newFrag, UNO_QUERY); + Reference< XDocumentFragment > const xFrag(xImportedNode, + UNO_QUERY_THROW); + Reference< XDocumentFragment > const xNewFrag = + xDocument->createDocumentFragment(); + xNode.set(xNewFrag, UNO_QUERY); break; } case NodeType_ELEMENT_NODE: { - Reference< XElement > element(importedNode, UNO_QUERY); - OUString aNsUri = importedNode->getNamespaceURI(); - OUString aNsPrefix = importedNode->getPrefix(); - OUString aQName = element->getTagName(); - Reference< XElement > newElement; + Reference< XElement > const xElement(xImportedNode, + UNO_QUERY_THROW); + OUString const aNsUri = xImportedNode->getNamespaceURI(); + OUString const aNsPrefix = xImportedNode->getPrefix(); + OUString aQName = xElement->getTagName(); + Reference< XElement > xNewElement; if (aNsUri.getLength() > 0) { - - if (aNsPrefix.getLength() > 0) - aQName = aNsPrefix + OUString::createFromAscii(":") + aQName; - newElement = createElementNS(aNsUri, aQName); + if (aNsPrefix.getLength() > 0) { + aQName = aNsPrefix + OUString::createFromAscii(":") + + aQName; + } + xNewElement = xDocument->createElementNS(aNsUri, aQName); + } else { + xNewElement = xDocument->createElement(aQName); } - else - newElement = createElement(aQName); // get attributes - if (element->hasAttributes()) + if (xElement->hasAttributes()) { - Reference< XNamedNodeMap > attribs = element->getAttributes(); - Reference< XAttr > curAttr; + Reference< XNamedNodeMap > attribs = xElement->getAttributes(); for (sal_Int32 i = 0; i < attribs->getLength(); i++) { - curAttr = Reference< XAttr >(attribs->item(i), UNO_QUERY); - OUString aAttrUri = curAttr->getNamespaceURI(); - OUString aAttrPrefix = curAttr->getPrefix(); + Reference< XAttr > const curAttr(attribs->item(i), + UNO_QUERY_THROW); + OUString const aAttrUri = curAttr->getNamespaceURI(); + OUString const aAttrPrefix = curAttr->getPrefix(); OUString aAttrName = curAttr->getName(); + OUString const sValue = curAttr->getValue(); if (aAttrUri.getLength() > 0) { - if (aAttrPrefix.getLength() > 0) - aAttrName = aAttrPrefix + OUString::createFromAscii(":") + aAttrName; - newElement->setAttributeNS(aAttrUri, aAttrName, curAttr->getValue()); + if (aAttrPrefix.getLength() > 0) { + aAttrName = aAttrPrefix + + OUString::createFromAscii(":") + aAttrName; + } + xNewElement->setAttributeNS( + aAttrUri, aAttrName, sValue); + } else { + xNewElement->setAttribute(aAttrName, sValue); } - else - newElement->setAttribute(aAttrName, curAttr->getValue()); } } - aNode.set(newElement, UNO_QUERY); + xNode.set(xNewElement, UNO_QUERY); break; } case NodeType_ENTITY_REFERENCE_NODE: { - Reference< XEntityReference > ref(importedNode, UNO_QUERY); - Reference< XEntityReference > newRef(createEntityReference(ref->getNodeName())); - aNode.set(newRef, UNO_QUERY); + Reference< XEntityReference > const xRef(xImportedNode, + UNO_QUERY_THROW); + Reference< XEntityReference > const xNewRef( + xDocument->createEntityReference(xRef->getNodeName())); + xNode.set(xNewRef, UNO_QUERY); break; } case NodeType_PROCESSING_INSTRUCTION_NODE: { - Reference< XProcessingInstruction > pi(importedNode, UNO_QUERY); - Reference< XProcessingInstruction > newPi( - createProcessingInstruction(pi->getTarget(), pi->getData())); - aNode.set(newPi, UNO_QUERY); + Reference< XProcessingInstruction > const xPi(xImportedNode, + UNO_QUERY_THROW); + Reference< XProcessingInstruction > const xNewPi( + xDocument->createProcessingInstruction( + xPi->getTarget(), xPi->getData())); + xNode.set(xNewPi, UNO_QUERY); break; } case NodeType_TEXT_NODE: { - Reference< XText > text(importedNode, UNO_QUERY); - Reference< XText > newText(createTextNode(text->getData())); - aNode.set(newText, UNO_QUERY); + Reference< XText > const xText(xImportedNode, UNO_QUERY_THROW); + Reference< XText > const xNewText( + xDocument->createTextNode(xText->getData())); + xNode.set(xNewText, UNO_QUERY); break; } case NodeType_ENTITY_NODE: @@ -567,10 +882,10 @@ namespace DOM if (deep) { // get children and import them - Reference< XNode > child = importedNode->getFirstChild(); - if (child.is()) + Reference< XNode > const xChild = xImportedNode->getFirstChild(); + if (xChild.is()) { - _import_siblings(child, aNode, this); + lcl_ImportSiblings(xDocument, xNode, xChild); } } @@ -585,30 +900,86 @@ namespace DOM * Cancelable: No * Context Info: None */ - if (aNode.is()) + if (xNode.is()) { - Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY); - Reference< XMutationEvent > event(docevent->createEvent( - OUString::createFromAscii("DOMNodeInsertedIntoDocument")), UNO_QUERY); - event->initMutationEvent(OUString::createFromAscii("DOMNodeInsertedIntoDocument") + Reference< XDocumentEvent > const xDocevent(xDocument, UNO_QUERY); + Reference< XMutationEvent > const event(xDocevent->createEvent( + OUString::createFromAscii("DOMNodeInsertedIntoDocument")), + UNO_QUERY_THROW); + event->initMutationEvent( + OUString::createFromAscii("DOMNodeInsertedIntoDocument") , sal_True, sal_False, Reference< XNode >(), OUString(), OUString(), OUString(), (AttrChangeType)0 ); - dispatchEvent(Reference< XEvent >(event, UNO_QUERY)); + Reference< XEventTarget > const xDocET(xDocument, UNO_QUERY); + xDocET->dispatchEvent(Reference< XEvent >(event, UNO_QUERY)); } - return aNode; + return xNode; } + + Reference< XNode > SAL_CALL CDocument::importNode( + Reference< XNode > const& xImportedNode, sal_Bool deep) + throw (RuntimeException, DOMException) + { + if (!xImportedNode.is()) { throw RuntimeException(); } + + // NB: this whole operation inherently accesses 2 distinct documents. + // The imported node could even be from a different DOM implementation, + // so this implementation cannot make any assumptions about the + // locking strategy of the imported node. + // So the import takes no lock on this document; + // it only calls UNO methods on this document that temporarily + // lock the document, and UNO methods on the imported node that + // may temporarily lock the other document. + // As a consequence, the import is not atomic with regard to + // concurrent modifications of either document, but it should not + // deadlock. + // To ensure that no members are accessed, the implementation is in + // static non-member functions. + + Reference< XDocument > const xDocument(this); + // already in doc? + if (xImportedNode->getOwnerDocument() == xDocument) { + return xImportedNode; + } + + Reference< XNode > const xNode( + lcl_ImportNode(xDocument, xImportedNode, deep) ); + return xNode; + } + + OUString SAL_CALL CDocument::getNodeName()throw (RuntimeException) { + // does not need mutex currently return OUString::createFromAscii("#document"); } + OUString SAL_CALL CDocument::getNodeValue() throw (RuntimeException) { + // does not need mutex currently return OUString(); } + Reference< XNode > SAL_CALL CDocument::cloneNode(sal_Bool bDeep) + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + OSL_ASSERT(0 != m_aNodePtr); + if (0 == m_aNodePtr) { + return 0; + } + xmlDocPtr const pClone(xmlCopyDoc(m_aDocPtr, (bDeep) ? 1 : 0)); + if (0 == pClone) { return 0; } + Reference< XNode > const xRet( + static_cast<CNode*>(CDocument::CreateCDocument(pClone).get())); + return xRet; + } + Reference< XEvent > SAL_CALL CDocument::createEvent(const OUString& aType) throw (RuntimeException) { + // does not need mutex currently events::CEvent *pEvent = 0; if ( aType.compareToAscii("DOMSubtreeModified") == 0|| @@ -650,8 +1021,10 @@ namespace DOM const Sequence< beans::StringPair >& i_rNamespaces) throw (RuntimeException, SAXException) { + ::osl::MutexGuard const g(m_Mutex); + // add new namespaces to root node - xmlNodePtr pRoot = _getDocumentRootPtr(m_aDocPtr); + xmlNodePtr const pRoot = lcl_getDocumentRootPtr(m_aDocPtr); if (0 != pRoot) { const beans::StringPair * pSeq = i_rNamespaces.getConstArray(); for (const beans::StringPair *pNsDef = pSeq; @@ -665,7 +1038,7 @@ namespace DOM reinterpret_cast<const xmlChar*>(prefix.getStr())); } // eliminate duplicate namespace declarations - _nscleanup(pRoot->children, pRoot); + nscleanup(pRoot->children, pRoot); } saxify(i_xHandler); } @@ -677,8 +1050,10 @@ namespace DOM const Sequence< beans::Pair< rtl::OUString, sal_Int32 > >& i_rRegisterNamespaces ) throw (SAXException, RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); + // add new namespaces to root node - xmlNodePtr pRoot = _getDocumentRootPtr(m_aDocPtr); + xmlNodePtr const pRoot = lcl_getDocumentRootPtr(m_aDocPtr); if (0 != pRoot) { const beans::StringPair * pSeq = i_rNamespaces.getConstArray(); for (const beans::StringPair *pNsDef = pSeq; @@ -692,7 +1067,7 @@ namespace DOM reinterpret_cast<const xmlChar*>(prefix.getStr())); } // eliminate duplicate namespace declarations - _nscleanup(pRoot->children, pRoot); + nscleanup(pRoot->children, pRoot); } Context aContext(i_xHandler, diff --git a/unoxml/source/dom/document.hxx b/unoxml/source/dom/document.hxx index 3fe593ff2b24..c85a85fba9a6 100644 --- a/unoxml/source/dom/document.hxx +++ b/unoxml/source/dom/document.hxx @@ -25,15 +25,19 @@ * ************************************************************************/ -#ifndef _DOCUMENT_HXX -#define _DOCUMENT_HXX +#ifndef DOM_DOCUMENT_HXX +#define DOM_DOCUMENT_HXX -#include <list> #include <set> +#include <memory> + +#include <libxml/tree.h> + #include <sal/types.h> + #include <cppuhelper/implbase6.hxx> + #include <com/sun/star/uno/Reference.h> -#include <com/sun/star/uno/Exception.hpp> #include <com/sun/star/beans/StringPair.hpp> #include <com/sun/star/xml/dom/XNode.hpp> #include <com/sun/star/xml/dom/XAttr.hpp> @@ -52,13 +56,11 @@ #include "node.hxx" -#include <libxml/tree.h> using namespace std; using ::rtl::OUString; using namespace com::sun::star; using namespace com::sun::star::uno; -using namespace com::sun::star::lang; using namespace com::sun::star::xml::sax; using namespace com::sun::star::io; using namespace com::sun::star::xml::dom; @@ -66,32 +68,70 @@ using namespace com::sun::star::xml::dom::events; namespace DOM { + namespace events { + class CEventDispatcher; + } + + class CElement; - class CDocument : public cppu::ImplInheritanceHelper6< - CNode, XDocument, XDocumentEvent, - XActiveDataControl, XActiveDataSource, XSAXSerializable, XFastSAXSerializable> + typedef ::cppu::ImplInheritanceHelper6< + CNode, XDocument, XDocumentEvent, + XActiveDataControl, XActiveDataSource, + XSAXSerializable, XFastSAXSerializable> + CDocument_Base; + + class CDocument + : public CDocument_Base { - friend class CNode; - typedef set< Reference< XStreamListener > > listenerlist_t; - private: - xmlDocPtr m_aDocPtr; + private: + /// this Mutex is used for synchronization of all UNO wrapper + /// objects that belong to this document + ::osl::Mutex m_Mutex; + /// the libxml document: freed in destructor + /// => all UNO wrapper objects must keep the CDocument alive + xmlDocPtr const m_aDocPtr; // datacontrol/source state + typedef set< Reference< XStreamListener > > listenerlist_t; listenerlist_t m_streamListeners; Reference< XOutputStream > m_rOutputStream; - protected: - CDocument(xmlDocPtr aDocPtr); + typedef std::map< const xmlNodePtr, + ::std::pair< WeakReference<XNode>, CNode* > > nodemap_t; + nodemap_t m_NodeMap; + + ::std::auto_ptr<events::CEventDispatcher> const m_pEventDispatcher; + + CDocument(xmlDocPtr const pDocPtr); + public: + /// factory: only way to create instance! + static ::rtl::Reference<CDocument> + CreateCDocument(xmlDocPtr const pDoc); virtual ~CDocument(); - virtual void SAL_CALL saxify( - const Reference< XDocumentHandler >& i_xHandler); + // needed by CXPathAPI + ::osl::Mutex & GetMutex() { return m_Mutex; } + + events::CEventDispatcher & GetEventDispatcher(); + ::rtl::Reference< CElement > GetDocumentElement(); + + /// get UNO wrapper instance for a libxml node + ::rtl::Reference<CNode> GetCNode( + xmlNodePtr const pNode, bool const bCreate = true); + /// remove a UNO wrapper instance + void RemoveCNode(xmlNodePtr const pNode, CNode const*const pCNode); + + virtual CDocument & GetOwnerDocument(); - virtual void SAL_CALL fastSaxify( Context& rContext ); + virtual void saxify(const Reference< XDocumentHandler >& i_xHandler); + + virtual void fastSaxify( Context& rContext ); + + virtual bool IsChildTypeAllowed(NodeType const nodeType); /** Creates an Attr of the given name. @@ -224,17 +264,14 @@ namespace DOM throw (RuntimeException); virtual OUString SAL_CALL getNodeValue() throw (RuntimeException); + virtual Reference< XNode > SAL_CALL cloneNode(sal_Bool deep) + throw (RuntimeException); // --- delegation for XNde base. virtual Reference< XNode > SAL_CALL appendChild(const Reference< XNode >& newChild) throw (RuntimeException, DOMException) { return CNode::appendChild(newChild); } - virtual Reference< XNode > SAL_CALL cloneNode(sal_Bool deep) - throw (RuntimeException) - { - return CNode::cloneNode(deep); - } virtual Reference< XNamedNodeMap > SAL_CALL getAttributes() throw (RuntimeException) { @@ -307,7 +344,7 @@ namespace DOM } virtual Reference< XNode > SAL_CALL insertBefore( const Reference< XNode >& newChild, const Reference< XNode >& refChild) - throw (DOMException) + throw (RuntimeException, DOMException) { return CNode::insertBefore(newChild, refChild); } diff --git a/unoxml/source/dom/documentbuilder.cxx b/unoxml/source/dom/documentbuilder.cxx index 484c04b7f23b..695ccb670e4c 100644 --- a/unoxml/source/dom/documentbuilder.cxx +++ b/unoxml/source/dom/documentbuilder.cxx @@ -25,9 +25,16 @@ * ************************************************************************/ -#include "documentbuilder.hxx" -#include "node.hxx" -#include "document.hxx" +#include <documentbuilder.hxx> + +#include <string.h> +#include <stdio.h> +#include <stdarg.h> + +#include <libxml/xmlerror.h> +#include <libxml/tree.h> + +#include <boost/shared_ptr.hpp> #include <rtl/alloc.h> #include <rtl/memory.h> @@ -35,17 +42,15 @@ #include <cppuhelper/implbase1.hxx> -#include <libxml/xmlerror.h> - #include <com/sun/star/xml/sax/SAXParseException.hpp> #include <com/sun/star/ucb/XCommandEnvironment.hpp> #include <com/sun/star/task/XInteractionHandler.hpp> + #include <ucbhelper/content.hxx> #include <ucbhelper/commandenvironment.hxx> -#include <string.h> -#include <stdio.h> -#include <stdarg.h> +#include <node.hxx> +#include <document.hxx> using ::rtl::OUStringBuffer; @@ -58,21 +63,6 @@ using ::com::sun::star::task::XInteractionHandler; namespace DOM { - extern "C" { - //char *strdup(const char *s); - /* - static char* strdupfunc(const char* s) - { - sal_Int32 len = 0; - while (s[len] != '\0') len++; - char *newStr = (char*)rtl_allocateMemory(len+1); - if (newStr != NULL) - rtl_copyMemory(newStr, s, len+1); - return newStr; - } - */ - } - class CDefaultEntityResolver : public cppu::WeakImplHelper1< XEntityResolver > { @@ -101,9 +91,10 @@ namespace DOM }; - CDocumentBuilder::CDocumentBuilder(const Reference< XMultiServiceFactory >& xFactory) - : m_aFactory(xFactory) - , m_aEntityResolver(Reference< XEntityResolver > (new CDefaultEntityResolver())) + CDocumentBuilder::CDocumentBuilder( + Reference< XMultiServiceFactory > const& xFactory) + : m_xFactory(xFactory) + , m_xEntityResolver(new CDefaultEntityResolver()) { // init libxml. libxml will protect itself against multiple // initializations so there is no problem here if this gets @@ -113,7 +104,6 @@ namespace DOM Reference< XInterface > CDocumentBuilder::_getInstance(const Reference< XMultiServiceFactory >& rSMgr) { - // XXX return static_cast< XDocumentBuilder* >(new CDocumentBuilder(rSMgr)); } @@ -182,9 +172,13 @@ namespace DOM Reference< XDocument > SAL_CALL CDocumentBuilder::newDocument() throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); + // create a new document xmlDocPtr pDocument = xmlNewDoc((const xmlChar*)"1.0"); - return Reference< XDocument >(static_cast< CDocument* >(CNode::get((xmlNodePtr)pDocument))); + Reference< XDocument > const xRet( + CDocument::CreateCDocument(pDocument).get()); + return xRet; } static OUString make_error_message(xmlParserCtxtPtr ctxt) @@ -287,11 +281,13 @@ namespace DOM return pInput; } +#if 0 static xmlParserInputPtr external_entity_loader(const char *URL, const char * /*ID*/, xmlParserCtxtPtr ctxt) { // just call our resolver function using the URL as systemId return resolve_func(ctxt, 0, (const xmlChar*)URL); } +#endif // default warning handler triggers assertion static void warning_func(void * ctx, const char * /*msg*/, ...) @@ -315,7 +311,6 @@ namespace DOM void throwEx(xmlParserCtxtPtr ctxt) { OUString msg = make_error_message(ctxt); - xmlFreeParserCtxt(ctxt); com::sun::star::xml::sax::SAXParseException saxex; saxex.Message = msg; saxex.LineNumber = static_cast<sal_Int32>(ctxt->lastError.line); @@ -326,6 +321,11 @@ namespace DOM Reference< XDocument > SAL_CALL CDocumentBuilder::parse(const Reference< XInputStream >& is) throw (RuntimeException, SAXParseException, IOException) { + if (!is.is()) { + throw RuntimeException(); + } + + ::osl::MutexGuard const g(m_Mutex); // encoding... /* @@ -333,14 +333,15 @@ namespace DOM xmlCharEncoding enc = xmlParseCharEncoding(encstr); */ - xmlParserCtxtPtr ctxt = xmlNewParserCtxt(); + ::boost::shared_ptr<xmlParserCtxt> const pContext( + xmlNewParserCtxt(), xmlFreeParserCtxt); // register error functions to prevent errors being printed // on the console - ctxt->_private = this; - ctxt->sax->error = error_func; - ctxt->sax->warning = warning_func; - ctxt->sax->resolveEntity = resolve_func; + pContext->_private = this; + pContext->sax->error = error_func; + pContext->sax->warning = warning_func; + pContext->sax->resolveEntity = resolve_func; // IO context struct context_t c; @@ -349,81 +350,63 @@ namespace DOM // we did not open the stream, thus we do not close it. c.close = false; c.freeOnClose = false; - xmlDocPtr pDoc = xmlCtxtReadIO(ctxt, xmlIO_read_func, xmlIO_close_func, &c, - 0, 0, 0); + xmlDocPtr const pDoc = xmlCtxtReadIO(pContext.get(), + xmlIO_read_func, xmlIO_close_func, &c, 0, 0, 0); if (pDoc == 0) { - throwEx(ctxt); + throwEx(pContext.get()); } - xmlFreeParserCtxt(ctxt); - return Reference< XDocument >(static_cast< CDocument* >(CNode::get((xmlNodePtr)pDoc))); - } - - Reference< XDocument > SAL_CALL CDocumentBuilder::parseSource(const InputSource& is) - throw (RuntimeException, SAXParseException, IOException) - { - // if there is an encoding specified in the input source, use it - xmlCharEncoding enc = XML_CHAR_ENCODING_NONE; - if (is.sEncoding.getLength() > 0) { - OString oEncstr = OUStringToOString(is.sEncoding, RTL_TEXTENCODING_UTF8); - char *encstr = (char*) oEncstr.getStr(); - enc = xmlParseCharEncoding(encstr); - } - - // set up parser context - xmlParserCtxtPtr ctxt = xmlNewParserCtxt(); - // register error functions to prevent errors being printed - // on the console - ctxt->_private = this; - ctxt->sax->error = error_func; - ctxt->sax->warning = warning_func; - - // setup entity resolver binding(s) - ctxt->sax->resolveEntity = resolve_func; - xmlSetExternalEntityLoader(external_entity_loader); - - // if an input stream is provided, use it - - // use the systemID - - return Reference< XDocument >(); + Reference< XDocument > const xRet( + CDocument::CreateCDocument(pDoc).get()); + return xRet; } Reference< XDocument > SAL_CALL CDocumentBuilder::parseURI(const OUString& sUri) throw (RuntimeException, SAXParseException, IOException) { - xmlParserCtxtPtr ctxt = xmlNewParserCtxt(); - ctxt->_private = this; - ctxt->sax->error = error_func; - ctxt->sax->warning = warning_func; - ctxt->sax->resolveEntity = resolve_func; + ::osl::MutexGuard const g(m_Mutex); + + ::boost::shared_ptr<xmlParserCtxt> const pContext( + xmlNewParserCtxt(), xmlFreeParserCtxt); + pContext->_private = this; + pContext->sax->error = error_func; + pContext->sax->warning = warning_func; + pContext->sax->resolveEntity = resolve_func; // xmlSetExternalEntityLoader(external_entity_loader); OString oUri = OUStringToOString(sUri, RTL_TEXTENCODING_UTF8); char *uri = (char*) oUri.getStr(); - xmlDocPtr pDoc = xmlCtxtReadFile(ctxt, uri, 0, 0); + xmlDocPtr pDoc = xmlCtxtReadFile(pContext.get(), uri, 0, 0); if (pDoc == 0) { - throwEx(ctxt); + throwEx(pContext.get()); } - xmlFreeParserCtxt(ctxt); - return Reference< XDocument >(static_cast< CDocument* >(CNode::get((xmlNodePtr)pDoc))); + Reference< XDocument > const xRet( + CDocument::CreateCDocument(pDoc).get()); + return xRet; } - void SAL_CALL CDocumentBuilder::setEntityResolver(const Reference< XEntityResolver >& er) + void SAL_CALL + CDocumentBuilder::setEntityResolver(Reference< XEntityResolver > const& xER) throw (RuntimeException) { - m_aEntityResolver = er; + ::osl::MutexGuard const g(m_Mutex); + + m_xEntityResolver = xER; } Reference< XEntityResolver > SAL_CALL CDocumentBuilder::getEntityResolver() throw (RuntimeException) { - return m_aEntityResolver; - } + ::osl::MutexGuard const g(m_Mutex); + return m_xEntityResolver; + } - void SAL_CALL CDocumentBuilder::setErrorHandler(const Reference< XErrorHandler >& eh) + void SAL_CALL + CDocumentBuilder::setErrorHandler(Reference< XErrorHandler > const& xEH) throw (RuntimeException) { - m_aErrorHandler = eh; + ::osl::MutexGuard const g(m_Mutex); + + m_xErrorHandler = xEH; } } diff --git a/unoxml/source/dom/documentbuilder.hxx b/unoxml/source/dom/documentbuilder.hxx index 7f5a2079a051..ea1bfcc603e8 100644 --- a/unoxml/source/dom/documentbuilder.hxx +++ b/unoxml/source/dom/documentbuilder.hxx @@ -25,16 +25,17 @@ * ************************************************************************/ -#ifndef _DOCUMENTBUILDER_HXX -#define _DOCUMENTBUILDER_HXX +#ifndef DOM_DOCUMENTBUILDER_HXX +#define DOM_DOCUMENTBUILDER_HXX #include <sal/types.h> + #include <cppuhelper/implbase2.hxx> + #include <com/sun/star/uno/Reference.h> #include <com/sun/star/uno/Sequence.h> #include <com/sun/star/uno/XInterface.hpp> -#include <com/sun/star/uno/Exception.hpp> #include <com/sun/star/xml/dom/XDocumentBuilder.hpp> #include <com/sun/star/xml/dom/XDocument.hpp> #include <com/sun/star/xml/dom/XDOMImplementation.hpp> @@ -44,10 +45,8 @@ #include <com/sun/star/io/XInputStream.hpp> #include <com/sun/star/io/IOException.hpp> #include <com/sun/star/lang/XServiceInfo.hpp> -#include <com/sun/star/lang/XSingleServiceFactory.hpp> #include <com/sun/star/lang/XMultiServiceFactory.hpp> -#include "libxml/tree.h" using ::rtl::OUString; using namespace com::sun::star::uno; @@ -58,28 +57,41 @@ using namespace com::sun::star::io; namespace DOM { - class CDocumentBuilder - : public ::cppu::WeakImplHelper2< XDocumentBuilder, XServiceInfo > + typedef ::cppu::WeakImplHelper2 + < XDocumentBuilder + , ::com::sun::star::lang::XServiceInfo + > CDocumentBuilder_Base; + + class CDocumentBuilder + : public CDocumentBuilder_Base { private: - Reference< XMultiServiceFactory > m_aFactory; - Reference< XEntityResolver > m_aEntityResolver; - Reference< XErrorHandler > m_aErrorHandler; + ::osl::Mutex m_Mutex; + Reference< ::com::sun::star::lang::XMultiServiceFactory > const + m_xFactory; + Reference< XEntityResolver > m_xEntityResolver; + Reference< XErrorHandler > m_xErrorHandler; public: // ctor - CDocumentBuilder(const Reference< XMultiServiceFactory >& xFactory); + CDocumentBuilder( + Reference< ::com::sun::star::lang::XMultiServiceFactory > const& + xFactory); // call for factory - static Reference< XInterface > getInstance(const Reference < XMultiServiceFactory >& xFactory); + static Reference< XInterface > getInstance( + Reference< ::com::sun::star::lang::XMultiServiceFactory > const& + xFactory); // static helpers for service info and component management static const char* aImplementationName; static const char* aSupportedServiceNames[]; static OUString _getImplementationName(); static Sequence< OUString > _getSupportedServiceNames(); - static Reference< XInterface > _getInstance(const Reference< XMultiServiceFactory >& rSMgr); + static Reference< XInterface > _getInstance( + Reference< ::com::sun::star::lang::XMultiServiceFactory > const& + rSMgr); // XServiceInfo virtual OUString SAL_CALL getImplementationName() @@ -130,10 +142,6 @@ namespace DOM virtual Reference< XDocument > SAL_CALL parseURI(const OUString& uri) throw (RuntimeException, SAXParseException, IOException); - virtual Reference< XDocument > SAL_CALL parseSource(const InputSource& is) - throw (RuntimeException, SAXParseException, IOException); - - /** Specify the EntityResolver to be used to resolve entities present in the XML document to be parsed. diff --git a/unoxml/source/dom/documentfragment.cxx b/unoxml/source/dom/documentfragment.cxx index a3f5ac40b5aa..683938e7f1e4 100644 --- a/unoxml/source/dom/documentfragment.cxx +++ b/unoxml/source/dom/documentfragment.cxx @@ -25,15 +25,33 @@ * ************************************************************************/ -#include "documentfragment.hxx" +#include <documentfragment.hxx> namespace DOM { - CDocumentFragment::CDocumentFragment(const xmlNodePtr aNodePtr) + CDocumentFragment::CDocumentFragment( + CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlNodePtr const pNode) + : CDocumentFragment_Base(rDocument, rMutex, + NodeType_DOCUMENT_FRAGMENT_NODE, pNode) { - m_aNodeType = NodeType_DOCUMENT_FRAGMENT_NODE; - init_node(aNodePtr); } + + bool CDocumentFragment::IsChildTypeAllowed(NodeType const nodeType) + { + switch (nodeType) { + case NodeType_ELEMENT_NODE: + case NodeType_PROCESSING_INSTRUCTION_NODE: + case NodeType_COMMENT_NODE: + case NodeType_TEXT_NODE: + case NodeType_CDATA_SECTION_NODE: + case NodeType_ENTITY_REFERENCE_NODE: + return true; + default: + return false; + } + } + OUString SAL_CALL CDocumentFragment::getNodeName()throw (RuntimeException) { return OUString::createFromAscii("#document-fragment"); diff --git a/unoxml/source/dom/documentfragment.hxx b/unoxml/source/dom/documentfragment.hxx index 7649f6368c9a..6236d5ca453a 100644 --- a/unoxml/source/dom/documentfragment.hxx +++ b/unoxml/source/dom/documentfragment.hxx @@ -25,14 +25,14 @@ * ************************************************************************/ -#ifndef _DOCUMENTFRAGMENT_HXX -#define _DOCUMENTFRAGMENT_HXX +#ifndef DOM_DOCUMENTFRAGMENT_HXX +#define DOM_DOCUMENTFRAGMENT_HXX #include <com/sun/star/uno/Reference.h> -#include <com/sun/star/uno/Exception.hpp> #include <com/sun/star/xml/dom/XDocumentFragment.hpp> -#include "node.hxx" +#include <node.hxx> + using ::rtl::OUString; using namespace com::sun::star::uno; @@ -40,13 +40,23 @@ using namespace com::sun::star::xml::dom; namespace DOM { - class CDocumentFragment : public cppu::ImplInheritanceHelper1< CNode, XDocumentFragment > + typedef ::cppu::ImplInheritanceHelper1< CNode, XDocumentFragment > + CDocumentFragment_Base; + + class CDocumentFragment + : public CDocumentFragment_Base { - friend class CNode; + private: + friend class CDocument; + protected: - CDocumentFragment(const xmlNodePtr aNodePtr); + CDocumentFragment( + CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlNodePtr const pNode); public: + virtual bool IsChildTypeAllowed(NodeType const nodeType); + // ---- resolve uno inheritance problems... // overrides for XNode base virtual OUString SAL_CALL getNodeName() diff --git a/unoxml/source/dom/documenttype.cxx b/unoxml/source/dom/documenttype.cxx index bc5004dfd23c..f105e804ec9f 100644 --- a/unoxml/source/dom/documenttype.cxx +++ b/unoxml/source/dom/documenttype.cxx @@ -25,20 +25,24 @@ * ************************************************************************/ -#include "documenttype.hxx" -#include "entitiesmap.hxx" -#include "notationsmap.hxx" +#include <documenttype.hxx> #include <string.h> +#include <entitiesmap.hxx> +#include <notationsmap.hxx> + + namespace DOM { - CDocumentType::CDocumentType(const xmlDtdPtr aDtdPtr) + CDocumentType::CDocumentType( + CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlDtdPtr const pDtd) + : CDocumentType_Base(rDocument, rMutex, + NodeType_DOCUMENT_TYPE_NODE, reinterpret_cast<xmlNodePtr>(pDtd)) + , m_aDtdPtr(pDtd) { - m_aNodeType = NodeType_DOCUMENT_TYPE_NODE; - m_aDtdPtr = aDtdPtr; - init_node((xmlNodePtr)aDtdPtr); } /** @@ -47,10 +51,12 @@ namespace DOM */ Reference< XNamedNodeMap > SAL_CALL CDocumentType::getEntities() throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + Reference< XNamedNodeMap > aMap; if (m_aDtdPtr != NULL) { - aMap = Reference< XNamedNodeMap >(new CEntitiesMap(this)); + aMap.set(new CEntitiesMap(this, m_rMutex)); } return aMap; } @@ -60,7 +66,8 @@ namespace DOM */ OUString SAL_CALL CDocumentType::getInternalSubset() throw (RuntimeException) { - // XXX + OSL_ENSURE(false, + "CDocumentType::getInternalSubset: not implemented (#i113683#)"); return OUString(); } @@ -70,6 +77,8 @@ namespace DOM */ OUString SAL_CALL CDocumentType::getName() throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + OUString aName; if (m_aDtdPtr != NULL) { @@ -83,10 +92,12 @@ namespace DOM */ Reference< XNamedNodeMap > SAL_CALL CDocumentType::getNotations() throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + Reference< XNamedNodeMap > aMap; if (m_aDtdPtr != NULL) { - aMap.set(new CNotationsMap(this)); + aMap.set(new CNotationsMap(this, m_rMutex)); } return aMap; } @@ -96,6 +107,8 @@ namespace DOM */ OUString SAL_CALL CDocumentType::getPublicId() throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + OUString aId; if (m_aDtdPtr != NULL) { @@ -109,6 +122,8 @@ namespace DOM */ OUString SAL_CALL CDocumentType::getSystemId() throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + OUString aId; if (m_aDtdPtr != NULL) { @@ -116,10 +131,12 @@ namespace DOM } return aId; } + OUString SAL_CALL CDocumentType::getNodeName()throw (RuntimeException) { return getName(); } + OUString SAL_CALL CDocumentType::getNodeValue() throw (RuntimeException) { return OUString(); diff --git a/unoxml/source/dom/documenttype.hxx b/unoxml/source/dom/documenttype.hxx index 4ea6d0c89219..ca276bb384e8 100644 --- a/unoxml/source/dom/documenttype.hxx +++ b/unoxml/source/dom/documenttype.hxx @@ -25,19 +25,20 @@ * ************************************************************************/ -#ifndef _DOCUMENTTYPE_HXX -#define _DOCUMENTTYPE_HXX +#ifndef DOM_DOCUMENTTYPE_HXX +#define DOM_DOCUMENTTYPE_HXX + +#include <libxml/tree.h> #include <sal/types.h> + #include <com/sun/star/uno/Reference.h> -#include <com/sun/star/uno/Exception.hpp> #include <com/sun/star/xml/dom/XDocumentType.hpp> #include <com/sun/star/xml/dom/XNodeList.hpp> #include <com/sun/star/xml/dom/XNamedNodeMap.hpp> -#include "node.hxx" +#include <node.hxx> -#include <libxml/tree.h> using ::rtl::OUString; using namespace com::sun::star::uno; @@ -45,14 +46,21 @@ using namespace com::sun::star::xml::dom; namespace DOM { - class CDocumentType : public cppu::ImplInheritanceHelper1< CNode, XDocumentType > + typedef ::cppu::ImplInheritanceHelper1< CNode, XDocumentType > + CDocumentType_Base; + + class CDocumentType + : public CDocumentType_Base { - friend class CNode; + private: + friend class CDocument; + private: xmlDtdPtr m_aDtdPtr; protected: - CDocumentType(const xmlDtdPtr aDtdPtr); + CDocumentType(CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlDtdPtr const pDtd); public: /** diff --git a/unoxml/source/dom/domimplementation.cxx b/unoxml/source/dom/domimplementation.cxx index 5d80147e7fb6..6f4cc692cba8 100644 --- a/unoxml/source/dom/domimplementation.cxx +++ b/unoxml/source/dom/domimplementation.cxx @@ -25,28 +25,41 @@ * ************************************************************************/ -#include "domimplementation.hxx" +#include <domimplementation.hxx> + +#include <rtl/instance.hxx> + namespace DOM { - CDOMImplementation* CDOMImplementation::aDOMImplementation = new CDOMImplementation(); + // why the heck is this thing static? + // perhaps it would be helpful to know what the implementation should + // do to answer this question... + namespace { + struct DOMImplementation + : public ::rtl::Static<CDOMImplementation, DOMImplementation> {}; + } + CDOMImplementation* CDOMImplementation::get() { - return CDOMImplementation::aDOMImplementation; + return & DOMImplementation::get(); } + // there is just 1 static instance, so these must not delete it! + void SAL_CALL CDOMImplementation::acquire() throw () { } + void SAL_CALL CDOMImplementation::release() throw () { } + /** Creates a DOM Document object of the specified type with its document element. */ Reference <XDocument > SAL_CALL CDOMImplementation::createDocument( - const OUString& namespaceURI, - const OUString& qualifiedName, - const Reference< XDocumentType >& doctype) + OUString const& /*rNamespaceURI*/, + OUString const& /*rQualifiedName*/, + Reference< XDocumentType > const& /*xDoctype*/) throw (RuntimeException) { - OUString aNamespaceURI = namespaceURI; - OUString aQName = qualifiedName; - Reference< XDocumentType > aType = doctype; + OSL_ENSURE(false, + "CDOMImplementation::createDocument: not implemented (#i113683#)"); return Reference<XDocument>(); } @@ -54,22 +67,24 @@ namespace DOM Creates an empty DocumentType node. */ Reference< XDocumentType > SAL_CALL CDOMImplementation::createDocumentType( - const OUString& qualifiedName, const OUString& publicId, const OUString& systemId) + OUString const& /*rQualifiedName*/, + OUString const& /*rPublicId*/, OUString const& /*rSystemId*/) throw (RuntimeException) { - OUString qName = qualifiedName; - OUString aPublicId = publicId; - OUString aSystemId = systemId; + OSL_ENSURE(false, "CDOMImplementation::createDocumentType: " + "not implemented (#i113683#)"); return Reference<XDocumentType>(); } + /** Test if the DOM implementation implements a specific feature. */ - sal_Bool SAL_CALL CDOMImplementation::hasFeature(const OUString& feature, const OUString& ver) + sal_Bool SAL_CALL + CDOMImplementation::hasFeature(OUString const& /*feature*/, OUString const& /*ver*/) throw (RuntimeException) { - OUString aFeature = feature; - OUString aVersion = ver; + OSL_ENSURE(false, + "CDOMImplementation::hasFeature: not implemented (#i113683#)"); return sal_False; } } diff --git a/unoxml/source/dom/domimplementation.hxx b/unoxml/source/dom/domimplementation.hxx index e0282fa8e3f4..53895287e59c 100644 --- a/unoxml/source/dom/domimplementation.hxx +++ b/unoxml/source/dom/domimplementation.hxx @@ -25,18 +25,18 @@ * ************************************************************************/ -#ifndef _DOMIMPLEMENTATION_HXX -#define _DOMIMPLEMENTATION_HXX +#ifndef DOM_DOMIMPLEMENTATION_HXX +#define DOM_DOMIMPLEMENTATION_HXX -#include <map> #include <sal/types.h> -#include <cppuhelper/implbase1.hxx> + #include <com/sun/star/uno/Reference.h> -#include <com/sun/star/uno/Exception.hpp> #include <com/sun/star/xml/dom/XDocument.hpp> #include <com/sun/star/xml/dom/XDocumentType.hpp> #include <com/sun/star/xml/dom/XDOMImplementation.hpp> -#include <com/sun/star/xml/dom/XDOMImplementation.hpp> + +#include <cppuhelper/implbase1.hxx> + using ::rtl::OUString; using namespace com::sun::star::uno; @@ -44,13 +44,17 @@ using namespace com::sun::star::xml::dom; namespace DOM { - class CDOMImplementation : public cppu::WeakImplHelper1< XDOMImplementation > + class CDOMImplementation + : public cppu::WeakImplHelper1< XDOMImplementation > { public: - static CDOMImplementation* aDOMImplementation; static CDOMImplementation* get(); + // there is just 1 static instance, so these must not delete it! + virtual void SAL_CALL acquire() throw (); + virtual void SAL_CALL release() throw (); + /** Creates a DOM Document object of the specified type with its document element. */ diff --git a/unoxml/source/dom/element.cxx b/unoxml/source/dom/element.cxx index 7de79e39e3e4..c034ca1257d2 100644 --- a/unoxml/source/dom/element.cxx +++ b/unoxml/source/dom/element.cxx @@ -25,30 +25,38 @@ * ************************************************************************/ -#include "node.hxx" -#include "element.hxx" -#include "attr.hxx" -#include "elementlist.hxx" -#include "attributesmap.hxx" -#include "../events/mutationevent.hxx" +#include <element.hxx> + +#include <string.h> + +#include <boost/shared_ptr.hpp> + +#include <rtl/ustrbuf.hxx> -#include "comphelper/attributelist.hxx" #include <com/sun/star/xml/sax/FastToken.hdl> -#include <string.h> +#include <comphelper/attributelist.hxx> + +#include <node.hxx> +#include <attr.hxx> +#include <elementlist.hxx> +#include <attributesmap.hxx> +#include <document.hxx> + +#include "../events/mutationevent.hxx" namespace DOM { - CElement::CElement(const xmlNodePtr aNodePtr) + CElement::CElement(CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlNodePtr const pNode) + : CElement_Base(rDocument, rMutex, NodeType_ELEMENT_NODE, pNode) { - m_aNodeType = NodeType_ELEMENT_NODE; - init_node(aNodePtr); } - void SAL_CALL CElement::saxify( - const Reference< XDocumentHandler >& i_xHandler) { + void CElement::saxify(const Reference< XDocumentHandler >& i_xHandler) + { if (!i_xHandler.is()) throw RuntimeException(); comphelper::AttributeList *pAttrs = new comphelper::AttributeList(); @@ -71,7 +79,8 @@ namespace DOM // add attributes for (xmlAttrPtr pAttr = m_aNodePtr->properties; pAttr != 0; pAttr = pAttr->next) { - CNode * pNode = CNode::get(reinterpret_cast<xmlNodePtr>(pAttr)); + ::rtl::Reference<CNode> const pNode = GetOwnerDocument().GetCNode( + reinterpret_cast<xmlNodePtr>(pAttr)); OSL_ENSURE(pNode != 0, "CNode::get returned 0"); OUString prefix = pNode->getPrefix(); OUString name = (prefix.getLength() == 0) @@ -89,14 +98,16 @@ namespace DOM // recurse for (xmlNodePtr pChild = m_aNodePtr->children; pChild != 0; pChild = pChild->next) { - CNode * pNode = CNode::get(pChild); + ::rtl::Reference<CNode> const pNode( + GetOwnerDocument().GetCNode(pChild)); OSL_ENSURE(pNode != 0, "CNode::get returned 0"); pNode->saxify(i_xHandler); } i_xHandler->endElement(name); } - void SAL_CALL CElement::fastSaxify( Context& i_rContext ) { + void CElement::fastSaxify( Context& i_rContext ) + { if (!i_rContext.mxDocHandler.is()) throw RuntimeException(); pushContext(i_rContext); addNamespaces(i_rContext,m_aNodePtr); @@ -105,7 +116,8 @@ namespace DOM i_rContext.mxAttribList->clear(); for (xmlAttrPtr pAttr = m_aNodePtr->properties; pAttr != 0; pAttr = pAttr->next) { - CNode * pNode = CNode::get(reinterpret_cast<xmlNodePtr>(pAttr)); + ::rtl::Reference<CNode> const pNode = GetOwnerDocument().GetCNode( + reinterpret_cast<xmlNodePtr>(pAttr)); OSL_ENSURE(pNode != 0, "CNode::get returned 0"); const xmlChar* xName = pAttr->name; @@ -168,7 +180,8 @@ namespace DOM // recurse for (xmlNodePtr pChild = m_aNodePtr->children; pChild != 0; pChild = pChild->next) { - CNode * pNode = CNode::get(pChild); + ::rtl::Reference<CNode> const pNode( + GetOwnerDocument().GetCNode(pChild)); OSL_ENSURE(pNode != 0, "CNode::get returned 0"); pNode->fastSaxify(i_rContext); } @@ -195,85 +208,135 @@ namespace DOM popContext(i_rContext); } + bool CElement::IsChildTypeAllowed(NodeType const nodeType) + { + switch (nodeType) { + case NodeType_ELEMENT_NODE: + case NodeType_TEXT_NODE: + case NodeType_COMMENT_NODE: + case NodeType_PROCESSING_INSTRUCTION_NODE: + case NodeType_CDATA_SECTION_NODE: + case NodeType_ENTITY_REFERENCE_NODE: + return true; + case NodeType_ATTRIBUTE_NODE: + /* this is not relly allowed by the DOM spec, but this + implementation has evidently supported it (by special case + handling, so the attribute does not actually become a child) + so allow it for backward compatiblity */ + return true; + default: + return false; + } + } + + /** Retrieves an attribute value by name. return empty string if attribute is not set */ - OUString CElement::getAttribute(const OUString& name) + OUString SAL_CALL CElement::getAttribute(OUString const& name) throw (RuntimeException) { - OUString aValue; - // search properties - if (m_aNodePtr != NULL) - { - OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8); - xmlChar *xValue = xmlGetProp(m_aNodePtr, (xmlChar*)o1.getStr()); - if (xValue != NULL) { - aValue = OUString((sal_Char*)xValue, strlen((char*)xValue), RTL_TEXTENCODING_UTF8); - } + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return ::rtl::OUString(); } - return aValue; + // search properties + OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8); + ::boost::shared_ptr<xmlChar const> const pValue( + xmlGetProp(m_aNodePtr, (xmlChar*)o1.getStr()), xmlFree); + OUString const ret( (pValue) + ? OUString(reinterpret_cast<sal_Char const*>(pValue.get()), + strlen(reinterpret_cast<char const*>(pValue.get())), + RTL_TEXTENCODING_UTF8) + : OUString() ); + return ret; } /** Retrieves an attribute node by name. */ - Reference< XAttr > CElement::getAttributeNode(const OUString& name) + Reference< XAttr > SAL_CALL CElement::getAttributeNode(OUString const& name) throw (RuntimeException) { - Reference< XAttr > aAttr; - if (m_aNodePtr != NULL) - { - OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8); - xmlChar *xName = (xmlChar*)o1.getStr(); - xmlAttrPtr pAttr = xmlHasProp(m_aNodePtr, xName); - aAttr = Reference< XAttr >(static_cast< CAttr* >(CNode::get((xmlNodePtr)pAttr))); + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return 0; } - return aAttr; + OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8); + xmlChar const*const pName = + reinterpret_cast<xmlChar const*>(o1.getStr()); + xmlAttrPtr const pAttr = xmlHasProp(m_aNodePtr, pName); + if (0 == pAttr) { + return 0; + } + Reference< XAttr > const xRet( + static_cast< XNode* >(GetOwnerDocument().GetCNode( + reinterpret_cast<xmlNodePtr>(pAttr)).get()), + UNO_QUERY_THROW); + return xRet; } /** Retrieves an Attr node by local name and namespace URI. */ - Reference< XAttr > CElement::getAttributeNodeNS( + Reference< XAttr > SAL_CALL CElement::getAttributeNodeNS( const OUString& namespaceURI, const OUString& localName) throw (RuntimeException) { - Reference< XAttr > aAttr; - if (m_aNodePtr != NULL) - { - OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8); - xmlChar *xName = (xmlChar*)o1.getStr(); - OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8); - xmlChar *xNS = (xmlChar*)o2.getStr(); - xmlAttrPtr pAttr = xmlHasNsProp(m_aNodePtr, xName, xNS); - aAttr = Reference< XAttr >(static_cast< CAttr* >(CNode::get((xmlNodePtr)pAttr))); + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return 0; } - return aAttr; + OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8); + xmlChar const*const pName = + reinterpret_cast<xmlChar const*>(o1.getStr()); + OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8); + xmlChar const*const pNS = + reinterpret_cast<xmlChar const*>(o2.getStr()); + xmlAttrPtr const pAttr = xmlHasNsProp(m_aNodePtr, pName, pNS); + if (0 == pAttr) { + return 0; + } + Reference< XAttr > const xRet( + static_cast< XNode* >(GetOwnerDocument().GetCNode( + reinterpret_cast<xmlNodePtr>(pAttr)).get()), + UNO_QUERY_THROW); + return xRet; } /** Retrieves an attribute value by local name and namespace URI. return empty string if attribute is not set */ - OUString CElement::getAttributeNS(const OUString& namespaceURI, const OUString& localName) + OUString SAL_CALL + CElement::getAttributeNS( + OUString const& namespaceURI, OUString const& localName) throw (RuntimeException) { - OUString aValue; - // search properties - if (m_aNodePtr != NULL) - { - OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8); - xmlChar *xName = (xmlChar*)o1.getStr(); - OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8); - xmlChar *xNS = (xmlChar*)o2.getStr(); - xmlChar *xValue = (xmlChar*)xmlGetNsProp(m_aNodePtr, xName, xNS); - if (xValue != NULL) { - aValue = OUString((sal_Char*)xValue, strlen((char*)xValue), RTL_TEXTENCODING_UTF8); - xmlFree(xValue); - } + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return ::rtl::OUString(); + } + OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8); + xmlChar const*const pName = + reinterpret_cast<xmlChar const*>(o1.getStr()); + OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8); + xmlChar const*const pNS = + reinterpret_cast<xmlChar const*>(o2.getStr()); + ::boost::shared_ptr<xmlChar const> const pValue( + xmlGetNsProp(m_aNodePtr, pName, pNS), xmlFree); + if (0 == pValue) { + return ::rtl::OUString(); } - return aValue; + OUString const ret(reinterpret_cast<sal_Char const*>(pValue.get()), + strlen(reinterpret_cast<char const*>(pValue.get())), + RTL_TEXTENCODING_UTF8); + return ret; } /** @@ -281,11 +344,15 @@ namespace DOM in the order in which they are encountered in a preorder traversal of this Element tree. */ - Reference< XNodeList > CElement::getElementsByTagName(const OUString& name) + Reference< XNodeList > SAL_CALL + CElement::getElementsByTagName(OUString const& rLocalName) throw (RuntimeException) { - Reference< XNodeList > aList = Reference< XNodeList >(new CElementList(this, name)); - return aList; + ::osl::MutexGuard const g(m_rMutex); + + Reference< XNodeList > const xList( + new CElementList(this, m_rMutex, rLocalName)); + return xList; } /** @@ -293,26 +360,32 @@ namespace DOM name and namespace URI in the order in which they are encountered in a preorder traversal of this Element tree. */ - Reference< XNodeList > CElement::getElementsByTagNameNS(const OUString& namespaceURI, - const OUString& localName) + Reference< XNodeList > SAL_CALL + CElement::getElementsByTagNameNS( + OUString const& rNamespaceURI, OUString const& rLocalName) throw (RuntimeException) { - Reference< XNodeList > aList = Reference< XNodeList >(new CElementList(this, localName, namespaceURI)); - return aList; + ::osl::MutexGuard const g(m_rMutex); + + Reference< XNodeList > const xList( + new CElementList(this, m_rMutex, rLocalName, &rNamespaceURI)); + return xList; } /** The name of the element. */ - OUString CElement::getTagName() + OUString SAL_CALL CElement::getTagName() throw (RuntimeException) { - OUString aName; - if (m_aNodePtr != NULL) - { - aName = OUString((sal_Char*)m_aNodePtr->name, strlen((char*)m_aNodePtr->name), RTL_TEXTENCODING_UTF8); + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return ::rtl::OUString(); } - return aName; + OUString const ret((sal_Char*)m_aNodePtr->name, + strlen((char*)m_aNodePtr->name), RTL_TEXTENCODING_UTF8); + return ret; } @@ -320,9 +393,11 @@ namespace DOM Returns true when an attribute with a given name is specified on this element or has a default value, false otherwise. */ - sal_Bool CElement::hasAttribute(const OUString& name) + sal_Bool SAL_CALL CElement::hasAttribute(OUString const& name) throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8); xmlChar *xName = (xmlChar*)o1.getStr(); return (m_aNodePtr != NULL && xmlHasProp(m_aNodePtr, xName) != NULL); @@ -332,9 +407,12 @@ namespace DOM Returns true when an attribute with a given local name and namespace URI is specified on this element or has a default value, false otherwise. */ - sal_Bool CElement::hasAttributeNS(const OUString& namespaceURI, const OUString& localName) + sal_Bool SAL_CALL CElement::hasAttributeNS( + OUString const& namespaceURI, OUString const& localName) throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8); xmlChar *xName = (xmlChar*)o1.getStr(); OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8); @@ -345,196 +423,253 @@ namespace DOM /** Removes an attribute by name. */ - void CElement::removeAttribute(const OUString& name) + void SAL_CALL CElement::removeAttribute(OUString const& name) throw (RuntimeException, DOMException) { - xmlChar *xName = (xmlChar*)OUStringToOString(name, RTL_TEXTENCODING_UTF8).getStr(); - if (m_aNodePtr != NULL) { - xmlUnsetProp(m_aNodePtr, xName); + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return; + } + OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8); + xmlChar const*const pName = + reinterpret_cast<xmlChar const*>(o1.getStr()); + xmlAttrPtr const pAttr = xmlHasProp(m_aNodePtr, pName); + if (0 == xmlUnsetProp(m_aNodePtr, pName)) { + ::rtl::Reference<CNode> const pCNode(GetOwnerDocument().GetCNode( + reinterpret_cast<xmlNodePtr>(pAttr), false)); + if (pCNode.is()) { + pCNode->invalidate(); // freed by xmlUnsetProp + } } } /** Removes an attribute by local name and namespace URI. */ - void CElement::removeAttributeNS(const OUString& namespaceURI, const OUString& localName) + void SAL_CALL CElement::removeAttributeNS( + OUString const& namespaceURI, OUString const& localName) throw (RuntimeException, DOMException) { + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return; + } OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8); - xmlChar *xName = (xmlChar*)o1.getStr(); + xmlChar const*const pName = + reinterpret_cast<xmlChar const*>(o1.getStr()); OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8); - xmlChar *xURI = (xmlChar*)o2.getStr(); - if (m_aNodePtr != NULL) { - // XXX - xmlNsPtr pNs = xmlSearchNsByHref(m_aNodePtr->doc, m_aNodePtr, xURI); - xmlUnsetNsProp(m_aNodePtr, pNs, xName); + xmlChar const*const pURI = + reinterpret_cast<xmlChar const*>(o2.getStr()); + xmlNsPtr const pNs = + xmlSearchNsByHref(m_aNodePtr->doc, m_aNodePtr, pURI); + xmlAttrPtr const pAttr = xmlHasNsProp(m_aNodePtr, pName, pURI); + if (0 == xmlUnsetNsProp(m_aNodePtr, pNs, pName)) { + ::rtl::Reference<CNode> const pCNode(GetOwnerDocument().GetCNode( + reinterpret_cast<xmlNodePtr>(pAttr), false)); + if (pCNode.is()) { + pCNode->invalidate(); // freed by xmlUnsetNsProp + } } } /** Removes the specified attribute node. */ - Reference< XAttr > CElement::removeAttributeNode(const Reference< XAttr >& oldAttr) + Reference< XAttr > SAL_CALL + CElement::removeAttributeNode(Reference< XAttr > const& oldAttr) throw (RuntimeException, DOMException) { - Reference< XAttr > aAttr; - if(m_aNodePtr != NULL) - { - xmlAttrPtr pAttr = (xmlAttrPtr) CNode::getNodePtr(oldAttr.get()); + ::osl::MutexGuard const g(m_rMutex); - if (pAttr->parent != m_aNodePtr) - { - DOMException e; - e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; - throw e; - } - if (pAttr->doc != m_aNodePtr->doc) - { - DOMException e; - e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR; - throw e; - } + if (0 == m_aNodePtr) { + return 0; + } - if (oldAttr->getNamespaceURI().getLength() > 0) - aAttr = oldAttr->getOwnerDocument()->createAttributeNS( - oldAttr->getNamespaceURI(), oldAttr->getName()); - else - aAttr = oldAttr->getOwnerDocument()->createAttribute(oldAttr->getName()); - aAttr->setValue(oldAttr->getValue()); - xmlRemoveProp(pAttr); + ::rtl::Reference<CNode> const pCNode( + CNode::GetImplementation(Reference<XNode>(oldAttr.get()))); + if (!pCNode.is()) { throw RuntimeException(); } + xmlNodePtr const pNode = pCNode->GetNodePtr(); + xmlAttrPtr const pAttr = (xmlAttrPtr) pNode; + if (!pAttr) { throw RuntimeException(); } + + if (pAttr->parent != m_aNodePtr) + { + DOMException e; + e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; + throw e; + } + if (pAttr->doc != m_aNodePtr->doc) + { + DOMException e; + e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR; + throw e; + } + + Reference< XAttr > aAttr; + if (oldAttr->getNamespaceURI().getLength() > 0) { + ::rtl::OUStringBuffer qname(oldAttr->getPrefix()); + if (0 != qname.getLength()) { + qname.append(sal_Unicode(':')); + } + qname.append(oldAttr->getName()); + aAttr = GetOwnerDocument().createAttributeNS( + oldAttr->getNamespaceURI(), qname.makeStringAndClear()); + } else { + aAttr = GetOwnerDocument().createAttribute(oldAttr->getName()); } + aAttr->setValue(oldAttr->getValue()); + xmlRemoveProp(pAttr); + pCNode->invalidate(); // freed by xmlRemoveProp + return aAttr; } /** Adds a new attribute node. */ - Reference< XAttr > CElement::_setAttributeNode(const Reference< XAttr >& newAttr, sal_Bool bNS) - throw (RuntimeException) + Reference< XAttr > + CElement::setAttributeNode_Impl_Lock( + Reference< XAttr > const& xNewAttr, bool const bNS) { - Reference< XAttr > aAttr; - if (m_aNodePtr != NULL) - { - // check whether the attrib belongs to this document - Reference< XDocument > newDoc(newAttr->getOwnerDocument(), UNO_QUERY); - Reference< XDocument > oldDoc(CNode::getOwnerDocument(), UNO_QUERY); - if (newDoc != oldDoc) { - throw RuntimeException(); - } - - // get the implementation - xmlAttrPtr pAttr = (xmlAttrPtr) CNode::getNodePtr(newAttr.get()); - - // check whether the attribute is not in use by another element - xmlNsPtr pNs = NULL; - if (pAttr->parent != NULL) - if(strcmp((char*)pAttr->parent->name, "__private") == 0 - && pNs && pAttr->ns != NULL) - { - pNs = xmlSearchNs(m_aNodePtr->doc, m_aNodePtr, pAttr->ns->prefix); - if (pNs == NULL || strcmp((char*)pNs->href, (char*)pAttr->ns->href) !=0 ) - pNs = xmlNewNs(m_aNodePtr, pAttr->ns->href, pAttr->ns->href); - else - throw RuntimeException(); - } + if (xNewAttr->getOwnerDocument() != getOwnerDocument()) { + DOMException e; + e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR; + throw e; + } - xmlAttrPtr res = NULL; + ::osl::ClearableMutexGuard guard(m_rMutex); - if (bNS) - res = xmlNewNsProp(m_aNodePtr, pNs, pAttr->name, pAttr->children->content); - else - res = xmlNewProp(m_aNodePtr, pAttr->name, pAttr->children->content); + if (0 == m_aNodePtr) { + throw RuntimeException(); + } - // free carrier node ... - if(pAttr->parent != NULL && strcmp((char*)pAttr->parent->name, "__private")== 0) - xmlFreeNode(pAttr->parent); - // ... remove the old attr from the node cache - CNode::remove((xmlNodePtr)pAttr); + // get the implementation + CAttr *const pCAttr = dynamic_cast<CAttr*>( + CNode::GetImplementation(xNewAttr)); + if (!pCAttr) { throw RuntimeException(); } + xmlAttrPtr const pAttr = + reinterpret_cast<xmlAttrPtr>(pCAttr->GetNodePtr()); + if (!pAttr) { throw RuntimeException(); } - // get the new attr node - aAttr = Reference< XAttr >(static_cast< CAttr* >(CNode::get((xmlNodePtr)res))); + // check whether the attribute is not in use by another element + if (pAttr->parent) { + DOMException e; + e.Code = DOMExceptionType_INUSE_ATTRIBUTE_ERR; + throw e; } - if (aAttr.is()) - { - // attribute adition event - // dispatch DOMAttrModified event - Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY); - Reference< XMutationEvent > event(docevent->createEvent( - OUString::createFromAscii("DOMAttrModified")), UNO_QUERY); - event->initMutationEvent(OUString::createFromAscii("DOMAttrModified"), - sal_True, sal_False, Reference< XNode >(aAttr, UNO_QUERY), - OUString(), aAttr->getValue(), aAttr->getName(), AttrChangeType_ADDITION); - dispatchEvent(Reference< XEvent >(event, UNO_QUERY)); - dispatchSubtreeModified(); + xmlAttrPtr res = NULL; + xmlChar const*const pContent( + (pAttr->children) ? pAttr->children->content : 0); + + if (bNS) { + xmlNsPtr const pNs( pCAttr->GetNamespace(m_aNodePtr) ); + res = xmlNewNsProp(m_aNodePtr, pNs, pAttr->name, pContent); + } else { + res = xmlNewProp(m_aNodePtr, pAttr->name, pContent); } - return aAttr; + + // get the new attr node + Reference< XAttr > const xAttr( + static_cast< XNode* >(GetOwnerDocument().GetCNode( + reinterpret_cast<xmlNodePtr>(res)).get()), + UNO_QUERY_THROW); + + // attribute adition event + // dispatch DOMAttrModified event + Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY); + Reference< XMutationEvent > event(docevent->createEvent( + OUString::createFromAscii("DOMAttrModified")), UNO_QUERY); + event->initMutationEvent(OUString::createFromAscii("DOMAttrModified"), + sal_True, sal_False, Reference< XNode >(xAttr, UNO_QUERY), + OUString(), xAttr->getValue(), xAttr->getName(), + AttrChangeType_ADDITION); + + guard.clear(); // release mutex before calling event handlers + + dispatchEvent(Reference< XEvent >(event, UNO_QUERY)); + dispatchSubtreeModified(); + + return xAttr; } - Reference< XAttr > CElement::setAttributeNode(const Reference< XAttr >& newAttr) + Reference< XAttr > + CElement::setAttributeNode(const Reference< XAttr >& newAttr) throw (RuntimeException, DOMException) { - return _setAttributeNode(newAttr, sal_False); + return setAttributeNode_Impl_Lock(newAttr, false); } /** Adds a new attribute. */ - Reference< XAttr > CElement::setAttributeNodeNS(const Reference< XAttr >& newAttr) + Reference< XAttr > + CElement::setAttributeNodeNS(const Reference< XAttr >& newAttr) throw (RuntimeException, DOMException) { - return _setAttributeNode(newAttr, sal_True); + return setAttributeNode_Impl_Lock(newAttr, true); } /** Adds a new attribute. */ - void CElement::setAttribute(const OUString& name, const OUString& value) + void SAL_CALL + CElement::setAttribute(OUString const& name, OUString const& value) throw (RuntimeException, DOMException) { + ::osl::ClearableMutexGuard guard(m_rMutex); + OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8); xmlChar *xName = (xmlChar*)o1.getStr(); OString o2 = OUStringToOString(value, RTL_TEXTENCODING_UTF8); xmlChar *xValue = (xmlChar*)o2.getStr(); - if (m_aNodePtr != NULL) - { - OUString oldValue; - AttrChangeType aChangeType = AttrChangeType_MODIFICATION; - xmlChar *xOld = xmlGetProp(m_aNodePtr, xName); - if (xOld == NULL) - { - aChangeType = AttrChangeType_ADDITION; - xmlNewProp(m_aNodePtr, xName, xValue); - } - else - { - oldValue = OUString((char*)xOld, strlen((char*)xOld), RTL_TEXTENCODING_UTF8); - xmlSetProp(m_aNodePtr, xName, xValue); - } - - // dispatch DOMAttrModified event - Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY); - Reference< XMutationEvent > event(docevent->createEvent( - OUString::createFromAscii("DOMAttrModified")), UNO_QUERY); - event->initMutationEvent(OUString::createFromAscii("DOMAttrModified"), - sal_True, sal_False, Reference< XNode >(getAttributeNode(name), UNO_QUERY), - oldValue, value, name, aChangeType); - dispatchEvent(Reference< XEvent >(event, UNO_QUERY)); - dispatchSubtreeModified(); + if (0 == m_aNodePtr) { + throw RuntimeException(); } + OUString oldValue; + AttrChangeType aChangeType = AttrChangeType_MODIFICATION; + ::boost::shared_ptr<xmlChar const> const pOld( + xmlGetProp(m_aNodePtr, xName), xmlFree); + if (pOld == NULL) { + aChangeType = AttrChangeType_ADDITION; + xmlNewProp(m_aNodePtr, xName, xValue); + } else { + oldValue = OUString(reinterpret_cast<sal_Char const*>(pOld.get()), + strlen(reinterpret_cast<char const*>(pOld.get())), + RTL_TEXTENCODING_UTF8); + xmlSetProp(m_aNodePtr, xName, xValue); + } + + // dispatch DOMAttrModified event + Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY); + Reference< XMutationEvent > event(docevent->createEvent( + OUString::createFromAscii("DOMAttrModified")), UNO_QUERY); + event->initMutationEvent(OUString::createFromAscii("DOMAttrModified"), + sal_True, sal_False, + Reference< XNode >(getAttributeNode(name), UNO_QUERY), + oldValue, value, name, aChangeType); + + guard.clear(); // release mutex before calling event handlers + dispatchEvent(Reference< XEvent >(event, UNO_QUERY)); + dispatchSubtreeModified(); } /** Adds a new attribute. */ - void CElement::setAttributeNS( - const OUString& namespaceURI, const OUString& qualifiedName, const OUString& value) + void SAL_CALL + CElement::setAttributeNS(OUString const& namespaceURI, + OUString const& qualifiedName, OUString const& value) throw (RuntimeException, DOMException) { if (namespaceURI.getLength() == 0) throw RuntimeException(); + ::osl::ClearableMutexGuard guard(m_rMutex); + OString o1, o2, o3, o4, o5; xmlChar *xPrefix = NULL; xmlChar *xLName = NULL; @@ -559,63 +694,72 @@ namespace DOM o5 = OUStringToOString(value, RTL_TEXTENCODING_UTF8); xmlChar *xURI= (xmlChar*)o4.getStr(); xmlChar *xValue = (xmlChar*)o5.getStr(); - if (m_aNodePtr != NULL) - { - //find the right namespace - xmlNsPtr pNs = xmlSearchNs(m_aNodePtr->doc, m_aNodePtr, xPrefix); - // if no namespace found, create a new one - if (pNs == NULL) - pNs = xmlNewNs(m_aNodePtr, xURI, xPrefix); - if (strcmp((char*)pNs->href, (char*)xURI) == 0) - { - // found namespace matches - - OUString oldValue; - AttrChangeType aChangeType = AttrChangeType_MODIFICATION; - xmlChar *xOld = xmlGetNsProp(m_aNodePtr, xLName, pNs->href); - if (xOld == NULL) - { - aChangeType = AttrChangeType_ADDITION; - xmlNewNsProp(m_aNodePtr, pNs, xLName, xValue); - } - else - { - oldValue = OUString((char *)xOld, strlen((char *)xOld), RTL_TEXTENCODING_UTF8); - xmlSetNsProp(m_aNodePtr, pNs, xLName, xValue); - } - // dispatch DOMAttrModified event - Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY); - Reference< XMutationEvent > event(docevent->createEvent( - OUString::createFromAscii("DOMAttrModified")), UNO_QUERY); - event->initMutationEvent(OUString::createFromAscii("DOMAttrModified"), sal_True, sal_False, - Reference< XNode >(getAttributeNodeNS(namespaceURI, OUString((char*)xLName, strlen((char*)xLName), RTL_TEXTENCODING_UTF8)), UNO_QUERY), - oldValue, value, qualifiedName, aChangeType); - dispatchEvent(Reference< XEvent >(event, UNO_QUERY)); - dispatchSubtreeModified(); - - } else { - // ambigious ns prefix - throw RuntimeException(); - } + if (0 == m_aNodePtr) { + throw RuntimeException(); + } + //find the right namespace + xmlNsPtr pNs = xmlSearchNs(m_aNodePtr->doc, m_aNodePtr, xPrefix); + // if no namespace found, create a new one + if (pNs == NULL) { + pNs = xmlNewNs(m_aNodePtr, xURI, xPrefix); } + + if (strcmp((char*)pNs->href, (char*)xURI) != 0) { + // ambiguous ns prefix + throw RuntimeException(); + } + + // found namespace matches + + OUString oldValue; + AttrChangeType aChangeType = AttrChangeType_MODIFICATION; + ::boost::shared_ptr<xmlChar const> const pOld( + xmlGetNsProp(m_aNodePtr, xLName, pNs->href), xmlFree); + if (pOld == NULL) { + aChangeType = AttrChangeType_ADDITION; + xmlNewNsProp(m_aNodePtr, pNs, xLName, xValue); + } else { + oldValue = OUString(reinterpret_cast<sal_Char const*>(pOld.get()), + strlen(reinterpret_cast<char const*>(pOld.get())), + RTL_TEXTENCODING_UTF8); + xmlSetNsProp(m_aNodePtr, pNs, xLName, xValue); + } + // dispatch DOMAttrModified event + Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY); + Reference< XMutationEvent > event(docevent->createEvent( + OUString::createFromAscii("DOMAttrModified")), UNO_QUERY); + event->initMutationEvent( + OUString::createFromAscii("DOMAttrModified"), + sal_True, sal_False, + Reference< XNode >(getAttributeNodeNS(namespaceURI, OUString((char*)xLName, strlen((char*)xLName), RTL_TEXTENCODING_UTF8)), UNO_QUERY), + oldValue, value, qualifiedName, aChangeType); + + guard.clear(); // release mutex before calling event handlers + dispatchEvent(Reference< XEvent >(event, UNO_QUERY)); + dispatchSubtreeModified(); } - Reference< XNamedNodeMap > SAL_CALL CElement::getAttributes()throw (RuntimeException) + Reference< XNamedNodeMap > SAL_CALL + CElement::getAttributes() throw (RuntimeException) { - Reference< XNamedNodeMap > aMap; - if (hasAttributes()) { - aMap = Reference< XNamedNodeMap >(new CAttributesMap(this)); - } - return aMap; + ::osl::MutexGuard const g(m_rMutex); + + Reference< XNamedNodeMap > const xMap( + new CAttributesMap(this, m_rMutex)); + return xMap; } + OUString SAL_CALL CElement::getNodeName()throw (RuntimeException) { return getLocalName(); } + OUString SAL_CALL CElement::getLocalName()throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + OUString aName; if (m_aNodePtr != NULL) { @@ -624,26 +768,31 @@ namespace DOM } return aName; } + OUString SAL_CALL CElement::getNodeValue() throw (RuntimeException) { return OUString(); } - void SAL_CALL CElement::setElementName(const OUString& aName) throw (RuntimeException, DOMException) + void SAL_CALL CElement::setElementName(const OUString& aName) + throw (RuntimeException, DOMException) { - if (aName.getLength() > 0 && aName.indexOf(OUString::createFromAscii(":")) < 0) - { - OString oName = OUStringToOString(aName, RTL_TEXTENCODING_UTF8); - xmlChar *xName = (xmlChar*)oName.getStr(); - // xmlFree((void*)m_aNodePtr->name); - m_aNodePtr->name = xmlStrdup(xName); - } - else + if ((aName.getLength() <= 0) || + (0 <= aName.indexOf(OUString::createFromAscii(":")))) { DOMException e; e.Code = DOMExceptionType_INVALID_CHARACTER_ERR; throw e; } + + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + throw RuntimeException(); + } + OString oName = OUStringToOString(aName, RTL_TEXTENCODING_UTF8); + xmlChar *xName = (xmlChar*)oName.getStr(); + xmlNodeSetName(m_aNodePtr, xName); } } diff --git a/unoxml/source/dom/element.hxx b/unoxml/source/dom/element.hxx index d0df7102f12f..58891ed0d21c 100644 --- a/unoxml/source/dom/element.hxx +++ b/unoxml/source/dom/element.hxx @@ -25,16 +25,19 @@ * ************************************************************************/ -#ifndef _ELEMENT_HXX -#define _ELEMENT_HXX +#ifndef DOM_ELEMENT_HXX +#define DOM_ELEMENT_HXX + +#include <libxml/tree.h> + #include <com/sun/star/uno/Reference.h> -#include <com/sun/star/uno/Exception.hpp> #include <com/sun/star/xml/dom/XNode.hpp> #include <com/sun/star/xml/dom/XNodeList.hpp> #include <com/sun/star/xml/dom/XNamedNodeMap.hpp> #include <com/sun/star/xml/dom/NodeType.hpp> -#include <libxml/tree.h> -#include "node.hxx" + +#include <node.hxx> + using ::rtl::OUString; using namespace com::sun::star::uno; @@ -42,22 +45,28 @@ using namespace com::sun::star::xml::dom; namespace DOM { - class CElement : public cppu::ImplInheritanceHelper1<CNode, XElement > + typedef ::cppu::ImplInheritanceHelper1<CNode, XElement > CElement_Base; + + class CElement + : public CElement_Base { - friend class CNode; private: - Reference< XAttr > _setAttributeNode(const Reference< XAttr >& newAttr, sal_Bool bNS) - throw (RuntimeException); + friend class CDocument; + + Reference< XAttr > setAttributeNode_Impl_Lock( + Reference< XAttr > const& xNewAttr, bool const bNS); protected: - CElement(const xmlNodePtr aNodePtr); + CElement(CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlNodePtr const pNode); public: - virtual void SAL_CALL saxify( - const Reference< XDocumentHandler >& i_xHandler); + virtual void saxify(const Reference< XDocumentHandler >& i_xHandler); + + virtual void fastSaxify( Context& i_rContext ); - virtual void SAL_CALL fastSaxify( Context& i_rContext ); + virtual bool IsChildTypeAllowed(NodeType const nodeType); /** Retrieves an attribute value by name. diff --git a/unoxml/source/dom/elementlist.cxx b/unoxml/source/dom/elementlist.cxx index 8db7b2d3bcb4..92285cca8ce0 100644 --- a/unoxml/source/dom/elementlist.cxx +++ b/unoxml/source/dom/elementlist.cxx @@ -29,45 +29,45 @@ #include <string.h> +#include <element.hxx> +#include <document.hxx> + + namespace DOM { - CElementList::CElementList(const CElement* aElement, const OUString& aName) - : m_pElement(aElement) - , m_aName(aName) - , xURI(0) - , m_bRebuild(sal_True) + static xmlChar* lcl_initXmlString(::rtl::OUString const& rString) { - OString o1 = OUStringToOString(aName, RTL_TEXTENCODING_UTF8); - xName = new xmlChar[o1.getLength()]; - strcpy((char*)xName, o1.getStr()); - registerListener(aElement); + ::rtl::OString const os = + ::rtl::OUStringToOString(rString, RTL_TEXTENCODING_UTF8); + xmlChar *const pRet = new xmlChar[os.getLength() + 1]; + strcpy(reinterpret_cast<char*>(pRet), os.getStr()); + return pRet; } - CElementList::CElementList(const CElement* aElement, const OUString& aName, const OUString& aURI) - : m_pElement(aElement) - , m_aName(aName) - , m_aURI(aURI) - , m_bRebuild(sal_True) + CElementList::CElementList(::rtl::Reference<CElement> const& pElement, + ::osl::Mutex & rMutex, + OUString const& rName, OUString const*const pURI) + : m_pElement(pElement) + , m_rMutex(rMutex) + , m_pName(lcl_initXmlString(rName)) + , m_pURI((pURI) ? lcl_initXmlString(*pURI) : 0) + , m_bRebuild(true) { - OString o1 = OUStringToOString(aName, RTL_TEXTENCODING_UTF8); - xName = new xmlChar[o1.getLength()]; - strcpy((char*)xName, o1.getStr()); - OString o2 = OUStringToOString(aURI, RTL_TEXTENCODING_UTF8); - xURI = new xmlChar[o2.getLength()]; - strcpy((char*)xURI, o2.getStr()); - registerListener(aElement); + if (m_pElement.is()) { + registerListener(*m_pElement); + } } - void CElementList::registerListener(const CElement* pElement) + void CElementList::registerListener(CElement & rElement) { try { - // get the XNode - Reference< XNode > xNode(CNode::get(static_cast<const CNode*>(pElement)->m_aNodePtr)); - Reference< XEventTarget > xTarget(xNode, UNO_QUERY_THROW); + Reference< XEventTarget > const xTarget( + static_cast<XElement*>(& rElement), UNO_QUERY_THROW); OUString aType = OUString::createFromAscii("DOMSubtreeModified"); sal_Bool capture = sal_False; - xTarget->addEventListener(aType, Reference< XEventListener >(this), capture); + xTarget->addEventListener(aType, + Reference< XEventListener >(this), capture); } catch (Exception &e){ OString aMsg("Exception caught while registering NodeList as listener:\n"); aMsg += OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US); @@ -84,19 +84,24 @@ namespace DOM return; } else { m_nodevector.erase(m_nodevector.begin(), m_nodevector.end()); - m_bRebuild = sal_False; // don't rebuild until tree is mutated + m_bRebuild = false; // don't rebuild until tree is mutated } } while (pNode != NULL ) { - if (pNode->type == XML_ELEMENT_NODE && strcmp((char*)pNode->name, (char*)xName)==0) + if (pNode->type == XML_ELEMENT_NODE && + (strcmp((char*)pNode->name, (char*)m_pName.get()) == 0)) { - if (xURI == NULL) + if (!m_pURI) { m_nodevector.push_back(pNode); - else - if (pNode->ns != NULL && strcmp((char*)pNode->ns->href, (char*)xURI) == 0) + } else { + if (pNode->ns != NULL && (0 == + strcmp((char*)pNode->ns->href, (char*)m_pURI.get()))) + { m_nodevector.push_back(pNode); + } + } } if (pNode->children != NULL) buildlist(pNode->children, sal_False); @@ -110,24 +115,41 @@ namespace DOM */ sal_Int32 SAL_CALL CElementList::getLength() throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + + if (!m_pElement.is()) { return 0; } + // this has to be 'live' - buildlist(static_cast<const CNode*>(m_pElement)->m_aNodePtr); + buildlist(m_pElement->GetNodePtr()); return m_nodevector.size(); } /** Returns the indexth item in the collection. */ - Reference< XNode > SAL_CALL CElementList::item(sal_Int32 index) throw (RuntimeException) + Reference< XNode > SAL_CALL CElementList::item(sal_Int32 index) + throw (RuntimeException) { if (index < 0) throw RuntimeException(); - buildlist(static_cast<const CNode*>(m_pElement)->m_aNodePtr); - return Reference< XNode >(CNode::get(m_nodevector[index])); + + ::osl::MutexGuard const g(m_rMutex); + + if (!m_pElement.is()) { return 0; } + + buildlist(m_pElement->GetNodePtr()); + if (m_nodevector.size() <= static_cast<size_t>(index)) { + throw RuntimeException(); + } + Reference< XNode > const xRet( + m_pElement->GetOwnerDocument().GetCNode(m_nodevector[index]).get()); + return xRet; } // tree mutations can change the list - void SAL_CALL CElementList::handleEvent(const Reference< XEvent >& evt) throw (RuntimeException) + void SAL_CALL CElementList::handleEvent(Reference< XEvent > const&) + throw (RuntimeException) { - Reference< XEvent > aEvent = evt; - m_bRebuild = sal_True; + ::osl::MutexGuard const g(m_rMutex); + + m_bRebuild = true; } } diff --git a/unoxml/source/dom/elementlist.hxx b/unoxml/source/dom/elementlist.hxx index 0ebfd2722eea..95b9960e700f 100644 --- a/unoxml/source/dom/elementlist.hxx +++ b/unoxml/source/dom/elementlist.hxx @@ -25,22 +25,27 @@ * ************************************************************************/ -#ifndef _ELEMENTLIST_HXX -#define _ELEMENTLIST_HXX +#ifndef DOM_ELEMENTLIST_HXX +#define DOM_ELEMENTLIST_HXX #include <vector> + +#include <boost/scoped_array.hpp> + +#include <libxml/tree.h> + #include <sal/types.h> -#include <cppuhelper/implbase1.hxx> -#include <cppuhelper/implbase2.hxx> +#include <rtl/ref.hxx> + #include <com/sun/star/uno/Reference.h> #include <com/sun/star/uno/Exception.hpp> #include <com/sun/star/xml/dom/XNode.hpp> #include <com/sun/star/xml/dom/XNodeList.hpp> #include <com/sun/star/xml/dom/events/XEvent.hpp> #include <com/sun/star/xml/dom/events/XEventListener.hpp> -#include "element.hxx" -#include "document.hxx" -#include "libxml/tree.h" + +#include <cppuhelper/implbase2.hxx> + using ::rtl::OUString; using namespace com::sun::star::uno; @@ -49,26 +54,30 @@ using namespace com::sun::star::xml::dom::events; namespace DOM { - typedef std::vector< xmlNodePtr > nodevector; + class CElement; + + typedef std::vector< xmlNodePtr > nodevector_t; - class CElementList : public cppu::WeakImplHelper2< XNodeList, com::sun::star::xml::dom::events::XEventListener > + class CElementList + : public cppu::WeakImplHelper2< XNodeList, + com::sun::star::xml::dom::events::XEventListener > { private: - const CElement* m_pElement; - const OUString m_aName; - const OUString m_aURI; - xmlChar *xName; - xmlChar *xURI; - sal_Bool m_bRebuild; - nodevector m_nodevector; - + ::rtl::Reference<CElement> const m_pElement; + ::osl::Mutex & m_rMutex; + ::boost::scoped_array<xmlChar> const m_pName; + ::boost::scoped_array<xmlChar> const m_pURI; + bool m_bRebuild; + nodevector_t m_nodevector; void buildlist(xmlNodePtr pNode, sal_Bool start=sal_True); - void registerListener(const CElement* pElement); + void registerListener(CElement & rElement); public: - CElementList(const CElement* aDoc, const OUString& aName); - CElementList(const CElement* aDoc, const OUString& aName, const OUString& aURI); + CElementList(::rtl::Reference<CElement> const& pElement, + ::osl::Mutex & rMutex, + OUString const& rName, OUString const*const pURI = 0); + /** The number of nodes in the list. */ @@ -76,10 +85,12 @@ namespace DOM /** Returns the indexth item in the collection. */ - virtual Reference< XNode > SAL_CALL item(sal_Int32 index) throw (RuntimeException); + virtual Reference< XNode > SAL_CALL item(sal_Int32 index) + throw (RuntimeException); // XEventListener - virtual void SAL_CALL handleEvent(const Reference< XEvent >& evt) throw (RuntimeException); + virtual void SAL_CALL handleEvent(const Reference< XEvent >& evt) + throw (RuntimeException); }; } diff --git a/unoxml/source/dom/entitiesmap.cxx b/unoxml/source/dom/entitiesmap.cxx index 98db3d2c7395..aab2f5551332 100644 --- a/unoxml/source/dom/entitiesmap.cxx +++ b/unoxml/source/dom/entitiesmap.cxx @@ -25,12 +25,17 @@ * ************************************************************************/ -#include "entitiesmap.hxx" +#include <entitiesmap.hxx> + +#include <documenttype.hxx> + namespace DOM { - CEntitiesMap::CEntitiesMap(const CDocumentType* aDocType) - : m_pDocType(aDocType) + CEntitiesMap::CEntitiesMap(::rtl::Reference<CDocumentType> const& pDocType, + ::osl::Mutex & rMutex) + : m_pDocType(pDocType) + , m_rMutex(rMutex) { } @@ -39,62 +44,91 @@ namespace DOM */ sal_Int32 SAL_CALL CEntitiesMap::getLength() throw (RuntimeException) { + OSL_ENSURE(false, + "CEntitiesMap::getLength: not implemented (#i113683#)"); return 0; } /** Retrieves a node specified by local name */ - Reference< XNode > SAL_CALL CEntitiesMap::getNamedItem(const OUString& /*name*/) throw (RuntimeException) + Reference< XNode > SAL_CALL + CEntitiesMap::getNamedItem(OUString const& /*name*/) throw (RuntimeException) { + OSL_ENSURE(false, + "CEntitiesMap::getNamedItem: not implemented (#i113683#)"); return Reference< XNode >(); } /** Retrieves a node specified by local name and namespace URI. */ - Reference< XNode > SAL_CALL CEntitiesMap::getNamedItemNS(const OUString& /*namespaceURI*/,const OUString& /*localName*/) throw (RuntimeException) + Reference< XNode > SAL_CALL + CEntitiesMap::getNamedItemNS( + OUString const& /*namespaceURI*/, OUString const& /*localName*/) + throw (RuntimeException) { + OSL_ENSURE(false, + "CEntitiesMap::getNamedItemNS: not implemented (#i113683#)"); return Reference< XNode >(); } /** Returns the indexth item in the map. */ - Reference< XNode > SAL_CALL CEntitiesMap::item(sal_Int32 /*index*/) throw (RuntimeException) + Reference< XNode > SAL_CALL + CEntitiesMap::item(sal_Int32 /*index*/) throw (RuntimeException) { + OSL_ENSURE(false, "CEntitiesMap::item: not implemented (#i113683#)"); return Reference< XNode >(); } /** Removes a node specified by name. */ - Reference< XNode > SAL_CALL CEntitiesMap::removeNamedItem(const OUString& /*name*/) throw (RuntimeException) + Reference< XNode > SAL_CALL + CEntitiesMap::removeNamedItem(OUString const& /*name*/) + throw (RuntimeException) { + OSL_ENSURE(false, + "CEntitiesMap::removeNamedItem: not implemented (#i113683#)"); return Reference< XNode >(); } /** // Removes a node specified by local name and namespace URI. */ - Reference< XNode > SAL_CALL CEntitiesMap::removeNamedItemNS(const OUString& /*namespaceURI*/, const OUString& /*localName*/) throw (RuntimeException) + Reference< XNode > SAL_CALL + CEntitiesMap::removeNamedItemNS( + OUString const& /*namespaceURI*/, OUString const& /*localName*/) + throw (RuntimeException) { + OSL_ENSURE(false, + "CEntitiesMap::removeNamedItemNS: not implemented (#i113683#)"); return Reference< XNode >(); } /** // Adds a node using its nodeName attribute. */ - Reference< XNode > SAL_CALL CEntitiesMap::setNamedItem(const Reference< XNode >& /*arg*/) throw (RuntimeException) + Reference< XNode > SAL_CALL + CEntitiesMap::setNamedItem(Reference< XNode > const& /*arg*/) + throw (RuntimeException) { + OSL_ENSURE(false, + "CEntitiesMap::setNamedItem: not implemented (#i113683#)"); return Reference< XNode >(); } /** Adds a node using its namespaceURI and localName. */ - Reference< XNode > SAL_CALL CEntitiesMap::setNamedItemNS(const Reference< XNode >& /*arg*/) throw (RuntimeException) + Reference< XNode > SAL_CALL + CEntitiesMap::setNamedItemNS(Reference< XNode > const& /*arg*/) + throw (RuntimeException) { + OSL_ENSURE(false, + "CEntitiesMap::setNamedItemNS: not implemented (#i113683#)"); return Reference< XNode >(); } } diff --git a/unoxml/source/dom/entitiesmap.hxx b/unoxml/source/dom/entitiesmap.hxx index 8480f1e0eecd..468e897639db 100644 --- a/unoxml/source/dom/entitiesmap.hxx +++ b/unoxml/source/dom/entitiesmap.hxx @@ -25,32 +25,37 @@ * ************************************************************************/ -#ifndef _ENTITIESMAP_HXX -#define _ENTITIESMAP_HXX +#ifndef DOM_ENTITIESMAP_HXX +#define DOM_ENTITIESMAP_HXX -#include <map> #include <sal/types.h> -#include <cppuhelper/implbase1.hxx> +#include <rtl/ref.hxx> + #include <com/sun/star/uno/Reference.h> -#include <com/sun/star/uno/Exception.hpp> #include <com/sun/star/xml/dom/XNode.hpp> #include <com/sun/star/xml/dom/XNamedNodeMap.hpp> -#include "document.hxx" -#include "documenttype.hxx" + +#include <cppuhelper/implbase1.hxx> + using ::rtl::OUString; using namespace com::sun::star::uno; -using namespace com::sun::star::lang; using namespace com::sun::star::xml::dom; namespace DOM { - class CEntitiesMap : public cppu::WeakImplHelper1< XNamedNodeMap > + class CDocumentType; + + class CEntitiesMap + : public cppu::WeakImplHelper1< XNamedNodeMap > { private: - const CDocumentType* m_pDocType; + ::rtl::Reference<CDocumentType> const m_pDocType; + ::osl::Mutex & m_rMutex; + public: - CEntitiesMap(const CDocumentType* aDocType); + CEntitiesMap(::rtl::Reference<CDocumentType> const& pDocType, + ::osl::Mutex & rMutex); /** The number of nodes in this map. @@ -60,37 +65,48 @@ namespace DOM /** Retrieves a node specified by local name */ - virtual Reference< XNode > SAL_CALL getNamedItem(const OUString& name) throw (RuntimeException); + virtual Reference< XNode > SAL_CALL + getNamedItem(const OUString& name) throw (RuntimeException); /** Retrieves a node specified by local name and namespace URI. */ - virtual Reference< XNode > SAL_CALL getNamedItemNS(const OUString& namespaceURI, const OUString& localName) throw (RuntimeException); + virtual Reference< XNode > SAL_CALL getNamedItemNS( + OUString const& namespaceURI, OUString const& localName) + throw (RuntimeException); /** Returns the indexth item in the map. */ - virtual Reference< XNode > SAL_CALL item(sal_Int32 index) throw (RuntimeException); + virtual Reference< XNode > SAL_CALL + item(sal_Int32 index) throw (RuntimeException); /** Removes a node specified by name. */ - virtual Reference< XNode > SAL_CALL removeNamedItem(const OUString& name) throw (RuntimeException); + virtual Reference< XNode > SAL_CALL + removeNamedItem(OUString const& name) throw (RuntimeException); /** // Removes a node specified by local name and namespace URI. */ - virtual Reference< XNode > SAL_CALL removeNamedItemNS(const OUString& namespaceURI, const OUString& localName) throw (RuntimeException); + virtual Reference< XNode > SAL_CALL removeNamedItemNS( + OUString const& namespaceURI, OUString const& localName) + throw (RuntimeException); /** // Adds a node using its nodeName attribute. */ - virtual Reference< XNode > SAL_CALL setNamedItem(const Reference< XNode >& arg) throw (RuntimeException); + virtual Reference< XNode > SAL_CALL + setNamedItem(Reference< XNode > const& arg) + throw (RuntimeException); /** Adds a node using its namespaceURI and localName. */ - virtual Reference< XNode > SAL_CALL setNamedItemNS(const Reference< XNode >& arg) throw (RuntimeException); + virtual Reference< XNode > SAL_CALL + setNamedItemNS(Reference< XNode > const& arg) + throw (RuntimeException); }; } diff --git a/unoxml/source/dom/entity.cxx b/unoxml/source/dom/entity.cxx index de711ae62d8d..3fb1790ab621 100644 --- a/unoxml/source/dom/entity.cxx +++ b/unoxml/source/dom/entity.cxx @@ -25,18 +25,35 @@ * ************************************************************************/ -#include "entity.hxx" +#include <entity.hxx> #include <string.h> + namespace DOM { - CEntity::CEntity(const xmlEntityPtr aEntityPtr) + CEntity::CEntity(CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlEntityPtr const pEntity) + : CEntity_Base(rDocument, rMutex, + NodeType_ENTITY_NODE, reinterpret_cast<xmlNodePtr>(pEntity)) + , m_aEntityPtr(pEntity) + { + } + + bool CEntity::IsChildTypeAllowed(NodeType const nodeType) { - m_aNodeType = NodeType_ENTITY_NODE; - m_aEntityPtr = aEntityPtr; - init_node((xmlNodePtr)aEntityPtr); + switch (nodeType) { + case NodeType_ELEMENT_NODE: + case NodeType_PROCESSING_INSTRUCTION_NODE: + case NodeType_COMMENT_NODE: + case NodeType_TEXT_NODE: + case NodeType_CDATA_SECTION_NODE: + case NodeType_ENTITY_REFERENCE_NODE: + return true; + default: + return false; + } } /** @@ -44,7 +61,8 @@ namespace DOM */ OUString SAL_CALL CEntity::getNotationName() throw (RuntimeException) { - // XXX + OSL_ENSURE(false, + "CEntity::getNotationName: not implemented (#i113683#)"); return OUString(); } @@ -53,6 +71,8 @@ namespace DOM */ OUString SAL_CALL CEntity::getPublicId() throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + OUString aID; if(m_aEntityPtr != NULL) { @@ -66,6 +86,8 @@ namespace DOM */ OUString SAL_CALL CEntity::getSystemId() throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + OUString aID; if(m_aEntityPtr != NULL) { @@ -75,6 +97,8 @@ namespace DOM } OUString SAL_CALL CEntity::getNodeName()throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + OUString aName; if (m_aNodePtr != NULL) { diff --git a/unoxml/source/dom/entity.hxx b/unoxml/source/dom/entity.hxx index 0343a13dda16..671ad8af91cf 100644 --- a/unoxml/source/dom/entity.hxx +++ b/unoxml/source/dom/entity.hxx @@ -25,16 +25,19 @@ * ************************************************************************/ -#ifndef _ENTITY_HXX -#define _ENTITY_HXX +#ifndef DOM_ENTITY_HXX +#define DOM_ENTITY_HXX + +#include <libxml/tree.h> +#include <libxml/entities.h> #include <sal/types.h> + #include <com/sun/star/uno/Reference.h> -#include <com/sun/star/uno/Exception.hpp> #include <com/sun/star/xml/dom/XEntity.hpp> -#include "node.hxx" -#include <libxml/tree.h> -#include <libxml/entities.h> + +#include <node.hxx> + using ::rtl::OUString; using namespace com::sun::star::uno; @@ -42,16 +45,23 @@ using namespace com::sun::star::xml::dom; namespace DOM { - class CEntity : public cppu::ImplInheritanceHelper1< CNode, XEntity > + typedef ::cppu::ImplInheritanceHelper1< CNode, XEntity > CEntity_Base; + + class CEntity + : public CEntity_Base { - friend class CNode; + private: + friend class CDocument; + private: xmlEntityPtr m_aEntityPtr; protected: - CEntity(const xmlEntityPtr aEntityPtr); + CEntity(CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlEntityPtr const pEntity); public: + virtual bool IsChildTypeAllowed(NodeType const nodeType); /** For unparsed entities, the name of the notation for the entity. diff --git a/unoxml/source/dom/entityreference.cxx b/unoxml/source/dom/entityreference.cxx index 6cdce0c8ed3d..0dda6bc3f495 100644 --- a/unoxml/source/dom/entityreference.cxx +++ b/unoxml/source/dom/entityreference.cxx @@ -25,18 +25,39 @@ * ************************************************************************/ -#include "entityreference.hxx" +#include <entityreference.hxx> + #include <string.h> namespace DOM { - CEntityReference::CEntityReference(const xmlNodePtr aNodePtr) + CEntityReference::CEntityReference( + CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlNodePtr const pNode) + : CEntityReference_Base(rDocument, rMutex, + NodeType_ENTITY_REFERENCE_NODE, pNode) + { + } + + bool CEntityReference::IsChildTypeAllowed(NodeType const nodeType) { - m_aNodeType = NodeType_ENTITY_REFERENCE_NODE; - init_node(aNodePtr); + switch (nodeType) { + case NodeType_ELEMENT_NODE: + case NodeType_PROCESSING_INSTRUCTION_NODE: + case NodeType_COMMENT_NODE: + case NodeType_TEXT_NODE: + case NodeType_CDATA_SECTION_NODE: + case NodeType_ENTITY_REFERENCE_NODE: + return true; + default: + return false; + } } + OUString SAL_CALL CEntityReference::getNodeName()throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + OUString aName; if (m_aNodePtr != NULL) { @@ -45,6 +66,7 @@ namespace DOM } return aName; } + OUString SAL_CALL CEntityReference::getNodeValue() throw (RuntimeException) { return OUString(); diff --git a/unoxml/source/dom/entityreference.hxx b/unoxml/source/dom/entityreference.hxx index 1ab8217bc628..d4e349076453 100644 --- a/unoxml/source/dom/entityreference.hxx +++ b/unoxml/source/dom/entityreference.hxx @@ -25,13 +25,16 @@ * ************************************************************************/ -#ifndef _ENTITYREFERENCE_HXX -#define _ENTITYREFERENCE_HXX +#ifndef DOM_ENTITYREFERENCE_HXX +#define DOM_ENTITYREFERENCE_HXX + +#include <libxml/tree.h> + #include <com/sun/star/uno/Reference.h> -#include <com/sun/star/uno/Exception.hpp> #include <com/sun/star/xml/dom/XEntityReference.hpp> -#include "node.hxx" -#include <libxml/tree.h> + +#include <node.hxx> + using ::rtl::OUString; using namespace com::sun::star::uno; @@ -39,13 +42,23 @@ using namespace com::sun::star::xml::dom; namespace DOM { - class CEntityReference : public cppu::ImplInheritanceHelper1< CNode, XEntityReference > + typedef ::cppu::ImplInheritanceHelper1< CNode, XEntityReference > + CEntityReference_Base; + + class CEntityReference + : public CEntityReference_Base { - friend class CNode; + private: + friend class CDocument; + protected: - CEntityReference(const xmlNodePtr aNodePtr); + CEntityReference( + CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlNodePtr const pNode); public: + virtual bool IsChildTypeAllowed(NodeType const nodeType); + // ---- resolve uno inheritance problems... // overrides for XNode base virtual OUString SAL_CALL getNodeName() diff --git a/unoxml/source/dom/makefile.mk b/unoxml/source/dom/makefile.mk deleted file mode 100644 index 32a35ebfd54b..000000000000 --- a/unoxml/source/dom/makefile.mk +++ /dev/null @@ -1,74 +0,0 @@ -#************************************************************************* -# -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# Copyright 2000, 2010 Oracle and/or its affiliates. -# -# OpenOffice.org - a multi-platform office productivity suite -# -# 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. -# -#************************************************************************* - -PRJ=..$/.. - -PRJNAME=unoxml -TARGET=domimpl - -ENABLE_EXCEPTIONS=TRUE - -# --- Settings ----------------------------------------------------- - -.INCLUDE : settings.mk - -.IF "$(SYSTEM_LIBXML)" == "YES" -CFLAGS+=-DSYSTEM_LIBXML $(LIBXML_CFLAGS) -.ENDIF - -# --- Files -------------------------------------------------------- - -SLOFILES = \ - $(SLO)$/attr.obj \ - $(SLO)$/cdatasection.obj \ - $(SLO)$/characterdata.obj \ - $(SLO)$/comment.obj \ - $(SLO)$/document.obj \ - $(SLO)$/documentbuilder.obj \ - $(SLO)$/documentfragment.obj \ - $(SLO)$/documenttype.obj \ - $(SLO)$/element.obj \ - $(SLO)$/entity.obj \ - $(SLO)$/entityreference.obj \ - $(SLO)$/node.obj \ - $(SLO)$/notation.obj \ - $(SLO)$/processinginstruction.obj \ - $(SLO)$/text.obj \ - $(SLO)$/domimplementation.obj \ - $(SLO)$/elementlist.obj \ - $(SLO)$/childlist.obj \ - $(SLO)$/notationsmap.obj \ - $(SLO)$/entitiesmap.obj \ - $(SLO)$/attributesmap.obj \ - $(SLO)$/saxbuilder.obj - - -# --- Targets ------------------------------------------------------ - -.INCLUDE : target.mk - - diff --git a/unoxml/source/dom/node.cxx b/unoxml/source/dom/node.cxx index d4b317b425b3..fb95fa6ade02 100644 --- a/unoxml/source/dom/node.cxx +++ b/unoxml/source/dom/node.cxx @@ -25,35 +25,47 @@ * ************************************************************************/ +#include <node.hxx> + #include <stdio.h> #include <string.h> -#include "node.hxx" -#include "element.hxx" -#include "text.hxx" -#include "cdatasection.hxx" -#include "entityreference.hxx" -#include "entity.hxx" -#include "processinginstruction.hxx" -#include "comment.hxx" -#include "document.hxx" -#include "documenttype.hxx" -#include "documentfragment.hxx" -#include "notation.hxx" -#include "childlist.hxx" -#include "attr.hxx" + +#include <libxml/xmlstring.h> + +#include <algorithm> + +#include <boost/bind.hpp> + +#include <rtl/uuid.h> +#include <rtl/instance.hxx> +#include <osl/mutex.hxx> #include <com/sun/star/xml/sax/FastToken.hpp> -#include "rtl/instance.hxx" -#include "osl/mutex.hxx" + +#include <document.hxx> +#include <attr.hxx> +#include <childlist.hxx> + #include "../events/eventdispatcher.hxx" #include "../events/mutationevent.hxx" -#include <boost/bind.hpp> -#include <algorithm> + + +using namespace ::com::sun::star; + namespace { -//see CNode::remove - struct NodeMutex: public ::rtl::Static<osl::Mutex, NodeMutex> {}; + struct UnoTunnelId + : public ::rtl::StaticWithInit< Sequence<sal_Int8>, UnoTunnelId > + { + Sequence<sal_Int8> operator() () + { + Sequence<sal_Int8> ret(16); + rtl_createUuid( + reinterpret_cast<sal_uInt8*>(ret.getArray()), 0, sal_True); + return ret; + } + }; } namespace DOM @@ -133,160 +145,64 @@ namespace DOM } - nodemap_t CNode::theNodeMap; - - void CNode::remove(const xmlNodePtr aNode) + CNode::CNode(CDocument const& rDocument, ::osl::Mutex const& rMutex, + NodeType const& reNodeType, xmlNodePtr const& rpNode) + : m_bUnlinked(false) + , m_aNodeType(reNodeType) + , m_aNodePtr(rpNode) + // keep containing document alive + // (but not if this is a document; that would create a leak!) + , m_xDocument( (m_aNodePtr->type != XML_DOCUMENT_NODE) + ? &const_cast<CDocument&>(rDocument) : 0 ) + , m_rMutex(const_cast< ::osl::Mutex & >(rMutex)) { - //Using the guard here protects against races when at the same time - //CNode::get() is called. This fix helps in many cases but is still - //incorrect. remove is called from ~CNode. That is, while the object - //is being destructed it can still be obtained by calling CNode::get(). - //Another bug currently prevents the correct destruction of CNodes. So - //the destructor is rarely called. - // - //Doing this right would probably mean to store WeakReferences in the - //map and also guard oder functions. To keep the risk at a minimum - //we keep this imperfect fix for the upcoming release and fix it later - //properly (http://qa.openoffice.org/issues/show_bug.cgi?id=113682) - ::osl::MutexGuard guard(NodeMutex::get()); - nodemap_t::iterator i = CNode::theNodeMap.find(aNode); - if (i != CNode::theNodeMap.end()) - { - // CNode *pNode = i->second; - CNode::theNodeMap.erase(i); - } + OSL_ASSERT(m_aNodePtr); } - - CNode* CNode::get(const xmlNodePtr aNode, sal_Bool bCreate) + void CNode::invalidate() { - CNode* pNode = 0; - if (aNode == NULL) - return 0; - //see CNode::remove - ::osl::MutexGuard guard(NodeMutex::get()); - //check whether there is already an instance for this node - nodemap_t::const_iterator i = CNode::theNodeMap.find(aNode); - if (i != CNode::theNodeMap.end()) - { - pNode = i->second; - } else - { - - // there is not yet an instance wrapping this node, - // create it and store it in the map - if (!bCreate) return NULL; - - switch (aNode->type) - { - case XML_ELEMENT_NODE: - // m_aNodeType = NodeType::ELEMENT_NODE; - pNode = static_cast< CNode* >(new CElement(aNode)); - break; - case XML_TEXT_NODE: - // m_aNodeType = NodeType::TEXT_NODE; - pNode = static_cast< CNode* >(new CText(aNode)); - break; - case XML_CDATA_SECTION_NODE: - // m_aNodeType = NodeType::CDATA_SECTION_NODE; - pNode = static_cast< CNode* >(new CCDATASection(aNode)); - break; - case XML_ENTITY_REF_NODE: - // m_aNodeType = NodeType::ENTITY_REFERENCE_NODE; - pNode = static_cast< CNode* >(new CEntityReference(aNode)); - break; - case XML_ENTITY_NODE: - // m_aNodeType = NodeType::ENTITY_NODE; - pNode = static_cast< CNode* >(new CEntity((xmlEntityPtr)aNode)); - break; - case XML_PI_NODE: - // m_aNodeType = NodeType::PROCESSING_INSTRUCTION_NODE; - pNode = static_cast< CNode* >(new CProcessingInstruction(aNode)); - break; - case XML_COMMENT_NODE: - // m_aNodeType = NodeType::COMMENT_NODE; - pNode = static_cast< CNode* >(new CComment(aNode)); - break; - case XML_DOCUMENT_NODE: - // m_aNodeType = NodeType::DOCUMENT_NODE; - pNode = static_cast< CNode* >(new CDocument((xmlDocPtr)aNode)); - break; - case XML_DOCUMENT_TYPE_NODE: - case XML_DTD_NODE: - // m_aNodeType = NodeType::DOCUMENT_TYPE_NODE; - pNode = static_cast< CNode* >(new CDocumentType((xmlDtdPtr)aNode)); - break; - case XML_DOCUMENT_FRAG_NODE: - // m_aNodeType = NodeType::DOCUMENT_FRAGMENT_NODE; - pNode = static_cast< CNode* >(new CDocumentFragment(aNode)); - break; - case XML_NOTATION_NODE: - // m_aNodeType = NodeType::NOTATION_NODE; - pNode = static_cast< CNode* >(new CNotation((xmlNotationPtr)aNode)); - break; - case XML_ATTRIBUTE_NODE: - // m_aNodeType = NodeType::NOTATION_NODE; - pNode = static_cast< CNode* >(new CAttr((xmlAttrPtr)aNode)); - break; - // unsupported node types - case XML_HTML_DOCUMENT_NODE: - case XML_ELEMENT_DECL: - case XML_ATTRIBUTE_DECL: - case XML_ENTITY_DECL: - case XML_NAMESPACE_DECL: - default: - pNode = 0; - break; - } - - if ( pNode != 0 ) - { - if(!CNode::theNodeMap.insert(nodemap_t::value_type(aNode, pNode)).second) - { - // if insertion failed, delete the new instance and return null - delete pNode; - pNode = 0; - } - } + //remove from list if this wrapper goes away + if (m_aNodePtr != 0 && m_xDocument.is()) { + m_xDocument->RemoveCNode(m_aNodePtr, this); + } + // #i113663#: unlinked nodes will not be freed by xmlFreeDoc + if (m_bUnlinked) { + xmlFreeNode(m_aNodePtr); } - OSL_ENSURE(pNode, "no node produced during CNode::get!"); - return pNode; + m_aNodePtr = 0; } - xmlNodePtr CNode::getNodePtr(const Reference< XNode >& aNode) + CNode::~CNode() { - try { - CNode* pNode=dynamic_cast<CNode*>(aNode.get()); - if( pNode ) - return pNode->m_aNodePtr; - } - catch(...) {} - return 0; + // if this is the document itself, the mutex is already freed! + if (NodeType_DOCUMENT_NODE == m_aNodeType) { + invalidate(); + } else { + ::osl::MutexGuard const g(m_rMutex); + invalidate(); // other nodes are still alive so must lock mutex + } } - CNode::CNode() - : m_aNodePtr(0) + CNode * + CNode::GetImplementation(uno::Reference<uno::XInterface> const& xNode) { + uno::Reference<lang::XUnoTunnel> const xUnoTunnel(xNode, UNO_QUERY); + if (!xUnoTunnel.is()) { return 0; } + CNode *const pCNode( reinterpret_cast< CNode* >( + ::sal::static_int_cast< sal_IntPtr >( + xUnoTunnel->getSomething(UnoTunnelId::get())))); + return pCNode; } - void CNode::init_node(const xmlNodePtr aNode) + CDocument & CNode::GetOwnerDocument() { - m_aNodePtr = aNode; - - // keep containing document alive - // (if we are not that document ourselves) - if (m_aNodePtr->type != XML_DOCUMENT_NODE) - m_rDocument = getOwnerDocument(); + OSL_ASSERT(m_xDocument.is()); + return *m_xDocument; // needs overriding in CDocument! } - CNode::~CNode() - { - //remove from list if this wrapper goes away - if (m_aNodePtr != 0) - CNode::remove(m_aNodePtr); - } - static void _nsexchange(const xmlNodePtr aNode, xmlNsPtr oldNs, xmlNsPtr newNs) + static void lcl_nsexchange( + xmlNodePtr const aNode, xmlNsPtr const oldNs, xmlNsPtr const newNs) { // recursively exchange any references to oldNs with references to newNs xmlNodePtr cur = aNode; @@ -303,13 +219,13 @@ namespace DOM curAttr->ns = newNs; curAttr = curAttr->next; } - _nsexchange(cur->children, oldNs, newNs); + lcl_nsexchange(cur->children, oldNs, newNs); } cur = cur->next; } } - /*static*/ void _nscleanup(const xmlNodePtr aNode, const xmlNodePtr aParent) + /*static*/ void nscleanup(const xmlNodePtr aNode, const xmlNodePtr aParent) { xmlNodePtr cur = aNode; @@ -331,7 +247,7 @@ namespace DOM while (cur != NULL) { - _nscleanup(cur->children, cur); + nscleanup(cur->children, cur); if (cur->ns != NULL) { xmlNsPtr ns = xmlSearchNs(cur->doc, aParent, cur->ns->prefix); @@ -346,7 +262,7 @@ namespace DOM { // reconnect ns pointers in sub-tree to newly found ns before // removing redundant nsdecl to prevent dangling pointers. - _nsexchange(cur, curDef, ns); + lcl_nsexchange(cur, curDef, ns); *refp = curDef->next; xmlFreeNs(curDef); curDef = *refp; @@ -361,184 +277,187 @@ namespace DOM } } - void SAL_CALL CNode::saxify( - const Reference< XDocumentHandler >& i_xHandler) { + void CNode::saxify(const Reference< XDocumentHandler >& i_xHandler) + { if (!i_xHandler.is()) throw RuntimeException(); // default: do nothing } - void SAL_CALL CNode::fastSaxify(Context& io_rContext) { + void CNode::fastSaxify(Context& io_rContext) + { if (!io_rContext.mxDocHandler.is()) throw RuntimeException(); // default: do nothing } + bool CNode::IsChildTypeAllowed(NodeType const /*nodeType*/) + { + // default: no children allowed + return false; + } + /** Adds the node newChild to the end of the list of children of this node. */ - Reference< XNode > CNode::appendChild(const Reference< XNode >& newChild) + Reference< XNode > SAL_CALL CNode::appendChild( + Reference< XNode > const& xNewChild) throw (RuntimeException, DOMException) { - Reference< XNode> aNode; - if (m_aNodePtr != NULL) { - xmlNodePtr cur = CNode::getNodePtr(newChild.get()); + ::osl::ClearableMutexGuard guard(m_rMutex); - // error checks: - // from other document - if (cur->doc != m_aNodePtr->doc) { - DOMException e; - e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR; - throw e; - } - // same node - if (cur == m_aNodePtr) { - DOMException e; - e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; - throw e; - } - // already has parant and is not attribute - if (cur->parent != NULL && cur->type != XML_ATTRIBUTE_NODE) { - DOMException e; - e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; - throw e; - } + if (0 == m_aNodePtr) { return 0; } - // check whether this is an attribute node so we remove it's - // carrier node if it has one - xmlNodePtr res = NULL; - if (cur->type == XML_ATTRIBUTE_NODE) - { - if (cur->parent != NULL) - { - if (m_aNodePtr->type != XML_ELEMENT_NODE || - strcmp((char*)cur->parent->name, "__private") != 0) - { - DOMException e; - e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; - throw e; - } - - xmlNsPtr pAttrNs = cur->ns; - xmlNsPtr pParentNs = xmlSearchNs(m_aNodePtr->doc, m_aNodePtr, pAttrNs->prefix); - if (pParentNs == NULL || strcmp((char*)pParentNs->href, (char*)pAttrNs->href) != 0) - pParentNs = xmlNewNs(m_aNodePtr, pAttrNs->href, pAttrNs->prefix); + CNode *const pNewChild(CNode::GetImplementation(xNewChild)); + if (!pNewChild) { throw RuntimeException(); } + xmlNodePtr const cur = pNewChild->GetNodePtr(); + if (!cur) { throw RuntimeException(); } - if (cur->children != NULL) - res = (xmlNodePtr)xmlNewNsProp(m_aNodePtr, pParentNs, cur->name, cur->children->content); - else - res = (xmlNodePtr)xmlNewProp(m_aNodePtr, cur->name, (xmlChar*) ""); + // error checks: + // from other document + if (cur->doc != m_aNodePtr->doc) { + DOMException e; + e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR; + throw e; + } + // same node + if (cur == m_aNodePtr) { + DOMException e; + e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; + throw e; + } + if (cur->parent != NULL) { + DOMException e; + e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; + throw e; + } + if (!IsChildTypeAllowed(pNewChild->m_aNodeType)) { + DOMException e; + e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; + throw e; + } - xmlFreeNode(cur->parent); - cur->parent = NULL; - } - else - { - if (cur->children != NULL) - res = (xmlNodePtr)xmlNewProp(m_aNodePtr, cur->name, cur->children->content); - else - res = (xmlNodePtr)xmlNewProp(m_aNodePtr, cur->name, (xmlChar*) ""); - } - } - else - { - res = xmlAddChild(m_aNodePtr, cur); + // check whether this is an attribute node; it needs special handling + xmlNodePtr res = NULL; + if (cur->type == XML_ATTRIBUTE_NODE) + { + xmlChar const*const pChildren((cur->children) + ? cur->children->content + : reinterpret_cast<xmlChar const*>("")); + CAttr *const pCAttr(dynamic_cast<CAttr *>(pNewChild)); + if (!pCAttr) { throw RuntimeException(); } + xmlNsPtr const pNs( pCAttr->GetNamespace(m_aNodePtr) ); + if (pNs) { + res = reinterpret_cast<xmlNodePtr>( + xmlNewNsProp(m_aNodePtr, pNs, cur->name, pChildren)); + } else { + res = reinterpret_cast<xmlNodePtr>( + xmlNewProp(m_aNodePtr, cur->name, pChildren)); } + } + else + { + res = xmlAddChild(m_aNodePtr, cur); - // libxml can do optimizations, when appending nodes. + // libxml can do optimization when appending nodes. // if res != cur, something was optimized and the newchild-wrapper // should be updated - if (cur != res) - CNode::remove(cur); + if (res && (cur != res)) { + pNewChild->invalidate(); // cur has been freed + } + } + + if (!res) { return 0; } - // use custom ns cleanup instaead of - // xmlReconciliateNs(m_aNodePtr->doc, m_aNodePtr); + // use custom ns cleanup instead of + // xmlReconciliateNs(m_aNodePtr->doc, m_aNodePtr); // because that will not remove unneeded ns decls - _nscleanup(res, m_aNodePtr); + nscleanup(res, m_aNodePtr); - aNode = Reference< XNode>(CNode::get(res)); - } - //XXX check for errors + ::rtl::Reference<CNode> const pNode = GetOwnerDocument().GetCNode(res); + + if (!pNode.is()) { return 0; } // dispatch DOMNodeInserted event, target is the new node // this node is the related node // does bubble - if (aNode.is()) - { - Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY); - Reference< XMutationEvent > event(docevent->createEvent( - OUString::createFromAscii("DOMNodeInserted")), UNO_QUERY); - event->initMutationEvent(OUString::createFromAscii("DOMNodeInserted") - , sal_True, sal_False, Reference< XNode >(CNode::get(m_aNodePtr)), - OUString(), OUString(), OUString(), (AttrChangeType)0 ); - dispatchEvent(Reference< XEvent >(event, UNO_QUERY)); + pNode->m_bUnlinked = false; // will be deleted by xmlFreeDoc + Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY); + Reference< XMutationEvent > event(docevent->createEvent( + OUString::createFromAscii("DOMNodeInserted")), UNO_QUERY); + event->initMutationEvent(OUString::createFromAscii("DOMNodeInserted") + , sal_True, sal_False, + this, + OUString(), OUString(), OUString(), (AttrChangeType)0 ); - // dispatch subtree modified for this node - dispatchSubtreeModified(); - } - return aNode; + // the following dispatch functions use only UNO interfaces + // and call event listeners, so release mutex to prevent deadlocks. + guard.clear(); + + dispatchEvent(Reference< XEvent >(event, UNO_QUERY)); + // dispatch subtree modified for this node + dispatchSubtreeModified(); + + return pNode.get(); } /** Returns a duplicate of this node, i.e., serves as a generic copy constructor for nodes. */ - Reference< XNode > CNode::cloneNode(sal_Bool bDeep) + Reference< XNode > SAL_CALL CNode::cloneNode(sal_Bool bDeep) throw (RuntimeException) { - Reference< XNode> aNode; - if (m_aNodePtr != NULL) - { - aNode = Reference< XNode>(CNode::get( - xmlCopyNode (m_aNodePtr, static_cast< int >(bDeep)) - )); + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return 0; } - //XXX check for errors - return aNode; + ::rtl::Reference<CNode> const pNode = GetOwnerDocument().GetCNode( + xmlCopyNode(m_aNodePtr, (bDeep) ? 1 : 0)); + if (!pNode.is()) { return 0; } + pNode->m_bUnlinked = true; // not linked yet + return pNode.get(); } /** A NamedNodeMap containing the attributes of this node (if it is an Element) or null otherwise. */ - Reference< XNamedNodeMap > CNode::getAttributes() + Reference< XNamedNodeMap > SAL_CALL CNode::getAttributes() throw (RuntimeException) { - // return empty reference - // only element node may override this impl + // return empty reference; only element node may override this impl return Reference< XNamedNodeMap>(); - - // get all children that are attributes - /* --> CElement - Reference< NamedNodeMap > aNodeMap(new AttributeNamedNodeMap(m_aNodePtr), UNO_QUERY); - return aNodeMap; - */ } /** A NodeList that contains all children of this node. */ - Reference< XNodeList > CNode::getChildNodes() + Reference< XNodeList > SAL_CALL CNode::getChildNodes() throw (RuntimeException) { - Reference< XNodeList > aNodeList; - if (m_aNodePtr != NULL) - { - aNodeList = Reference< XNodeList >(new CChildList(CNode::get(m_aNodePtr))); + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return 0; } - // XXX check for errors? - return aNodeList; + Reference< XNodeList > const xNodeList(new CChildList(this, m_rMutex)); + return xNodeList; } /** The first child of this node. */ - Reference< XNode > CNode::getFirstChild() + Reference< XNode > SAL_CALL CNode::getFirstChild() throw (RuntimeException) { - Reference< XNode > aNode; - if (m_aNodePtr != NULL) { - aNode = Reference< XNode >(CNode::get(m_aNodePtr->children)); + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return 0; } - return aNode; + Reference< XNode > const xNode( + GetOwnerDocument().GetCNode(m_aNodePtr->children).get()); + return xNode; } /** @@ -547,11 +466,14 @@ namespace DOM Reference< XNode > SAL_CALL CNode::getLastChild() throw (RuntimeException) { - Reference< XNode > aNode; - if (m_aNodePtr != NULL) { - aNode = Reference< XNode >(CNode::get(xmlGetLastChild(m_aNodePtr))); + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return 0; } - return aNode; + Reference< XNode > const xNode( + GetOwnerDocument().GetCNode(xmlGetLastChild(m_aNodePtr)).get()); + return xNode; } /** @@ -560,17 +482,8 @@ namespace DOM OUString SAL_CALL CNode::getLocalName() throw (RuntimeException) { - OUString aName; - /* - --> Element / Attribute - if(m_aNodePtr != NULL && (m_aNodeType == NodeType::ATTRIBUTE_NODE - || m_aNodeType == NodeType::ELEMENT_NODE)) - { - aName = OUString(m_aNodePtr->name, RTL_TEXTENCODING_UTF8); - } - //XXX error checking - */ - return aName; + // see CElement/CAttr + return ::rtl::OUString(); } @@ -580,6 +493,8 @@ namespace DOM OUString SAL_CALL CNode::getNamespaceURI() throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + OUString aURI; if (m_aNodePtr != NULL && (m_aNodePtr->type == XML_ELEMENT_NODE || m_aNodePtr->type == XML_ATTRIBUTE_NODE) && @@ -597,12 +512,14 @@ namespace DOM Reference< XNode > SAL_CALL CNode::getNextSibling() throw (RuntimeException) { - Reference< XNode > aNode; - if(m_aNodePtr != NULL) - { - aNode = Reference< XNode >(CNode::get(m_aNodePtr->next)); + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return 0; } - return aNode; + Reference< XNode > const xNode( + GetOwnerDocument().GetCNode(m_aNodePtr->next).get()); + return xNode; } /** @@ -639,6 +556,8 @@ namespace DOM NodeType SAL_CALL CNode::getNodeType() throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + return m_aNodeType; } @@ -658,14 +577,13 @@ namespace DOM Reference< XDocument > SAL_CALL CNode::getOwnerDocument() throw (RuntimeException) { - Reference<XDocument> aDoc; - if (m_aNodePtr != NULL) - { - aDoc = Reference< XDocument >(static_cast< CDocument* >( - CNode::get((xmlNodePtr)m_aNodePtr->doc))); - } - return aDoc; + ::osl::MutexGuard const g(m_rMutex); + if (0 == m_aNodePtr) { + return 0; + } + Reference< XDocument > const xDoc(& GetOwnerDocument()); + return xDoc; } /** @@ -674,12 +592,14 @@ namespace DOM Reference< XNode > SAL_CALL CNode::getParentNode() throw (RuntimeException) { - Reference<XNode> aNode; - if (m_aNodePtr != NULL) - { - aNode = Reference< XNode >(CNode::get(m_aNodePtr->parent)); + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return 0; } - return aNode; + Reference< XNode > const xNode( + GetOwnerDocument().GetCNode(m_aNodePtr->parent).get()); + return xNode; } /** @@ -688,6 +608,8 @@ namespace DOM OUString SAL_CALL CNode::getPrefix() throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + OUString aPrefix; if (m_aNodePtr != NULL && (m_aNodePtr->type == XML_ELEMENT_NODE || m_aNodePtr->type == XML_ATTRIBUTE_NODE) && @@ -707,12 +629,14 @@ namespace DOM Reference< XNode > SAL_CALL CNode::getPreviousSibling() throw (RuntimeException) { - Reference< XNode > aNode; - if (m_aNodePtr != NULL) - { - aNode = Reference< XNode >(CNode::get(m_aNodePtr->prev)); + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return 0; } - return aNode; + Reference< XNode > const xNode( + GetOwnerDocument().GetCNode(m_aNodePtr->prev).get()); + return xNode; } /** @@ -721,6 +645,8 @@ namespace DOM sal_Bool SAL_CALL CNode::hasAttributes() throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + return (m_aNodePtr != NULL && m_aNodePtr->properties != NULL); } @@ -730,6 +656,8 @@ namespace DOM sal_Bool SAL_CALL CNode::hasChildNodes() throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + return (m_aNodePtr != NULL && m_aNodePtr->children != NULL); } @@ -740,6 +668,7 @@ namespace DOM const Reference< XNode >& newChild, const Reference< XNode >& refChild) throw (RuntimeException, DOMException) { + if (!newChild.is() || !refChild.is()) { throw RuntimeException(); } if (newChild->getOwnerDocument() != getOwnerDocument()) { DOMException e; @@ -752,11 +681,42 @@ namespace DOM throw e; } - xmlNodePtr pRefChild = CNode::getNodePtr(refChild.get()); - xmlNodePtr pNewChild = CNode::getNodePtr(newChild.get()); + ::osl::ClearableMutexGuard guard(m_rMutex); + + CNode *const pNewNode(CNode::GetImplementation(newChild)); + CNode *const pRefNode(CNode::GetImplementation(refChild)); + if (!pNewNode || !pRefNode) { throw RuntimeException(); } + xmlNodePtr const pNewChild(pNewNode->GetNodePtr()); + xmlNodePtr const pRefChild(pRefNode->GetNodePtr()); + if (!pNewChild || !pRefChild) { throw RuntimeException(); } + + if (pNewChild == m_aNodePtr) { + DOMException e; + e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; + throw e; + } + // already has parent + if (pNewChild->parent != NULL) + { + DOMException e; + e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; + throw e; + } + if (!IsChildTypeAllowed(pNewNode->m_aNodeType)) { + DOMException e; + e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; + throw e; + } + + // attributes are unordered anyway, so just do appendChild + if (XML_ATTRIBUTE_NODE == pNewChild->type) { + guard.clear(); + return appendChild(newChild); + } + xmlNodePtr cur = m_aNodePtr->children; - //search cild before which to insert + //search child before which to insert while (cur != NULL) { if (cur == pRefChild) { @@ -764,8 +724,16 @@ namespace DOM pNewChild->next = cur; pNewChild->prev = cur->prev; cur->prev = pNewChild; - if( pNewChild->prev != NULL) + if (pNewChild->prev != NULL) { pNewChild->prev->next = pNewChild; + } + pNewChild->parent = cur->parent; + if (pNewChild->parent->children == cur) { + pNewChild->parent->children = pNewChild; + } + // do not update parent->last here! + pNewNode->m_bUnlinked = false; // will be deleted by xmlFreeDoc + break; } cur = cur->next; } @@ -779,7 +747,7 @@ namespace DOM sal_Bool SAL_CALL CNode::isSupported(const OUString& /*feature*/, const OUString& /*ver*/) throw (RuntimeException) { - // XXX + OSL_ENSURE(false, "CNode::isSupported: not implemented (#i113683#)"); return sal_False; } @@ -794,58 +762,54 @@ namespace DOM throw (RuntimeException) { //XXX combine adjacent text nodes and remove empty ones + OSL_ENSURE(false, "CNode::normalize: not implemented (#i113683#)"); } /** Removes the child node indicated by oldChild from the list of children, and returns it. */ - Reference< XNode > SAL_CALL CNode::removeChild(const Reference< XNode >& oldChild) + Reference< XNode > SAL_CALL + CNode::removeChild(const Reference< XNode >& xOldChild) throw (RuntimeException, DOMException) { + if (!xOldChild.is()) { + throw RuntimeException(); + } - if (oldChild->getParentNode() != Reference< XNode >(this)) { + if (xOldChild->getOwnerDocument() != getOwnerDocument()) { + DOMException e; + e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR; + throw e; + } + if (xOldChild->getParentNode() != Reference< XNode >(this)) { DOMException e; e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; throw e; } - Reference<XNode> xReturn( oldChild ); + ::osl::ClearableMutexGuard guard(m_rMutex); + + if (!m_aNodePtr) { throw RuntimeException(); } - xmlNodePtr old = CNode::getNodePtr(oldChild); + Reference<XNode> xReturn( xOldChild ); + + ::rtl::Reference<CNode> const pOld(CNode::GetImplementation(xOldChild)); + if (!pOld.is()) { throw RuntimeException(); } + xmlNodePtr const old = pOld->GetNodePtr(); + if (!old) { throw RuntimeException(); } if( old->type == XML_ATTRIBUTE_NODE ) { - xmlAttrPtr pAttr = (xmlAttrPtr) old; + xmlAttrPtr pAttr = reinterpret_cast<xmlAttrPtr>(old); xmlRemoveProp( pAttr ); + pOld->invalidate(); // freed by xmlRemoveProp xReturn.clear(); } else { - - // update .last - if (m_aNodePtr->last == old) - m_aNodePtr->last = old->prev; - - xmlNodePtr cur = m_aNodePtr->children; - //find old node in child list - while (cur != NULL) - { - if(cur == old) - { - // unlink node from list - if (cur->prev != NULL) - cur->prev->next = cur->next; - if (cur->next != NULL) - cur->next->prev = cur->prev; - if (cur->parent != NULL && cur->parent->children == cur) - cur->parent->children = cur->next; - cur->prev = NULL; - cur->next = NULL; - cur->parent = NULL; - } - cur = cur->next; - } + xmlUnlinkNode(old); + pOld->m_bUnlinked = true; } /*DOMNodeRemoved @@ -856,19 +820,23 @@ namespace DOM * Cancelable: No * Context Info: relatedNode holds the parent node */ - if (oldChild.is()) - { - Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY); - Reference< XMutationEvent > event(docevent->createEvent( - OUString::createFromAscii("DOMNodeRemoved")), UNO_QUERY); - event->initMutationEvent(OUString::createFromAscii("DOMNodeRemoved"), sal_True, - sal_False, Reference< XNode >(CNode::get(m_aNodePtr)), - OUString(), OUString(), OUString(), (AttrChangeType)0 ); - dispatchEvent(Reference< XEvent >(event, UNO_QUERY)); + Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY); + Reference< XMutationEvent > event(docevent->createEvent( + OUString::createFromAscii("DOMNodeRemoved")), UNO_QUERY); + event->initMutationEvent(OUString::createFromAscii("DOMNodeRemoved"), + sal_True, + sal_False, + this, + OUString(), OUString(), OUString(), (AttrChangeType)0 ); + + // the following dispatch functions use only UNO interfaces + // and call event listeners, so release mutex to prevent deadlocks. + guard.clear(); + + dispatchEvent(Reference< XEvent >(event, UNO_QUERY)); + // subtree modified for this node + dispatchSubtreeModified(); - // subtree modofied for this node - dispatchSubtreeModified(); - } return xReturn; } @@ -877,23 +845,56 @@ namespace DOM and returns the oldChild node. */ Reference< XNode > SAL_CALL CNode::replaceChild( - const Reference< XNode >& newChild, const Reference< XNode >& oldChild) + Reference< XNode > const& xNewChild, + Reference< XNode > const& xOldChild) throw (RuntimeException, DOMException) { - // XXX check node types + if (!xOldChild.is() || !xNewChild.is()) { + throw RuntimeException(); + } - if (oldChild->getParentNode() != Reference< XNode >(this)) { + if (xNewChild->getOwnerDocument() != getOwnerDocument()) { + DOMException e; + e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR; + throw e; + } + if (xOldChild->getParentNode() != Reference< XNode >(this)) { DOMException e; e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; throw e; } + ::osl::ClearableMutexGuard guard(m_rMutex); + /* Reference< XNode > aNode = removeChild(oldChild); appendChild(newChild); */ - xmlNodePtr pOld = CNode::getNodePtr(oldChild); - xmlNodePtr pNew = CNode::getNodePtr(newChild); + ::rtl::Reference<CNode> const pOldNode( + CNode::GetImplementation(xOldChild)); + ::rtl::Reference<CNode> const pNewNode( + CNode::GetImplementation(xNewChild)); + if (!pOldNode.is() || !pNewNode.is()) { throw RuntimeException(); } + xmlNodePtr const pOld = pOldNode->GetNodePtr(); + xmlNodePtr const pNew = pNewNode->GetNodePtr(); + if (!pOld || !pNew) { throw RuntimeException(); } + + if (pNew == m_aNodePtr) { + DOMException e; + e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; + throw e; + } + // already has parent + if (pNew->parent != NULL) { + DOMException e; + e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; + throw e; + } + if (!IsChildTypeAllowed(pNewNode->m_aNodeType)) { + DOMException e; + e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; + throw e; + } if( pOld->type == XML_ATTRIBUTE_NODE ) { @@ -907,7 +908,8 @@ namespace DOM xmlAttrPtr pAttr = (xmlAttrPtr)pOld; xmlRemoveProp( pAttr ); - appendChild( newChild ); + pOldNode->invalidate(); // freed by xmlRemoveProp + appendChild(xNewChild); } else { @@ -933,24 +935,30 @@ namespace DOM pOld->next = NULL; pOld->prev = NULL; pOld->parent = NULL; + pOldNode->m_bUnlinked = true; + pNewNode->m_bUnlinked = false; // will be deleted by xmlFreeDoc } cur = cur->next; } } + guard.clear(); // release for calling event handlers dispatchSubtreeModified(); - return oldChild; + return xOldChild; } void CNode::dispatchSubtreeModified() { + // only uses UNO interfaces => needs no mutex + // dispatch DOMSubtreeModified // target is _this_ node Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY); Reference< XMutationEvent > event(docevent->createEvent( OUString::createFromAscii("DOMSubtreeModified")), UNO_QUERY); - event->initMutationEvent(OUString::createFromAscii("DOMSubtreeModified"), sal_True, + event->initMutationEvent( + OUString::createFromAscii("DOMSubtreeModified"), sal_True, sal_False, Reference< XNode >(), OUString(), OUString(), OUString(), (AttrChangeType)0 ); dispatchEvent(Reference< XEvent >(event, UNO_QUERY)); @@ -959,7 +967,7 @@ namespace DOM /** The value of this node, depending on its type; see the table above. */ - void SAL_CALL CNode::setNodeValue(const OUString& /*nodeValue*/) + void SAL_CALL CNode::setNodeValue(const OUString& /*nodeValue*/) throw (RuntimeException, DOMException) { // use specific node implememntation @@ -975,13 +983,22 @@ namespace DOM void SAL_CALL CNode::setPrefix(const OUString& prefix) throw (RuntimeException, DOMException) { + ::osl::MutexGuard const g(m_rMutex); + + if ((0 == m_aNodePtr) || + ((m_aNodePtr->type != XML_ELEMENT_NODE) && + (m_aNodePtr->type != XML_ATTRIBUTE_NODE))) + { + DOMException e; + e.Code = DOMExceptionType_NO_MODIFICATION_ALLOWED_ERR; + throw e; + } OString o1 = OUStringToOString(prefix, RTL_TEXTENCODING_UTF8); xmlChar *pBuf = (xmlChar*)o1.getStr(); - // XXX copy buf? - // XXX free old string? (leak?) if (m_aNodePtr != NULL && m_aNodePtr->ns != NULL) { - m_aNodePtr->ns->prefix = pBuf; + xmlFree(const_cast<xmlChar *>(m_aNodePtr->ns->prefix)); + m_aNodePtr->ns->prefix = xmlStrdup(pBuf); } } @@ -992,7 +1009,11 @@ namespace DOM sal_Bool useCapture) throw (RuntimeException) { - events::CEventDispatcher::addListener(m_aNodePtr, eventType, listener, useCapture); + ::osl::MutexGuard const g(m_rMutex); + + CDocument & rDocument(GetOwnerDocument()); + events::CEventDispatcher & rDispatcher(rDocument.GetEventDispatcher()); + rDispatcher.addListener(m_aNodePtr, eventType, listener, useCapture); } void SAL_CALL CNode::removeEventListener(const OUString& eventType, @@ -1000,20 +1021,43 @@ namespace DOM sal_Bool useCapture) throw (RuntimeException) { - events::CEventDispatcher::removeListener(m_aNodePtr, eventType, listener, useCapture); + ::osl::MutexGuard const g(m_rMutex); + + CDocument & rDocument(GetOwnerDocument()); + events::CEventDispatcher & rDispatcher(rDocument.GetEventDispatcher()); + rDispatcher.removeListener(m_aNodePtr, eventType, listener, useCapture); } sal_Bool SAL_CALL CNode::dispatchEvent(const Reference< XEvent >& evt) throw(RuntimeException, EventException) { - events::CEventDispatcher::dispatchEvent(m_aNodePtr, evt); + CDocument * pDocument; + events::CEventDispatcher * pDispatcher; + xmlNodePtr pNode; + { + ::osl::MutexGuard const g(m_rMutex); + + pDocument = & GetOwnerDocument(); + pDispatcher = & pDocument->GetEventDispatcher(); + pNode = m_aNodePtr; + } + // this calls event listeners, do not call with locked mutex + pDispatcher->dispatchEvent(*pDocument, m_rMutex, pNode, this, evt); return sal_True; } - ::sal_Int64 SAL_CALL CNode::getSomething(const Sequence< ::sal_Int8 >& /*aIdentifier*/) + ::sal_Int64 SAL_CALL + CNode::getSomething(Sequence< ::sal_Int8 > const& rId) throw (RuntimeException) { - return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(m_aNodePtr)); + if ((rId.getLength() == 16) && + (0 == rtl_compareMemory(UnoTunnelId::get().getConstArray(), + rId.getConstArray(), 16))) + { + return ::sal::static_int_cast< sal_Int64 >( + reinterpret_cast< sal_IntPtr >(this) ); + } + return 0; } } diff --git a/unoxml/source/dom/node.hxx b/unoxml/source/dom/node.hxx index a4397e7053fd..6d9c4afcfafb 100644 --- a/unoxml/source/dom/node.hxx +++ b/unoxml/source/dom/node.hxx @@ -25,37 +25,35 @@ * ************************************************************************/ -#ifndef _NODE_HXX -#define _NODE_HXX +#ifndef DOM_NODE_HXX +#define DOM_NODE_HXX +#include <hash_map> + +#include <libxml/tree.h> + +#include <sal/types.h> #include <rtl/ref.hxx> #include <rtl/string.hxx> #include <rtl/ustring.hxx> -#include <sal/types.h> -#include <sax/fastattribs.hxx> -#include <cppuhelper/implbase1.hxx> + #include <cppuhelper/implbase3.hxx> + +#include <sax/fastattribs.hxx> + #include <com/sun/star/uno/Reference.h> -#include <com/sun/star/uno/Exception.hpp> +#include <com/sun/star/uno/Sequence.h> #include <com/sun/star/lang/XUnoTunnel.hpp> #include <com/sun/star/xml/dom/XNode.hpp> #include <com/sun/star/xml/dom/XNodeList.hpp> #include <com/sun/star/xml/dom/XNamedNodeMap.hpp> #include <com/sun/star/xml/dom/NodeType.hpp> -#include <com/sun/star/uno/Sequence.h> #include <com/sun/star/xml/dom/events/XEventTarget.hpp> -#include <com/sun/star/xml/dom/events/XDocumentEvent.hpp> #include <com/sun/star/xml/dom/events/XEvent.hpp> -#include <com/sun/star/xml/dom/events/XMutationEvent.hpp> -#include <com/sun/star/xml/dom/events/XUIEvent.hpp> -#include <com/sun/star/xml/dom/events/XMouseEvent.hpp> #include <com/sun/star/xml/dom/DOMException.hpp> #include <com/sun/star/xml/sax/XDocumentHandler.hpp> #include <com/sun/star/xml/sax/XFastDocumentHandler.hpp> -#include <libxml/tree.h> -#include <map> -#include <hash_map> using ::rtl::OUString; using ::rtl::OString; @@ -64,9 +62,9 @@ using namespace com::sun::star::uno; using namespace com::sun::star::xml::sax; using namespace com::sun::star::xml::dom; using namespace com::sun::star::xml::dom::events; - using com::sun::star::lang::XUnoTunnel; + namespace DOM { struct Context @@ -113,31 +111,29 @@ namespace DOM /// add namespaces on this node to context void addNamespaces(Context& io_rContext, xmlNodePtr pNode); - class CNode; - typedef std::map< const xmlNodePtr, CNode* > nodemap_t; - + class CDocument; class CNode : public cppu::WeakImplHelper3< XNode, XUnoTunnel, XEventTarget > { friend class CDocument; friend class CElement; friend class CAttributesMap; - friend class CChildList; - friend class CElementList; - friend class CEntitiesMap; - friend class CNotationsMap; + private: - static nodemap_t theNodeMap; + bool m_bUnlinked; /// node has been removed from document protected: - NodeType m_aNodeType; + NodeType const m_aNodeType; + /// libxml node; NB: not const, because invalidate may reset it to 0! xmlNodePtr m_aNodePtr; - Reference< XDocument > m_rDocument; + ::rtl::Reference< CDocument > const m_xDocument; + ::osl::Mutex & m_rMutex; // for initialization by classes derived through ImplInheritanceHelper - CNode(); - void init_node(const xmlNodePtr aNode); + CNode(CDocument const& rDocument, ::osl::Mutex const& rMutex, + NodeType const& reNodeType, xmlNodePtr const& rpNode); + void invalidate(); void dispatchSubtreeModified(); @@ -145,29 +141,29 @@ namespace DOM virtual ~CNode(); - // get a representaion for a libxml node - static CNode* get(const xmlNodePtr aNode, sal_Bool bCreate = sal_True); - // remove a wrapper instance - static void remove(const xmlNodePtr aNode); + static CNode * GetImplementation(::com::sun::star::uno::Reference< + ::com::sun::star::uno::XInterface> const& xNode); - // get the libxml node implementation - static xmlNodePtr getNodePtr(const Reference< XNode >& aNode); + xmlNodePtr GetNodePtr() { return m_aNodePtr; } - //static Sequence< sal_Int8 > + virtual CDocument & GetOwnerDocument(); // recursively create SAX events - virtual void SAL_CALL saxify( - const Reference< XDocumentHandler >& i_xHandler); + virtual void saxify(const Reference< XDocumentHandler >& i_xHandler); // recursively create SAX events - virtual void SAL_CALL fastSaxify( Context& io_rContext ); + virtual void fastSaxify( Context& io_rContext ); + + // constrains child relationship between nodes based on type + virtual bool IsChildTypeAllowed(NodeType const nodeType); // ---- DOM interfaces /** Adds the node newChild to the end of the list of children of this node. */ - virtual Reference< XNode > SAL_CALL appendChild(const Reference< XNode >& newChild) + virtual Reference< XNode > SAL_CALL + appendChild(Reference< XNode > const& xNewChild) throw (RuntimeException, DOMException); /** @@ -178,8 +174,8 @@ namespace DOM throw (RuntimeException); /** - A NamedNodeMap containing the attributes of this node (if it is an Element) - or null otherwise. + A NamedNodeMap containing the attributes of this node + (if it is an Element) or null otherwise. */ virtual Reference< XNamedNodeMap > SAL_CALL getAttributes() throw (RuntimeException); @@ -343,12 +339,13 @@ namespace DOM throw(RuntimeException, EventException); // --- XUnoTunnel - virtual ::sal_Int64 SAL_CALL getSomething(const Sequence< ::sal_Int8 >& aIdentifier) + virtual ::sal_Int64 SAL_CALL + getSomething(Sequence< ::sal_Int8 > const& rId) throw (RuntimeException); }; /// eliminate redundant namespace declarations - void _nscleanup(const xmlNodePtr aNode, const xmlNodePtr aParent); + void nscleanup(const xmlNodePtr aNode, const xmlNodePtr aParent); } #endif diff --git a/unoxml/source/dom/notation.cxx b/unoxml/source/dom/notation.cxx index 9781b6877eef..5988d1a9761f 100644 --- a/unoxml/source/dom/notation.cxx +++ b/unoxml/source/dom/notation.cxx @@ -25,21 +25,24 @@ * ************************************************************************/ -#include "notation.hxx" +#include <notation.hxx> + #include <string.h> namespace DOM { - CNotation::CNotation(const xmlNotationPtr aNotationPtr) + CNotation::CNotation(CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlNotationPtr const pNotation) + : CNotation_Base(rDocument, rMutex, + NodeType_NOTATION_NODE, reinterpret_cast<xmlNodePtr>(pNotation)) + , m_aNotationPtr(pNotation) { - m_aNodeType = NodeType_NOTATION_NODE; - m_aNotationPtr = aNotationPtr; - init_node((xmlNodePtr)aNotationPtr); } OUString SAL_CALL CNotation::getPublicId() throw (RuntimeException) { - // XXX + OSL_ENSURE(false, + "CNotation::getPublicId: not implemented (#i113683#)"); return OUString(); } @@ -48,13 +51,16 @@ namespace DOM */ OUString SAL_CALL CNotation::getSystemId() throw (RuntimeException) { - // XXX + OSL_ENSURE(false, + "CNotation::getSystemId: not implemented (#i113683#)"); return OUString(); } OUString SAL_CALL CNotation::getNodeName()throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + OUString aName; if (m_aNodePtr != NULL) { @@ -63,6 +69,7 @@ namespace DOM } return aName; } + OUString SAL_CALL CNotation::getNodeValue() throw (RuntimeException) { return OUString(); diff --git a/unoxml/source/dom/notation.hxx b/unoxml/source/dom/notation.hxx index a8fdf7994fc4..c98e81b353a3 100644 --- a/unoxml/source/dom/notation.hxx +++ b/unoxml/source/dom/notation.hxx @@ -25,14 +25,16 @@ * ************************************************************************/ -#ifndef _NOTATION_HXX -#define _NOTATION_HXX +#ifndef DOM_NOTATION_HXX +#define DOM_NOTATION_HXX + +#include <libxml/tree.h> #include <com/sun/star/uno/Reference.h> -#include <com/sun/star/uno/Exception.hpp> #include <com/sun/star/xml/dom/XNotation.hpp> -#include "node.hxx" -#include <libxml/tree.h> + +#include <node.hxx> + using ::rtl::OUString; using namespace com::sun::star::uno; @@ -40,14 +42,20 @@ using namespace com::sun::star::xml::dom; namespace DOM { - class CNotation : public cppu::ImplInheritanceHelper1< CNode, XNotation > + typedef cppu::ImplInheritanceHelper1< CNode, XNotation > CNotation_Base; + + class CNotation + : public CNotation_Base { - friend class CNode; + private: + friend class CDocument; + private: xmlNotationPtr m_aNotationPtr; protected: - CNotation(const xmlNotationPtr); + CNotation(CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlNotationPtr const pNotation); /** The public identifier of this notation. diff --git a/unoxml/source/dom/notationsmap.cxx b/unoxml/source/dom/notationsmap.cxx index 477d40277374..a37fed98cc04 100644 --- a/unoxml/source/dom/notationsmap.cxx +++ b/unoxml/source/dom/notationsmap.cxx @@ -25,12 +25,18 @@ * ************************************************************************/ -#include "notationsmap.hxx" +#include <notationsmap.hxx> + +#include <documenttype.hxx> + namespace DOM { - CNotationsMap::CNotationsMap(const CDocumentType* aDocType) - : m_pDocType(aDocType) + CNotationsMap::CNotationsMap( + ::rtl::Reference<CDocumentType> const& pDocType, + ::osl::Mutex & rMutex) + : m_pDocType(pDocType) + , m_rMutex(rMutex) { } @@ -39,63 +45,92 @@ namespace DOM */ sal_Int32 SAL_CALL CNotationsMap::getLength() throw (RuntimeException) { + OSL_ENSURE(false, + "CNotationsMap::getLength: not implemented (#i113683#)"); return 0; } /** Retrieves a node specified by local name */ - Reference< XNode > SAL_CALL CNotationsMap::getNamedItem(const OUString& /* name */) throw (RuntimeException) + Reference< XNode > SAL_CALL + CNotationsMap::getNamedItem(OUString const& /*name*/) + throw (RuntimeException) { + OSL_ENSURE(false, + "CNotationsMap::getNamedItem: not implemented (#i113683#)"); return Reference< XNode >(); } /** Retrieves a node specified by local name and namespace URI. */ - Reference< XNode > SAL_CALL CNotationsMap::getNamedItemNS(const OUString& /*namespaceURI*/, const OUString& /*localName*/) -throw (RuntimeException) + Reference< XNode > SAL_CALL + CNotationsMap::getNamedItemNS( + OUString const& /*namespaceURI*/, OUString const& /*localName*/) + throw (RuntimeException) { + OSL_ENSURE(false, + "CNotationsMap::getNamedItemNS: not implemented (#i113683#)"); return Reference< XNode >(); } /** Returns the indexth item in the map. */ - Reference< XNode > SAL_CALL CNotationsMap::item(sal_Int32 /*index*/) throw (RuntimeException) + Reference< XNode > SAL_CALL + CNotationsMap::item(sal_Int32 /*index*/) throw (RuntimeException) { + OSL_ENSURE(false, "CNotationsMap::item: not implemented (#i113683#)"); return Reference< XNode >(); } /** Removes a node specified by name. */ - Reference< XNode > SAL_CALL CNotationsMap::removeNamedItem(const OUString& /*name*/) throw (RuntimeException) + Reference< XNode > SAL_CALL + CNotationsMap::removeNamedItem(OUString const& /*name*/) + throw (RuntimeException) { + OSL_ENSURE(false, + "CNotationsMap::removeNamedItem: not implemented (#i113683#)"); return Reference< XNode >(); } /** // Removes a node specified by local name and namespace URI. */ - Reference< XNode > SAL_CALL CNotationsMap::removeNamedItemNS(const OUString& /*namespaceURI*/, const OUString& /*localName*/) throw (RuntimeException) + Reference< XNode > SAL_CALL + CNotationsMap::removeNamedItemNS( + OUString const& /*namespaceURI*/, OUString const& /*localName*/) + throw (RuntimeException) { + OSL_ENSURE(false, + "CNotationsMap::removeNamedItemNS: not implemented (#i113683#)"); return Reference< XNode >(); } /** // Adds a node using its nodeName attribute. */ - Reference< XNode > SAL_CALL CNotationsMap::setNamedItem(const Reference< XNode >& /*arg*/) throw (RuntimeException) + Reference< XNode > SAL_CALL + CNotationsMap::setNamedItem(Reference< XNode > const& /*arg*/) + throw (RuntimeException) { + OSL_ENSURE(false, + "CNotationsMap::setNamedItem: not implemented (#i113683#)"); return Reference< XNode >(); } /** Adds a node using its namespaceURI and localName. */ - Reference< XNode > SAL_CALL CNotationsMap::setNamedItemNS(const Reference< XNode >& /*arg*/) throw (RuntimeException) + Reference< XNode > SAL_CALL + CNotationsMap::setNamedItemNS(Reference< XNode > const& /*arg*/) + throw (RuntimeException) { + OSL_ENSURE(false, + "CNotationsMap::setNamedItemNS: not implemented (#i113683#)"); return Reference< XNode >(); } } diff --git a/unoxml/source/dom/notationsmap.hxx b/unoxml/source/dom/notationsmap.hxx index 9c950c64de4c..42648311374b 100644 --- a/unoxml/source/dom/notationsmap.hxx +++ b/unoxml/source/dom/notationsmap.hxx @@ -25,18 +25,18 @@ * ************************************************************************/ -#ifndef _NOTATIONSMAP_HXX -#define _NOTATIONSMAP_HXX +#ifndef DOM_NOTATIONSMAP_HXX +#define DOM_NOTATIONSMAP_HXX -#include <map> #include <sal/types.h> -#include <cppuhelper/implbase1.hxx> +#include <rtl/ref.hxx> + #include <com/sun/star/uno/Reference.h> -#include <com/sun/star/uno/Exception.hpp> #include <com/sun/star/xml/dom/XNode.hpp> #include <com/sun/star/xml/dom/XNamedNodeMap.hpp> -#include "document.hxx" -#include "documenttype.hxx" + +#include <cppuhelper/implbase1.hxx> + using ::rtl::OUString; using namespace com::sun::star::uno; @@ -44,13 +44,18 @@ using namespace com::sun::star::xml::dom; namespace DOM { - class CNotationsMap : public cppu::WeakImplHelper1< XNamedNodeMap > + class CDocumentType; + + class CNotationsMap + : public cppu::WeakImplHelper1< XNamedNodeMap > { private: - const CDocumentType* m_pDocType; + ::rtl::Reference<CDocumentType> const m_pDocType; + ::osl::Mutex & m_rMutex; public: - CNotationsMap(const CDocumentType* aDocType); + CNotationsMap(::rtl::Reference<CDocumentType> const& pDocType, + ::osl::Mutex & rMutex); /** The number of nodes in this map. @@ -60,37 +65,48 @@ namespace DOM /** Retrieves a node specified by local name */ - virtual Reference< XNode > SAL_CALL getNamedItem(const OUString& name) throw (RuntimeException); + virtual Reference< XNode > SAL_CALL + getNamedItem(OUString const& name) throw (RuntimeException); /** Retrieves a node specified by local name and namespace URI. */ - virtual Reference< XNode > SAL_CALL getNamedItemNS(const OUString& namespaceURI,const OUString& localName) throw (RuntimeException); + virtual Reference< XNode > SAL_CALL getNamedItemNS( + OUString const& namespaceURI, OUString const& localName) + throw (RuntimeException); /** Returns the indexth item in the map. */ - virtual Reference< XNode > SAL_CALL item(sal_Int32 index) throw (RuntimeException); + virtual Reference< XNode > SAL_CALL + item(sal_Int32 index) throw (RuntimeException); /** Removes a node specified by name. */ - virtual Reference< XNode > SAL_CALL removeNamedItem(const OUString& name) throw (RuntimeException); + virtual Reference< XNode > SAL_CALL + removeNamedItem(OUString const& name) throw (RuntimeException); /** // Removes a node specified by local name and namespace URI. */ - virtual Reference< XNode > SAL_CALL removeNamedItemNS(const OUString& namespaceURI, const OUString& localName) throw (RuntimeException); + virtual Reference< XNode > SAL_CALL removeNamedItemNS( + OUString const& namespaceURI, OUString const& localName) + throw (RuntimeException); /** // Adds a node using its nodeName attribute. */ - virtual Reference< XNode > SAL_CALL setNamedItem(const Reference< XNode >& arg) throw (RuntimeException); + virtual Reference< XNode > SAL_CALL + setNamedItem(Reference< XNode > const& arg) + throw (RuntimeException); /** Adds a node using its namespaceURI and localName. */ - virtual Reference< XNode > SAL_CALL setNamedItemNS(const Reference< XNode >& arg) throw (RuntimeException); + virtual Reference< XNode > SAL_CALL + setNamedItemNS(Reference< XNode > const& arg) + throw (RuntimeException); }; } diff --git a/unoxml/source/dom/processinginstruction.cxx b/unoxml/source/dom/processinginstruction.cxx index 37e52086cbd8..b604a3284032 100644 --- a/unoxml/source/dom/processinginstruction.cxx +++ b/unoxml/source/dom/processinginstruction.cxx @@ -25,19 +25,24 @@ * ************************************************************************/ -#include "processinginstruction.hxx" -#include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp> +#include <processinginstruction.hxx> + #include <string.h> +#include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp> + + namespace DOM { - CProcessingInstruction::CProcessingInstruction(const xmlNodePtr aNodePtr) + CProcessingInstruction::CProcessingInstruction( + CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlNodePtr const pNode) + : CProcessingInstruction_Base(rDocument, rMutex, + NodeType_PROCESSING_INSTRUCTION_NODE, pNode) { - m_aNodeType = NodeType_PROCESSING_INSTRUCTION_NODE; - init_node(aNodePtr); } - void SAL_CALL CProcessingInstruction::saxify( + void CProcessingInstruction::saxify( const Reference< XDocumentHandler >& i_xHandler) { if (!i_xHandler.is()) throw RuntimeException(); Reference< XExtendedDocumentHandler > xExtended(i_xHandler, UNO_QUERY); @@ -49,44 +54,90 @@ namespace DOM /** The content of this processing instruction. */ - OUString SAL_CALL CProcessingInstruction::getData() throw (RuntimeException) + OUString SAL_CALL + CProcessingInstruction::getData() throw (RuntimeException) { - // XXX - return OUString(); + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return ::rtl::OUString(); + } + + char const*const pContent( + reinterpret_cast<char const*>(m_aNodePtr->content)); + if (0 == pContent) { + return ::rtl::OUString(); + } + OUString const ret(pContent, strlen(pContent), RTL_TEXTENCODING_UTF8); + return ret; } /** The target of this processing instruction. */ - OUString SAL_CALL CProcessingInstruction::getTarget() throw (RuntimeException) + OUString SAL_CALL + CProcessingInstruction::getTarget() throw (RuntimeException) { - // XXX - return OUString(); - } + ::osl::MutexGuard const g(m_rMutex); + if (0 == m_aNodePtr) { + return ::rtl::OUString(); + } + + char const*const pName( + reinterpret_cast<char const*>(m_aNodePtr->name)); + if (0 == pName) { + return ::rtl::OUString(); + } + OUString const ret(pName, strlen(pName), RTL_TEXTENCODING_UTF8); + return ret; + } /** The content of this processing instruction. */ - void SAL_CALL CProcessingInstruction::setData(const OUString& /*data*/) throw (RuntimeException, DOMException) + void SAL_CALL CProcessingInstruction::setData(OUString const& rData) + throw (RuntimeException, DOMException) { - // XXX - } + ::osl::MutexGuard const g(m_rMutex); + if (0 == m_aNodePtr) { + throw RuntimeException(); + } + + OString const data( + ::rtl::OUStringToOString(rData, RTL_TEXTENCODING_UTF8)); + xmlChar const*const pData( + reinterpret_cast<xmlChar const*>(data.getStr()) ); + xmlFree(m_aNodePtr->content); + m_aNodePtr->content = xmlStrdup(pData); + } - OUString SAL_CALL CProcessingInstruction::getNodeName()throw (RuntimeException) + OUString SAL_CALL + CProcessingInstruction::getNodeName() throw (RuntimeException) { - OUString aName; - if (m_aNodePtr != NULL) - { - const xmlChar* xName = m_aNodePtr->name; - aName = OUString((sal_Char*)xName, strlen((char*)xName), RTL_TEXTENCODING_UTF8); + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return ::rtl::OUString(); } - return aName; + + sal_Char const*const pName = + reinterpret_cast<sal_Char const*>(m_aNodePtr->name); + OUString const ret(pName, strlen(pName), RTL_TEXTENCODING_UTF8); + return ret; } - OUString SAL_CALL CProcessingInstruction::getNodeValue() throw (RuntimeException) + OUString SAL_CALL CProcessingInstruction::getNodeValue() + throw (RuntimeException) { return getData(); } + + void SAL_CALL + CProcessingInstruction::setNodeValue(OUString const& rNodeValue) + throw (RuntimeException, DOMException) + { + return setData(rNodeValue); + } } diff --git a/unoxml/source/dom/processinginstruction.hxx b/unoxml/source/dom/processinginstruction.hxx index b794d31e159d..4bf8d52f3c41 100644 --- a/unoxml/source/dom/processinginstruction.hxx +++ b/unoxml/source/dom/processinginstruction.hxx @@ -25,14 +25,16 @@ * ************************************************************************/ -#ifndef _PROCESSINGINSTRUCTION_HXX -#define _PROCESSINGINSTRUCTION_HXX +#ifndef DOM_PROCESSINGINSTRUCTION_HXX +#define DOM_PROCESSINGINSTRUCTION_HXX + +#include <libxml/tree.h> #include <com/sun/star/uno/Reference.h> -#include <com/sun/star/uno/Exception.hpp> #include <com/sun/star/xml/dom/XProcessingInstruction.hpp> -#include "node.hxx" -#include <libxml/tree.h> + +#include <node.hxx> + using ::rtl::OUString; using namespace com::sun::star::uno; @@ -40,17 +42,23 @@ using namespace com::sun::star::xml::dom; namespace DOM { - class CProcessingInstruction : public cppu::ImplInheritanceHelper1< CNode, XProcessingInstruction > + typedef ::cppu::ImplInheritanceHelper1< CNode, XProcessingInstruction > + CProcessingInstruction_Base; + + class CProcessingInstruction + : public CProcessingInstruction_Base { - friend class CNode; + private: + friend class CDocument; protected: - CProcessingInstruction(const xmlNodePtr aNodePtr); + CProcessingInstruction( + CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlNodePtr const pNode); public: - virtual void SAL_CALL saxify( - const Reference< XDocumentHandler >& i_xHandler); + virtual void saxify(const Reference< XDocumentHandler >& i_xHandler); /** The content of this processing instruction. @@ -73,6 +81,9 @@ namespace DOM throw (RuntimeException); virtual OUString SAL_CALL getNodeValue() throw (RuntimeException); + virtual void SAL_CALL setNodeValue(OUString const& rNodeValue) + throw (RuntimeException, DOMException); + // --- delegation for XNde base. virtual Reference< XNode > SAL_CALL appendChild(const Reference< XNode >& newChild) throw (RuntimeException, DOMException) @@ -181,11 +192,6 @@ namespace DOM { return CNode::replaceChild(newChild, oldChild); } - virtual void SAL_CALL setNodeValue(const OUString& nodeValue) - throw (RuntimeException, DOMException) - { - return CNode::setNodeValue(nodeValue); - } virtual void SAL_CALL setPrefix(const OUString& prefix) throw (RuntimeException, DOMException) { diff --git a/unoxml/source/dom/saxbuilder.cxx b/unoxml/source/dom/saxbuilder.cxx index e968eee3e2f6..524e4353e2a2 100644 --- a/unoxml/source/dom/saxbuilder.cxx +++ b/unoxml/source/dom/saxbuilder.cxx @@ -28,11 +28,10 @@ #pragma warning(disable : 4701) #endif -#include "node.hxx" #include "saxbuilder.hxx" + #include <com/sun/star/xml/dom/XDocumentBuilder.hpp> -#include <libxml/tree.h> -#include <com/sun/star/uno/Sequence.h> + namespace DOM { @@ -93,12 +92,16 @@ namespace DOM SAXDocumentBuilderState SAL_CALL CSAXDocumentBuilder::getState() throw (RuntimeException) { + ::osl::MutexGuard g(m_Mutex); + return m_aState; } void SAL_CALL CSAXDocumentBuilder::reset() throw (RuntimeException) { + ::osl::MutexGuard g(m_Mutex); + m_aDocument = Reference< XDocument >(); m_aFragment = Reference< XDocumentFragment >(); while (!m_aNodeStack.empty()) m_aNodeStack.pop(); @@ -109,6 +112,8 @@ namespace DOM Reference< XDocument > SAL_CALL CSAXDocumentBuilder::getDocument() throw (RuntimeException) { + ::osl::MutexGuard g(m_Mutex); + if (m_aState != SAXDocumentBuilderState_DOCUMENT_FINISHED) throw RuntimeException(); @@ -118,6 +123,8 @@ namespace DOM Reference< XDocumentFragment > SAL_CALL CSAXDocumentBuilder::getDocumentFragment() throw (RuntimeException) { + ::osl::MutexGuard g(m_Mutex); + if (m_aState != SAXDocumentBuilderState_FRAGMENT_FINISHED) throw RuntimeException(); return m_aFragment; @@ -126,6 +133,8 @@ namespace DOM void SAL_CALL CSAXDocumentBuilder::startDocumentFragment(const Reference< XDocument >& ownerDoc) throw (RuntimeException) { + ::osl::MutexGuard g(m_Mutex); + // start a new document fragment and push it onto the stack // we have to be in a clean state to do this if (!m_aState == SAXDocumentBuilderState_READY) @@ -141,6 +150,8 @@ namespace DOM void SAL_CALL CSAXDocumentBuilder::endDocumentFragment() throw (RuntimeException) { + ::osl::MutexGuard g(m_Mutex); + // there should only be the document left on the node stack if (m_aState != SAXDocumentBuilderState_BUILDING_FRAGMENT) throw RuntimeException(); @@ -156,6 +167,7 @@ namespace DOM void SAL_CALL CSAXDocumentBuilder::startDocument() throw (RuntimeException, SAXException) { + ::osl::MutexGuard g(m_Mutex); // start a new document and push it onto the stack // we have to be in a clean state to do this @@ -172,6 +184,8 @@ namespace DOM void SAL_CALL CSAXDocumentBuilder::endDocument() throw (RuntimeException, SAXException) { + ::osl::MutexGuard g(m_Mutex); + // there should only be the document left on the node stack if (!m_aState == SAXDocumentBuilderState_BUILDING_DOCUMENT) throw SAXException(); @@ -186,6 +200,8 @@ namespace DOM void SAL_CALL CSAXDocumentBuilder::startElement(const OUString& aName, const Reference< XAttributeList>& attribs) throw (RuntimeException, SAXException) { + ::osl::MutexGuard g(m_Mutex); + if ( m_aState != SAXDocumentBuilderState_BUILDING_DOCUMENT && m_aState != SAXDocumentBuilderState_BUILDING_FRAGMENT) { @@ -241,7 +257,8 @@ namespace DOM if ( result != aNSMap.end()) { // found a URI for prefix - aElement = m_aDocument->createElementNS( result->second, aName); // qualified name + // qualified name + aElement = m_aDocument->createElementNS( result->second, aName); } else { @@ -286,6 +303,8 @@ namespace DOM void SAL_CALL CSAXDocumentBuilder::endElement(const OUString& aName) throw (RuntimeException, SAXException) { + ::osl::MutexGuard g(m_Mutex); + // pop the current element from the stack if ( m_aState != SAXDocumentBuilderState_BUILDING_DOCUMENT && m_aState != SAXDocumentBuilderState_BUILDING_FRAGMENT) @@ -313,6 +332,8 @@ namespace DOM void SAL_CALL CSAXDocumentBuilder::characters(const OUString& aChars) throw (RuntimeException, SAXException) { + ::osl::MutexGuard g(m_Mutex); + // append text node to the current top element if (m_aState != SAXDocumentBuilderState_BUILDING_DOCUMENT && m_aState != SAXDocumentBuilderState_BUILDING_FRAGMENT) @@ -325,6 +346,8 @@ namespace DOM void SAL_CALL CSAXDocumentBuilder::ignorableWhitespace(const OUString& ) throw (RuntimeException, SAXException) { + ::osl::MutexGuard g(m_Mutex); + // ignore ignorable whitespace if ( m_aState != SAXDocumentBuilderState_BUILDING_DOCUMENT && m_aState != SAXDocumentBuilderState_BUILDING_FRAGMENT) @@ -334,6 +357,8 @@ namespace DOM void SAL_CALL CSAXDocumentBuilder::processingInstruction(const OUString& aTarget, const OUString& aData) throw (RuntimeException, SAXException) { + ::osl::MutexGuard g(m_Mutex); + // append PI node to the current top if ( m_aState != SAXDocumentBuilderState_BUILDING_DOCUMENT && m_aState != SAXDocumentBuilderState_BUILDING_FRAGMENT) @@ -347,6 +372,8 @@ namespace DOM void SAL_CALL CSAXDocumentBuilder::setDocumentLocator(const Reference< XLocator >& aLocator) throw (RuntimeException, SAXException) { + ::osl::MutexGuard g(m_Mutex); + // set the document locator... m_aLocator = aLocator; } diff --git a/unoxml/source/dom/saxbuilder.hxx b/unoxml/source/dom/saxbuilder.hxx index c243877aae2b..cd280c9f7129 100644 --- a/unoxml/source/dom/saxbuilder.hxx +++ b/unoxml/source/dom/saxbuilder.hxx @@ -25,13 +25,14 @@ * ************************************************************************/ -#ifndef _SAXBUILDER_HXX -#define _SAXBUILDER_HXX +#ifndef DOM_SAXBUILDER_HXX +#define DOM_SAXBUILDER_HXX #include <stack> #include <map> #include <sal/types.h> +#include <osl/mutex.hxx> #include <cppuhelper/implbase3.hxx> #include <com/sun/star/uno/Reference.h> #include <com/sun/star/uno/Sequence.h> @@ -49,8 +50,6 @@ #include <com/sun/star/lang/XSingleServiceFactory.hpp> #include <com/sun/star/lang/XMultiServiceFactory.hpp> -#include "libxml/tree.h" - using ::rtl::OUString; using namespace com::sun::star::uno; using namespace com::sun::star::xml::dom; @@ -73,6 +72,7 @@ namespace DOM { private: + ::osl::Mutex m_Mutex; const Reference< XMultiServiceFactory > m_aServiceManager; SAXDocumentBuilderState m_aState; diff --git a/unoxml/source/dom/text.cxx b/unoxml/source/dom/text.cxx index d60fcf234ebf..5d07aa86a6d4 100644 --- a/unoxml/source/dom/text.cxx +++ b/unoxml/source/dom/text.cxx @@ -25,40 +25,32 @@ * ************************************************************************/ -#include "text.hxx" -namespace DOM -{ - CText::CText(const xmlNodePtr aNodePtr) - { - m_aNodeType = NodeType_TEXT_NODE; - init_characterdata(aNodePtr); - } +#include <text.hxx> - void SAL_CALL CText::saxify( - const Reference< XDocumentHandler >& i_xHandler) { - if (!i_xHandler.is()) throw RuntimeException(); - i_xHandler->characters(getData()); - } - void CText::init_text(const xmlNodePtr aNodePtr) +namespace DOM +{ + CText::CText(CDocument const& rDocument, ::osl::Mutex const& rMutex, + NodeType const& reNodeType, xmlNodePtr const& rpNode) + : CText_Base(rDocument, rMutex, reNodeType, rpNode) { - init_characterdata(aNodePtr); } - Reference< XText > SAL_CALL CText::splitText(sal_Int32 /*offset*/) - throw (RuntimeException) + CText::CText(CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlNodePtr const pNode) + : CText_Base(rDocument, rMutex, NodeType_TEXT_NODE, pNode) { - return Reference< XText >(this); } - OUString SAL_CALL CText::getNodeName()throw (RuntimeException) - { - return OUString::createFromAscii("#text"); + void CText::saxify( + const Reference< XDocumentHandler >& i_xHandler) { + if (!i_xHandler.is()) throw RuntimeException(); + i_xHandler->characters(getData()); } - void SAL_CALL CText::fastSaxify( Context& io_rContext ) + void CText::fastSaxify( Context& io_rContext ) { - if( io_rContext.mxCurrentHandler.is() ) + if (io_rContext.mxCurrentHandler.is()) { try { @@ -69,4 +61,15 @@ namespace DOM } } + OUString SAL_CALL CText::getNodeName() throw (RuntimeException) + { + return OUString::createFromAscii("#text"); + } + + Reference< XText > SAL_CALL CText::splitText(sal_Int32 /*offset*/) + throw (RuntimeException) + { + OSL_ENSURE(false, "CText::splitText: not implemented (#i113683#)"); + return Reference< XText >(this); + } } diff --git a/unoxml/source/dom/text.hxx b/unoxml/source/dom/text.hxx index a99f4ff2aa5d..c58a4e14255e 100644 --- a/unoxml/source/dom/text.hxx +++ b/unoxml/source/dom/text.hxx @@ -25,41 +25,47 @@ * ************************************************************************/ -#ifndef _TEXT_HXX -#define _TEXT_HXX +#ifndef DOM_TEXT_HXX +#define DOM_TEXT_HXX + +#include <libxml/tree.h> #include <sal/types.h> + #include <cppuhelper/implbase1.hxx> + #include <com/sun/star/uno/Reference.h> -#include <com/sun/star/uno/Exception.hpp> #include <com/sun/star/xml/dom/XNode.hpp> #include <com/sun/star/xml/dom/XText.hpp> -#include <com/sun/star/xml/dom/XCharacterData.hpp> -#include <libxml/tree.h> -#include "characterdata.hxx" + +#include <characterdata.hxx> + using ::rtl::OUString; using namespace com::sun::star::uno; -using namespace com::sun::star::lang; using namespace com::sun::star::xml::dom; namespace DOM { - class CText : public cppu::ImplInheritanceHelper1< CCharacterData, XText > + typedef ::cppu::ImplInheritanceHelper1< CCharacterData, XText > CText_Base; + + class CText + : public CText_Base { - friend class CNode; + private: + friend class CDocument; protected: - CText(){} - CText(const xmlNodePtr aNodePtr); - void init_text(const xmlNodePtr aNodePtr); + CText(CDocument const& rDocument, ::osl::Mutex const& rMutex, + NodeType const& reNodeType, xmlNodePtr const& rpNode); + CText(CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlNodePtr const pNode); public: - virtual void SAL_CALL saxify( - const Reference< XDocumentHandler >& i_xHandler); + virtual void saxify(const Reference< XDocumentHandler >& i_xHandler); - virtual void SAL_CALL fastSaxify( Context& io_rContext ); + virtual void fastSaxify( Context& io_rContext ); // Breaks this node into two nodes at the specified offset, keeping // both in the tree as siblings. diff --git a/unoxml/source/events/event.cxx b/unoxml/source/events/event.cxx index 1d41bbba9911..87201d7eece7 100644 --- a/unoxml/source/events/event.cxx +++ b/unoxml/source/events/event.cxx @@ -1,59 +1,108 @@ -#include "event.hxx" +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <event.hxx> namespace DOM { namespace events { + CEvent::CEvent() + : m_canceled(sal_False) + , m_phase(PhaseType_CAPTURING_PHASE) + , m_bubbles(sal_False) + , m_cancelable(sal_True) + { + } + CEvent::~CEvent() { } OUString SAL_CALL CEvent::getType() throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); return m_eventType; } - Reference< XEventTarget > SAL_CALL CEvent::getTarget() throw (RuntimeException) + Reference< XEventTarget > SAL_CALL + CEvent::getTarget() throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); return m_target; } - Reference< XEventTarget > SAL_CALL CEvent::getCurrentTarget() throw (RuntimeException) + Reference< XEventTarget > SAL_CALL + CEvent::getCurrentTarget() throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); return m_currentTarget; } PhaseType SAL_CALL CEvent::getEventPhase() throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); return m_phase; } sal_Bool SAL_CALL CEvent::getBubbles() throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); return m_bubbles; } sal_Bool SAL_CALL CEvent::getCancelable() throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); return m_cancelable; } - com::sun::star::util::Time SAL_CALL CEvent::getTimeStamp() throw (RuntimeException) + com::sun::star::util::Time SAL_CALL + CEvent::getTimeStamp() throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); return m_time; } void SAL_CALL CEvent::stopPropagation() throw (RuntimeException) { - if (m_cancelable) m_canceled = sal_True; + ::osl::MutexGuard const g(m_Mutex); + if (m_cancelable) { m_canceled = sal_True; } } void SAL_CALL CEvent::preventDefault() throw (RuntimeException) { } - void SAL_CALL CEvent::initEvent(const OUString& eventTypeArg, sal_Bool canBubbleArg, + void SAL_CALL + CEvent::initEvent(OUString const& eventTypeArg, sal_Bool canBubbleArg, sal_Bool cancelableArg) throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); + m_eventType = eventTypeArg; m_bubbles = canBubbleArg; m_cancelable = cancelableArg; diff --git a/unoxml/source/events/event.hxx b/unoxml/source/events/event.hxx index 3620d84374dc..0336be16412f 100644 --- a/unoxml/source/events/event.hxx +++ b/unoxml/source/events/event.hxx @@ -1,19 +1,44 @@ -#ifndef __EVENT_HXX -#define __EVENT_HXX +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +#ifndef EVENT_EVENT_HXX +#define EVENT_EVENT_HXX #include <sal/types.h> -#include <cppuhelper/implbase1.hxx> -#include <cppuhelper/implbase2.hxx> -#include <cppuhelper/implbase3.hxx> #include <com/sun/star/uno/Reference.h> -#include <com/sun/star/uno/Exception.hpp> +#include <com/sun/star/xml/dom/events/XEvent.hpp> #include <com/sun/star/xml/dom/events/XEventTarget.hpp> #include <com/sun/star/util/Time.hpp> +#include <cppuhelper/implbase1.hxx> + #include "../dom/node.hxx" -#include <libxml/tree.h> using namespace com::sun::star::uno; using namespace com::sun::star::xml::dom; @@ -25,23 +50,13 @@ namespace DOM {namespace events class CEvent : public cppu::WeakImplHelper1< XEvent > { friend class CEventDispatcher; -friend class CNode; -friend class CDocument; -friend class CElement; -friend class CText; -friend class CCharacterData; -friend class CAttr; - - -private: - sal_Bool m_canceled; protected: + ::osl::Mutex m_Mutex; + sal_Bool m_canceled; OUString m_eventType; Reference< XEventTarget > m_target; Reference< XEventTarget > m_currentTarget; - //xmlNodePtr m_target; - //xmlNodePtr m_currentTarget; PhaseType m_phase; sal_Bool m_bubbles; sal_Bool m_cancelable; @@ -49,7 +64,7 @@ protected: public: - CEvent() : m_canceled(sal_False){} + explicit CEvent(); virtual ~CEvent(); virtual OUString SAL_CALL getType() throw (RuntimeException); diff --git a/unoxml/source/events/eventdispatcher.cxx b/unoxml/source/events/eventdispatcher.cxx index 4b1c1548bf38..4b4cac807538 100644 --- a/unoxml/source/events/eventdispatcher.cxx +++ b/unoxml/source/events/eventdispatcher.cxx @@ -1,19 +1,46 @@ -#include "eventdispatcher.hxx" -#include "event.hxx" -#include "mutationevent.hxx" -#include "uievent.hxx" -#include "mouseevent.hxx" -#include "../dom/node.hxx" +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ -namespace DOM { namespace events { +#include <eventdispatcher.hxx> + +#include <event.hxx> +#include <mutationevent.hxx> +#include <uievent.hxx> +#include <mouseevent.hxx> - TypeListenerMap CEventDispatcher::captureListeners; - TypeListenerMap CEventDispatcher::targetListeners; +#include "../dom/document.hxx" + + +namespace DOM { namespace events { void CEventDispatcher::addListener(xmlNodePtr pNode, OUString aType, const Reference<XEventListener>& aListener, sal_Bool bCapture) { - TypeListenerMap* pTMap = &targetListeners; - if (bCapture) pTMap = &captureListeners; + TypeListenerMap *const pTMap = (bCapture) + ? (& m_CaptureListeners) : (& m_TargetListeners); // get the multimap for the specified type ListenerMap *pMap = 0; @@ -31,8 +58,8 @@ namespace DOM { namespace events { void CEventDispatcher::removeListener(xmlNodePtr pNode, OUString aType, const Reference<XEventListener>& aListener, sal_Bool bCapture) { - TypeListenerMap *pTMap = &targetListeners; - if (bCapture) pTMap = &captureListeners; + TypeListenerMap *const pTMap = (bCapture) + ? (& m_CaptureListeners) : (& m_TargetListeners); // get the multimap for the specified type TypeListenerMap::const_iterator tIter = pTMap->find(aType); @@ -55,14 +82,14 @@ namespace DOM { namespace events { } } - void CEventDispatcher::callListeners(xmlNodePtr pNode, OUString aType, const Reference< XEvent >& xEvent, sal_Bool bCapture) + void CEventDispatcher::callListeners( + TypeListenerMap const& rTMap, + xmlNodePtr const pNode, + OUString aType, Reference< XEvent > const& xEvent) { - TypeListenerMap *pTMap = &targetListeners; - if (bCapture) pTMap = &captureListeners; - // get the multimap for the specified type - TypeListenerMap::const_iterator tIter = pTMap->find(aType); - if (tIter != pTMap->end()) { + TypeListenerMap::const_iterator tIter = rTMap.find(aType); + if (tIter != rTMap.end()) { ListenerMap *pMap = tIter->second; ListenerMap::const_iterator iter = pMap->lower_bound(pNode); ListenerMap::const_iterator ibound = pMap->upper_bound(pNode); @@ -74,12 +101,14 @@ namespace DOM { namespace events { } } - sal_Bool CEventDispatcher::dispatchEvent(xmlNodePtr aNodePtr, const Reference< XEvent >& aEvent) + bool CEventDispatcher::dispatchEvent( + DOM::CDocument & rDocument, ::osl::Mutex & rMutex, + xmlNodePtr const pNode, Reference<XNode> const& xNode, + Reference< XEvent > const& i_xEvent) const { CEvent *pEvent = 0; // pointer to internal event representation - Reference< XEvent > xEvent; // reference to the event being dispatched; - OUString aType = aEvent->getType(); + OUString const aType = i_xEvent->getType(); if (aType.compareToAscii("DOMSubtreeModified") == 0|| aType.compareToAscii("DOMNodeInserted") == 0|| aType.compareToAscii("DOMNodeRemoved") == 0|| @@ -88,7 +117,8 @@ namespace DOM { namespace events { aType.compareToAscii("DOMAttrModified") == 0|| aType.compareToAscii("DOMCharacterDataModified") == 0) { - Reference< XMutationEvent > aMEvent(aEvent, UNO_QUERY); + Reference< XMutationEvent > const aMEvent(i_xEvent, + UNO_QUERY_THROW); // dispatch a mutation event // we need to clone the event in order to have complete control // over the implementation @@ -104,7 +134,7 @@ namespace DOM { namespace events { aType.compareToAscii("DOMFocusOut") == 0|| aType.compareToAscii("DOMActivate") == 0) { - Reference< XUIEvent > aUIEvent(aEvent, UNO_QUERY); + Reference< XUIEvent > const aUIEvent(i_xEvent, UNO_QUERY_THROW); CUIEvent* pUIEvent = new CUIEvent; pUIEvent->initUIEvent(aType, aUIEvent->getBubbles(), aUIEvent->getCancelable(), @@ -118,7 +148,8 @@ namespace DOM { namespace events { aType.compareToAscii("mousemove") == 0|| aType.compareToAscii("mouseout") == 0) { - Reference< XMouseEvent > aMouseEvent(aEvent, UNO_QUERY); + Reference< XMouseEvent > const aMouseEvent(i_xEvent, + UNO_QUERY_THROW); CMouseEvent *pMouseEvent = new CMouseEvent; pMouseEvent->initMouseEvent(aType, aMouseEvent->getBubbles(), aMouseEvent->getCancelable(), @@ -134,23 +165,35 @@ namespace DOM { namespace events { { pEvent = new CEvent; pEvent->initEvent( - aType, aEvent->getBubbles(), aEvent->getCancelable()); + aType, i_xEvent->getBubbles(), i_xEvent->getCancelable()); } - pEvent->m_target = Reference< XEventTarget >(DOM::CNode::get(aNodePtr)); - pEvent->m_currentTarget = aEvent->getCurrentTarget(); - pEvent->m_time = aEvent->getTimeStamp(); + pEvent->m_target.set(xNode, UNO_QUERY_THROW); + pEvent->m_currentTarget = i_xEvent->getCurrentTarget(); + pEvent->m_time = i_xEvent->getTimeStamp(); // create the reference to the provate event implementation // that will be dispatched to the listeners - xEvent = Reference< XEvent >(pEvent); + Reference< XEvent > const xEvent(pEvent); // build the path from target node to the root - NodeVector captureVector; - xmlNodePtr cur = DOM::CNode::getNodePtr(Reference< XNode >(xEvent->getTarget(), UNO_QUERY_THROW)); - while (cur != NULL) + typedef std::vector< ::std::pair<Reference<XEventTarget>, xmlNodePtr> > + NodeVector_t; + NodeVector_t captureVector; + TypeListenerMap captureListeners; + TypeListenerMap targetListeners; { - captureVector.push_back(cur); - cur = cur->parent; + ::osl::MutexGuard g(rMutex); + + xmlNodePtr cur = pNode; + while (cur != NULL) + { + Reference< XEventTarget > const xRef( + rDocument.GetCNode(cur).get()); + captureVector.push_back(::std::make_pair(xRef, cur)); + cur = cur->parent; + } + captureListeners = m_CaptureListeners; + targetListeners = m_TargetListeners; } // the caputre vector now holds the node path from target to root @@ -158,36 +201,38 @@ namespace DOM { namespace events { // to target. after that, any target listeners have to be called // then bubbeling phase listeners are called in target to root // order - NodeVector::const_iterator inode; - // start at the root - inode = captureVector.end(); - inode--; - if (inode != captureVector.end()) + NodeVector_t::const_reverse_iterator rinode = + const_cast<NodeVector_t const&>(captureVector).rbegin(); + if (rinode != const_cast<NodeVector_t const&>(captureVector).rend()) { // capturing phase: pEvent->m_phase = PhaseType_CAPTURING_PHASE; - while (inode != captureVector.begin()) + while (rinode != + const_cast<NodeVector_t const&>(captureVector).rend()) { - //pEvent->m_currentTarget = *inode; - pEvent->m_currentTarget = Reference< XEventTarget >(DOM::CNode::get(*inode)); - callListeners(*inode, aType, xEvent, sal_True); + pEvent->m_currentTarget = rinode->first; + callListeners(captureListeners, rinode->second, aType, xEvent); if (pEvent->m_canceled) return sal_True; - inode--; + rinode++; } + NodeVector_t::const_iterator inode = captureVector.begin(); + // target phase pEvent->m_phase = PhaseType_AT_TARGET; - callListeners(*inode, aType, xEvent, sal_False); + pEvent->m_currentTarget = inode->first; + callListeners(targetListeners, inode->second, aType, xEvent); if (pEvent->m_canceled) return sal_True; // bubbeling phase inode++; - if (aEvent->getBubbles()) { + if (i_xEvent->getBubbles()) { pEvent->m_phase = PhaseType_BUBBLING_PHASE; while (inode != captureVector.end()) { - pEvent->m_currentTarget = Reference< XEventTarget >(DOM::CNode::get(*inode)); - callListeners(*inode, aType, xEvent, sal_False); + pEvent->m_currentTarget = inode->first; + callListeners(targetListeners, + inode->second, aType, xEvent); if (pEvent->m_canceled) return sal_True; inode++; } diff --git a/unoxml/source/events/eventdispatcher.hxx b/unoxml/source/events/eventdispatcher.hxx index 2af5884842f6..62cb2d38b3f5 100644 --- a/unoxml/source/events/eventdispatcher.hxx +++ b/unoxml/source/events/eventdispatcher.hxx @@ -1,51 +1,95 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +#ifndef EVENT_EVENT_DISPATCHER_HXX +#define EVENT_EVENT_DISPATCHER_HXX -//#include <multimap> #include <map> #include <vector> +#include <libxml/tree.h> + +#include <rtl/ustring.hxx> + #include <com/sun/star/uno/Reference.h> +#include <com/sun/star/xml/dom/XNode.hpp> #include <com/sun/star/xml/dom/events/EventType.hpp> #include <com/sun/star/xml/dom/events/PhaseType.hpp> #include <com/sun/star/xml/dom/events/XEvent.hpp> -#include "event.hxx" + using namespace com::sun::star::uno; using namespace com::sun::star::xml::dom; using namespace com::sun::star::xml::dom::events; -namespace DOM { namespace events -{ +namespace DOM { + +class CDocument; + +namespace events { -typedef std::vector< xmlNodePtr > NodeVector; typedef std::multimap< xmlNodePtr, Reference< com::sun::star::xml::dom::events::XEventListener> > ListenerMap; -typedef std::map<OUString, ListenerMap*> TypeListenerMap; +typedef std::map< ::rtl::OUString, ListenerMap*> TypeListenerMap; typedef std::vector<ListenerMap::value_type> ListenerPairVector; class CEventDispatcher { private: - static TypeListenerMap captureListeners; - static TypeListenerMap targetListeners; + TypeListenerMap m_CaptureListeners; + TypeListenerMap m_TargetListeners; public: - static sal_Bool dispatchEvent(xmlNodePtr aNode, const Reference< XEvent >& aEvent); - - static void addListener( + void addListener( xmlNodePtr pNode, - OUString aType, + ::rtl::OUString aType, const Reference<com::sun::star::xml::dom::events::XEventListener>& aListener, sal_Bool bCapture); - static void removeListener( + void removeListener( xmlNodePtr pNode, - OUString aType, + ::rtl::OUString aType, const Reference<com::sun::star::xml::dom::events::XEventListener>& aListener, sal_Bool bCapture); static void callListeners( - xmlNodePtr pNode, - OUString aType, - const Reference< XEvent >& xEvent, - sal_Bool bCapture); + TypeListenerMap const& rTMap, + xmlNodePtr const pNode, + ::rtl::OUString aType, + const Reference< XEvent >& xEvent); + + bool dispatchEvent( + DOM::CDocument & rDocument, + ::osl::Mutex & rMutex, + xmlNodePtr const pNode, + Reference<XNode> const& xNode, + Reference< XEvent > const& xEvent) const; }; + }} + +#endif + diff --git a/unoxml/source/events/mouseevent.cxx b/unoxml/source/events/mouseevent.cxx index 362a1149ba72..02d1ea619c84 100644 --- a/unoxml/source/events/mouseevent.cxx +++ b/unoxml/source/events/mouseevent.cxx @@ -1,46 +1,96 @@ -#include "mouseevent.hxx" +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <mouseevent.hxx> namespace DOM { namespace events { + CMouseEvent::CMouseEvent() + : CMouseEvent_Base() + , m_screenX(0) + , m_screenY(0) + , m_clientX(0) + , m_clientY(0) + , m_ctrlKey(sal_False) + , m_shiftKey(sal_False) + , m_altKey(sal_False) + , m_metaKey(sal_False) + , m_button(0) + { + } sal_Int32 SAL_CALL CMouseEvent::getScreenX() throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); return m_screenX; } sal_Int32 SAL_CALL CMouseEvent::getScreenY() throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); return m_screenY; } sal_Int32 SAL_CALL CMouseEvent::getClientX() throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); return m_clientX; } sal_Int32 SAL_CALL CMouseEvent::getClientY() throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); return m_clientY; } sal_Bool SAL_CALL CMouseEvent::getCtrlKey() throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); return m_ctrlKey; } sal_Bool SAL_CALL CMouseEvent::getShiftKey() throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); return m_shiftKey; } sal_Bool SAL_CALL CMouseEvent::getAltKey() throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); return m_altKey; } sal_Bool SAL_CALL CMouseEvent::getMetaKey() throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); return m_metaKey; } sal_Int16 SAL_CALL CMouseEvent::getButton() throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); return m_button; } Reference< XEventTarget > SAL_CALL CMouseEvent::getRelatedTarget() throw(RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); return m_relatedTarget; } @@ -62,6 +112,8 @@ namespace DOM { namespace events const Reference< XEventTarget >& /*relatedTargetArg*/) throw(RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); + CUIEvent::initUIEvent(typeArg, canBubbleArg, cancelableArg, viewArg, detailArg); m_screenX = screenXArg; m_screenY = screenYArg; diff --git a/unoxml/source/events/mouseevent.hxx b/unoxml/source/events/mouseevent.hxx index d70f1c1ac605..0bbcbf7698b7 100644 --- a/unoxml/source/events/mouseevent.hxx +++ b/unoxml/source/events/mouseevent.hxx @@ -1,27 +1,51 @@ -#ifndef __MOUSEEVENT_HXX -#define __MOUSEEVENT_HXX +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +#ifndef EVENT_MOUSEEVENT_HXX +#define EVENT_MOUSEEVENT_HXX -#include <sal/types.h> -#include <cppuhelper/implbase1.hxx> -#include <cppuhelper/implbase2.hxx> -#include <cppuhelper/implbase3.hxx> -#include <com/sun/star/uno/Reference.h> -#include <com/sun/star/xml/dom/events/EventType.hpp> #include <com/sun/star/xml/dom/events/PhaseType.hpp> -#include <com/sun/star/xml/dom/events/AttrChangeType.hpp> -#include <com/sun/star/xml/dom/events/XEvent.hpp> -#include <com/sun/star/xml/dom/events/XUIEvent.hpp> #include <com/sun/star/xml/dom/events/XMouseEvent.hpp> -#include "event.hxx" + +#include <cppuhelper/implbase1.hxx> + #include "uievent.hxx" + using ::rtl::OUString; namespace DOM { namespace events { -class CMouseEvent : public cppu::ImplInheritanceHelper1< CUIEvent, XMouseEvent > +typedef ::cppu::ImplInheritanceHelper1< CUIEvent, XMouseEvent > + CMouseEvent_Base; + +class CMouseEvent + : public CMouseEvent_Base { - friend class CEventDispatcher; protected: sal_Int32 m_screenX; sal_Int32 m_screenY; @@ -35,6 +59,7 @@ protected: Reference< XEventTarget > m_relatedTarget; public: + explicit CMouseEvent(); virtual sal_Int32 SAL_CALL getScreenX() throw (RuntimeException); virtual sal_Int32 SAL_CALL getScreenY() throw (RuntimeException); diff --git a/unoxml/source/events/mutationevent.cxx b/unoxml/source/events/mutationevent.cxx index bc06cb2af61a..201fbe9e07da 100644 --- a/unoxml/source/events/mutationevent.cxx +++ b/unoxml/source/events/mutationevent.cxx @@ -1,33 +1,71 @@ -#include "mutationevent.hxx" +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <mutationevent.hxx> namespace DOM { namespace events { + CMutationEvent::CMutationEvent() + : CMutationEvent_Base() + , m_attrChangeType(AttrChangeType_MODIFICATION) + { + } + CMutationEvent::~CMutationEvent() { } Reference< XNode > SAL_CALL CMutationEvent::getRelatedNode() throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); return m_relatedNode; } OUString SAL_CALL CMutationEvent::getPrevValue() throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); return m_prevValue; } OUString SAL_CALL CMutationEvent::getNewValue() throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); return m_newValue; } OUString SAL_CALL CMutationEvent::getAttrName() throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); return m_attrName; } AttrChangeType SAL_CALL CMutationEvent::getAttrChange() throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); return m_attrChangeType; } @@ -37,7 +75,9 @@ namespace DOM { namespace events const OUString& newValueArg, const OUString& attrNameArg, AttrChangeType attrChangeArg) throw (RuntimeException) { - initEvent(typeArg, canBubbleArg, cancelableArg); + ::osl::MutexGuard const g(m_Mutex); + + CEvent::initEvent(typeArg, canBubbleArg, cancelableArg); m_relatedNode = relatedNodeArg; m_prevValue = prevValueArg; m_newValue = newValueArg; diff --git a/unoxml/source/events/mutationevent.hxx b/unoxml/source/events/mutationevent.hxx index e28613ad5df9..20b8dbf4523a 100644 --- a/unoxml/source/events/mutationevent.hxx +++ b/unoxml/source/events/mutationevent.hxx @@ -1,25 +1,56 @@ -#ifndef __MUTATIONEVENT_HXX -#define __MUTATIONEVENT_HXX +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +#ifndef EVENT_MUTATIONEVENT_HXX +#define EVENT_MUTATIONEVENT_HXX #include <sal/types.h> -#include <cppuhelper/implbase1.hxx> -#include <cppuhelper/implbase2.hxx> -#include <cppuhelper/implbase3.hxx> + #include <com/sun/star/uno/Reference.h> -#include <com/sun/star/xml/dom/events/EventType.hpp> + #include <com/sun/star/xml/dom/events/PhaseType.hpp> #include <com/sun/star/xml/dom/events/AttrChangeType.hpp> -#include <com/sun/star/xml/dom/events/XEvent.hpp> #include <com/sun/star/xml/dom/events/XMutationEvent.hpp> + +#include <cppuhelper/implbase1.hxx> + #include "event.hxx" + using ::rtl::OUString; namespace DOM { namespace events { -class CMutationEvent : public cppu::ImplInheritanceHelper1< CEvent, XMutationEvent > +typedef ::cppu::ImplInheritanceHelper1< CEvent, XMutationEvent > + CMutationEvent_Base; + +class CMutationEvent + : public CMutationEvent_Base { - friend class CEventDispatcher; protected: Reference< XNode > m_relatedNode; OUString m_prevValue; @@ -28,6 +59,7 @@ protected: AttrChangeType m_attrChangeType; public: + explicit CMutationEvent(); virtual ~CMutationEvent(); diff --git a/unoxml/source/events/testlistener.cxx b/unoxml/source/events/testlistener.cxx index 64806c84017d..a493aefb55f8 100644 --- a/unoxml/source/events/testlistener.cxx +++ b/unoxml/source/events/testlistener.cxx @@ -33,6 +33,10 @@ #define U2S(s) OUStringToOString(s, RTL_TEXTENCODING_UTF8).getStr() +using ::com::sun::star::lang::XMultiServiceFactory; +using ::com::sun::star::lang::IllegalArgumentException; + + namespace DOM { namespace events { diff --git a/unoxml/source/events/testlistener.hxx b/unoxml/source/events/testlistener.hxx index b6d6abdc700f..1d96edefca34 100644 --- a/unoxml/source/events/testlistener.hxx +++ b/unoxml/source/events/testlistener.hxx @@ -25,47 +25,46 @@ * ************************************************************************/ -#ifndef _TESTLISTENER_HXX -#define _TESTLISTENER_HXX - -#include <map> +#ifndef EVENT_TESTLISTENER_HXX +#define EVENT_TESTLISTENER_HXX #include <sal/types.h> -#include <cppuhelper/implbase3.hxx> + #include <com/sun/star/uno/Reference.h> #include <com/sun/star/uno/Sequence.h> #include <com/sun/star/uno/XInterface.hpp> #include <com/sun/star/uno/Exception.hpp> -#include <com/sun/star/xml/dom/XNode.hpp> #include <com/sun/star/lang/XServiceInfo.hpp> #include <com/sun/star/lang/XInitialization.hpp> -#include <com/sun/star/lang/XSingleServiceFactory.hpp> #include <com/sun/star/lang/XMultiServiceFactory.hpp> -#include <com/sun/star/lang/XUnoTunnel.hpp> #include <com/sun/star/xml/dom/events/XEventTarget.hpp> #include <com/sun/star/xml/dom/events/XEventListener.hpp> #include <com/sun/star/xml/dom/events/XEvent.hpp> -#include <com/sun/star/xml/dom/events/EventType.hpp> -#include <com/sun/star/xml/dom/events/XMutationEvent.hpp> -#include "libxml/tree.h" +#include <cppuhelper/implbase3.hxx> + using ::rtl::OUString; using namespace com::sun::star::uno; -using namespace com::sun::star::lang; using namespace com::sun::star::xml::dom; using namespace com::sun::star::xml::dom::events; namespace DOM { namespace events { + typedef ::cppu::WeakImplHelper3 + < ::com::sun::star::xml::dom::events::XEventListener + , ::com::sun::star::lang::XInitialization + , ::com::sun::star::lang::XServiceInfo + > CTestListener_Base; + class CTestListener - : public ::cppu::WeakImplHelper3< com::sun::star::xml::dom::events::XEventListener, XInitialization, XServiceInfo > + : public CTestListener_Base { private: - Reference< XMultiServiceFactory > m_factory; + Reference< ::com::sun::star::lang::XMultiServiceFactory > m_factory; Reference <XEventTarget> m_target; OUString m_type; sal_Bool m_capture; @@ -78,9 +77,13 @@ namespace DOM { namespace events static const char* aSupportedServiceNames[]; static OUString _getImplementationName(); static Sequence< OUString > _getSupportedServiceNames(); - static Reference< XInterface > _getInstance(const Reference< XMultiServiceFactory >& rSMgr); + static Reference< XInterface > _getInstance( + const Reference< ::com::sun::star::lang::XMultiServiceFactory >& + rSMgr); - CTestListener(const Reference< XMultiServiceFactory >& rSMgr) + CTestListener( + const Reference< ::com::sun::star::lang::XMultiServiceFactory >& + rSMgr) : m_factory(rSMgr){}; virtual ~CTestListener(); diff --git a/unoxml/source/events/uievent.cxx b/unoxml/source/events/uievent.cxx index 29d2e10e57dc..68e5dbbc6862 100644 --- a/unoxml/source/events/uievent.cxx +++ b/unoxml/source/events/uievent.cxx @@ -1,16 +1,50 @@ -#include "event.hxx" -#include "uievent.hxx" +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <uievent.hxx> namespace DOM { namespace events { + CUIEvent::CUIEvent() + : CUIEvent_Base() + , m_detail(0) + { + } - Reference< XAbstractView > SAL_CALL CUIEvent::getView() throw(RuntimeException) + Reference< XAbstractView > SAL_CALL + CUIEvent::getView() throw(RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); return m_view; } sal_Int32 SAL_CALL CUIEvent::getDetail() throw(RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); return m_detail; } @@ -20,7 +54,9 @@ namespace DOM { namespace events const Reference< XAbstractView >& viewArg, sal_Int32 detailArg) throw(RuntimeException) { - initEvent(typeArg, canBubbleArg, cancelableArg); + ::osl::MutexGuard const g(m_Mutex); + + CEvent::initEvent(typeArg, canBubbleArg, cancelableArg); m_view = viewArg; m_detail = detailArg; } diff --git a/unoxml/source/events/uievent.hxx b/unoxml/source/events/uievent.hxx index f7c5806e48e0..2f1c6f28dc3d 100644 --- a/unoxml/source/events/uievent.hxx +++ b/unoxml/source/events/uievent.hxx @@ -1,32 +1,61 @@ -#ifndef __UIEVENT_HXX -#define __UIEVENT_HXX +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +#ifndef EVENT_UIEVENT_HXX +#define EVENT_UIEVENT_HXX #include <sal/types.h> -#include <cppuhelper/implbase1.hxx> -#include <cppuhelper/implbase2.hxx> -#include <cppuhelper/implbase3.hxx> -#include <com/sun/star/uno/Reference.h> -#include <com/sun/star/xml/dom/events/EventType.hpp> + #include <com/sun/star/xml/dom/events/PhaseType.hpp> -#include <com/sun/star/xml/dom/events/AttrChangeType.hpp> -#include <com/sun/star/xml/dom/events/XEvent.hpp> #include <com/sun/star/xml/dom/events/XUIEvent.hpp> #include <com/sun/star/xml/dom/views/XAbstractView.hpp> + +#include <cppuhelper/implbase1.hxx> + #include "event.hxx" + using ::rtl::OUString; using namespace com::sun::star::xml::dom::views; namespace DOM { namespace events { -class CUIEvent : public cppu::ImplInheritanceHelper1< CEvent, XUIEvent > +typedef ::cppu::ImplInheritanceHelper1< CEvent, XUIEvent > CUIEvent_Base; + +class CUIEvent + : public CUIEvent_Base { - friend class CEventDispatcher; protected: sal_Int32 m_detail; Reference< XAbstractView > m_view; public: + explicit CUIEvent(); + virtual Reference< XAbstractView > SAL_CALL getView() throw(RuntimeException); virtual sal_Int32 SAL_CALL getDetail() throw(RuntimeException); virtual void SAL_CALL initUIEvent(const OUString& typeArg, diff --git a/unoxml/source/rdf/librdf_services.cxx b/unoxml/source/rdf/librdf_services.cxx index 08e776d214fe..4c614eef433b 100644 --- a/unoxml/source/rdf/librdf_services.cxx +++ b/unoxml/source/rdf/librdf_services.cxx @@ -38,7 +38,7 @@ using namespace ::com::sun::star; extern "C" { -void SAL_CALL +SAL_DLLPUBLIC_EXPORT void SAL_CALL component_getImplementationEnvironment(const sal_Char **o_ppEnvironmentTypeName, uno_Environment ** /* ppEnvironment */) { @@ -65,7 +65,8 @@ static ::cppu::ImplementationEntry const entries[] = { { 0, 0, 0, 0, 0, 0 } }; -extern "C" void * SAL_CALL component_getFactory( +SAL_DLLPUBLIC_EXPORT void * SAL_CALL +component_getFactory( const char * implName, void * serviceManager, void * registryKey) { return ::cppu::component_getFactoryHelper( diff --git a/unoxml/source/rdf/makefile.mk b/unoxml/source/rdf/makefile.mk deleted file mode 100644 index 1dbcffb8b6ac..000000000000 --- a/unoxml/source/rdf/makefile.mk +++ /dev/null @@ -1,92 +0,0 @@ -#************************************************************************* -# -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# Copyright 2000, 2010 Oracle and/or its affiliates. -# -# OpenOffice.org - a multi-platform office productivity suite -# -# 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. -# -#************************************************************************* - -PRJ=..$/.. - -PRJNAME=unoxml -TARGET=unordf -LIBTARGET=NO - -ENABLE_EXCEPTIONS=TRUE - -# --- Settings ----------------------------------------------------- - -.INCLUDE : settings.mk - -.IF "$(SYSTEM_REDLAND)" == "YES" -CFLAGS+=-DSYSTEM_REDLAND $(REDLAND_CFLAGS) -.ENDIF - -.IF "$(SYSTEM_LIBXSLT)" == "YES" -CFLAGS+= $(LIBXSLT_CFLAGS) -.ELSE -LIBXSLTINCDIR=external$/libxslt -CFLAGS+= -I$(SOLARINCDIR)$/$(LIBXSLTINCDIR) -.ENDIF - -# --- Files -------------------------------------------------------- -.IF "$(L10N_framework)"=="" - -SLOFILES = \ - $(SLO)$/CBlankNode.obj \ - $(SLO)$/CURI.obj \ - $(SLO)$/CLiteral.obj \ - $(SLO)$/librdf_repository.obj \ - $(SLO)$/librdf_services.obj - - -SHL1DEPN= makefile.mk -SHL1OBJS= $(SLOFILES) - -SHL1TARGET= $(TARGET)$(DLLPOSTFIX) -SHL1IMPLIB= i$(TARGET) - -SHL1VERSIONMAP=$(SOLARENV)/src/component.map -SHL1DEF=$(MISC)$/$(SHL1TARGET).def -DEF1NAME=$(SHL1TARGET) - -SHL1STDLIBS= \ - $(REDLANDLIB) \ - $(XSLTLIB) \ - $(CPPUHELPERLIB) \ - $(CPPULIB) \ - $(SALLIB) \ - -.ENDIF - -# --- Targets ------------------------------------------------------ - -.INCLUDE : target.mk - - -ALLTAR : $(MISC)/unordf.component - -$(MISC)/unordf.component .ERRREMOVE : $(SOLARENV)/bin/createcomponent.xslt \ - unordf.component - $(XSLTPROC) --nonet --stringparam uri \ - '$(COMPONENTPREFIX_BASIS_NATIVE)$(SHL1TARGETN:f)' -o $@ \ - $(SOLARENV)/bin/createcomponent.xslt unordf.component diff --git a/unoxml/source/service/makefile.mk b/unoxml/source/service/makefile.mk deleted file mode 100644 index 5fbe62f67ec4..000000000000 --- a/unoxml/source/service/makefile.mk +++ /dev/null @@ -1,86 +0,0 @@ -#************************************************************************* -# -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# Copyright 2000, 2010 Oracle and/or its affiliates. -# -# OpenOffice.org - a multi-platform office productivity suite -# -# 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. -# -#************************************************************************* - -PRJ=..$/.. - -PRJNAME=unoxml -TARGET=unoxml -LIBTARGET=NO - -ENABLE_EXCEPTIONS=TRUE - -# --- Settings ----------------------------------------------------- - -.INCLUDE : settings.mk - -.IF "$(SYSTEM_LIBXML)" == "YES" -CFLAGS+=-DSYSTEM_LIBXML $(LIBXML_CFLAGS) -.ENDIF - -# --- Files -------------------------------------------------------- - -SLOFILES = \ - $(SLO)$/services.obj - - -SHL1DEPN= makefile.mk -SHL1OBJS= $(SLOFILES) - -SHL1TARGET= $(TARGET)$(DLLPOSTFIX) -SHL1IMPLIB= i$(TARGET) - -SHL1VERSIONMAP=$(SOLARENV)/src/component.map -SHL1DEF=$(MISC)$/$(SHL1TARGET).def -DEF1NAME=$(SHL1TARGET) - -SHL1LIBS= \ - $(SLB)$/domimpl.lib \ - $(SLB)$/xpathimpl.lib \ - $(SLB)$/eventsimpl.lib - -SHL1STDLIBS= \ - $(UCBHELPERLIB) \ - $(LIBXML2LIB) \ - $(COMPHELPERLIB) \ - $(CPPUHELPERLIB) \ - $(CPPULIB) \ - $(SAXLIB) \ - $(SALLIB)\ - $(EXPATASCII3RDLIB) - -# --- Targets ------------------------------------------------------ - -.INCLUDE : target.mk - - -ALLTAR : $(MISC)/unoxml.component - -$(MISC)/unoxml.component .ERRREMOVE : $(SOLARENV)/bin/createcomponent.xslt \ - unoxml.component - $(XSLTPROC) --nonet --stringparam uri \ - '$(COMPONENTPREFIX_BASIS_NATIVE)$(SHL1TARGETN:f)' -o $@ \ - $(SOLARENV)/bin/createcomponent.xslt unoxml.component diff --git a/unoxml/source/service/services.cxx b/unoxml/source/service/services.cxx index 6b1a2f6f0979..c50faf3e8522 100644 --- a/unoxml/source/service/services.cxx +++ b/unoxml/source/service/services.cxx @@ -54,13 +54,13 @@ using namespace ::com::sun::star::registry; extern "C" { -void SAL_CALL +SAL_DLLPUBLIC_EXPORT void SAL_CALL component_getImplementationEnvironment(const sal_Char **ppEnvironmentTypeName, uno_Environment ** /*ppEnvironment */) { *ppEnvironmentTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME ; } -void* SAL_CALL +SAL_DLLPUBLIC_EXPORT void* SAL_CALL component_getFactory(const sal_Char *pImplementationName, void *pServiceManager, void * /*pRegistryKey*/) { void* pReturn = NULL ; diff --git a/unoxml/source/xpath/nodelist.cxx b/unoxml/source/xpath/nodelist.cxx index dd44d8bfcc06..05add3ca44bc 100644 --- a/unoxml/source/xpath/nodelist.cxx +++ b/unoxml/source/xpath/nodelist.cxx @@ -25,13 +25,19 @@ * ************************************************************************/ -#include "nodelist.hxx" -#include "../dom/node.hxx" +#include <nodelist.hxx> + +#include "../dom/document.hxx" namespace XPath { - CNodeList::CNodeList(boost::shared_ptr<xmlXPathObject>& rxpathObj) - : m_pNodeSet(0) + CNodeList::CNodeList( + ::rtl::Reference<DOM::CDocument> const& pDocument, + ::osl::Mutex & rMutex, + boost::shared_ptr<xmlXPathObject> const& rxpathObj) + : m_pDocument(pDocument) + , m_rMutex(rMutex) + , m_pNodeSet(0) { if (rxpathObj != NULL && rxpathObj->type == XPATH_NODESET) { @@ -45,6 +51,8 @@ namespace XPath */ sal_Int32 SAL_CALL CNodeList::getLength() throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + sal_Int32 value = 0; if (m_pNodeSet != NULL) value = xmlXPathNodeSetGetLength(m_pNodeSet); @@ -54,12 +62,17 @@ namespace XPath /** Returns the indexth item in the collection. */ - Reference< XNode > SAL_CALL CNodeList::item(sal_Int32 index) throw (RuntimeException) + Reference< XNode > SAL_CALL CNodeList::item(sal_Int32 index) + throw (RuntimeException) { - Reference< XNode > aNode; - if (m_pNodeSet != NULL) - aNode = Reference< XNode >(DOM::CNode::get(xmlXPathNodeSetItem(m_pNodeSet, index))); - return aNode; + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_pNodeSet) { + return 0; + } + xmlNodePtr const pNode = xmlXPathNodeSetItem(m_pNodeSet, index); + Reference< XNode > const xNode(m_pDocument->GetCNode(pNode).get()); + return xNode; } } diff --git a/unoxml/source/xpath/nodelist.hxx b/unoxml/source/xpath/nodelist.hxx index 68f419f10174..fd6b428af27e 100644 --- a/unoxml/source/xpath/nodelist.hxx +++ b/unoxml/source/xpath/nodelist.hxx @@ -25,38 +25,52 @@ * ************************************************************************/ -#ifndef _NODELIST_HXX -#define _NODELIST_HXX +#ifndef XPATH_NODELIST_HXX +#define XPATH_NODELIST_HXX -#include <vector> #include <sal/types.h> +#include <rtl/ref.hxx> + #include <cppuhelper/implbase1.hxx> + #include <com/sun/star/uno/Reference.h> -#include <com/sun/star/uno/Exception.hpp> #include <com/sun/star/xml/dom/XNode.hpp> #include <com/sun/star/xml/dom/XNodeList.hpp> #include <com/sun/star/xml/xpath/XXPathObject.hpp> + #include "libxml/tree.h" #include "libxml/xpath.h" + #include <boost/shared_ptr.hpp> + using ::rtl::OUString; using namespace com::sun::star::uno; -using namespace com::sun::star::lang; using namespace com::sun::star::xml::dom; using namespace com::sun::star::xml::xpath; +namespace DOM { + class CDocument; +} + namespace XPath { class CNodeList : public cppu::WeakImplHelper1< XNodeList > { private: + /// #i115995# keep document alive + ::rtl::Reference< DOM::CDocument > const m_pDocument; + ::osl::Mutex & m_rMutex; + /// retain the result set in case the CXPathObject is released boost::shared_ptr<xmlXPathObject> m_pXPathObj; xmlNodeSetPtr m_pNodeSet; public: - CNodeList(boost::shared_ptr<xmlXPathObject> &rxpathObj); + CNodeList( + ::rtl::Reference<DOM::CDocument> const& pDocument, + ::osl::Mutex & rMutex, + boost::shared_ptr<xmlXPathObject> const& rxpathObj); /** The number of nodes in the list. */ @@ -64,7 +78,8 @@ namespace XPath /** Returns the indexth item in the collection. */ - virtual Reference< XNode > SAL_CALL item(sal_Int32 index) throw (RuntimeException); + virtual Reference< XNode > SAL_CALL item(sal_Int32 index) + throw (RuntimeException); }; } diff --git a/unoxml/source/xpath/xpathapi.cxx b/unoxml/source/xpath/xpathapi.cxx index f40082e25e9b..00d13be6348c 100644 --- a/unoxml/source/xpath/xpathapi.cxx +++ b/unoxml/source/xpath/xpathapi.cxx @@ -25,19 +25,26 @@ * ************************************************************************/ -#include "xpathapi.hxx" -#include "nodelist.hxx" -#include "xpathobject.hxx" -#include "../dom/node.hxx" +#include <xpathapi.hxx> -#include <rtl/ustrbuf.hxx> +#include <stdarg.h> +#include <string.h> +#include <libxml/tree.h> #include <libxml/xmlerror.h> #include <libxml/xpath.h> #include <libxml/xpathInternals.h> -#include <stdarg.h> -#include <string.h> +#include <rtl/ustrbuf.hxx> + +#include <nodelist.hxx> +#include <xpathobject.hxx> + +#include "../dom/node.hxx" +#include "../dom/document.hxx" + + +using ::com::sun::star::lang::XMultiServiceFactory; namespace XPath @@ -105,6 +112,8 @@ namespace XPath const OUString& aURI) throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); + m_nsmap.insert(nsmap_t::value_type(aPrefix, aURI)); } @@ -113,13 +122,16 @@ namespace XPath const OUString& aURI) throw (RuntimeException) { - if ((m_nsmap.find(aPrefix))->second.equals(aURI)) + ::osl::MutexGuard const g(m_Mutex); + + if ((m_nsmap.find(aPrefix))->second.equals(aURI)) { m_nsmap.erase(aPrefix); + } } // register all namespaces stored in the namespace list for this object // with the current xpath evaluation context - static void _registerNamespaces( + static void lcl_registerNamespaces( xmlXPathContextPtr ctx, const nsmap_t& nsmap) { @@ -137,13 +149,16 @@ namespace XPath } } - // get all ns decls on a node (and parent nodes, if any) and register them - static void _collectNamespaces( - CXPathAPI* pAPI, - const Reference< XNode >& namespaceNode) + // get all ns decls on a node (and parent nodes, if any) + static void lcl_collectNamespaces( + nsmap_t & rNamespaces, Reference< XNode > const& xNamespaceNode) { - // get namespace decls from node... - xmlNodePtr pNode = DOM::CNode::getNodePtr(namespaceNode); + DOM::CNode *const pCNode(DOM::CNode::GetImplementation(xNamespaceNode)); + if (!pCNode) { throw RuntimeException(); } + + ::osl::MutexGuard const g(pCNode->GetOwnerDocument().GetMutex()); + + xmlNodePtr pNode = pCNode->GetNodePtr(); while (pNode != 0) { xmlNsPtr curDef = pNode->nsDef; while (curDef != 0) { @@ -151,16 +166,32 @@ namespace XPath OUString aURI((sal_Char*)xHref, strlen((char*)xHref), RTL_TEXTENCODING_UTF8); const xmlChar* xPre = curDef->prefix; OUString aPrefix((sal_Char*)xPre, strlen((char*)xPre), RTL_TEXTENCODING_UTF8); - pAPI->registerNS(aPrefix, aURI); + // we could already have this prefix from a child node + if (rNamespaces.find(aPrefix) == rNamespaces.end()) + { + rNamespaces.insert(::std::make_pair(aPrefix, aURI)); + } curDef = curDef->next; } pNode = pNode->parent; } } + static void lcl_collectRegisterNamespaces( + CXPathAPI & rAPI, Reference< XNode > const& xNamespaceNode) + { + nsmap_t namespaces; + lcl_collectNamespaces(namespaces, xNamespaceNode); + for (nsmap_t::const_iterator iter = namespaces.begin(); + iter != namespaces.end(); ++iter) + { + rAPI.registerNS(iter->first, iter->second); + } + } + // register function and variable lookup functions with the current // xpath evaluation context - static void _registerExtensions( + static void lcl_registerExtensions( xmlXPathContextPtr ctx, const extensions_t& extensions) { @@ -209,7 +240,7 @@ namespace XPath const Reference< XNode >& namespaceNode) throw (RuntimeException, XPathException) { - _collectNamespaces(this, namespaceNode); + lcl_collectRegisterNamespaces(*this, namespaceNode); return selectNodeList(contextNode, expr); } @@ -236,7 +267,7 @@ namespace XPath const Reference< XNode >& namespaceNode ) throw (RuntimeException, XPathException) { - _collectNamespaces(this, namespaceNode); + lcl_collectRegisterNamespaces(*this, namespaceNode); return selectSingleNode(contextNode, expr); } @@ -307,15 +338,34 @@ namespace XPath * the context Node */ Reference< XXPathObject > SAL_CALL CXPathAPI::eval( - const Reference< XNode >& contextNode, + Reference< XNode > const& xContextNode, const OUString& expr) throw (RuntimeException, XPathException) { - xmlXPathContextPtr xpathCtx; - xmlXPathObjectPtr xpathObj; + if (!xContextNode.is()) { throw RuntimeException(); } + + nsmap_t nsmap; + extensions_t extensions; + + { + ::osl::MutexGuard const g(m_Mutex); + nsmap = m_nsmap; + extensions = m_extensions; + } // get the node and document - xmlNodePtr pNode = DOM::CNode::getNodePtr(contextNode); + ::rtl::Reference<DOM::CDocument> const pCDoc( + dynamic_cast<DOM::CDocument*>( DOM::CNode::GetImplementation( + xContextNode->getOwnerDocument()))); + if (!pCDoc.is()) { throw RuntimeException(); } + + DOM::CNode *const pCNode = DOM::CNode::GetImplementation(xContextNode); + if (!pCNode) { throw RuntimeException(); } + + ::osl::MutexGuard const g(pCDoc->GetMutex()); // lock the document! + + xmlNodePtr const pNode = pCNode->GetNodePtr(); + if (!pNode) { throw RuntimeException(); } xmlDocPtr pDoc = pNode->doc; /* NB: workaround for #i87252#: @@ -330,8 +380,9 @@ namespace XPath } /* Create xpath evaluation context */ - xpathCtx = xmlXPathNewContext(pDoc); - if (xpathCtx == NULL) throw XPathException(); + ::boost::shared_ptr<xmlXPathContext> const xpathCtx( + xmlXPathNewContext(pDoc), xmlXPathFreeContext); + if (xpathCtx == NULL) { throw XPathException(); } // set context node xpathCtx->node = pNode; @@ -340,20 +391,21 @@ namespace XPath xmlSetGenericErrorFunc(NULL, generic_error_func); // register namespaces and extension - _registerNamespaces(xpathCtx, m_nsmap); - _registerExtensions(xpathCtx, m_extensions); + lcl_registerNamespaces(xpathCtx.get(), nsmap); + lcl_registerExtensions(xpathCtx.get(), extensions); /* run the query */ OString o1 = OUStringToOString(expr, RTL_TEXTENCODING_UTF8); xmlChar *xStr = (xmlChar*)o1.getStr(); - if ((xpathObj = xmlXPathEval(xStr, xpathCtx)) == NULL) { + ::boost::shared_ptr<xmlXPathObject> const xpathObj( + xmlXPathEval(xStr, xpathCtx.get()), xmlXPathFreeObject); + if (0 == xpathObj) { // OSL_ENSURE(xpathCtx->lastError == NULL, xpathCtx->lastError->message); - xmlXPathFreeContext(xpathCtx); throw XPathException(); } - xmlXPathFreeContext(xpathCtx); - Reference< XXPathObject > aObj(new CXPathObject(xpathObj, contextNode)); - return aObj; + Reference<XXPathObject> const xObj( + new CXPathObject(pCDoc, pCDoc->GetMutex(), xpathObj)); + return xObj; } /** @@ -365,7 +417,7 @@ namespace XPath const Reference< XNode >& namespaceNode) throw (RuntimeException, XPathException) { - _collectNamespaces(this, namespaceNode); + lcl_collectRegisterNamespaces(*this, namespaceNode); return eval(contextNode, expr); } @@ -378,9 +430,12 @@ namespace XPath const OUString& aName) throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); + // get extension from service manager - Reference< XXPathExtension > aExtension(m_aFactory->createInstance(aName), UNO_QUERY_THROW); - m_extensions.push_back( aExtension ); + Reference< XXPathExtension > const xExtension( + m_aFactory->createInstance(aName), UNO_QUERY_THROW); + m_extensions.push_back(xExtension); } /** @@ -388,13 +443,13 @@ namespace XPath * XPathAPI instance */ void SAL_CALL CXPathAPI::registerExtensionInstance( - const Reference< XXPathExtension>& aExtension) + Reference< XXPathExtension> const& xExtension) throw (RuntimeException) { - if (aExtension.is()) { - m_extensions.push_back( aExtension ); - } else { + if (!xExtension.is()) { throw RuntimeException(); } + ::osl::MutexGuard const g(m_Mutex); + m_extensions.push_back( xExtension ); } } diff --git a/unoxml/source/xpath/xpathapi.hxx b/unoxml/source/xpath/xpathapi.hxx index 048fafaae8e9..a64eff7444c7 100644 --- a/unoxml/source/xpath/xpathapi.hxx +++ b/unoxml/source/xpath/xpathapi.hxx @@ -25,14 +25,16 @@ * ************************************************************************/ -#ifndef _XPATHAPI_HXX -#define _XPATHAPI_HXX +#ifndef XPATH_XPATHAPI_HXX +#define XPATH_XPATHAPI_HXX #include <map> #include <vector> #include <sal/types.h> + #include <cppuhelper/implbase2.hxx> + #include <com/sun/star/uno/Reference.h> #include <com/sun/star/uno/Sequence.h> @@ -50,11 +52,9 @@ #include <com/sun/star/lang/XSingleServiceFactory.hpp> #include <com/sun/star/lang/XMultiServiceFactory.hpp> -#include "libxml/tree.h" using ::rtl::OUString; using namespace com::sun::star::uno; -using namespace com::sun::star::lang; using namespace com::sun::star::xml::dom; using namespace com::sun::star::xml::xpath; @@ -63,28 +63,40 @@ namespace XPath typedef std::map<OUString, OUString> nsmap_t; typedef std::vector< Reference<XXPathExtension> > extensions_t; + typedef ::cppu::WeakImplHelper2 + < XXPathAPI + , ::com::sun::star::lang::XServiceInfo + > CXPathAPI_Base; + class CXPathAPI - : public ::cppu::WeakImplHelper2< XXPathAPI, XServiceInfo > + : public CXPathAPI_Base { private: + ::osl::Mutex m_Mutex; nsmap_t m_nsmap; - const Reference< XMultiServiceFactory > m_aFactory; + const Reference< ::com::sun::star::lang::XMultiServiceFactory > m_aFactory; extensions_t m_extensions; public: // ctor - CXPathAPI(const Reference< XMultiServiceFactory >& rSMgr); + CXPathAPI( + const Reference< ::com::sun::star::lang::XMultiServiceFactory >& + rSMgr); // call for factory - static Reference< XInterface > getInstance(const Reference < XMultiServiceFactory >& xFactory); + static Reference< XInterface > getInstance( + const Reference < ::com::sun::star::lang::XMultiServiceFactory >& + xFactory); // static helpers for service info and component management static const char* aImplementationName; static const char* aSupportedServiceNames[]; static OUString _getImplementationName(); static Sequence< OUString > _getSupportedServiceNames(); - static Reference< XInterface > _getInstance(const Reference< XMultiServiceFactory >& rSMgr); + static Reference< XInterface > _getInstance( + const Reference< ::com::sun::star::lang::XMultiServiceFactory >& + rSMgr); // XServiceInfo virtual OUString SAL_CALL getImplementationName() diff --git a/unoxml/source/xpath/xpathobject.cxx b/unoxml/source/xpath/xpathobject.cxx index 757de0c5aac4..36fdf1ba933e 100644 --- a/unoxml/source/xpath/xpathobject.cxx +++ b/unoxml/source/xpath/xpathobject.cxx @@ -25,67 +25,75 @@ * ************************************************************************/ +#include <xpathobject.hxx> + #include <string.h> -#include "xpathobject.hxx" -#include "nodelist.hxx" + +#include "../dom/document.hxx" +#include <nodelist.hxx> + namespace XPath { - CXPathObject::CXPathObject(xmlXPathObjectPtr xpathObj, const Reference< XNode >& contextNode) - : m_pXPathObj(xpathObj, xmlXPathFreeObject), m_xContextNode(contextNode) + static XPathObjectType lcl_GetType(xmlXPathObjectPtr const pXPathObj) { - switch (m_pXPathObj->type) + switch (pXPathObj->type) { - case XPATH_UNDEFINED: - m_xPathObjectType = XPathObjectType_XPATH_UNDEFINED; - break; - case XPATH_NODESET: - m_xPathObjectType = XPathObjectType_XPATH_NODESET; - break; - case XPATH_BOOLEAN: - m_xPathObjectType = XPathObjectType_XPATH_BOOLEAN; - break; - case XPATH_NUMBER: - m_xPathObjectType = XPathObjectType_XPATH_NUMBER; - break; - case XPATH_STRING: - m_xPathObjectType = XPathObjectType_XPATH_STRING; - break; - case XPATH_POINT: - m_xPathObjectType = XPathObjectType_XPATH_POINT; - break; - case XPATH_RANGE: - m_xPathObjectType = XPathObjectType_XPATH_RANGE; - break; - case XPATH_LOCATIONSET: - m_xPathObjectType = XPathObjectType_XPATH_LOCATIONSET; - break; - case XPATH_USERS: - m_xPathObjectType = XPathObjectType_XPATH_USERS; - break; - case XPATH_XSLT_TREE: - m_xPathObjectType = XPathObjectType_XPATH_XSLT_TREE; - break; - default: - m_xPathObjectType = XPathObjectType_XPATH_UNDEFINED; - break; + case XPATH_UNDEFINED: + return XPathObjectType_XPATH_UNDEFINED; + case XPATH_NODESET: + return XPathObjectType_XPATH_NODESET; + case XPATH_BOOLEAN: + return XPathObjectType_XPATH_BOOLEAN; + case XPATH_NUMBER: + return XPathObjectType_XPATH_NUMBER; + case XPATH_STRING: + return XPathObjectType_XPATH_STRING; + case XPATH_POINT: + return XPathObjectType_XPATH_POINT; + case XPATH_RANGE: + return XPathObjectType_XPATH_RANGE; + case XPATH_LOCATIONSET: + return XPathObjectType_XPATH_LOCATIONSET; + case XPATH_USERS: + return XPathObjectType_XPATH_USERS; + case XPATH_XSLT_TREE: + return XPathObjectType_XPATH_XSLT_TREE; + default: + return XPathObjectType_XPATH_UNDEFINED; } } + CXPathObject::CXPathObject( + ::rtl::Reference<DOM::CDocument> const& pDocument, + ::osl::Mutex & rMutex, + ::boost::shared_ptr<xmlXPathObject> const& pXPathObj) + : m_pDocument(pDocument) + , m_rMutex(rMutex) + , m_pXPathObj(pXPathObj) + , m_XPathObjectType(lcl_GetType(pXPathObj.get())) + { + } + /** get object type */ XPathObjectType CXPathObject::getObjectType() throw (RuntimeException) { - return m_xPathObjectType; + return m_XPathObjectType; } /** get the nodes from a nodelist type object */ - Reference< XNodeList > SAL_CALL CXPathObject::getNodeList() throw (RuntimeException) + Reference< XNodeList > SAL_CALL + CXPathObject::getNodeList() throw (RuntimeException) { - return Reference< XNodeList >(new CNodeList(m_pXPathObj)); + ::osl::MutexGuard const g(m_rMutex); + + Reference< XNodeList > const xRet( + new CNodeList(m_pDocument, m_rMutex, m_pXPathObj)); + return xRet; } /** @@ -93,6 +101,8 @@ namespace XPath */ sal_Bool SAL_CALL CXPathObject::getBoolean() throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + return (sal_Bool) xmlXPathCastToBoolean(m_pXPathObj.get()); } @@ -101,6 +111,8 @@ namespace XPath */ sal_Int8 SAL_CALL CXPathObject::getByte() throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + return (sal_Int8) xmlXPathCastToNumber(m_pXPathObj.get()); } @@ -109,6 +121,8 @@ namespace XPath */ sal_Int16 SAL_CALL CXPathObject::getShort() throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + return (sal_Int16) xmlXPathCastToNumber(m_pXPathObj.get()); } @@ -117,6 +131,8 @@ namespace XPath */ sal_Int32 SAL_CALL CXPathObject::getLong() throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + return (sal_Int32) xmlXPathCastToNumber(m_pXPathObj.get()); } @@ -125,6 +141,8 @@ namespace XPath */ sal_Int64 SAL_CALL CXPathObject::getHyper() throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + return (sal_Int64) xmlXPathCastToNumber(m_pXPathObj.get()); } @@ -133,6 +151,8 @@ namespace XPath */ float SAL_CALL CXPathObject::getFloat() throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + return (float) xmlXPathCastToNumber(m_pXPathObj.get()); } @@ -141,6 +161,8 @@ namespace XPath */ double SAL_CALL CXPathObject::getDouble() throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + return xmlXPathCastToNumber(m_pXPathObj.get()); } @@ -149,8 +171,12 @@ namespace XPath */ OUString SAL_CALL CXPathObject::getString() throw (RuntimeException) { - const sal_Char* x1 = (sal_Char*) xmlXPathCastToString(m_pXPathObj.get()); - return OUString(x1, strlen(x1), RTL_TEXTENCODING_UTF8); + ::osl::MutexGuard const g(m_rMutex); + + ::boost::shared_ptr<xmlChar const> str( + xmlXPathCastToString(m_pXPathObj.get()), xmlFree); + sal_Char const*const pS(reinterpret_cast<sal_Char const*>(str.get())); + return OUString(pS, strlen(pS), RTL_TEXTENCODING_UTF8); } } diff --git a/unoxml/source/xpath/xpathobject.hxx b/unoxml/source/xpath/xpathobject.hxx index 348fae8e21e6..f15aed9ded95 100644 --- a/unoxml/source/xpath/xpathobject.hxx +++ b/unoxml/source/xpath/xpathobject.hxx @@ -25,38 +25,48 @@ * ************************************************************************/ -#ifndef _XPATHOBJECT_HXX -#define _XPATHOBJECT_HXX +#ifndef XPATH_XPATHOBJECT_HXX +#define XPATH_XPATHOBJECT_HXX + +#include <boost/shared_ptr.hpp> + +#include <libxml/tree.h> +#include <libxml/xpath.h> -#include <map> #include <sal/types.h> +#include <rtl/ref.hxx> + #include <cppuhelper/implbase1.hxx> + #include <com/sun/star/uno/Reference.h> -#include <com/sun/star/uno/Exception.hpp> -#include <com/sun/star/xml/dom/XNode.hpp> #include <com/sun/star/xml/dom/XNodeList.hpp> #include <com/sun/star/xml/xpath/XXPathObject.hpp> -#include <libxml/tree.h> -#include <libxml/xpath.h> -#include <boost/shared_ptr.hpp> + using ::rtl::OUString; using namespace com::sun::star::uno; -using namespace com::sun::star::lang; using namespace com::sun::star::xml::dom; using namespace com::sun::star::xml::xpath; + +namespace DOM { + class CDocument; +} + namespace XPath { class CXPathObject : public cppu::WeakImplHelper1< XXPathObject > { private: - boost::shared_ptr<xmlXPathObject> m_pXPathObj; - const Reference< XNode > m_xContextNode; - XPathObjectType m_xPathObjectType; + ::rtl::Reference< DOM::CDocument > const m_pDocument; + ::osl::Mutex & m_rMutex; + boost::shared_ptr<xmlXPathObject> const m_pXPathObj; + XPathObjectType const m_XPathObjectType; public: - CXPathObject(xmlXPathObjectPtr xpathObj, const Reference< XNode >& contextNode); + CXPathObject( ::rtl::Reference<DOM::CDocument> const& pDocument, + ::osl::Mutex & rMutex, + ::boost::shared_ptr<xmlXPathObject> const& pXPathObj); /** get object type @@ -66,7 +76,8 @@ namespace XPath /** get the nodes from a nodelist type object */ - virtual Reference< XNodeList > SAL_CALL getNodeList() throw (RuntimeException); + virtual Reference< XNodeList > SAL_CALL getNodeList() + throw (RuntimeException); /** get value of a boolean object |