diff options
Diffstat (limited to 'ucb')
348 files changed, 103626 insertions, 0 deletions
diff --git a/ucb/inc/makefile.mk b/ucb/inc/makefile.mk new file mode 100644 index 000000000000..1ed22bada671 --- /dev/null +++ b/ucb/inc/makefile.mk @@ -0,0 +1,48 @@ +#************************************************************************* +# +# 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=ucb +TARGET=inc + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- +# --- Targets ------------------------------------------------------- + +.INCLUDE : target.mk +.IF "$(L10N_framework)"=="" + +.IF "$(ENABLE_PCH)"!="" +ALLTAR : \ + $(SLO)$/precompiled.pch \ + $(SLO)$/precompiled_ex.pch + +.ENDIF # "$(ENABLE_PCH)"!="" +.ENDIF # L10N_framework diff --git a/ucb/inc/pch/precompiled_ucb.cxx b/ucb/inc/pch/precompiled_ucb.cxx new file mode 100644 index 000000000000..31acd44cd3f8 --- /dev/null +++ b/ucb/inc/pch/precompiled_ucb.cxx @@ -0,0 +1,29 @@ +/************************************************************************* + * + * 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 "precompiled_ucb.hxx" + diff --git a/ucb/inc/pch/precompiled_ucb.hxx b/ucb/inc/pch/precompiled_ucb.hxx new file mode 100644 index 000000000000..e272c541e4c0 --- /dev/null +++ b/ucb/inc/pch/precompiled_ucb.hxx @@ -0,0 +1,184 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): Generated on 2006-09-01 17:50:16.045215 + +#ifdef PRECOMPILED_HEADERS +//---MARKER--- +#include "sal/types.h" + +#include "com/sun/star/beans/IllegalTypeException.hpp" +#include "com/sun/star/beans/Property.hpp" +#include "com/sun/star/beans/PropertyAttribute.hpp" +#include "com/sun/star/beans/PropertyChangeEvent.hpp" +#include "com/sun/star/beans/PropertySetInfoChange.hpp" +#include "com/sun/star/beans/PropertySetInfoChangeEvent.hpp" +#include "com/sun/star/beans/PropertyState.hpp" +#include "com/sun/star/beans/PropertyValue.hpp" +#include "com/sun/star/beans/UnknownPropertyException.hpp" +#include "com/sun/star/beans/XPropertiesChangeListener.hpp" +#include "com/sun/star/beans/XPropertiesChangeNotifier.hpp" +#include "com/sun/star/beans/XPropertyAccess.hpp" +#include "com/sun/star/beans/XPropertyChangeListener.hpp" +#include "com/sun/star/beans/XPropertyContainer.hpp" +#include "com/sun/star/beans/XPropertySet.hpp" +#include "com/sun/star/beans/XPropertySetInfo.hpp" +#include "com/sun/star/beans/XPropertySetInfoChangeListener.hpp" +#include "com/sun/star/beans/XPropertySetInfoChangeNotifier.hpp" +#include "com/sun/star/bridge/XUnoUrlResolver.hpp" +#include "com/sun/star/container/XChild.hpp" +#include "com/sun/star/container/XEnumeration.hpp" +#include "com/sun/star/container/XEnumerationAccess.hpp" +#include "com/sun/star/container/XHierarchicalNameAccess.hpp" +#include "com/sun/star/container/XNameAccess.hpp" +#include "com/sun/star/container/XNameContainer.hpp" +#include "com/sun/star/container/XNameReplace.hpp" +#include "com/sun/star/container/XNamed.hpp" +#include "com/sun/star/document/XEventBroadcaster.hpp" +#include "com/sun/star/document/XEventListener.hpp" +#include "com/sun/star/document/XStorageBasedDocument.hpp" +#include "com/sun/star/embed/ElementModes.hpp" +#include "com/sun/star/embed/XStorage.hpp" +#include "com/sun/star/embed/XTransactedObject.hpp" +#include "com/sun/star/frame/XModel.hpp" +#include "com/sun/star/frame/XModuleManager.hpp" +#include "com/sun/star/frame/XStorable.hpp" +#include "com/sun/star/io/IOException.hpp" +#include "com/sun/star/io/XActiveDataSink.hpp" +#include "com/sun/star/io/XActiveDataStreamer.hpp" +#include "com/sun/star/io/XAsyncOutputMonitor.hpp" +#include "com/sun/star/io/XInputStream.hpp" +#include "com/sun/star/io/XOutputStream.hpp" +#include "com/sun/star/io/XSeekable.hpp" +#include "com/sun/star/io/XStream.hpp" +#include "com/sun/star/io/XTruncate.hpp" +#include "com/sun/star/lang/DisposedException.hpp" +#include "com/sun/star/lang/IllegalAccessException.hpp" +#include "com/sun/star/lang/IllegalArgumentException.hpp" +#include "com/sun/star/lang/XComponent.hpp" +#include "com/sun/star/lang/XInitialization.hpp" +#include "com/sun/star/lang/XMultiServiceFactory.hpp" +#include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/lang/XSingleServiceFactory.hpp" +#include "com/sun/star/lang/XTypeProvider.hpp" +#include "com/sun/star/packages/WrongPasswordException.hpp" +#include "com/sun/star/reflection/XProxyFactory.hpp" +#include "com/sun/star/registry/XRegistryKey.hpp" +#include "com/sun/star/script/XTypeConverter.hpp" +#include "com/sun/star/sdbc/DataType.hpp" +#include "com/sun/star/sdbc/FetchDirection.hpp" +#include "com/sun/star/sdbc/ResultSetType.hpp" +#include "com/sun/star/sdbc/XCloseable.hpp" +#include "com/sun/star/sdbc/XResultSet.hpp" +#include "com/sun/star/sdbc/XResultSetMetaData.hpp" +#include "com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp" +#include "com/sun/star/sdbc/XRow.hpp" +#include "com/sun/star/task/DocumentPasswordRequest.hpp" +#include "com/sun/star/task/NoMasterException.hpp" +#include "com/sun/star/task/PasswordRequestMode.hpp" +#include "com/sun/star/task/XInteractionAbort.hpp" +#include "com/sun/star/task/XInteractionApprove.hpp" +#include "com/sun/star/task/XInteractionDisapprove.hpp" +#include "com/sun/star/task/XInteractionHandler.hpp" +#include "com/sun/star/task/XInteractionPassword.hpp" +#include "com/sun/star/task/XInteractionRequest.hpp" +#include "com/sun/star/task/XPasswordContainer.hpp" +#include "com/sun/star/uno/Any.hxx" +#include "com/sun/star/uno/Exception.hpp" +#include "com/sun/star/uno/Reference.h" +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/RuntimeException.hpp" +#include "com/sun/star/uno/Sequence.hxx" +#include "com/sun/star/uno/Type.hxx" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/uno/XInterface.hpp" +#include "com/sun/star/uno/XReference.hpp" +#include "com/sun/star/uno/XWeak.hpp" +#include "com/sun/star/util/Date.hpp" +#include "com/sun/star/util/DateTime.hpp" +#include "com/sun/star/util/Time.hpp" +#include "com/sun/star/util/XChangesBatch.hpp" +#include "com/sun/star/util/XChangesNotifier.hpp" +#include "com/sun/star/util/XMacroExpander.hpp" +#include "com/sun/star/util/XOfficeInstallationDirectories.hpp" + +#include "comphelper/processfactory.hxx" + +#include "cppuhelper/bootstrap.hxx" +#include "cppuhelper/compbase2.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "cppuhelper/factory.hxx" +#include "cppuhelper/implbase1.hxx" +#include "cppuhelper/implbase2.hxx" +#include "cppuhelper/implbase5.hxx" +#include "cppuhelper/implementationentry.hxx" +#include "cppuhelper/interfacecontainer.h" +#include "cppuhelper/interfacecontainer.hxx" +#include "cppuhelper/queryinterface.hxx" +#include "cppuhelper/typeprovider.hxx" +#include "cppuhelper/weak.hxx" +#include "cppuhelper/weakref.hxx" + +#include "libxml/parser.h" + +#include "osl/conditn.hxx" +#include "osl/diagnose.h" +#include "osl/doublecheckedlocking.h" +#include "osl/file.hxx" +#include "osl/interlck.h" +#include "osl/module.h" +#include "osl/mutex.hxx" +#include "osl/process.h" +#include "osl/security.hxx" +#include "osl/socket.h" +#include "osl/socket.hxx" +#include "osl/thread.h" +#include "osl/time.h" + +#include "rtl/alloc.h" +#include "rtl/memory.h" +#include "rtl/string.hxx" +#include "rtl/ustrbuf.hxx" +#include "rtl/ustring.h" +#include "rtl/ustring.hxx" + +#include "salhelper/simplereferenceobject.hxx" + +#include "sys/types.h" + +#include "ucbhelper/configurationkeys.hxx" +#include "ucbhelper/macros.hxx" +#include "ucbhelper/proxydecider.hxx" + +#include "vos/diagnose.hxx" +#include "vos/mutex.hxx" +#include "vos/process.hxx" +#include "vos/ref.hxx" +#include "vos/refernce.hxx" +//---MARKER--- + +#endif diff --git a/ucb/prj/build.lst b/ucb/prj/build.lst new file mode 100644 index 000000000000..dad79213047e --- /dev/null +++ b/ucb/prj/build.lst @@ -0,0 +1,18 @@ +uc ucb : cppuhelper CURL:curl OPENSSL:openssl NEON:neon LIBXML2:libxml2 offapi sal salhelper ucbhelper udkapi comphelper tools NULL +uc ucb usr1 - all uc_mkout NULL +uc ucb\inc nmake - all uc_inc NULL +uc ucb\source\regexp nmake - all uc_regexp uc_inc NULL +uc ucb\source\core nmake - all uc_core uc_regexp uc_inc NULL +uc ucb\source\cacher nmake - all uc_cacher uc_inc NULL +uc ucb\source\sorter nmake - all uc_sorter uc_inc NULL +uc ucb\source\ucp\ftp nmake - all uc_ftp uc_inc NULL +uc ucb\source\ucp\file nmake - all uc_file uc_inc NULL +uc ucb\source\ucp\gvfs nmake - u uc_gvfs uc_inc NULL +uc ucb\source\ucp\gio nmake - u uc_gio uc_inc NULL +uc ucb\source\ucp\hierarchy nmake - all uc_hierarchy uc_inc NULL +uc ucb\source\ucp\webdav nmake - all uc_webdav uc_inc NULL +uc ucb\source\ucp\package nmake - all uc_package uc_inc NULL +uc ucb\source\ucp\tdoc nmake - all uc_tdoc uc_inc NULL +uc ucb\source\ucp\expand nmake - all uc_expand uc_inc NULL +uc ucb\source\ucp\ext nmake - all uc_ext uc_inc NULL +uc ucb\qa\unoapi nmake - all uc_qa_unoapi NULL diff --git a/ucb/prj/d.lst b/ucb/prj/d.lst new file mode 100644 index 000000000000..65a32e21fba3 --- /dev/null +++ b/ucb/prj/d.lst @@ -0,0 +1,46 @@ +..\%__SRC%\bin\cached*.dll %_DEST%\bin%_EXT%\cached*.dll +..\%__SRC%\lib\libcached*.* %_DEST%\lib%_EXT%\libcached*.* +..\%__SRC%\bin\cached*.map %_DEST%\bin%_EXT%\cached*.map +..\%__SRC%\bin\cached*.sym %_DEST%\bin%_EXT%\cached*.sym +..\source\cacher\cached.xml %_DEST%\xml%_EXT%\cached.xml + +..\%__SRC%\bin\srtrs*.dll %_DEST%\bin%_EXT%\srtrs*.dll +..\%__SRC%\lib\libsrtrs*.* %_DEST%\lib%_EXT%\libsrtrs*.* +..\%__SRC%\bin\srtrs*.map %_DEST%\bin%_EXT%\srtrs*.map +..\%__SRC%\bin\srtrs*.sym %_DEST%\bin%_EXT%\srtrs*.sym +..\source\sorter\srtrs.xml %_DEST%\xml%_EXT%\srtrs.xml + +..\%__SRC%\bin\ucb*.dll %_DEST%\bin%_EXT%\ucb*.dll +..\%__SRC%\lib\libucb*.* %_DEST%\lib%_EXT%\libucb*.* +..\%__SRC%\misc\ucb*.map %_DEST%\bin%_EXT%\ucb*.map +..\%__SRC%\misc\ucb*.sym %_DEST%\bin%_EXT%\ucb*.sym +..\source\core\ucb.xml %_DEST%\xml%_EXT%\ucb.xml + +..\%__SRC%\bin\ucp*.dll %_DEST%\bin%_EXT%\ucp*.dll +..\%__SRC%\lib\libucp*.so %_DEST%\lib%_EXT%\libucp*.so +..\%__SRC%\lib\libucp*.dylib %_DEST%\lib%_EXT%\libucp*.dylib +..\%__SRC%\lib\ucp*.uno.so %_DEST%\lib%_EXT%\ucp*.uno.so +..\%__SRC%\lib\ucp*.uno.dylib %_DEST%\lib%_EXT%\ucp*.uno.dylib +..\%__SRC%\misc\ucp*.map %_DEST%\bin%_EXT%\ucp*.map +..\%__SRC%\misc\ucp*.sym %_DEST%\bin%_EXT%\ucp*.sym +..\source\ucp\file\ucpfile.xml %_DEST%\xml%_EXT%\ucpfile.xml +..\source\ucp\ftp\ucpftp.xml %_DEST%\xml%_EXT%\ucpftp.xml +..\source\ucp\hierarchy\ucphier.xml %_DEST%\xml%_EXT%\ucphier.xml +..\source\ucp\package\ucppkg.xml %_DEST%\xml%_EXT%\ucppkg.xml +..\source\ucp\webdav\ucpdav.xml %_DEST%\xml%_EXT%\ucpdav.xml +..\source\ucp\gvfs\ucpgvfs.xml %_DEST%\xml%_EXT%\ucpgvfs.xml +..\source\ucp\tdoc\ucptdoc.xml %_DEST%\xml%_EXT%\ucptdoc.xml + +..\%__SRC%\misc\ucpgvfs.component %_DEST%\xml%_EXT%\ucpgvfs.component +..\%__SRC%\misc\ucpgio.component %_DEST%\xml%_EXT%\ucpgio.component +..\%__SRC%\misc\cached1.component %_DEST%\xml%_EXT%\cached1.component +..\%__SRC%\misc\srtrs1.component %_DEST%\xml%_EXT%\srtrs1.component +..\%__SRC%\misc\ucb1.component %_DEST%\xml%_EXT%\ucb1.component +..\%__SRC%\misc\ucpdav1.component %_DEST%\xml%_EXT%\ucpdav1.component +..\%__SRC%\misc\ucpexpand1.component %_DEST%\xml%_EXT%\ucpexpand1.component +..\%__SRC%\misc\ucpext.component %_DEST%\xml%_EXT%\ucpext.component +..\%__SRC%\misc\ucpfile1.component %_DEST%\xml%_EXT%\ucpfile1.component +..\%__SRC%\misc\ucpftp1.component %_DEST%\xml%_EXT%\ucpftp1.component +..\%__SRC%\misc\ucphier1.component %_DEST%\xml%_EXT%\ucphier1.component +..\%__SRC%\misc\ucppkg1.component %_DEST%\xml%_EXT%\ucppkg1.component +..\%__SRC%\misc\ucptdoc1.component %_DEST%\xml%_EXT%\ucptdoc1.component diff --git a/ucb/qa/complex/tdoc/CheckContentProvider.java b/ucb/qa/complex/tdoc/CheckContentProvider.java new file mode 100755 index 000000000000..a20a96829e0b --- /dev/null +++ b/ucb/qa/complex/tdoc/CheckContentProvider.java @@ -0,0 +1,398 @@ +/************************************************************************* + * + * 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.tdoc; + +import com.sun.star.beans.XPropertiesChangeNotifier; +import com.sun.star.beans.XPropertyContainer; +import com.sun.star.beans.XPropertySetInfoChangeNotifier; +import com.sun.star.container.XChild; +import com.sun.star.lang.XComponent; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.lang.XServiceInfo; +import com.sun.star.lang.XTypeProvider; +import com.sun.star.text.XTextDocument; +import com.sun.star.ucb.XCommandInfoChangeNotifier; +import com.sun.star.ucb.XCommandProcessor; +import com.sun.star.ucb.XContent; +import com.sun.star.ucb.XContentIdentifier; +import com.sun.star.ucb.XContentIdentifierFactory; +import com.sun.star.ucb.XContentProvider; +import com.sun.star.uno.UnoRuntime; +import complexlib.ComplexTestCase; +import complex.tdoc.interfaces._XChild; +import complex.tdoc.interfaces._XCommandInfoChangeNotifier; +import complex.tdoc.interfaces._XComponent; +import complex.tdoc.interfaces._XServiceInfo; +import complex.tdoc.interfaces._XTypeProvider; +import complex.tdoc.interfaces._XCommandProcessor; +import complex.tdoc.interfaces._XContent; +import complex.tdoc.interfaces._XPropertiesChangeNotifier; +import complex.tdoc.interfaces._XPropertyContainer; +import complex.tdoc.interfaces._XPropertySetInfoChangeNotifier; +import lib.TestEnvironment; +import util.WriterTools; +import util.utils; + +/** + * Check the TransientDocumentsContentProvider (TDOC). Three documents are + * loaded. Then every possible TDCP content type is instantiated and its + * interfaces are tested.<br> + * Important: opened documents are numbered in the order they are opened and + * numbers are not reused. This test will work only, if you start a new office + * with an accept parameter (writer is initially opened). Otherwise loaded + * documents are not found. + */ +public class CheckContentProvider extends ComplexTestCase { + private final String testDocuments[] = new String[]{"filter.sxw", "chinese.sxw", "Iterator.sxw"}; + private final int countDocs = testDocuments.length; + private XMultiServiceFactory xMSF = null; + private XTextDocument[] xTextDoc = null; + private XContent xContent = null; + + /** + * The test methods: the test methods have to be executed in a specified + * order. This order is: + * <ol> + * <li>"checkTDOCRoot"</li> + * <li>"checkTDOCRootInterfaces"</li> + * <li>"checkTDOCDocument"</li> + * <li>"checkTDOCDocumentInterfaces"</li> + * <li>"checkTDOCFolder"</li> + * <li>"checkTDOCFolderInterfaces"</li> + * <li>"checkTDOCStream"</li> + * <li>"checkTDOCStreamInterfaces"</li> + * </ol> + * Important is, that the test of the element comes first, then the test of + * its interfaces. + **/ + public String[] getTestMethodNames() { + return new String[]{"checkTDOCRoot", + "checkTDOCRootInterfaces", + "checkTDOCDocument", + "checkTDOCDocumentInterfaces", + "checkTDOCFolder", + "checkTDOCFolderInterfaces", + "checkTDOCStream", + "checkTDOCStreamInterfaces", + }; + } + + /** + * Open some documents before the test + */ + public void before() { + xMSF = (XMultiServiceFactory)param.getMSF(); + xTextDoc = new XTextDocument[countDocs]; + log.println("Open some new documents."); + for (int i=0; i<countDocs; i++) { + String fileName = utils.getFullTestURL(testDocuments[i]); + System.out.println("Doc " + i + ": " + fileName); + xTextDoc[i] = WriterTools.loadTextDoc(xMSF, fileName); + } + } + + /** + * Close the documents + */ + public void after() { + log.println("Close all documents."); + for (int i=0; i<countDocs; i++) { + xTextDoc[i].dispose(); + } + } + + /** + * Check the tdcp root. + */ + public void checkTDOCRoot() { + try { + // create a content provider + Object o = xMSF.createInstance("com.sun.star.comp.ucb.TransientDocumentsContentProvider"); + XContentProvider xContentProvider = + (XContentProvider)UnoRuntime.queryInterface(XContentProvider.class, o); + + // create the ucb + XContentIdentifierFactory xContentIdentifierFactory = + (XContentIdentifierFactory)UnoRuntime.queryInterface( + XContentIdentifierFactory.class, xMSF.createInstance( + "com.sun.star.ucb.UniversalContentBroker")); + // create a content identifier from the ucb for tdoc + XContentIdentifier xContentIdentifier = + xContentIdentifierFactory.createContentIdentifier("vnd.sun.star.tdoc:/"); + // get content + xContent = xContentProvider.queryContent(xContentIdentifier); + + String content = xContent.getContentType(); + log.println("#### Content root: " + content); + + // try to get some documents: should be "countDocs" at least. + XContentIdentifier[] xContentId = new XContentIdentifier[countDocs+5]; + XContent[] xCont = new XContent[countDocs+5]; + + for (int i=0; i<countDocs+5; i++) { + xContentId[i] = xContentIdentifierFactory.createContentIdentifier("vnd.sun.star.tdoc:/" + i); + // get content + xCont[i] = xContentProvider.queryContent(xContentId[i]); + int returnVal = xContentProvider.compareContentIds(xContentId[i], xContentIdentifier); + String cont = null; + if (xCont[i] != null) + cont = xCont[i].getContentType(); + log.println("Document Content " + i + ": " + cont + " compare with root: " + returnVal); + + xContentId[i] = xContentIdentifierFactory.createContentIdentifier("vnd.sun.star.tdoc:/" + i + "/content.xml"); + // get content + xCont[i] = xContentProvider.queryContent(xContentId[i]); + cont = null; + if (xCont[i] != null) + cont = xCont[i].getContentType(); + log.println("\tContent.xml Content " + i + ": " + cont); + } + + util.dbg.printInterfaces(xContent); + } + catch(Exception e) { + e.printStackTrace((java.io.PrintWriter)log); + failed("Unexpected Exception: " + e.getMessage()); + } + } + + /** + * Check the interfaces of the root. + */ + public void checkTDOCRootInterfaces() { + checkInterfaces(false); + } + + /** + * Check the tdcp document: document 3 is used. + */ + public void checkTDOCDocument() { + try { + xContent = null; + Object o = xMSF.createInstance("com.sun.star.comp.ucb.TransientDocumentsContentProvider"); + XContentProvider xContentProvider = + (XContentProvider)UnoRuntime.queryInterface(XContentProvider.class, o); + // create the ucb + XContentIdentifierFactory xContentIdentifierFactory = + (XContentIdentifierFactory)UnoRuntime.queryInterface( + XContentIdentifierFactory.class, xMSF.createInstance( + "com.sun.star.ucb.UniversalContentBroker")); + // create a content identifier from the ucb for tdoc + XContentIdentifier xContentIdentifier = + xContentIdentifierFactory.createContentIdentifier("vnd.sun.star.tdoc:/3"); + // get content + xContent = xContentProvider.queryContent(xContentIdentifier); + + String content = xContent.getContentType(); + log.println("#### Document root: " + content); + } + catch(Exception e) { + e.printStackTrace((java.io.PrintWriter)log); + failed("Unexpected Exception: " + e.getMessage()); + } + } + + /** + * Check the interfaces on the document. + */ + public void checkTDOCDocumentInterfaces() { + checkInterfaces(true); + } + + /** + * Check a folder on document 2 (document 2 contains an embedded picture and + * therefore contans a subfolder "Pictures" + */ + public void checkTDOCFolder() { + try { + xContent = null; + Object o = xMSF.createInstance("com.sun.star.comp.ucb.TransientDocumentsContentProvider"); + XContentProvider xContentProvider = + (XContentProvider)UnoRuntime.queryInterface(XContentProvider.class, o); + // create the ucb + XContentIdentifierFactory xContentIdentifierFactory = + (XContentIdentifierFactory)UnoRuntime.queryInterface( + XContentIdentifierFactory.class, xMSF.createInstance( + "com.sun.star.ucb.UniversalContentBroker")); + // create a content identifier from the ucb for tdoc + XContentIdentifier xContentIdentifier = + xContentIdentifierFactory.createContentIdentifier("vnd.sun.star.tdoc:/2/Pictures"); + // get content + xContent = xContentProvider.queryContent(xContentIdentifier); + + String content = xContent.getContentType(); + log.println("#### Folder type: " + content); + } + catch(Exception e) { + e.printStackTrace((java.io.PrintWriter)log); + failed("Unexpected Exception: " + e.getMessage()); + } + } + + /** + * Check the interfaces on the folder. + */ + public void checkTDOCFolderInterfaces() { + checkInterfaces(true); + } + + /** + * Open a stream to the embedded picture of document 1. + */ + public void checkTDOCStream() { + try { + xContent = null; + Object o = xMSF.createInstance("com.sun.star.comp.ucb.TransientDocumentsContentProvider"); + XContentProvider xContentProvider = + (XContentProvider)UnoRuntime.queryInterface(XContentProvider.class, o); + + // create the ucb + XContentIdentifierFactory xContentIdentifierFactory = + (XContentIdentifierFactory)UnoRuntime.queryInterface( + XContentIdentifierFactory.class, xMSF.createInstance( + "com.sun.star.ucb.UniversalContentBroker")); + // create a content identifier from the ucb for tdoc + XContentIdentifier xContentIdentifier = + xContentIdentifierFactory.createContentIdentifier("vnd.sun.star.tdoc:/1/Pictures/10000000000000640000004B9C743800.gif"); + // get content + xContent = xContentProvider.queryContent(xContentIdentifier); + + String content = xContent.getContentType(); + log.println("#### Folder type: " + content); + } + catch(Exception e) { + e.printStackTrace((java.io.PrintWriter)log); + failed("Unexpected Exception: " + e.getMessage()); + } + } + + /** + * Check the interfaces on the stream. + */ + public void checkTDOCStreamInterfaces() { + checkInterfaces(true); + } + + /** + * Since all tdcp content types implement (nearly) the same interfaces, they + * are called here. + * Executed interface tests are (in this order): + * <ol> + * <li>XTypeProvider</li> + * <li>XServiceInfo</li> + * <li>XCommandProcessor</li> + * <li>XChild</li> + * <li>XPropertiesChangeNotifier</li> + * <li>XPropertySetInfoChangeNotifier</li> + * <li>XCommandInfoChangeNotifier</li> + * <li>XContent</li> + * <li>XPropertyContainer</li> + * <li>XComponent</li> + * </ol> + * @param hasParent True, if the tested content type does have a parent: + * only the root has not. Used in the XChild interface test. + */ + private void checkInterfaces(boolean hasParent) { + // check the XTypeProvider interface + _XTypeProvider xTypeProvider = new _XTypeProvider(); + xTypeProvider.oObj = (XTypeProvider)UnoRuntime.queryInterface(XTypeProvider.class, xContent); + xTypeProvider.log = log; + assure("getImplementationId()", xTypeProvider._getImplementationId()); + assure("getTypes()", xTypeProvider._getTypes()); + + // check the XSewrviceInfo interface + _XServiceInfo xServiceInfo = new _XServiceInfo(); + xServiceInfo.oObj = (XServiceInfo)UnoRuntime.queryInterface(XServiceInfo.class, xContent); + xServiceInfo.log = log; + assure("getImplementationName()", xServiceInfo._getImplementationName()); + assure("getSupportedServiceNames()", xServiceInfo._getSupportedServiceNames()); + assure("supportsService()", xServiceInfo._supportsService()); + + // check the XCommandProcessor interface + _XCommandProcessor xCommandProcessor = new _XCommandProcessor(); + xCommandProcessor.oObj = (XCommandProcessor)UnoRuntime.queryInterface(XCommandProcessor.class, xContent); + xCommandProcessor.log = log; + xCommandProcessor.before((XMultiServiceFactory)param.getMSF()); + assure("createCommandIdentifier()", xCommandProcessor._createCommandIdentifier()); + assure("execute()", xCommandProcessor._execute()); + assure("abort()", xCommandProcessor._abort()); + + // check the XChild interface + _XChild xChild = new _XChild(); + xChild.oObj = (XChild)UnoRuntime.queryInterface(XChild.class, xContent); + xChild.log = log; + // hasParent dermines, if this content has a parent + assure("getParent()", xChild._getParent(hasParent)); + // parameter does dermine, if this funczion is supported: generally not supported with tdcp content + assure("setParent()", xChild._setParent(false)); + + // check the XPropertyChangeNotifier interface + _XPropertiesChangeNotifier xPropChange = new _XPropertiesChangeNotifier(); + xPropChange.oObj = (XPropertiesChangeNotifier)UnoRuntime.queryInterface(XPropertiesChangeNotifier.class, xContent); + xPropChange.log = log; + assure("addPropertiesChangeListener()", xPropChange._addPropertiesChangeListener()); + assure("removePropertiesChangeListener()", xPropChange._removePropertiesChangeListener()); + + // check the XPropertySetInfoChangeNotifier interface + _XPropertySetInfoChangeNotifier xPropSetInfo = new _XPropertySetInfoChangeNotifier(); + xPropSetInfo.oObj = (XPropertySetInfoChangeNotifier)UnoRuntime.queryInterface(XPropertySetInfoChangeNotifier.class, xContent); + xPropSetInfo.log = log; + assure("addPropertiesChangeListener()", xPropSetInfo._addPropertiesChangeListener()); + assure("removePropertiesChangeListener()", xPropSetInfo._removePropertiesChangeListener()); + + // check the XCommandInfoChangeNotifier interface + _XCommandInfoChangeNotifier xCommandChange = new _XCommandInfoChangeNotifier(); + xCommandChange.oObj = (XCommandInfoChangeNotifier)UnoRuntime.queryInterface(XCommandInfoChangeNotifier.class, xContent); + xCommandChange.log = log; + assure("addCommandInfoChangeListener()", xCommandChange._addCommandInfoChangeListener()); + assure("removeCommandInfoChangeListener()", xCommandChange._removeCommandInfoChangeListener()); + + // check the XContent interface + _XContent xCont = new _XContent(); + xCont.oObj = (XContent)UnoRuntime.queryInterface(XContent.class, xContent); + xCont.log = log; + assure("addContentEventListener()", xCont._addContentEventListener()); + assure("getContentType()", xCont._getContentType()); + assure("getIdentifier()", xCont._getIdentifier()); + assure("removeContentEventListener()", xCont._removeContentEventListener()); + + // check the XPropertyContainer interface + _XPropertyContainer xPropCont = new _XPropertyContainer(); + xPropCont.oObj = (XPropertyContainer)UnoRuntime.queryInterface(XPropertyContainer.class, xContent); + xPropCont.log = log; + assure("addProperty()", xPropCont._addProperty()); + assure("removeProperty()", xPropCont._removeProperty()); + + // check the XComponent interface + _XComponent xComponent = new _XComponent(); + xComponent.oObj = (XComponent)UnoRuntime.queryInterface(XComponent.class, xContent); + xComponent.log = log; + assure("addEventListener()", xComponent._addEventListener()); + assure("removeEventListener()", xComponent._removeEventListener()); +// assure("dispose()", xComponent._dispose()); + } +} diff --git a/ucb/qa/complex/tdoc/CheckTransientDocumentsContent.java b/ucb/qa/complex/tdoc/CheckTransientDocumentsContent.java new file mode 100755 index 000000000000..b492fd219119 --- /dev/null +++ b/ucb/qa/complex/tdoc/CheckTransientDocumentsContent.java @@ -0,0 +1,145 @@ +/************************************************************************* + * + * 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.tdoc; + +import com.sun.star.beans.Property; +import com.sun.star.beans.XPropertySetInfo; +import com.sun.star.frame.XModel; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.lang.XServiceInfo; +import com.sun.star.sdbc.XResultSet; +import com.sun.star.text.XTextDocument; +import com.sun.star.ucb.Command; +import com.sun.star.ucb.OpenCommandArgument2; +import com.sun.star.ucb.OpenMode; +import com.sun.star.ucb.XCommandProcessor; +import com.sun.star.ucb.XContent; +import com.sun.star.ucb.XContentAccess; +import com.sun.star.ucb.XContentIdentifier; +import com.sun.star.ucb.XContentIdentifierFactory; +import com.sun.star.ucb.XContentProvider; +import com.sun.star.ucb.XDynamicResultSet; +import com.sun.star.uno.UnoRuntime; +import complexlib.ComplexTestCase; +import util.WriterTools; +import util.utils; + +/** + * + */ +public class CheckTransientDocumentsContent extends ComplexTestCase{ + private final String testDocuments[] = new String[]{"sForm.sxw"};//, "chinese.sxw", "Iterator.sxw"}; + private final int countDocs = testDocuments.length; + private XMultiServiceFactory xMSF = null; + private XTextDocument[] xTextDoc = null; + + public String[] getTestMethodNames() { + return new String[] {"checkTransientDocumentsContent"}; + } + + public void before() { + xMSF = (XMultiServiceFactory)param.getMSF(); + xTextDoc = new XTextDocument[countDocs]; + log.println("Open some documents."); + for (int i=0; i<countDocs; i++) { + String fileName = utils.getFullTestURL(testDocuments[i]); + xTextDoc[i] = WriterTools.loadTextDoc(xMSF, fileName); + } + } + public void after() { + log.println("Close all documents."); + for (int i=0; i<countDocs; i++) { + xTextDoc[i].dispose(); + } + } + + /** + * Check the content of one document + */ + public void checkTransientDocumentsContent() { + try { + // create the ucb + XContentIdentifierFactory xContentIdentifierFactory = + (XContentIdentifierFactory)UnoRuntime.queryInterface( + XContentIdentifierFactory.class, xMSF.createInstance( + "com.sun.star.ucb.UniversalContentBroker")); + XContentProvider xContentProvider = + (XContentProvider)UnoRuntime.queryInterface(XContentProvider.class, xContentIdentifierFactory); + // create a content identifier from the ucb for tdoc + XContentIdentifier xContentIdentifier = + xContentIdentifierFactory.createContentIdentifier("vnd.sun.star.tdoc:/1"); + // get content + XContent xContent = xContentProvider.queryContent(xContentIdentifier); + + // actual test: commands to get some properties + XCommandProcessor xCommandProcessor = (XCommandProcessor)UnoRuntime.queryInterface(XCommandProcessor.class, xContent); + // build up the command + Command command = new Command(); + command.Name = "getPropertySetInfo"; + command.Handle = -1; + + // execute the command + Object result = xCommandProcessor.execute(command, 0, null); + + // check the result + log.println("Result: "+ result.getClass().toString()); + XPropertySetInfo xPropertySetInfo = (XPropertySetInfo)UnoRuntime.queryInterface(XPropertySetInfo.class, result); + Property[] props = xPropertySetInfo.getProperties(); + boolean res = false; + for(int i=0; i<props.length; i++) { + String propName = props[i].Name; + res |= propName.equals("DocumentModel"); + log.println("Found property: " + propName + " type: " + props[i].Type.getTypeName()); + } + assure("Did not find property 'DocumentModel' in the Property array.", res); + + // get on property + command.Name = "getPropertyValues"; + command.Handle = -1; + Property[] prop = new Property[1]; + prop[0] = new Property(); + prop[0].Name = "DocumentModel"; + prop[0].Handle = -1; + command.Argument = prop; + + // execute the command + result = xCommandProcessor.execute(command, 0, null); + + // check the result + log.println("Result: "+ result.getClass().toString()); + + XModel xModel = (XModel)UnoRuntime.queryInterface(XModel.class, result); + assure("Did not get property 'DocumentModel'.", xModel == null); + } + catch (com.sun.star.uno.Exception e) { + e.printStackTrace((java.io.PrintWriter)log); + failed("Could not create test objects."); + } + + } + +} diff --git a/ucb/qa/complex/tdoc/CheckTransientDocumentsContentProvider.java b/ucb/qa/complex/tdoc/CheckTransientDocumentsContentProvider.java new file mode 100755 index 000000000000..ddac0cbb2d47 --- /dev/null +++ b/ucb/qa/complex/tdoc/CheckTransientDocumentsContentProvider.java @@ -0,0 +1,143 @@ +/************************************************************************* + * + * 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.tdoc; + +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.lang.XServiceInfo; +import com.sun.star.sdbc.XResultSet; +import com.sun.star.text.XTextDocument; +import com.sun.star.ucb.Command; +import com.sun.star.ucb.OpenCommandArgument2; +import com.sun.star.ucb.OpenMode; +import com.sun.star.ucb.XCommandProcessor; +import com.sun.star.ucb.XContent; +import com.sun.star.ucb.XContentAccess; +import com.sun.star.ucb.XContentIdentifier; +import com.sun.star.ucb.XContentIdentifierFactory; +import com.sun.star.ucb.XContentProvider; +import com.sun.star.ucb.XDynamicResultSet; +import com.sun.star.uno.UnoRuntime; +import complexlib.ComplexTestCase; +import util.WriterTools; +import util.utils; + +/** + * + */ +public class CheckTransientDocumentsContentProvider extends ComplexTestCase { + private final String testDocuments[] = new String[]{"sForm.sxw", "chinese.sxw", "Iterator.sxw"}; + private final int countDocs = testDocuments.length; + private XMultiServiceFactory xMSF = null; + private XTextDocument[] xTextDoc = null; + + public String[] getTestMethodNames() { + return new String[]{"checkTransientDocumentsContentProvider"}; + } + + public void before() { + xMSF = (XMultiServiceFactory)param.getMSF(); + xTextDoc = new XTextDocument[countDocs]; + log.println("Open some documents."); + for (int i=0; i<countDocs; i++) { + String fileName = utils.getFullTestURL(testDocuments[i]); + xTextDoc[i] = WriterTools.loadTextDoc(xMSF, fileName); + } + } + public void after() { + log.println("Close all documents."); + for (int i=0; i<countDocs; i++) { + xTextDoc[i].dispose(); + } + } + + /** + * Check the provider of document content: open some documents + * and look if they are accessible. + */ + public void checkTransientDocumentsContentProvider() { + try { + // create a content provider + Object o = xMSF.createInstance("com.sun.star.comp.ucb.TransientDocumentsContentProvider"); + XContentProvider xContentProvider = + (XContentProvider)UnoRuntime.queryInterface(XContentProvider.class, o); + + // create the ucb + XContentIdentifierFactory xContentIdentifierFactory = + (XContentIdentifierFactory)UnoRuntime.queryInterface( + XContentIdentifierFactory.class, xMSF.createInstance( + "com.sun.star.ucb.UniversalContentBroker")); + // create a content identifier from the ucb for tdoc + XContentIdentifier xContentIdentifier = + xContentIdentifierFactory.createContentIdentifier("vnd.sun.star.tdoc:/"); + // get content + XContent xContent = xContentProvider.queryContent(xContentIdentifier); + + // actual test: execute an "open" command with the content + XCommandProcessor xCommandProcessor = (XCommandProcessor)UnoRuntime.queryInterface(XCommandProcessor.class, xContent); + // build up the command + Command command = new Command(); + OpenCommandArgument2 commandarg2 = new OpenCommandArgument2(); + commandarg2.Mode = OpenMode.ALL; + command.Name = "open"; + command.Argument = commandarg2; + + // execute the command + Object result = xCommandProcessor.execute(command, 0, null); + + // check the result + log.println("Result: "+ result.getClass().toString()); + XDynamicResultSet xDynamicResultSet = (XDynamicResultSet)UnoRuntime.queryInterface(XDynamicResultSet.class, result); + + // check bug of wrong returned service name. + XServiceInfo xServiceInfo = (XServiceInfo)UnoRuntime.queryInterface(XServiceInfo.class, xDynamicResultSet); + String[] sNames = xServiceInfo.getSupportedServiceNames(); + String serviceName = sNames[0]; + if (sNames.length > 1) + failed("Implementation has been changed. Check this test!"); + assure("The service name '" + serviceName + "' is not valid.", !serviceName.equals("com.sun.star.ucb.DynamicContentResultSet"), true); + + XResultSet xResultSet = xDynamicResultSet.getStaticResultSet(); + XContentAccess xContentAccess = (XContentAccess)UnoRuntime.queryInterface(XContentAccess.class, xResultSet); + // iterate over the result: three docs were opened, we should have at least three content identifier strings + int countContentIdentifiers = 0; + while(xResultSet.next()) { + countContentIdentifiers++; + String identifier = xContentAccess.queryContentIdentifierString(); + log.println("Identifier of row " + xResultSet.getRow() + ": " + identifier); + } + // some feeble test: if the amount >2, we're ok. + // 2do: check better + assure("Did only find " + countContentIdentifiers + " open documents." + + " Should have been at least 3.", countContentIdentifiers>2); + } + catch (com.sun.star.uno.Exception e) { + e.printStackTrace((java.io.PrintWriter)log); + failed("Could not create test objects."); + } + + } +} diff --git a/ucb/qa/complex/tdoc/CheckTransientDocumentsDocumentContent.java b/ucb/qa/complex/tdoc/CheckTransientDocumentsDocumentContent.java new file mode 100755 index 000000000000..229f5d388697 --- /dev/null +++ b/ucb/qa/complex/tdoc/CheckTransientDocumentsDocumentContent.java @@ -0,0 +1,179 @@ +/************************************************************************* + * + * 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.tdoc; + +import com.sun.star.beans.Property; +import com.sun.star.beans.PropertyValue; +import com.sun.star.document.XDocumentSubStorageSupplier; +import com.sun.star.embed.ElementModes; +import com.sun.star.embed.XStorage; +import com.sun.star.frame.XModel; +import com.sun.star.frame.XTransientDocumentsDocumentContentFactory; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.lang.XServiceInfo; +import com.sun.star.sdbc.XResultSet; +import com.sun.star.sdbc.XRow; +import com.sun.star.text.XTextDocument; +import com.sun.star.ucb.Command; +import com.sun.star.ucb.ContentInfo; +import com.sun.star.ucb.InsertCommandArgument; +import com.sun.star.ucb.OpenCommandArgument2; +import com.sun.star.ucb.OpenMode; +import com.sun.star.ucb.XCommandProcessor; +import com.sun.star.ucb.XContent; +import com.sun.star.ucb.XContentAccess; +import com.sun.star.ucb.XContentIdentifier; +import com.sun.star.ucb.XContentIdentifierFactory; +import com.sun.star.ucb.XContentProvider; +import com.sun.star.ucb.XDynamicResultSet; +import com.sun.star.uno.UnoRuntime; +import complexlib.ComplexTestCase; +import util.WriterTools; +import util.utils; + + +/** + * + */ +public class CheckTransientDocumentsDocumentContent extends ComplexTestCase { + private final String testDocuments = "sForm.sxw"; + private final String folderName = "TestFolder"; + private XMultiServiceFactory xMSF = null; + private XTextDocument xTextDoc = null; + + public String[] getTestMethodNames() { + return new String[]{"checkTransientDocumentsDocumentContent"}; + } + + public void before() { + xMSF = (XMultiServiceFactory)param.getMSF(); + log.println("Open a document."); + String fileName = utils.getFullTestURL(testDocuments); + xTextDoc = WriterTools.loadTextDoc(xMSF, fileName); + } + public void after() { + log.println("Close all documents."); + xTextDoc.dispose(); + } + + /** + * Check the provider of document content: open some documents + * and look if they are accessible. + */ + public void checkTransientDocumentsDocumentContent() { + try { + // create a content provider + Object o = xMSF.createInstance("com.sun.star.comp.ucb.TransientDocumentsDocumentContentFactory"); + + XTransientDocumentsDocumentContentFactory xTransientDocumentsDocumentContentFactory = + (XTransientDocumentsDocumentContentFactory)UnoRuntime.queryInterface( + XTransientDocumentsDocumentContentFactory.class, o); + // get the model from the opened document + XModel xModel = xTextDoc.getCurrentController().getModel(); + + // a little additional check for 114733 + XDocumentSubStorageSupplier xDocumentSubStorageSupplier = (XDocumentSubStorageSupplier) + UnoRuntime.queryInterface(XDocumentSubStorageSupplier.class, xModel); + String[]names = xDocumentSubStorageSupplier.getDocumentSubStoragesNames(); + for (int i=0; i<names.length; i++) { + log.println("SubStorage names " + i + ": " +names[i]); + } + XStorage xStorage = xDocumentSubStorageSupplier.getDocumentSubStorage(names[0], ElementModes.READWRITE); + assure("Could not get a storage from the XDocumentStorageSupplier.", xStorage != null); + // get content + XContent xContent = xTransientDocumentsDocumentContentFactory.createDocumentContent(xModel); + // actual test: execute some commands + XCommandProcessor xCommandProcessor = (XCommandProcessor)UnoRuntime.queryInterface(XCommandProcessor.class, xContent); + + // create the command and arguments + Command command = new Command(); + OpenCommandArgument2 cmargs2 = new OpenCommandArgument2(); + Property[]props = new Property[1]; + props[0] = new Property(); + props[0].Name = "Title"; + props[0].Handle = -1; + cmargs2.Mode = OpenMode.ALL; + cmargs2.Properties = props; + + command.Name = "open"; + command.Argument = cmargs2; + + Object result = xCommandProcessor.execute(command, 0, null); + XDynamicResultSet xDynamicResultSet = (XDynamicResultSet)UnoRuntime.queryInterface(XDynamicResultSet.class, result); + XResultSet xResultSet = xDynamicResultSet.getStaticResultSet(); + XRow xRow = (XRow)UnoRuntime.queryInterface(XRow.class, xResultSet); + // create the new folder 'folderName': first, check if it's already there + while(xResultSet.next()) { + String existingFolderName = xRow.getString(1); + log.println("Found existing folder: '" + existingFolderName + "'"); + if (folderName.equals(existingFolderName)) { + failed("Cannot create a new folder: folder already exists: adapt test or choose a different document."); + } + } + // create a folder + log.println("Create new folder "+ folderName); + ContentInfo contentInfo = new ContentInfo(); + contentInfo.Type = "application/vnd.sun.star.tdoc-folder"; + + command.Name = "createNewContent"; + command.Argument = contentInfo; + + result = xCommandProcessor.execute(command, 0, null); + XContent xNewFolder = (XContent)UnoRuntime.queryInterface(XContent.class, result); + + XCommandProcessor xFolderCommandProcessor = (XCommandProcessor)UnoRuntime.queryInterface(XCommandProcessor.class, xNewFolder); + log.println("Got the new folder: " + utils.getImplName(xNewFolder)); + + // name the new folder + PropertyValue[] titleProp = new PropertyValue[1]; + titleProp[0] = new PropertyValue(); + titleProp[0].Name = "Title"; + titleProp[0].Handle = -1; + titleProp[0].Value = folderName; + Command titleSetCommand = new Command(); + titleSetCommand.Name = "setPropertyValues"; + titleSetCommand.Argument = titleProp; + xFolderCommandProcessor.execute(titleSetCommand, 0, null); + + // 2do: check all this stuff! + // commit changes +/* InsertCommandArgument insertArgs = new InsertCommandArgument(); + insertArgs.Data = null; + insertArgs.ReplaceExisting = true; + Command commitCommand = new Command(); + commitCommand.Name = "insert"; + commitCommand.Argument = insertArgs; + xFolderCommandProcessor.execute(commitCommand, 0, null); */ + } + catch (com.sun.star.uno.Exception e) { + e.printStackTrace((java.io.PrintWriter)log); + failed("Could not create test objects."); + } + + } + +} diff --git a/ucb/qa/complex/tdoc/interfaces/_XChild.java b/ucb/qa/complex/tdoc/interfaces/_XChild.java new file mode 100755 index 000000000000..351fc6f84aa1 --- /dev/null +++ b/ucb/qa/complex/tdoc/interfaces/_XChild.java @@ -0,0 +1,104 @@ +/************************************************************************* + * + * 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.tdoc.interfaces; + +import lib.MultiMethodTest; +import lib.Status; + +import com.sun.star.container.XChild; +import com.sun.star.container.XNamed; +import com.sun.star.uno.UnoRuntime; +import share.LogWriter; + +/* +* Testing <code>com.sun.star.container.XChild</code> +* interface methods : +* <ul> +* <li><code> getParent()</code></li> +* <li><code> setParent()</code></li> +* </ul> +* @see com.sun.star.container.XChild +*/ +public class _XChild { + + public XChild oObj = null; + public Object gotten = null; + public LogWriter log = null; + + + /** + * Test calls the method and checks return value and that + * no exceptions were thrown. Parent returned is stored.<p> + * Has <b> OK </b> status if the method returns not null value + * and no exceptions were thrown. <p> + */ + public boolean _getParent(boolean hasParent) { + gotten = oObj.getParent(); + if (!hasParent) + return gotten == null; + XNamed the_name = (XNamed) UnoRuntime.queryInterface(XNamed.class,gotten); + if (the_name != null) + log.println("Parent:"+the_name.getName()); + return gotten != null; + } + + /** + * Sets existing parent and checks that + * no exceptions were thrown. <p> + * Has <b> OK </b> status if no exceptions were thrown. <p> + * The following method tests are to be completed successfully before : + * <ul> + * <li> <code> getParent() </code> : to get the parent. </li> + * </ul> + */ + public boolean _setParent(boolean supported) { +// requiredMethod("getParent()") ; + + String parentComment = null;//String) tEnv.getObjRelation("cannotSwitchParent"); + + if (parentComment != null) { + log.println(parentComment); + return true; + } + + try { + oObj.setParent(gotten); + } + catch (com.sun.star.lang.NoSupportException ex) { + log.println("Exception occured during setParent() - " + (supported?"FAILED":"OK")); + if (supported) { + ex.printStackTrace((java.io.PrintWriter)log); + return false; + } + } + return true; + } + +} // finish class _XChild + + diff --git a/ucb/qa/complex/tdoc/interfaces/_XCommandInfoChangeNotifier.java b/ucb/qa/complex/tdoc/interfaces/_XCommandInfoChangeNotifier.java new file mode 100755 index 000000000000..9800c5c0a398 --- /dev/null +++ b/ucb/qa/complex/tdoc/interfaces/_XCommandInfoChangeNotifier.java @@ -0,0 +1,64 @@ +/************************************************************************* + * + * 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.tdoc.interfaces; + +import com.sun.star.ucb.XCommandInfoChangeListener; +import com.sun.star.ucb.XCommandInfoChangeNotifier; +import share.LogWriter; + +/** + * + */ +public class _XCommandInfoChangeNotifier { + public XCommandInfoChangeNotifier oObj = null; + public LogWriter log = null; + private CommandInfoChangeListener listener = new CommandInfoChangeListener(); + + public boolean _addCommandInfoChangeListener() { + oObj.addCommandInfoChangeListener(listener); + return true; + } + + public boolean _removeCommandInfoChangeListener() { + oObj.removeCommandInfoChangeListener(listener); + return true; + } + + private class CommandInfoChangeListener implements XCommandInfoChangeListener { + boolean disposing = false; + boolean infoChanged = false; + + public void commandInfoChange(com.sun.star.ucb.CommandInfoChangeEvent commandInfoChangeEvent) { + infoChanged = true; + } + + public void disposing(com.sun.star.lang.EventObject eventObject) { + disposing = true; + } + + } +} diff --git a/ucb/qa/complex/tdoc/interfaces/_XCommandProcessor.java b/ucb/qa/complex/tdoc/interfaces/_XCommandProcessor.java new file mode 100755 index 000000000000..2fc31a4bd586 --- /dev/null +++ b/ucb/qa/complex/tdoc/interfaces/_XCommandProcessor.java @@ -0,0 +1,286 @@ +/************************************************************************* + * + * 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.tdoc.interfaces; + +import com.sun.star.beans.Property; +import com.sun.star.beans.XPropertySetInfo; +import lib.MultiMethodTest; +import lib.StatusException; + +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.ucb.Command; +import com.sun.star.ucb.CommandAbortedException; +import com.sun.star.ucb.CommandInfo; +import com.sun.star.ucb.GlobalTransferCommandArgument; +import com.sun.star.ucb.NameClash; +import com.sun.star.ucb.TransferCommandOperation; +import com.sun.star.ucb.UnsupportedCommandException; +import com.sun.star.ucb.XCommandInfo; +import com.sun.star.ucb.XCommandProcessor; +import com.sun.star.uno.Exception; +import com.sun.star.uno.UnoRuntime; +import share.LogWriter; + +/** +* Tests <code>XCommandProcessor</code>. The TestCase can pass (but doesn't have +* to) "XCommandProcessor.AbortCommand" relation, to specify command to abort in +* <code>abort()</code> test. +* +* Testing <code>com.sun.star.ucb.XCommandProcessor</code> +* interface methods : +* <ul> +* <li><code> createCommandIdentifier()</code></li> +* <li><code> execute()</code></li> +* <li><code> abort()</code></li> +* </ul> <p> +* This test needs the following object relations : +* <ul> +* <li> <code>'XCommandProcessor.AbortCommand'</code> <b>optional</b> +* (of type <code>com.sun.star.ucb.Command</code>): +* specify command to abort in <code>abort()</code> test. +* If the relation is not specified the 'GlobalTransfer' +* command is used.</li> +* <ul> <p> +* The following predefined files needed to complete the test: +* <ul> +* <li> <code>poliball.gif</code> : this file is required in case +* if the relation <code>'XCommandProcessor.AbortCommand'</code> +* is not specified. This file is used by 'GlobalTransfer' +* command as a source file for copying.</li> +* <ul> <p> +* Test is <b> NOT </b> multithread compilant. <p> +* @see com.sun.star.ucb.XCommandProcessor +*/ +public class _XCommandProcessor { + + /** + * Conatins the tested object. + */ + public XCommandProcessor oObj; + public LogWriter log = null; + private XMultiServiceFactory xMSF = null; + + /** + * Contains the command id returned by <code>createCommandIdentifier() + * </code>. It is used in <code>abort()</code> test. + */ + int cmdId; + + public void before(XMultiServiceFactory _xMSF) { + xMSF = _xMSF; + } + + /** + * Tests <code>createCommandIdentifier()</code>. Calls it for two times + * and checks returned values. <p> + * Has <b>OK</b> status if values are unique correct idenifiers: not 0. + */ + public boolean _createCommandIdentifier() { + log.println("creating a command line identifier"); + + int testCmdId = oObj.createCommandIdentifier(); + cmdId = oObj.createCommandIdentifier(); + + if (cmdId == 0 || testCmdId == 0) { + log.println("createCommandLineIdentifier() returned 0 - FAILED"); + } + + if (cmdId == testCmdId) { + log.println("the command identifier is not unique"); + } + + return testCmdId != 0 && cmdId != 0 && cmdId != testCmdId; + } + + /** + * First executes 'geCommandInfo' command and examines returned + * command info information. Second tries to execute inproper + * command. <p> + * Has <b> OK </b> status if in the first case returned information + * contains info about 'getCommandInfo' command and in the second + * case an exception is thrown. <p> + */ + public boolean _execute() { + String[]commands = new String[] {"getCommandInfo", "getPropertySetInfo"}; + boolean returnVal = true; + for (int j=0; j<commands.length; j++) { + String commandName = commands[j]; + Command command = new Command(commandName, -1, null); + + Object result; + + log.println("executing command " + commandName); + try { + result = oObj.execute(command, 0, null); + } catch (CommandAbortedException e) { + log.println("The command aborted " + e.getMessage()); + e.printStackTrace((java.io.PrintWriter)log); + throw new StatusException("Unexpected exception", e); + } catch (Exception e) { + log.println("Unexpected exception " + e.getMessage()); + e.printStackTrace((java.io.PrintWriter)log); + throw new StatusException("Unexpected exception", e); + } + + boolean found = false; + + XCommandInfo xCmdInfo = (XCommandInfo)UnoRuntime.queryInterface( + XCommandInfo.class, result); + if (xCmdInfo != null) { + CommandInfo[] cmdInfo = xCmdInfo.getCommands(); + for (int i = 0; i < cmdInfo.length; i++) { + log.println("\t##### " + cmdInfo[i].Name + " - " + cmdInfo[i].Handle + " - " + cmdInfo[i].ArgType.getTypeName()); + if (cmdInfo[i].Name.equals(commandName)) { + found = true; +// break; + } + } + } + + XPropertySetInfo xPropInfo = (XPropertySetInfo)UnoRuntime.queryInterface( + XPropertySetInfo.class, result); + if (xPropInfo != null) { + Property[] props = xPropInfo.getProperties(); + String[] defProps = new String[] {"ContentType", "IsDocument", "IsFolder", "Title"}; + int propCount = defProps.length; + for (int i = 0; i < props.length; i++) { + for (int k=0; k<defProps.length; k++) { + if (props[i].Name.equals(defProps[k])) { + propCount--; + log.println("Property '" + defProps[k] + "' has been found."); + } + } + } + found = propCount == 0; + } + + returnVal &= found; + + if (!found) { + log.println("Command '" + commandName + "' was not executed correctly."); + } + } +/* log.println("testing execute with wrong command"); + + Command badCommand = new Command("bad command", -1, null); + + try { + oObj.execute(badCommand, 0, null); + } catch (CommandAbortedException e) { + log.println("CommandAbortedException thrown - OK"); + } catch (UnsupportedCommandException e) { + log.println("UnsupportedCommandException thrown - OK"); + } catch (Exception e) { + log.println("Wrong exception thrown " + e.getMessage()); + e.printStackTrace((java.io.PrintWriter)log); + throw new StatusException("Unexpected exception", e); + } +*/ + return returnVal; + } + + /** + * First a separate thread where <code>abort</code> method + * is called permanently. Then a "long" command (for example, + * "transfer") is started. I case if relation is not + * specified 'GlobalTransfer' command starts to + * copy a file to temporary directory (if the relation is present + * then the its command starts to work). <p> + * Has <b> OK </b> status if the command execution is aborted, i.e. + * <code>CommandAbortedException</code> is thrown. <p> + * The following method tests are to be completed successfully before : + * <ul> + * <li> <code> createCommandIdentifier() </code> : to have a unique + * identifier which is used to abourt started command. </li> + * </ul> + */ + public boolean _abort() { + //executeMethod("createCommandIdentifier()"); + +// Command command = null;//(Command)tEnv.getObjRelation( + //"XCommandProcessor.AbortCommand"); + Command command = new Command("getCommandInfo", -1, null); + + if (command == null) { + String commandName = "globalTransfer"; + + String srcURL = util.utils.getFullTestURL("solibrary.jar") ; + String tmpURL = util.utils.getOfficeTemp(xMSF) ; + log.println("Copying '" + srcURL + "' to '" + tmpURL) ; + + GlobalTransferCommandArgument arg = new + GlobalTransferCommandArgument( + TransferCommandOperation.COPY, srcURL, + tmpURL, "", NameClash.OVERWRITE); + + command = new Command(commandName, -1, arg); + } + + Thread aborter = new Thread() { + public void run() { + for (int i = 0; i < 10; i++) { + log.println("try to abort command"); + oObj.abort(cmdId); + try { + Thread.sleep(10); + } catch (InterruptedException e) { + } + } + } + }; + + aborter.start(); + + try { + Thread.sleep(15); + } catch (InterruptedException e) { + } + + log.println("executing command"); + try { + oObj.execute(command, cmdId, null); + log.println("Command execution completed"); + log.println("CommandAbortedException is not thrown"); + log.println("This is OK since there is no command implemented "+ + "that can be aborted"); + } catch (CommandAbortedException e) { + return true; + } catch (Exception e) { + log.println("Unexpected exception " + e.getMessage()); + e.printStackTrace((java.io.PrintWriter)log); + return false; + } + + try { + aborter.join(5000); + aborter.interrupt(); + } catch(java.lang.InterruptedException e) { + } + return true; + } +} diff --git a/ucb/qa/complex/tdoc/interfaces/_XComponent.java b/ucb/qa/complex/tdoc/interfaces/_XComponent.java new file mode 100755 index 000000000000..1716e51d1358 --- /dev/null +++ b/ucb/qa/complex/tdoc/interfaces/_XComponent.java @@ -0,0 +1,171 @@ +/************************************************************************* + * + * 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.tdoc.interfaces; + +import com.sun.star.container.XNameContainer; +import lib.MultiMethodTest; + +import com.sun.star.frame.XDesktop; +import com.sun.star.lang.EventObject; +import com.sun.star.lang.XComponent; +import com.sun.star.lang.XEventListener; +import share.LogWriter; + +/** +* Testing <code>com.sun.star.lang.XComponent</code> +* interface methods : +* <ul> +* <li><code> dispose()</code></li> +* <li><code> addEventListener()</code></li> +* <li><code> removeEventListener()</code></li> +* </ul> +* After this interface test object <b>must be recreated</b>. <p> +* Multithreaded test ability <b>not implemented</b> yet. +* @see com.sun.star.lang.XComponent +*/ +public class _XComponent { + + public static XComponent oObj = null; + private XNameContainer xContainer = null; + private XComponent altDispose = null; + public LogWriter log = null; + + boolean listenerDisposed[] = new boolean[2]; + String[] Loutput = new String[2]; + + /** + * Listener which added but not removed, and its method must be called + * on <code>dispose</code> call. + */ + public class MyEventListener implements XEventListener { + public void disposing ( EventObject oEvent ) { + Loutput[0] = Thread.currentThread() + " is DISPOSING EV1" + this; + listenerDisposed[0] = true; + } + }; + + /** + * Listener which added and then removed, and its method must <b>not</b> + * be called on <code>dispose</code> call. + */ + public class MyEventListener2 implements XEventListener { + public void disposing ( EventObject oEvent ) { + Loutput[0] = Thread.currentThread() + " is DISPOSING EV2" + this; + listenerDisposed[1] = true; + } + }; + + XEventListener listener1 = new MyEventListener(); + XEventListener listener2 = new MyEventListener2(); + + /** + * For the cfgmgr2.OSetElement tests: dispose the owner element. + */ + protected void before() { + // do not dispose this component, but parent instead +// altDispose = (XComponent)tEnv.getObjRelation("XComponent.DisposeThis"); + + } + + /** + * Adds two listeners. <p> + * Has OK status if then the first listener will receive an event + * on <code>dispose</code> method call. + */ + public boolean _addEventListener() { + + listenerDisposed[0] = false; + listenerDisposed[1] = false; + + oObj.addEventListener( listener1 ); + oObj.addEventListener( listener2 ); + + return true; + } // finished _addEventListener() + + /** + * Removes the second of two added listeners. <p> + * Method tests to be completed successfully : + * <ul> + * <li> <code>addEventListener</code> : method must add two listeners. </li> + * </ul> <p> + * Has OK status if no events will be sent to the second listener on + * <code>dispose</code> method call. + */ + public boolean _removeEventListener() { +// executeMethod("addEventListener()"); + if (disposed) return true; + // the second listener should not be called + oObj.removeEventListener( listener2 ); + log.println(Thread.currentThread() + " is removing EL " + listener2); + return true; + } // finished _removeEventListener() + + static boolean disposed = false; + + /** + * Disposes the object and then check appropriate listeners were + * called or not. <p> + * Method tests to be completed successfully : + * <ul> + * <li> <code>removeEventListener</code> : method must remove one of two + * listeners. </li> + * </ul> <p> + * Has OK status if liseter removed wasn't called and other listener + * was. + */ + public boolean _dispose() { + disposed = false; +// executeMethod("removeEventListener()"); + + log.println( "begin dispose" + Thread.currentThread()); + oObj.dispose(); + + try { + Thread.sleep(500) ; + } catch (InterruptedException e) {} + if (Loutput[0]!=null) log.println(Loutput[0]); + if (Loutput[1]!=null) log.println(Loutput[1]); + log.println( "end dispose" + Thread.currentThread()); + disposed = true; + + // check that dispose() works OK. + return listenerDisposed[0] && !listenerDisposed[1]; + + } // finished _dispose() + + /** + * Forces object recreation. + */ + protected void after() { +// disposeEnvironment(); + } + +} // finished class _XComponent + + diff --git a/ucb/qa/complex/tdoc/interfaces/_XContent.java b/ucb/qa/complex/tdoc/interfaces/_XContent.java new file mode 100755 index 000000000000..4c84ecc1d8df --- /dev/null +++ b/ucb/qa/complex/tdoc/interfaces/_XContent.java @@ -0,0 +1,86 @@ +/************************************************************************* + * + * 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.tdoc.interfaces; + +import com.sun.star.ucb.XContent; +import com.sun.star.ucb.XContentEventListener; +import com.sun.star.ucb.XContentIdentifier; +import share.LogWriter; + +/** + * + * @author sg128468 + */ +public class _XContent { + public XContent oObj = null; + public LogWriter log = null; + private ContentListener listener = null; + + public boolean _addContentEventListener() { + listener = new ContentListener(); + oObj.addContentEventListener(listener); + return true; + } + public boolean _getContentType() { + String type = oObj.getContentType(); + log.println("Type: " + type); + return type != null && type.indexOf("vnd.sun.star.tdoc") != -1; + } + public boolean _getIdentifier() { + XContentIdentifier xIdent = oObj.getIdentifier(); + String id = xIdent.getContentIdentifier(); + String scheme = xIdent.getContentProviderScheme(); + log.println("Id: " + id); + log.println("Scheme: " + scheme); + return id != null && scheme != null && id.indexOf("vnd.sun.star.tdoc") != -1 && scheme.indexOf("vnd.sun.star.tdoc") != -1; + } + public boolean _removeContentEventListener() { + System.out.println("Event: " + (listener.disposed || listener.firedEvent)); + oObj.removeContentEventListener(listener); + return true; + } + + + private class ContentListener implements XContentEventListener { + private boolean disposed = false; + private boolean firedEvent = false; + + public void reset() { + disposed = false; + firedEvent = false; + } + + public void contentEvent(com.sun.star.ucb.ContentEvent contentEvent) { + firedEvent = true; + } + + public void disposing(com.sun.star.lang.EventObject eventObject) { + disposed = true; + } + + } +} diff --git a/ucb/qa/complex/tdoc/interfaces/_XPropertiesChangeNotifier.java b/ucb/qa/complex/tdoc/interfaces/_XPropertiesChangeNotifier.java new file mode 100755 index 000000000000..790f295c7be5 --- /dev/null +++ b/ucb/qa/complex/tdoc/interfaces/_XPropertiesChangeNotifier.java @@ -0,0 +1,67 @@ +/************************************************************************* + * + * 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.tdoc.interfaces; + +import com.sun.star.beans.XPropertiesChangeListener; +import com.sun.star.beans.XPropertiesChangeNotifier; +import share.LogWriter; + +/** + * Check the XPropertiesChangeNotifier + */ +public class _XPropertiesChangeNotifier { + public XPropertiesChangeNotifier oObj = null; + public LogWriter log = null; + + PropertiesChangeListener listener = new PropertiesChangeListener(); + String[] args = null; + + + public boolean _addPropertiesChangeListener() { + oObj.addPropertiesChangeListener(args, listener); + return true; + } + + public boolean _removePropertiesChangeListener() { + oObj.removePropertiesChangeListener(args, listener); + return true; + } + + private class PropertiesChangeListener implements XPropertiesChangeListener { + public boolean disposed = false; + public boolean propChanged = false; + + public void disposing(com.sun.star.lang.EventObject eventObject) { + disposed = true; + } + + public void propertiesChange(com.sun.star.beans.PropertyChangeEvent[] propertyChangeEvent) { + propChanged = true; + } + + } +} diff --git a/ucb/qa/complex/tdoc/interfaces/_XPropertyContainer.java b/ucb/qa/complex/tdoc/interfaces/_XPropertyContainer.java new file mode 100755 index 000000000000..fd7ff94c8f8f --- /dev/null +++ b/ucb/qa/complex/tdoc/interfaces/_XPropertyContainer.java @@ -0,0 +1,102 @@ +/************************************************************************* + * + * 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.tdoc.interfaces; + +import com.sun.star.beans.XPropertyContainer; +import share.LogWriter; + +/** + * + * @author sg128468 + */ +public class _XPropertyContainer { + public XPropertyContainer oObj = null; + public LogWriter log = null; + + public boolean _addProperty() { + boolean result = true; + // add illegal property + try { + oObj.addProperty("MyIllegalProperty", (short)0, null); + } + catch(com.sun.star.beans.PropertyExistException e) { + e.printStackTrace((java.io.PrintWriter)log); + result = false; + } + catch(com.sun.star.lang.IllegalArgumentException e) { + e.printStackTrace((java.io.PrintWriter)log); + log.println("'IllegalArgument' Unexpected but correct."); + } + catch(com.sun.star.beans.IllegalTypeException e) { + log.println("'IllegalType' Correctly thrown"); + } + // add valid property + try { + oObj.addProperty("MyLegalProperty", (short)0, "Just a value"); + } + catch(com.sun.star.beans.PropertyExistException e) { + e.printStackTrace((java.io.PrintWriter)log); + result = false; + } + catch(com.sun.star.lang.IllegalArgumentException e) { + e.printStackTrace((java.io.PrintWriter)log); + result = false; + } + catch(com.sun.star.beans.IllegalTypeException e) { + e.printStackTrace((java.io.PrintWriter)log); + result = false; + } + return result; + } + + public boolean _removeProperty() { + boolean result = true; + try { + oObj.removeProperty("MyIllegalProperty"); + } + catch(com.sun.star.beans.UnknownPropertyException e) { + log.println("'UnknownProperty' Correctly thrown"); + } + catch(com.sun.star.beans.NotRemoveableException e) { + e.printStackTrace((java.io.PrintWriter)log); + result = false; + } + try { + oObj.removeProperty("MyLegalProperty"); + } + catch(com.sun.star.beans.UnknownPropertyException e) { + e.printStackTrace((java.io.PrintWriter)log); + result = false; + } + catch(com.sun.star.beans.NotRemoveableException e) { + e.printStackTrace((java.io.PrintWriter)log); + result = false; + } + return result; + } + +} diff --git a/ucb/qa/complex/tdoc/interfaces/_XPropertySetInfoChangeNotifier.java b/ucb/qa/complex/tdoc/interfaces/_XPropertySetInfoChangeNotifier.java new file mode 100755 index 000000000000..ec1d7d64ada5 --- /dev/null +++ b/ucb/qa/complex/tdoc/interfaces/_XPropertySetInfoChangeNotifier.java @@ -0,0 +1,67 @@ +/************************************************************************* + * + * 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.tdoc.interfaces; + +import com.sun.star.beans.XPropertySetInfoChangeListener; +import com.sun.star.beans.XPropertySetInfoChangeNotifier; +import share.LogWriter; + +/** + * + */ +public class _XPropertySetInfoChangeNotifier { + public XPropertySetInfoChangeNotifier oObj = null; + public LogWriter log = null; + + PropertySetInfoChangeListener listener = new PropertySetInfoChangeListener(); + String[] args = null; + + + public boolean _addPropertiesChangeListener() { + oObj.addPropertySetInfoChangeListener(listener); + return true; + } + + public boolean _removePropertiesChangeListener() { + oObj.removePropertySetInfoChangeListener(listener); + return true; + } + + private class PropertySetInfoChangeListener implements XPropertySetInfoChangeListener { + public boolean disposed = false; + public boolean propChanged = false; + + public void disposing(com.sun.star.lang.EventObject eventObject) { + disposed = true; + } + + public void propertySetInfoChange(com.sun.star.beans.PropertySetInfoChangeEvent propertySetInfoChangeEvent) { + } + + } + +} diff --git a/ucb/qa/complex/tdoc/interfaces/_XServiceInfo.java b/ucb/qa/complex/tdoc/interfaces/_XServiceInfo.java new file mode 100755 index 000000000000..761cca87998a --- /dev/null +++ b/ucb/qa/complex/tdoc/interfaces/_XServiceInfo.java @@ -0,0 +1,99 @@ +/************************************************************************* + * + * 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.tdoc.interfaces; + +import lib.MultiMethodTest; + +import com.sun.star.lang.XServiceInfo; +import share.LogWriter; + +/** +* Testing <code>com.sun.star.lang.XServiceInfo</code> +* interface methods : +* <ul> +* <li><code> getImplementationName()</code></li> +* <li><code> supportsService()</code></li> +* <li><code> getSupportedServiceNames()</code></li> +* </ul> <p> +* Test is multithread compilant. <p> +* @see com.sun.star.lang.XServiceInfo +*/ +public class _XServiceInfo { + public static XServiceInfo oObj = null; + public static String[] names = null; + public LogWriter log = null; + + /** + * Just calls the method.<p> + * Has <b>OK</b> status if no runtime exceptions occured. + */ + public boolean _getImplementationName() { + boolean result = true; + log.println("testing getImplementationName() ... "); + + log.println("The ImplementationName ist "+oObj.getImplementationName()); + result=true; + + return result; + + } // end getImplementationName() + + + /** + * Just calls the method.<p> + * Has <b>OK</b> status if no runtime exceptions occured. + */ + public boolean _getSupportedServiceNames() { + boolean result = true; + log.println("getting supported Services..."); + names = oObj.getSupportedServiceNames(); + for (int i=0;i<names.length;i++) { + int k = i+1; + log.println(k+". Supported Service is "+names[i]); + } + result=true; + + return result; + + } // end getSupportedServiceNames() + + /** + * Gets one of the service names returned by + * <code>getSupportedServiceNames</code> method and + * calls the <code>supportsService</code> methos with this + * name. <p> + * Has <b>OK</b> status if <code>true</code> value is + * returned. + */ + public boolean _supportsService() { + log.println("testing supportsService"); + names = oObj.getSupportedServiceNames(); + return oObj.supportsService(names[0]); + } // end supportsService() +} + diff --git a/ucb/qa/complex/tdoc/interfaces/_XTypeProvider.java b/ucb/qa/complex/tdoc/interfaces/_XTypeProvider.java new file mode 100755 index 000000000000..aef931bdeef1 --- /dev/null +++ b/ucb/qa/complex/tdoc/interfaces/_XTypeProvider.java @@ -0,0 +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. + * + ************************************************************************/ + +package complex.tdoc.interfaces; + +import lib.MultiMethodTest; + +import com.sun.star.lang.XTypeProvider; +import com.sun.star.uno.Type; +import share.LogWriter; + +/** +* Testing <code>com.sun.star.lang.XTypeProvider</code> +* interface methods : +* <ul> +* <li><code> getTypes()</code></li> +* <li><code> getImplementationId()</code></li> +* </ul> <p> +* Test is <b> NOT </b> multithread compilant. <p> +* @see com.sun.star.lang.XTypeProvider +*/ +public class _XTypeProvider { + + public static XTypeProvider oObj = null; + public static Type[] types = null; + public LogWriter log = null; + + /** + * Just calls the method.<p> + * Has <b>OK</b> status if no runtime exceptions occured. + */ + public boolean _getImplementationId() { + boolean result = true; + log.println("testing getImplementationId() ... "); + + log.println("The ImplementationId is "+oObj.getImplementationId()); + result = true; + + return result; + + } // end getImplementationId() + + + /** + * ?alls the method and checks the return value.<p> + * Has <b>OK</b> status if one of the return value equals to the + * type <code>com.sun.star.lang.XTypeProvider</code>. + */ + public boolean _getTypes() { + boolean result = false; + log.println("getting Types..."); + types = oObj.getTypes(); + for (int i=0;i<types.length;i++) { + int k = i+1; + log.println(k+". Type is "+types[i].toString()); + if (types[i].toString().equals + ("Type[com.sun.star.lang.XTypeProvider]")) { + result = true; + } + } + if (!result) { + log.println("Component must provide Type " + +"<com.sun.star.lang.XTypeProvider>"); + } + + return result; + + } // end getTypes() + +} + diff --git a/ucb/qa/complex/tdoc/interfaces/makefile.mk b/ucb/qa/complex/tdoc/interfaces/makefile.mk new file mode 100755 index 000000000000..3a57d1501ca4 --- /dev/null +++ b/ucb/qa/complex/tdoc/interfaces/makefile.mk @@ -0,0 +1,63 @@ +#************************************************************************* +# +# 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 = ..$/..$/..$/.. +TARGET = TransientDocument +PRJNAME = $(TARGET) +PACKAGE = complex$/tdoc$/interfaces + +# --- Settings ----------------------------------------------------- +.INCLUDE: settings.mk + + +#----- compile .java files ----------------------------------------- + +JARFILES = ridl.jar unoil.jar jurt.jar juh.jar java_uno.jar OOoRunner.jar +JAVAFILES = _XChild.java \ + _XCommandInfoChangeNotifier.java \ + _XCommandProcessor.java \ + _XComponent.java \ + _XContent.java \ + _XPropertiesChangeNotifier.java \ + _XPropertyContainer.java \ + _XPropertySetInfoChangeNotifier.java \ + _XServiceInfo.java \ + _XTypeProvider.java + +#----- make a jar from compiled files ------------------------------ + +MAXLINELENGTH = 100000 + +JARCLASSDIRS = $(PACKAGE) +JARTARGET = $(TARGET).jar +JARCOMPRESS = TRUE + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + + diff --git a/ucb/qa/complex/tdoc/makefile.mk b/ucb/qa/complex/tdoc/makefile.mk new file mode 100755 index 000000000000..175184de0f27 --- /dev/null +++ b/ucb/qa/complex/tdoc/makefile.mk @@ -0,0 +1,86 @@ +#************************************************************************* +# +# 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 = ..$/..$/.. +TARGET = TransientDocument +PRJNAME = $(TARGET) +PACKAGE = complex.tdoc + +# --- Settings ----------------------------------------------------- +.INCLUDE: settings.mk + + +#----- compile .java files ----------------------------------------- + +JARFILES = ridl.jar unoil.jar jurt.jar juh.jar java_uno.jar OOoRunner.jar +JAVAFILES = CheckContentProvider.java \ + CheckTransientDocumentsContent.java \ + CheckTransientDocumentsContentProvider.java \ + CheckTransientDocumentsDocumentContent.java + +# CheckSimpleFileAccess.java \ +#----- make a jar from compiled files ------------------------------ + +MAXLINELENGTH = 100000 + +JARCLASSDIRS = $(PACKAGE) +JARTARGET = $(TARGET).jar +JARCOMPRESS = TRUE + +# --- Parameters for the test -------------------------------------- + +# start an office if the parameter is set for the makefile +.IF "$(OFFICE)" == "" +CT_APPEXECCOMMAND = +.ELSE +CT_APPEXECCOMMAND = -AppExecutionCommand \ + "$(OFFICE)$/soffice -accept=socket,host=localhost,port=8100;urp;" +.ENDIF + +# test base is java complex +CT_TESTBASE = -TestBase java_complex + +# replace $/ with . in package name +CT_PACKAGE = -o $(PACKAGE:s\$/\.\) + +# start the runner application +CT_APP = org.openoffice.Runner + +# test document path +CT_TESTDOCS = -tdoc $(PWD)$/..$/test_documents + +# --- Targets ------------------------------------------------------ + +run: ALLTAR + @echo . + @echo "The followig tests are available:" + @echo $(foreach,i,$(JAVAFILES) "dmake $(i:b) ") + +.INCLUDE : target.mk + +Check%: + +java -cp $(CLASSPATH) $(CT_APP) $(CT_TESTBASE) $(CT_TESTDOCS) $(CT_APPEXECCOMMAND) $(CT_PACKAGE).$@ diff --git a/ucb/qa/complex/test_documents/Iterator.sxw b/ucb/qa/complex/test_documents/Iterator.sxw Binary files differnew file mode 100644 index 000000000000..9a7f8961bb47 --- /dev/null +++ b/ucb/qa/complex/test_documents/Iterator.sxw diff --git a/ucb/qa/complex/test_documents/chinese.sxw b/ucb/qa/complex/test_documents/chinese.sxw Binary files differnew file mode 100644 index 000000000000..53b242a292c3 --- /dev/null +++ b/ucb/qa/complex/test_documents/chinese.sxw diff --git a/ucb/qa/complex/test_documents/filter.sxw b/ucb/qa/complex/test_documents/filter.sxw Binary files differnew file mode 100644 index 000000000000..e4b077c65f11 --- /dev/null +++ b/ucb/qa/complex/test_documents/filter.sxw diff --git a/ucb/qa/complex/ucb/UCB.java b/ucb/qa/complex/ucb/UCB.java new file mode 100755 index 000000000000..f7b1d2a8e918 --- /dev/null +++ b/ucb/qa/complex/ucb/UCB.java @@ -0,0 +1,232 @@ +/************************************************************************* + * + * 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.ucb; + +/** + * @author ab106281 + * + * To change the template for this generated type comment go to + * Window>Preferences>Java>Code Generation>Code and Comments + */ + +import complexlib.ComplexTestCase; +import java.util.List; +import java.util.Vector; + +import com.sun.star.beans.Property; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.sdbc.XResultSet; +import com.sun.star.sdbc.XRow; +import com.sun.star.uno.XComponentContext; +import com.sun.star.ucb.*; +import com.sun.star.bridge.XUnoUrlResolver; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XComponentContext; +import com.sun.star.lang.XMultiComponentFactory; +import com.sun.star.beans.XPropertySet; +/** + * @author rpiterman + * This class is used to copy the content of a folder to + * another folder. + * There is an incosistency with argument order. + * It should be always: dir,filename. + */ +public class UCB extends ComplexTestCase { + private Object ucb; + + public String[] getTestMethodNames() { + return new String[] {"checkWrongFtpConnection"}; + } + + public void init(XMultiServiceFactory xmsf) throws Exception { + String[] keys = new String[2]; + keys[0] = "Local"; + keys[1] = "Office"; + ucb = + xmsf.createInstanceWithArguments( + "com.sun.star.ucb.UniversalContentBroker", + keys); + } + + public void delete(String filename) throws Exception { + executeCommand(getContent(filename), "delete", Boolean.TRUE); + } + + /** + * target name can be "", in which case the name stays lige the source name + * @param sourceDir + * @param filename + * @param targetDir + * @param targetName + * @return + */ + + public Object executeCommand( + Object xContent, + String aCommandName, + Object aArgument) + throws com.sun.star.ucb.CommandAbortedException, com.sun.star.uno.Exception { + XCommandProcessor xCmdProcessor = + (XCommandProcessor) UnoRuntime.queryInterface( + XCommandProcessor.class, + xContent); + Command aCommand = new Command(); + aCommand.Name = aCommandName; + aCommand.Handle = -1; // not available + aCommand.Argument = aArgument; + return xCmdProcessor.execute(aCommand, 0, null); + } + + private List listFiles(String path, Verifier verifier) throws Exception { + Object xContent = getContent(path); + + OpenCommandArgument2 aArg = new OpenCommandArgument2(); + aArg.Mode = OpenMode.ALL; + aArg.Priority = 32768; + + // Fill info for the properties wanted. + aArg.Properties = new Property[] { new Property()}; + + aArg.Properties[0].Name = "Title"; + aArg.Properties[0].Handle = -1; + + XDynamicResultSet xSet; + + xSet = + (XDynamicResultSet) UnoRuntime.queryInterface( + XDynamicResultSet.class, + executeCommand(xContent, "open", aArg)); + + XResultSet xResultSet = xSet.getStaticResultSet(); + + List files = new Vector(); + + if (xResultSet.first()) { + // obtain XContentAccess interface for child content access and XRow for properties + XContentAccess xContentAccess = + (XContentAccess) UnoRuntime.queryInterface( + XContentAccess.class, + xResultSet); + XRow xRow = + (XRow) UnoRuntime.queryInterface(XRow.class, xResultSet); + do { + // Obtain URL of child. + String aId = xContentAccess.queryContentIdentifierString(); + // First column: Title (column numbers are 1-based!) + String aTitle = xRow.getString(1); + if (aTitle.length() == 0 && xRow.wasNull()); + //ignore + else + files.add(aTitle); + } while (xResultSet.next()); // next child + } + + if (verifier != null) + for (int i = 0; i < files.size(); i++) + if (!verifier.verify(files.get(i))) + files.remove(i--); + + return files; + } + + public Object getContentProperty( + Object content, + String propName, + Class type) + throws Exception { + Property[] pv = new Property[1]; + pv[0] = new Property(); + pv[0].Name = propName; + pv[0].Handle = -1; + + Object row = executeCommand(content, "getPropertyValues", pv); + XRow xrow = (XRow) UnoRuntime.queryInterface(XRow.class, row); + if (type.equals(String.class)) + return xrow.getString(1); + else if (type.equals(Boolean.class)) + return xrow.getBoolean(1) ? Boolean.TRUE : Boolean.FALSE; + else if (type.equals(Integer.class)) + return new Integer(xrow.getInt(1)); + else if (type.equals(Short.class)) + return new Short(xrow.getShort(1)); + else + return null; + + } + + public Object getContent(String path) throws Exception { + XContentIdentifier id = + ( + (XContentIdentifierFactory) UnoRuntime.queryInterface( + XContentIdentifierFactory.class, + ucb)).createContentIdentifier( + path); + + return ( + (XContentProvider) UnoRuntime.queryInterface( + XContentProvider.class, + ucb)).queryContent( + id); + } + + public static interface Verifier { + public boolean verify(Object object); + } + + public void checkWrongFtpConnection() { + //localhost ;Lo-1.Germany.sun.com; 10.16.65.155 + try { + XMultiServiceFactory xLocMSF = (XMultiServiceFactory)param.getMSF(); + String acountUrl = "ftp://noname:nopasswd@nohost"; + log.println(acountUrl); + init(xLocMSF); + Object content = getContent(acountUrl); + + OpenCommandArgument2 aArg = new OpenCommandArgument2(); + aArg.Mode = OpenMode.ALL; // FOLDER, DOCUMENTS -> simple filter + aArg.Priority = 32768; // Ignored by most implementations + + log.println("now executing open"); + executeCommand(content, "open", aArg); + failed("Expected 'IllegalArgumentException' was not thrown."); + } catch (com.sun.star.lang.IllegalArgumentException ex) { + //TODO error message; + log.println("Correct exception thrown: " + ex.getClass().toString()); + } catch(com.sun.star.ucb.InteractiveNetworkResolveNameException ex) { + log.println("This Exception is correctly thrown when no Proxy in StarOffice is used."); + log.println("To reproduce the bug behaviour, use a Proxy and try again."); + } catch (Exception ex) { + ex.printStackTrace((java.io.PrintWriter)log); + String exceptionName = ex.toString(); + log.println("ExName: '"+exceptionName+"'"); + failed("Wrong exception thrown: " + exceptionName); + } +// System.exit(0); + } + +} diff --git a/ucb/qa/complex/ucb/makefile.mk b/ucb/qa/complex/ucb/makefile.mk new file mode 100755 index 000000000000..4664bd3cfae7 --- /dev/null +++ b/ucb/qa/complex/ucb/makefile.mk @@ -0,0 +1,78 @@ +#************************************************************************* +# +# 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 = ..$/..$/.. +TARGET = UCB +PRJNAME = $(TARGET) +PACKAGE = complex$/ucb + +# --- Settings ----------------------------------------------------- +.INCLUDE: settings.mk + + +#----- compile .java files ----------------------------------------- + +JARFILES = mysql.jar ridl.jar unoil.jar jurt.jar juh.jar java_uno.jar OOoRunner.jar +JAVAFILES = UCB.java +JAVACLASSFILES = $(foreach,i,$(JAVAFILES) $(CLASSDIR)$/$(PACKAGE)$/$(i:b).class) + +#----- make a jar from compiled files ------------------------------ + +MAXLINELENGTH = 100000 + +JARCLASSDIRS = $(PACKAGE) +JARTARGET = $(TARGET).jar +JARCOMPRESS = TRUE + +# --- Parameters for the test -------------------------------------- + +# start an office if the parameter is set for the makefile +.IF "$(OFFICE)" == "" +CT_APPEXECCOMMAND = +.ELSE +CT_APPEXECCOMMAND = -AppExecutionCommand "$(OFFICE)$/soffice -accept=socket,host=localhost,port=8100;urp;" +.ENDIF + +# test base is java complex +CT_TESTBASE = -TestBase java_complex + +# test looks something like the.full.package.TestName +CT_TEST = -o $(PACKAGE:s\$/\.\).$(JAVAFILES:b) + +# start the runner application +CT_APP = org.openoffice.Runner + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + +RUN: + +java -cp $(CLASSPATH) $(CT_APP) $(CT_APPEXECCOMMAND) $(CT_TESTBASE) $(CT_TEST) + +run: RUN + + diff --git a/ucb/qa/unoapi/Test.java b/ucb/qa/unoapi/Test.java new file mode 100644 index 000000000000..145716d871d4 --- /dev/null +++ b/ucb/qa/unoapi/Test.java @@ -0,0 +1,51 @@ +/************************************************************************* +* 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 org.openoffice.ucb.qa.unoapi; + +import org.openoffice.Runner; +import org.openoffice.test.OfficeConnection; +import static org.junit.Assert.*; + +public final class Test { + @org.junit.Before public void setUp() throws Exception { + connection.setUp(); + } + + @org.junit.After public void tearDown() + throws InterruptedException, com.sun.star.uno.Exception + { + connection.tearDown(); + } + + @org.junit.Test public void test() { + assertTrue( + Runner.run( + "-sce", "ucb.sce", "-xcl", "knownissues.xcl", "-cs", + connection.getDescription())); + } + + private final OfficeConnection connection = new OfficeConnection(); +} diff --git a/ucb/qa/unoapi/knownissues.xcl b/ucb/qa/unoapi/knownissues.xcl new file mode 100644 index 000000000000..7929c1612c18 --- /dev/null +++ b/ucb/qa/unoapi/knownissues.xcl @@ -0,0 +1,2 @@ +### i86626 ### +ucb.UniversalContentBroker::com::sun::star::ucb::XCommandProcessor diff --git a/ucb/qa/unoapi/makefile.mk b/ucb/qa/unoapi/makefile.mk new file mode 100644 index 000000000000..80c7caae73b7 --- /dev/null +++ b/ucb/qa/unoapi/makefile.mk @@ -0,0 +1,48 @@ +#************************************************************************* +# 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. +#***********************************************************************/ + +.IF "$(OOO_SUBSEQUENT_TESTS)" == "" +nothing .PHONY: +.ELSE + +PRJ = ../.. +PRJNAME = ucb +TARGET = qa_unoapi + +.IF "$(OOO_JUNIT_JAR)" != "" +PACKAGE = org/openoffice/ucb/qa/unoapi +JAVATESTFILES = Test.java +JAVAFILES = $(JAVATESTFILES) +JARFILES = OOoRunner.jar ridl.jar test.jar +EXTRAJARFILES = $(OOO_JUNIT_JAR) +.END + +.INCLUDE: settings.mk +.INCLUDE: target.mk +.INCLUDE: installationtest.mk + +ALLTAR : javatest + +.END diff --git a/ucb/qa/unoapi/ucb.sce b/ucb/qa/unoapi/ucb.sce new file mode 100644 index 000000000000..6d8cd4584ed2 --- /dev/null +++ b/ucb/qa/unoapi/ucb.sce @@ -0,0 +1,11 @@ +-o ucb.UcbContentProviderProxyFactory +-o ucb.UcbPropertiesManager +-o ucb.UcbStore +-o ucb.UniversalContentBroker +-o ucpchelp.CHelpContentProvider +-o ucpdav.WebDAVContentProvider +-o ucpfile.FileProvider +-o ucpftp.FTPContentProvider +-o ucphier.HierarchyContentProvider +-o ucphier.HierarchyDataSource +-o ucppkg.PackageContentProvider diff --git a/ucb/source/cacher/cached.xml b/ucb/source/cacher/cached.xml new file mode 100644 index 000000000000..208520272f7c --- /dev/null +++ b/ucb/source/cacher/cached.xml @@ -0,0 +1,146 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE module-description PUBLIC "-//StarOffice//DTD ComponentDescription 1.0//EN" "module-description.dtd"> +<module-description xmlns:xlink="http://www.w3.org/1999/xlink"> + + <module-name> + cached + </module-name> + + <component-description> + <author> + Ingrid Halama + </author> + <name> + com.sun.star.comp.ucb.CachedContentResultSetFactory + </name> + <description> + This component implements a factory for locally cached resultsets. + </description> + <loader-name> + com.sun.star.loader.SharedLibrary + </loader-name> + <language> + c++ + </language> + <status value="final"/> + <supported-service> + com.sun.star.ucb.CachedContentResultSetFactory + </supported-service> + + <service-dependency> + com.sun.star.script.Converter + </service-dependency> + </component-description> + <component-description> + <author> + Ingrid Halama + </author> + <name> + com.sun.star.comp.ucb.CachedContentResultSetStubFactory + </name> + <description> + This component implements a factory for stubs for locally cached + resultsets. + </description> + <loader-name> + com.sun.star.loader.SharedLibrary + </loader-name> + <language> + c++ + </language> + <status value="final"/> + <supported-service> + com.sun.star.ucb.CachedContentResultSetStubFactory + </supported-service> + </component-description> + <component-description> + <author> + Ingrid Halama + </author> + <name> + com.sun.star.comp.ucb.CachedDynamicResultSetFactory + </name> + <description> + This component implements a factory for locally cached dynamic + resultsets. + </description> + <loader-name> + com.sun.star.loader.SharedLibrary + </loader-name> + <language> + c++ + </language> + <status value="final"/> + <supported-service> + com.sun.star.ucb.CachedDynamicResultSetFactory + </supported-service> + </component-description> + <component-description> + <author> + Ingrid Halama + </author> + <name> + com.sun.star.comp.ucb.CachedDynamicResultSetStubFactory + </name> + <description> + This component implements a factory for stubs for locally cached + dynamic resultsets. + </description> + <loader-name> + com.sun.star.loader.SharedLibrary + </loader-name> + <language> + c++ + </language> + <status value="final"/> + <supported-service> + com.sun.star.ucb.CachedDynamicResultSetStubFactory + </supported-service> + + <service-dependency> + com.sun.star.ucb.SortedDynamicResultSetFactory + </service-dependency> + </component-description> + + <project-build-dependency> sal </project-build-dependency> + <project-build-dependency> cppu </project-build-dependency> + <project-build-dependency> cppuhelper </project-build-dependency> + + <runtime-module-dependency> sal3 </runtime-module-dependency> + <runtime-module-dependency> cppu3 </runtime-module-dependency> + <runtime-module-dependency> cppuhelper3$(COM) </runtime-module-dependency> + + <type> com.sun.star.beans.PropertyAttribute </type> + <type> com.sun.star.beans.XPropertySet </type> + <type> com.sun.star.lang.DisposedException </type> + <type> com.sun.star.lang.XComponent </type> + <type> com.sun.star.lang.XMultiServiceFactory </type> + <type> com.sun.star.lang.XServiceInfo </type> + <type> com.sun.star.lang.XSingleServiceFactory </type> + <type> com.sun.star.lang.XTypeProvider </type> + <type> com.sun.star.registry.XRegistryKey </type> + <type> com.sun.star.script.XTypeConverter </type> + <type> com.sun.star.sdbc.FetchDirection </type> + <type> com.sun.star.sdbc.ResultSetType </type> + <type> com.sun.star.sdbc.XCloseable </type> + <type> com.sun.star.sdbc.XResultSet </type> + <type> com.sun.star.sdbc.XResultSetMetaDataSupplier </type> + <type> com.sun.star.sdbc.XRow </type> + <type> com.sun.star.ucb.ContentResultSetCapability </type> + <type> com.sun.star.ucb.FetchError </type> + <type> com.sun.star.ucb.ListActionType </type> + <type> com.sun.star.ucb.ResultSetException </type> + <type> com.sun.star.ucb.WelcomeDynamicResultSetStruct </type> + <type> com.sun.star.ucb.XContentAccess </type> + <type> com.sun.star.ucb.XCachedContentResultSetFactory </type> + <type> com.sun.star.ucb.XCachedContentResultSetStubFactory </type> + <type> com.sun.star.ucb.XCachedDynamicResultSetFactory </type> + <type> com.sun.star.ucb.XCachedDynamicResultSetStubFactory </type> + <type> com.sun.star.ucb.XContentIdentifierMapping </type> + <type> com.sun.star.ucb.XDynamicResultSet </type> + <type> com.sun.star.ucb.XFetchProvider </type> + <type> com.sun.star.ucb.XFetchProviderForContentAccess </type> + <type> com.sun.star.ucb.XSortedDynamicResultSetFactory </type> + <type> com.sun.star.ucb.XSourceInitialization </type> + <type> com.sun.star.uno.XWeak </type> +</module-description> diff --git a/ucb/source/cacher/cached1.component b/ucb/source/cacher/cached1.component new file mode 100644 index 000000000000..aa19e54b5da3 --- /dev/null +++ b/ucb/source/cacher/cached1.component @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* 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. +* +**********************************************************************--> + +<component loader="com.sun.star.loader.SharedLibrary" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.ucb.CachedContentResultSetFactory"> + <service name="com.sun.star.ucb.CachedContentResultSetFactory"/> + </implementation> + <implementation name="com.sun.star.comp.ucb.CachedContentResultSetStubFactory"> + <service name="com.sun.star.ucb.CachedContentResultSetStubFactory"/> + </implementation> + <implementation name="com.sun.star.comp.ucb.CachedDynamicResultSetFactory"> + <service name="com.sun.star.ucb.CachedDynamicResultSetFactory"/> + </implementation> + <implementation name="com.sun.star.comp.ucb.CachedDynamicResultSetStubFactory"> + <service name="com.sun.star.ucb.CachedDynamicResultSetStubFactory"/> + </implementation> +</component> diff --git a/ucb/source/cacher/cachedcontentresultset.cxx b/ucb/source/cacher/cachedcontentresultset.cxx new file mode 100644 index 000000000000..e5c879448338 --- /dev/null +++ b/ucb/source/cacher/cachedcontentresultset.cxx @@ -0,0 +1,2229 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +#include <cachedcontentresultset.hxx> +#include <com/sun/star/sdbc/FetchDirection.hpp> +#include <com/sun/star/ucb/FetchError.hpp> +#include <com/sun/star/ucb/ResultSetException.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/script/XTypeConverter.hpp> +#include <com/sun/star/sdbc/ResultSetType.hpp> +#include <rtl/ustring.hxx> +#include <osl/diagnose.h> + +using namespace com::sun::star::beans; +using namespace com::sun::star::lang; +using namespace com::sun::star::script; +using namespace com::sun::star::sdbc; +using namespace com::sun::star::ucb; +using namespace com::sun::star::uno; +using namespace com::sun::star::util; +using namespace cppu; +using namespace rtl; + +#define COMSUNSTARUCBCCRS_DEFAULT_FETCH_SIZE 256 +#define COMSUNSTARUCBCCRS_DEFAULT_FETCH_DIRECTION FetchDirection::FORWARD + +//-------------------------------------------------------------------------- +//-------------------------------------------------------------------------- +//define for getXXX methods of interface XRow +//-------------------------------------------------------------------------- +//-------------------------------------------------------------------------- + +//if you change this macro please pay attention to +//function ::getObject, where this is similar implemented + +#define XROW_GETXXX( getXXX, Type ) \ +impl_EnsureNotDisposed(); \ +ReacquireableGuard aGuard( m_aMutex ); \ +sal_Int32 nRow = m_nRow; \ +sal_Int32 nFetchSize = m_nFetchSize; \ +sal_Int32 nFetchDirection = m_nFetchDirection; \ +if( !m_aCache.hasRow( nRow ) ) \ +{ \ + if( !m_aCache.hasCausedException( nRow ) ) \ +{ \ + if( !m_xFetchProvider.is() ) \ + { \ + OSL_ENSURE( sal_False, "broadcaster was disposed already" ); \ + throw SQLException(); \ + } \ + aGuard.clear(); \ + if( impl_isForwardOnly() ) \ + applyPositionToOrigin( nRow ); \ + \ + impl_fetchData( nRow, nFetchSize, nFetchDirection ); \ + } \ + aGuard.reacquire(); \ + if( !m_aCache.hasRow( nRow ) ) \ + { \ + m_bLastReadWasFromCache = sal_False; \ + aGuard.clear(); \ + applyPositionToOrigin( nRow ); \ + impl_init_xRowOrigin(); \ + return m_xRowOrigin->getXXX( columnIndex ); \ + } \ +} \ +const Any& rValue = m_aCache.getAny( nRow, columnIndex );\ +Type aRet = Type(); \ +m_bLastReadWasFromCache = sal_True; \ +m_bLastCachedReadWasNull = !( rValue >>= aRet ); \ +/* Last chance. Try type converter service... */ \ +if ( m_bLastCachedReadWasNull && rValue.hasValue() ) \ +{ \ + Reference< XTypeConverter > xConverter \ + = getTypeConverter(); \ + if ( xConverter.is() ) \ + { \ + try \ + { \ + Any aConvAny = xConverter->convertTo( \ + rValue, \ + getCppuType( static_cast< \ + const Type * >( 0 ) ) ); \ + m_bLastCachedReadWasNull = !( aConvAny >>= aRet ); \ + } \ + catch ( IllegalArgumentException ) \ + { \ + } \ + catch ( CannotConvertException ) \ + { \ + } \ + } \ +} \ +return aRet; + +//-------------------------------------------------------------------------- +//-------------------------------------------------------------------------- +// CCRS_Cache methoeds. +//-------------------------------------------------------------------------- +//-------------------------------------------------------------------------- + +CachedContentResultSet::CCRS_Cache::CCRS_Cache( + const Reference< XContentIdentifierMapping > & xMapping ) + : m_pResult( NULL ) + , m_xContentIdentifierMapping( xMapping ) + , m_pMappedReminder( NULL ) +{ +} + +CachedContentResultSet::CCRS_Cache::~CCRS_Cache() +{ + delete m_pResult; +} + +void SAL_CALL CachedContentResultSet::CCRS_Cache + ::clear() +{ + if( m_pResult ) + { + delete m_pResult; + m_pResult = NULL; + } + clearMappedReminder(); +} + +void SAL_CALL CachedContentResultSet::CCRS_Cache + ::loadData( const FetchResult& rResult ) +{ + clear(); + m_pResult = new FetchResult( rResult ); +} + +sal_Bool SAL_CALL CachedContentResultSet::CCRS_Cache + ::hasRow( sal_Int32 row ) +{ + if( !m_pResult ) + return sal_False; + long nStart = m_pResult->StartIndex; + long nEnd = nStart; + if( m_pResult->Orientation ) + nEnd += m_pResult->Rows.getLength() - 1; + else + nStart -= m_pResult->Rows.getLength() + 1; + + return nStart <= row && row <= nEnd; +} + +sal_Int32 SAL_CALL CachedContentResultSet::CCRS_Cache + ::getMaxRow() +{ + if( !m_pResult ) + return 0; + long nEnd = m_pResult->StartIndex; + if( m_pResult->Orientation ) + return nEnd += m_pResult->Rows.getLength() - 1; + else + return nEnd; +} + +sal_Bool SAL_CALL CachedContentResultSet::CCRS_Cache + ::hasKnownLast() +{ + if( !m_pResult ) + return sal_False; + + if( ( m_pResult->FetchError & FetchError::ENDOFDATA ) + && m_pResult->Orientation + && m_pResult->Rows.getLength() ) + return sal_True; + + return sal_False; +} + +sal_Bool SAL_CALL CachedContentResultSet::CCRS_Cache + ::hasCausedException( sal_Int32 nRow ) +{ + if( !m_pResult ) + return sal_False; + if( !( m_pResult->FetchError & FetchError::EXCEPTION ) ) + return sal_False; + + long nEnd = m_pResult->StartIndex; + if( m_pResult->Orientation ) + nEnd += m_pResult->Rows.getLength(); + + return nRow == nEnd+1; +} + +Any& SAL_CALL CachedContentResultSet::CCRS_Cache + ::getRowAny( sal_Int32 nRow ) + throw( SQLException, + RuntimeException ) +{ + if( !nRow ) + throw SQLException(); + if( !m_pResult ) + throw SQLException(); + if( !hasRow( nRow ) ) + throw SQLException(); + + long nDiff = nRow - m_pResult->StartIndex; + if( nDiff < 0 ) + nDiff *= -1; + + return (m_pResult->Rows)[nDiff]; +} + +void SAL_CALL CachedContentResultSet::CCRS_Cache + ::remindMapped( sal_Int32 nRow ) +{ + //remind that this row was mapped + if( !m_pResult ) + return; + long nDiff = nRow - m_pResult->StartIndex; + if( nDiff < 0 ) + nDiff *= -1; + Sequence< sal_Bool >* pMappedReminder = getMappedReminder(); + if( nDiff < pMappedReminder->getLength() ) + (*pMappedReminder)[nDiff] = sal_True; +} + +sal_Bool SAL_CALL CachedContentResultSet::CCRS_Cache + ::isRowMapped( sal_Int32 nRow ) +{ + if( !m_pMappedReminder || !m_pResult ) + return sal_False; + long nDiff = nRow - m_pResult->StartIndex; + if( nDiff < 0 ) + nDiff *= -1; + if( nDiff < m_pMappedReminder->getLength() ) + return (*m_pMappedReminder)[nDiff]; + return sal_False; +} + +void SAL_CALL CachedContentResultSet::CCRS_Cache + ::clearMappedReminder() +{ + delete m_pMappedReminder; + m_pMappedReminder = NULL; +} + +Sequence< sal_Bool >* SAL_CALL CachedContentResultSet::CCRS_Cache + ::getMappedReminder() +{ + if( !m_pMappedReminder ) + { + sal_Int32 nCount = m_pResult->Rows.getLength(); + m_pMappedReminder = new Sequence< sal_Bool >( nCount ); + for( ;nCount; nCount-- ) + (*m_pMappedReminder)[nCount] = sal_False; + } + return m_pMappedReminder; +} + +const Any& SAL_CALL CachedContentResultSet::CCRS_Cache + ::getAny( sal_Int32 nRow, sal_Int32 nColumnIndex ) + throw( SQLException, + RuntimeException ) +{ + if( !nColumnIndex ) + throw SQLException(); + if( m_xContentIdentifierMapping.is() && !isRowMapped( nRow ) ) + { + Any& rRow = getRowAny( nRow ); + Sequence< Any > aValue; + rRow >>= aValue; + if( m_xContentIdentifierMapping->mapRow( aValue ) ) + { + rRow <<= aValue; + remindMapped( nRow ); + } + else + m_xContentIdentifierMapping.clear(); + } + const Sequence< Any >& rRow = + (* reinterpret_cast< const Sequence< Any > * > + (getRowAny( nRow ).getValue() )); + + if( nColumnIndex > rRow.getLength() ) + throw SQLException(); + return rRow[nColumnIndex-1]; +} + +const rtl::OUString& SAL_CALL CachedContentResultSet::CCRS_Cache + ::getContentIdentifierString( sal_Int32 nRow ) + throw( com::sun::star::uno::RuntimeException ) +{ + try + { + if( m_xContentIdentifierMapping.is() && !isRowMapped( nRow ) ) + { + Any& rRow = getRowAny( nRow ); + rtl::OUString aValue; + rRow >>= aValue; + rRow <<= m_xContentIdentifierMapping->mapContentIdentifierString( aValue ); + remindMapped( nRow ); + } + return (* reinterpret_cast< const rtl::OUString * > + (getRowAny( nRow ).getValue() )); + } + catch( SQLException ) + { + throw RuntimeException(); + } +} + +const Reference< XContentIdentifier >& SAL_CALL CachedContentResultSet::CCRS_Cache + ::getContentIdentifier( sal_Int32 nRow ) + throw( com::sun::star::uno::RuntimeException ) +{ + try + { + if( m_xContentIdentifierMapping.is() && !isRowMapped( nRow ) ) + { + Any& rRow = getRowAny( nRow ); + Reference< XContentIdentifier > aValue; + rRow >>= aValue; + rRow <<= m_xContentIdentifierMapping->mapContentIdentifier( aValue ); + remindMapped( nRow ); + } + return (* reinterpret_cast< const Reference< XContentIdentifier > * > + (getRowAny( nRow ).getValue() )); + } + catch( SQLException ) + { + throw RuntimeException(); + } +} + +const Reference< XContent >& SAL_CALL CachedContentResultSet::CCRS_Cache + ::getContent( sal_Int32 nRow ) + throw( com::sun::star::uno::RuntimeException ) +{ + try + { + if( m_xContentIdentifierMapping.is() && !isRowMapped( nRow ) ) + { + Any& rRow = getRowAny( nRow ); + Reference< XContent > aValue; + rRow >>= aValue; + rRow <<= m_xContentIdentifierMapping->mapContent( aValue ); + remindMapped( nRow ); + } + return (* reinterpret_cast< const Reference< XContent > * > + (getRowAny( nRow ).getValue() )); + } + catch( SQLException ) + { + throw RuntimeException(); + } +} + +//-------------------------------------------------------------------------- +//-------------------------------------------------------------------------- +// class CCRS_PropertySetInfo +//-------------------------------------------------------------------------- +//-------------------------------------------------------------------------- + +class CCRS_PropertySetInfo : + public cppu::OWeakObject, + public com::sun::star::lang::XTypeProvider, + public com::sun::star::beans::XPropertySetInfo +{ + friend class CachedContentResultSet; + + //my Properties + Sequence< com::sun::star::beans::Property >* + m_pProperties; + + //some helping variables ( names for my special properties ) + static rtl::OUString m_aPropertyNameForCount; + static rtl::OUString m_aPropertyNameForFinalCount; + static rtl::OUString m_aPropertyNameForFetchSize; + static rtl::OUString m_aPropertyNameForFetchDirection; + + long m_nFetchSizePropertyHandle; + long m_nFetchDirectionPropertyHandle; + +private: + sal_Int32 SAL_CALL + impl_getRemainedHandle() const; + + sal_Bool SAL_CALL + impl_queryProperty( + const rtl::OUString& rName + , com::sun::star::beans::Property& rProp ) const; + sal_Int32 SAL_CALL + impl_getPos( const rtl::OUString& rName ) const; + + static sal_Bool SAL_CALL + impl_isMyPropertyName( const rtl::OUString& rName ); + +public: + CCRS_PropertySetInfo( Reference< + XPropertySetInfo > xPropertySetInfoOrigin ); + + virtual ~CCRS_PropertySetInfo(); + + // XInterface + XINTERFACE_DECL() + + // XTypeProvider + XTYPEPROVIDER_DECL() + + // XPropertySetInfo + virtual Sequence< com::sun::star::beans::Property > SAL_CALL + getProperties() + throw( RuntimeException ); + + virtual com::sun::star::beans::Property SAL_CALL + getPropertyByName( const rtl::OUString& aName ) + throw( com::sun::star::beans::UnknownPropertyException, RuntimeException ); + + virtual sal_Bool SAL_CALL + hasPropertyByName( const rtl::OUString& Name ) + throw( RuntimeException ); +}; + +OUString CCRS_PropertySetInfo::m_aPropertyNameForCount( OUString::createFromAscii( "RowCount" ) ); +OUString CCRS_PropertySetInfo::m_aPropertyNameForFinalCount( OUString::createFromAscii( "IsRowCountFinal" ) ); +OUString CCRS_PropertySetInfo::m_aPropertyNameForFetchSize( OUString::createFromAscii( "FetchSize" ) ); +OUString CCRS_PropertySetInfo::m_aPropertyNameForFetchDirection( OUString::createFromAscii( "FetchDirection" ) ); + +CCRS_PropertySetInfo::CCRS_PropertySetInfo( + Reference< XPropertySetInfo > xInfo ) + : m_pProperties( NULL ) + , m_nFetchSizePropertyHandle( -1 ) + , m_nFetchDirectionPropertyHandle( -1 ) +{ + //initialize list of properties: + + // it is required, that the received xInfo contains the two + // properties with names 'm_aPropertyNameForCount' and + // 'm_aPropertyNameForFinalCount' + + if( xInfo.is() ) + { + Sequence<Property> aProps = xInfo->getProperties(); + m_pProperties = new Sequence<Property> ( aProps ); + } + else + { + OSL_ENSURE( sal_False, "The received XPropertySetInfo doesn't contain required properties" ); + m_pProperties = new Sequence<Property>; + } + + //ensure, that we haven't got the Properties 'FetchSize' and 'Direction' twice: + sal_Int32 nFetchSize = impl_getPos( m_aPropertyNameForFetchSize ); + sal_Int32 nFetchDirection = impl_getPos( m_aPropertyNameForFetchDirection ); + sal_Int32 nDeleted = 0; + if( nFetchSize != -1 ) + nDeleted++; + if( nFetchDirection != -1 ) + nDeleted++; + + Sequence< Property >* pOrigProps = new Sequence<Property> ( *m_pProperties ); + sal_Int32 nOrigProps = pOrigProps->getLength(); + + m_pProperties->realloc( nOrigProps + 2 - nDeleted );//note that nDeleted is <= 2 + for( sal_Int32 n = 0, m = 0; n < nOrigProps; n++, m++ ) + { + if( n == nFetchSize || n == nFetchDirection ) + m--; + else + (*m_pProperties)[ m ] = (*pOrigProps)[ n ]; + } + { + Property& rMyProp = (*m_pProperties)[ nOrigProps - nDeleted ]; + rMyProp.Name = m_aPropertyNameForFetchSize; + rMyProp.Type = getCppuType( static_cast< const sal_Int32 * >( 0 ) ); + rMyProp.Attributes = PropertyAttribute::BOUND | PropertyAttribute::MAYBEDEFAULT; + + if( nFetchSize != -1 ) + m_nFetchSizePropertyHandle = (*pOrigProps)[nFetchSize].Handle; + else + m_nFetchSizePropertyHandle = impl_getRemainedHandle(); + + rMyProp.Handle = m_nFetchSizePropertyHandle; + + } + { + Property& rMyProp = (*m_pProperties)[ nOrigProps - nDeleted + 1 ]; + rMyProp.Name = m_aPropertyNameForFetchDirection; + rMyProp.Type = getCppuType( static_cast< const sal_Bool * >( 0 ) ); + rMyProp.Attributes = PropertyAttribute::BOUND | PropertyAttribute::MAYBEDEFAULT; + + if( nFetchSize != -1 ) + m_nFetchDirectionPropertyHandle = (*pOrigProps)[nFetchDirection].Handle; + else + m_nFetchDirectionPropertyHandle = impl_getRemainedHandle(); + + m_nFetchDirectionPropertyHandle = rMyProp.Handle; + } + delete pOrigProps; +} + +CCRS_PropertySetInfo::~CCRS_PropertySetInfo() +{ + delete m_pProperties; +} + +//-------------------------------------------------------------------------- +// XInterface methods. +//-------------------------------------------------------------------------- +//list all interfaces inclusive baseclasses of interfaces +XINTERFACE_IMPL_2( CCRS_PropertySetInfo + , XTypeProvider + , XPropertySetInfo + ); + +//-------------------------------------------------------------------------- +// XTypeProvider methods. +//-------------------------------------------------------------------------- +//list all interfaces exclusive baseclasses +XTYPEPROVIDER_IMPL_2( CCRS_PropertySetInfo + , XTypeProvider + , XPropertySetInfo + ); +//-------------------------------------------------------------------------- +// XPropertySetInfo methods. +//-------------------------------------------------------------------------- +//virtual +Sequence< Property > SAL_CALL CCRS_PropertySetInfo + ::getProperties() throw( RuntimeException ) +{ + return *m_pProperties; +} + +//virtual +Property SAL_CALL CCRS_PropertySetInfo + ::getPropertyByName( const rtl::OUString& aName ) + throw( UnknownPropertyException, RuntimeException ) +{ + if ( !aName.getLength() ) + throw UnknownPropertyException(); + + Property aProp; + if ( impl_queryProperty( aName, aProp ) ) + return aProp; + + throw UnknownPropertyException(); +} + +//virtual +sal_Bool SAL_CALL CCRS_PropertySetInfo + ::hasPropertyByName( const rtl::OUString& Name ) + throw( RuntimeException ) +{ + return ( impl_getPos( Name ) != -1 ); +} + +//-------------------------------------------------------------------------- +// impl_ methods. +//-------------------------------------------------------------------------- + +sal_Int32 SAL_CALL CCRS_PropertySetInfo + ::impl_getPos( const OUString& rName ) const +{ + for( sal_Int32 nN = m_pProperties->getLength(); nN--; ) + { + const Property& rMyProp = (*m_pProperties)[nN]; + if( rMyProp.Name == rName ) + return nN; + } + return -1; +} + +sal_Bool SAL_CALL CCRS_PropertySetInfo + ::impl_queryProperty( const OUString& rName, Property& rProp ) const +{ + for( sal_Int32 nN = m_pProperties->getLength(); nN--; ) + { + const Property& rMyProp = (*m_pProperties)[nN]; + if( rMyProp.Name == rName ) + { + rProp.Name = rMyProp.Name; + rProp.Handle = rMyProp.Handle; + rProp.Type = rMyProp.Type; + rProp.Attributes = rMyProp.Attributes; + + return sal_True; + } + } + return sal_False; +} + +//static +sal_Bool SAL_CALL CCRS_PropertySetInfo + ::impl_isMyPropertyName( const OUString& rPropertyName ) +{ + return ( rPropertyName == m_aPropertyNameForCount + || rPropertyName == m_aPropertyNameForFinalCount + || rPropertyName == m_aPropertyNameForFetchSize + || rPropertyName == m_aPropertyNameForFetchDirection ); +} + +sal_Int32 SAL_CALL CCRS_PropertySetInfo + ::impl_getRemainedHandle( ) const +{ + sal_Int32 nHandle = 1; + + if( !m_pProperties ) + { + OSL_ENSURE( sal_False, "Properties not initialized yet" ); + return nHandle; + } + sal_Bool bFound = sal_True; + while( bFound ) + { + bFound = sal_False; + for( sal_Int32 nN = m_pProperties->getLength(); nN--; ) + { + if( nHandle == (*m_pProperties)[nN].Handle ) + { + bFound = sal_True; + nHandle++; + break; + } + } + } + return nHandle; +} + +//-------------------------------------------------------------------------- +//-------------------------------------------------------------------------- +// class CachedContentResultSet +//-------------------------------------------------------------------------- +//-------------------------------------------------------------------------- + +CachedContentResultSet::CachedContentResultSet( + const Reference< XMultiServiceFactory > & xSMgr + , const Reference< XResultSet > & xOrigin + , const Reference< XContentIdentifierMapping > & + xContentIdentifierMapping ) + : ContentResultSetWrapper( xOrigin ) + + , m_xSMgr( xSMgr ) + , m_xFetchProvider( NULL ) + , m_xFetchProviderForContentAccess( NULL ) + + , m_xMyPropertySetInfo( NULL ) + , m_pMyPropSetInfo( NULL ) + + , m_xContentIdentifierMapping( xContentIdentifierMapping ) + , m_nRow( 0 ) // Position is one-based. Zero means: before first element. + , m_bAfterLast( sal_False ) + , m_nLastAppliedPos( 0 ) + , m_bAfterLastApplied( sal_False ) + , m_nKnownCount( 0 ) + , m_bFinalCount( sal_False ) + , m_nFetchSize( + COMSUNSTARUCBCCRS_DEFAULT_FETCH_SIZE ) + , m_nFetchDirection( + COMSUNSTARUCBCCRS_DEFAULT_FETCH_DIRECTION ) + + , m_bLastReadWasFromCache( sal_False ) + , m_bLastCachedReadWasNull( sal_True ) + , m_aCache( m_xContentIdentifierMapping ) + , m_aCacheContentIdentifierString( m_xContentIdentifierMapping ) + , m_aCacheContentIdentifier( m_xContentIdentifierMapping ) + , m_aCacheContent( m_xContentIdentifierMapping ) + , m_bTriedToGetTypeConverter( sal_False ) + , m_xTypeConverter( NULL ) +{ + m_xFetchProvider = Reference< XFetchProvider >( m_xResultSetOrigin, UNO_QUERY ); + OSL_ENSURE( m_xFetchProvider.is(), "interface XFetchProvider is required" ); + + m_xFetchProviderForContentAccess = Reference< XFetchProviderForContentAccess >( m_xResultSetOrigin, UNO_QUERY ); + OSL_ENSURE( m_xFetchProviderForContentAccess.is(), "interface XFetchProviderForContentAccess is required" ); + + impl_init(); +}; + +CachedContentResultSet::~CachedContentResultSet() +{ + impl_deinit(); + //do not delete m_pMyPropSetInfo, cause it is hold via reference +}; + +//-------------------------------------------------------------------------- +// impl_ methods. +//-------------------------------------------------------------------------- + +sal_Bool SAL_CALL CachedContentResultSet + ::applyPositionToOrigin( sal_Int32 nRow ) + throw( SQLException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + //------------------------------------------------------------------------- + /** + @returns + <TRUE/> if the cursor is on a valid row; <FALSE/> if it is off + the result set. + */ + + ReacquireableGuard aGuard( m_aMutex ); + OSL_ENSURE( nRow >= 0, "only positive values supported" ); + if( !m_xResultSetOrigin.is() ) + { + OSL_ENSURE( sal_False, "broadcaster was disposed already" ); + return sal_False; + } +// OSL_ENSURE( nRow <= m_nKnownCount, "don't step into regions you don't know with this method" ); + + sal_Int32 nLastAppliedPos = m_nLastAppliedPos; + sal_Bool bAfterLastApplied = m_bAfterLastApplied; + sal_Bool bAfterLast = m_bAfterLast; + sal_Int32 nForwardOnly = m_nForwardOnly; + + aGuard.clear(); + + if( bAfterLastApplied || nLastAppliedPos != nRow ) + { + if( nForwardOnly == 1 ) + { + if( bAfterLastApplied || bAfterLast || !nRow || nRow < nLastAppliedPos ) + throw SQLException(); + + sal_Int32 nN = nRow - nLastAppliedPos; + sal_Int32 nM; + for( nM = 0; nN--; nM++ ) + { + if( !m_xResultSetOrigin->next() ) + break; + } + + aGuard.reacquire(); + m_nLastAppliedPos += nM; + m_bAfterLastApplied = nRow != m_nLastAppliedPos; + return nRow == m_nLastAppliedPos; + } + + if( !nRow ) //absolute( 0 ) will throw exception + { + m_xResultSetOrigin->beforeFirst(); + + aGuard.reacquire(); + m_nLastAppliedPos = 0; + m_bAfterLastApplied = sal_False; + return sal_False; + } + try + { + //move absolute, if !nLastAppliedPos + //because move relative would throw exception + if( !nLastAppliedPos || bAfterLast || bAfterLastApplied ) + { + sal_Bool bValid = m_xResultSetOrigin->absolute( nRow ); + + aGuard.reacquire(); + m_nLastAppliedPos = nRow; + m_bAfterLastApplied = !bValid; + return bValid; + } + else + { + sal_Bool bValid = m_xResultSetOrigin->relative( nRow - nLastAppliedPos ); + + aGuard.reacquire(); + m_nLastAppliedPos += ( nRow - nLastAppliedPos ); + m_bAfterLastApplied = !bValid; + return bValid; + } + } + catch( SQLException& rEx ) + { + if( !bAfterLastApplied && !bAfterLast && nRow > nLastAppliedPos && impl_isForwardOnly() ) + { + sal_Int32 nN = nRow - nLastAppliedPos; + sal_Int32 nM; + for( nM = 0; nN--; nM++ ) + { + if( !m_xResultSetOrigin->next() ) + break; + } + + aGuard.reacquire(); + m_nLastAppliedPos += nM; + m_bAfterLastApplied = nRow != m_nLastAppliedPos; + } + else + throw rEx; + } + + return nRow == m_nLastAppliedPos; + } + return sal_True; +}; + +//-------------------------------------------------------------------------- +//-------------------------------------------------------------------------- +//define for fetching data +//-------------------------------------------------------------------------- +//-------------------------------------------------------------------------- + +#define FETCH_XXX( aCache, fetchInterface, fetchMethod ) \ +sal_Bool bDirection = !!( \ + nFetchDirection != FetchDirection::REVERSE ); \ +FetchResult aResult = \ + fetchInterface->fetchMethod( nRow, nFetchSize, bDirection ); \ +osl::ClearableGuard< osl::Mutex > aGuard2( m_aMutex ); \ +aCache.loadData( aResult ); \ +sal_Int32 nMax = aCache.getMaxRow(); \ +sal_Int32 nCurCount = m_nKnownCount; \ +sal_Bool bIsFinalCount = aCache.hasKnownLast(); \ +sal_Bool bCurIsFinalCount = m_bFinalCount; \ +aGuard2.clear(); \ +if( nMax > nCurCount ) \ + impl_changeRowCount( nCurCount, nMax ); \ +if( bIsFinalCount && !bCurIsFinalCount ) \ + impl_changeIsRowCountFinal( bCurIsFinalCount, bIsFinalCount ); + +void SAL_CALL CachedContentResultSet + ::impl_fetchData( sal_Int32 nRow + , sal_Int32 nFetchSize, sal_Int32 nFetchDirection ) + throw( com::sun::star::uno::RuntimeException ) +{ + FETCH_XXX( m_aCache, m_xFetchProvider, fetch ); +} + +void SAL_CALL CachedContentResultSet + ::impl_changeRowCount( sal_Int32 nOld, sal_Int32 nNew ) +{ + OSL_ENSURE( nNew > nOld, "RowCount only can grow" ); + if( nNew <= nOld ) + return; + + //create PropertyChangeEvent and set value + PropertyChangeEvent aEvt; + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + aEvt.Source = static_cast< XPropertySet * >( this ); + aEvt.Further = sal_False; + aEvt.OldValue <<= nOld; + aEvt.NewValue <<= nNew; + + m_nKnownCount = nNew; + } + + //send PropertyChangeEvent to listeners + impl_notifyPropertyChangeListeners( aEvt ); +} + +void SAL_CALL CachedContentResultSet + ::impl_changeIsRowCountFinal( sal_Bool bOld, sal_Bool bNew ) +{ + OSL_ENSURE( !bOld && bNew, "This change is not allowed for IsRowCountFinal" ); + if( ! (!bOld && bNew ) ) + return; + + //create PropertyChangeEvent and set value + PropertyChangeEvent aEvt; + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + aEvt.Source = static_cast< XPropertySet * >( this ); + aEvt.Further = sal_False; + aEvt.OldValue <<= bOld; + aEvt.NewValue <<= bNew; + + m_bFinalCount = bNew; + } + + //send PropertyChangeEvent to listeners + impl_notifyPropertyChangeListeners( aEvt ); +} + +sal_Bool SAL_CALL CachedContentResultSet + ::impl_isKnownValidPosition( sal_Int32 nRow ) +{ + return m_nKnownCount && nRow + && nRow <= m_nKnownCount; +} + +sal_Bool SAL_CALL CachedContentResultSet + ::impl_isKnownInvalidPosition( sal_Int32 nRow ) +{ + if( !nRow ) + return sal_True; + if( !m_bFinalCount ) + return sal_False; + return nRow > m_nKnownCount; +} + + +//virtual +void SAL_CALL CachedContentResultSet + ::impl_initPropertySetInfo() +{ + ContentResultSetWrapper::impl_initPropertySetInfo(); + + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + if( m_pMyPropSetInfo ) + return; + m_pMyPropSetInfo = new CCRS_PropertySetInfo( m_xPropertySetInfo ); + m_xMyPropertySetInfo = m_pMyPropSetInfo; + m_xPropertySetInfo = m_xMyPropertySetInfo; +} + +//-------------------------------------------------------------------------- +// XInterface methods. ( inherited ) +//-------------------------------------------------------------------------- +XINTERFACE_COMMON_IMPL( CachedContentResultSet ) + +Any SAL_CALL CachedContentResultSet + ::queryInterface( const Type& rType ) + throw ( RuntimeException ) +{ + //list all interfaces inclusive baseclasses of interfaces + + Any aRet = ContentResultSetWrapper::queryInterface( rType ); + if( aRet.hasValue() ) + return aRet; + + aRet = cppu::queryInterface( rType, + static_cast< XTypeProvider* >( this ), + static_cast< XServiceInfo* >( this ) ); + + return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ); +} + +//-------------------------------------------------------------------------- +// XTypeProvider methods. +//-------------------------------------------------------------------------- +//list all interfaces exclusive baseclasses +XTYPEPROVIDER_IMPL_11( CachedContentResultSet + , XTypeProvider + , XServiceInfo + , XComponent + , XCloseable + , XResultSetMetaDataSupplier + , XPropertySet + + , XPropertyChangeListener + , XVetoableChangeListener + + , XContentAccess + + , XResultSet + , XRow ); + +//-------------------------------------------------------------------------- +// XServiceInfo methods. +//-------------------------------------------------------------------------- + +XSERVICEINFO_NOFACTORY_IMPL_1( CachedContentResultSet, + OUString::createFromAscii( + "com.sun.star.comp.ucb.CachedContentResultSet" ), + OUString::createFromAscii( + CACHED_CONTENT_RESULTSET_SERVICE_NAME ) ); + +//-------------------------------------------------------------------------- +// XPropertySet methods. ( inherited ) +//-------------------------------------------------------------------------- + +// virtual +void SAL_CALL CachedContentResultSet + ::setPropertyValue( const OUString& aPropertyName, const Any& aValue ) + throw( UnknownPropertyException, + PropertyVetoException, + IllegalArgumentException, + WrappedTargetException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + + if( !getPropertySetInfo().is() ) + { + OSL_ENSURE( sal_False, "broadcaster was disposed already" ); + throw UnknownPropertyException(); + } + + Property aProp = m_pMyPropSetInfo->getPropertyByName( aPropertyName ); + //throws UnknownPropertyException, if so + + if( aProp.Attributes & PropertyAttribute::READONLY ) + { + //It is assumed, that the properties + //'RowCount' and 'IsRowCountFinal' are readonly! + throw IllegalArgumentException(); + } + if( aProp.Name == CCRS_PropertySetInfo + ::m_aPropertyNameForFetchDirection ) + { + //check value + sal_Int32 nNew; + if( !( aValue >>= nNew ) ) + { + throw IllegalArgumentException(); + } + + if( nNew == FetchDirection::UNKNOWN ) + { + nNew = COMSUNSTARUCBCCRS_DEFAULT_FETCH_DIRECTION; + } + else if( !( nNew == FetchDirection::FORWARD + || nNew == FetchDirection::REVERSE ) ) + { + throw IllegalArgumentException(); + } + + //create PropertyChangeEvent and set value + PropertyChangeEvent aEvt; + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + aEvt.Source = static_cast< XPropertySet * >( this ); + aEvt.PropertyName = aPropertyName; + aEvt.Further = sal_False; + aEvt.PropertyHandle = m_pMyPropSetInfo-> + m_nFetchDirectionPropertyHandle; + aEvt.OldValue <<= m_nFetchDirection; + aEvt.NewValue <<= nNew; + + m_nFetchDirection = nNew; + } + + //send PropertyChangeEvent to listeners + impl_notifyPropertyChangeListeners( aEvt ); + } + else if( aProp.Name == CCRS_PropertySetInfo + ::m_aPropertyNameForFetchSize ) + { + //check value + sal_Int32 nNew; + if( !( aValue >>= nNew ) ) + { + throw IllegalArgumentException(); + } + + if( nNew < 0 ) + { + nNew = COMSUNSTARUCBCCRS_DEFAULT_FETCH_SIZE; + } + + //create PropertyChangeEvent and set value + PropertyChangeEvent aEvt; + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + aEvt.Source = static_cast< XPropertySet * >( this ); + aEvt.PropertyName = aPropertyName; + aEvt.Further = sal_False; + aEvt.PropertyHandle = m_pMyPropSetInfo-> + m_nFetchSizePropertyHandle; + aEvt.OldValue <<= m_nFetchSize; + aEvt.NewValue <<= nNew; + + m_nFetchSize = nNew; + } + + //send PropertyChangeEvent to listeners + impl_notifyPropertyChangeListeners( aEvt ); + } + else + { + impl_init_xPropertySetOrigin(); + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + if( !m_xPropertySetOrigin.is() ) + { + OSL_ENSURE( sal_False, "broadcaster was disposed already" ); + return; + } + } + m_xPropertySetOrigin->setPropertyValue( aPropertyName, aValue ); + } +} + +//-------------------------------------------------------------------------- +// virtual +Any SAL_CALL CachedContentResultSet + ::getPropertyValue( const OUString& rPropertyName ) + throw( UnknownPropertyException, + WrappedTargetException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + + if( !getPropertySetInfo().is() ) + { + OSL_ENSURE( sal_False, "broadcaster was disposed already" ); + throw UnknownPropertyException(); + } + + Property aProp = m_pMyPropSetInfo->getPropertyByName( rPropertyName ); + //throws UnknownPropertyException, if so + + Any aValue; + if( rPropertyName == CCRS_PropertySetInfo + ::m_aPropertyNameForCount ) + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + aValue <<= m_nKnownCount; + } + else if( rPropertyName == CCRS_PropertySetInfo + ::m_aPropertyNameForFinalCount ) + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + aValue <<= m_bFinalCount; + } + else if( rPropertyName == CCRS_PropertySetInfo + ::m_aPropertyNameForFetchSize ) + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + aValue <<= m_nFetchSize; + } + else if( rPropertyName == CCRS_PropertySetInfo + ::m_aPropertyNameForFetchDirection ) + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + aValue <<= m_nFetchDirection; + } + else + { + impl_init_xPropertySetOrigin(); + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + if( !m_xPropertySetOrigin.is() ) + { + OSL_ENSURE( sal_False, "broadcaster was disposed already" ); + throw UnknownPropertyException(); + } + } + aValue = m_xPropertySetOrigin->getPropertyValue( rPropertyName ); + } + return aValue; +} + +//-------------------------------------------------------------------------- +// own methods. ( inherited ) +//-------------------------------------------------------------------------- + +//virtual +void SAL_CALL CachedContentResultSet + ::impl_disposing( const EventObject& rEventObject ) + throw( RuntimeException ) +{ + { + impl_EnsureNotDisposed(); + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + //release all references to the broadcaster: + m_xFetchProvider.clear(); + m_xFetchProviderForContentAccess.clear(); + } + ContentResultSetWrapper::impl_disposing( rEventObject ); +} + +//virtual +void SAL_CALL CachedContentResultSet + ::impl_propertyChange( const PropertyChangeEvent& rEvt ) + throw( RuntimeException ) +{ + impl_EnsureNotDisposed(); + + PropertyChangeEvent aEvt( rEvt ); + aEvt.Source = static_cast< XPropertySet * >( this ); + aEvt.Further = sal_False; + //--------- + + if( CCRS_PropertySetInfo + ::impl_isMyPropertyName( rEvt.PropertyName ) ) + { + //don't notify foreign events on fetchsize and fetchdirection + if( aEvt.PropertyName == CCRS_PropertySetInfo + ::m_aPropertyNameForFetchSize + || aEvt.PropertyName == CCRS_PropertySetInfo + ::m_aPropertyNameForFetchDirection ) + return; + + //adjust my props 'RowCount' and 'IsRowCountFinal' + if( aEvt.PropertyName == CCRS_PropertySetInfo + ::m_aPropertyNameForCount ) + {//RowCount changed + + //check value + sal_Int32 nNew = 0; + if( !( aEvt.NewValue >>= nNew ) ) + { + OSL_ENSURE( sal_False, "PropertyChangeEvent contains wrong data" ); + return; + } + + impl_changeRowCount( m_nKnownCount, nNew ); + } + else if( aEvt.PropertyName == CCRS_PropertySetInfo + ::m_aPropertyNameForFinalCount ) + {//IsRowCountFinal changed + + //check value + sal_Bool bNew = sal_False; + if( !( aEvt.NewValue >>= bNew ) ) + { + OSL_ENSURE( sal_False, "PropertyChangeEvent contains wrong data" ); + return; + } + impl_changeIsRowCountFinal( m_bFinalCount, bNew ); + } + return; + } + + //----------- + impl_notifyPropertyChangeListeners( aEvt ); +} + + +//virtual +void SAL_CALL CachedContentResultSet + ::impl_vetoableChange( const PropertyChangeEvent& rEvt ) + throw( PropertyVetoException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + + //don't notify events on my properties, cause they are not vetoable + if( CCRS_PropertySetInfo + ::impl_isMyPropertyName( rEvt.PropertyName ) ) + { + return; + } + + + PropertyChangeEvent aEvt( rEvt ); + aEvt.Source = static_cast< XPropertySet * >( this ); + aEvt.Further = sal_False; + + impl_notifyVetoableChangeListeners( aEvt ); +} + +//-------------------------------------------------------------------------- +// XContentAccess methods. ( inherited ) ( -- position dependent ) +//-------------------------------------------------------------------------- + +#define XCONTENTACCESS_queryXXX( queryXXX, XXX, TYPE ) \ +impl_EnsureNotDisposed(); \ +ReacquireableGuard aGuard( m_aMutex ); \ +sal_Int32 nRow = m_nRow; \ +sal_Int32 nFetchSize = m_nFetchSize; \ +sal_Int32 nFetchDirection = m_nFetchDirection; \ +if( !m_aCache##XXX.hasRow( nRow ) ) \ +{ \ + if( !m_aCache##XXX.hasCausedException( nRow ) ) \ +{ \ + if( !m_xFetchProviderForContentAccess.is() ) \ + { \ + OSL_ENSURE( sal_False, "broadcaster was disposed already" );\ + throw RuntimeException(); \ + } \ + aGuard.clear(); \ + if( impl_isForwardOnly() ) \ + applyPositionToOrigin( nRow ); \ + \ + FETCH_XXX( m_aCache##XXX, m_xFetchProviderForContentAccess, fetch##XXX##s ); \ + } \ + aGuard.reacquire(); \ + if( !m_aCache##XXX.hasRow( nRow ) ) \ + { \ + aGuard.clear(); \ + applyPositionToOrigin( nRow ); \ + TYPE aRet = ContentResultSetWrapper::queryXXX(); \ + if( m_xContentIdentifierMapping.is() ) \ + return m_xContentIdentifierMapping->map##XXX( aRet );\ + return aRet; \ + } \ +} \ +return m_aCache##XXX.get##XXX( nRow ); + +//-------------------------------------------------------------------------- +// virtual +OUString SAL_CALL CachedContentResultSet + ::queryContentIdentifierString() + throw( RuntimeException ) +{ + XCONTENTACCESS_queryXXX( queryContentIdentifierString, ContentIdentifierString, OUString ) +} + +//-------------------------------------------------------------------------- +// virtual +Reference< XContentIdentifier > SAL_CALL CachedContentResultSet + ::queryContentIdentifier() + throw( RuntimeException ) +{ + XCONTENTACCESS_queryXXX( queryContentIdentifier, ContentIdentifier, Reference< XContentIdentifier > ) +} + +//-------------------------------------------------------------------------- +// virtual +Reference< XContent > SAL_CALL CachedContentResultSet + ::queryContent() + throw( RuntimeException ) +{ + XCONTENTACCESS_queryXXX( queryContent, Content, Reference< XContent > ) +} + +//----------------------------------------------------------------- +// XResultSet methods. ( inherited ) +//----------------------------------------------------------------- +//virtual + +sal_Bool SAL_CALL CachedContentResultSet + ::next() + throw( SQLException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + + ReacquireableGuard aGuard( m_aMutex ); + //after last + if( m_bAfterLast ) + return sal_False; + //last + aGuard.clear(); + if( isLast() ) + { + aGuard.reacquire(); + m_nRow++; + m_bAfterLast = sal_True; + return sal_False; + } + aGuard.reacquire(); + //known valid position + if( impl_isKnownValidPosition( m_nRow + 1 ) ) + { + m_nRow++; + return sal_True; + } + + //unknown position + sal_Int32 nRow = m_nRow; + aGuard.clear(); + + sal_Bool bValid = applyPositionToOrigin( nRow + 1 ); + + aGuard.reacquire(); + m_nRow = nRow + 1; + m_bAfterLast = !bValid; + return bValid; +} + +//virtual +sal_Bool SAL_CALL CachedContentResultSet + ::previous() + throw( SQLException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + + if( impl_isForwardOnly() ) + throw SQLException(); + + ReacquireableGuard aGuard( m_aMutex ); + //before first ?: + if( !m_bAfterLast && !m_nRow ) + return sal_False; + //first ?: + if( !m_bAfterLast && m_nKnownCount && m_nRow == 1 ) + { + m_nRow--; + m_bAfterLast = sal_False; + return sal_False; + } + //known valid position ?: + if( impl_isKnownValidPosition( m_nRow - 1 ) ) + { + m_nRow--; + m_bAfterLast = sal_False; + return sal_True; + } + //unknown position: + sal_Int32 nRow = m_nRow; + aGuard.clear(); + + sal_Bool bValid = applyPositionToOrigin( nRow - 1 ); + + aGuard.reacquire(); + m_nRow = nRow - 1; + m_bAfterLast = sal_False; + return bValid; +} + +//virtual +sal_Bool SAL_CALL CachedContentResultSet + ::absolute( sal_Int32 row ) + throw( SQLException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + + if( !row ) + throw SQLException(); + + if( impl_isForwardOnly() ) + throw SQLException(); + + ReacquireableGuard aGuard( m_aMutex ); + + if( !m_xResultSetOrigin.is() ) + { + OSL_ENSURE( sal_False, "broadcaster was disposed already" ); + return sal_False; + } + if( row < 0 ) + { + if( m_bFinalCount ) + { + sal_Int32 nNewRow = m_nKnownCount + 1 + row; + sal_Bool bValid = sal_True; + if( nNewRow <= 0 ) + { + nNewRow = 0; + bValid = sal_False; + } + m_nRow = nNewRow; + m_bAfterLast = sal_False; + return bValid; + } + //unknown final count: + aGuard.clear(); + + // Solaris has problems catching or propagating derived exceptions + // when only the base class is known, so make ResultSetException + // (derived from SQLException) known here: + sal_Bool bValid; + try + { + bValid = m_xResultSetOrigin->absolute( row ); + } + catch (ResultSetException &) + { + throw; + } + + aGuard.reacquire(); + if( m_bFinalCount ) + { + sal_Int32 nNewRow = m_nKnownCount + 1 + row; + if( nNewRow < 0 ) + nNewRow = 0; + m_nLastAppliedPos = nNewRow; + m_nRow = nNewRow; + m_bAfterLastApplied = m_bAfterLast = sal_False; + return bValid; + } + aGuard.clear(); + + sal_Int32 nCurRow = m_xResultSetOrigin->getRow(); + + aGuard.reacquire(); + m_nLastAppliedPos = nCurRow; + m_nRow = nCurRow; + m_bAfterLast = sal_False; + return nCurRow != 0; + } + //row > 0: + if( m_bFinalCount ) + { + if( row > m_nKnownCount ) + { + m_nRow = m_nKnownCount + 1; + m_bAfterLast = sal_True; + return sal_False; + } + m_nRow = row; + m_bAfterLast = sal_False; + return sal_True; + } + //unknown new position: + aGuard.clear(); + + sal_Bool bValid = m_xResultSetOrigin->absolute( row ); + + aGuard.reacquire(); + if( m_bFinalCount ) + { + sal_Int32 nNewRow = row; + if( nNewRow > m_nKnownCount ) + { + nNewRow = m_nKnownCount + 1; + m_bAfterLastApplied = m_bAfterLast = sal_True; + } + else + m_bAfterLastApplied = m_bAfterLast = sal_False; + + m_nLastAppliedPos = nNewRow; + m_nRow = nNewRow; + return bValid; + } + aGuard.clear(); + + sal_Int32 nCurRow = m_xResultSetOrigin->getRow(); + sal_Bool bIsAfterLast = m_xResultSetOrigin->isAfterLast(); + + aGuard.reacquire(); + m_nLastAppliedPos = nCurRow; + m_nRow = nCurRow; + m_bAfterLastApplied = m_bAfterLast = bIsAfterLast; + return nCurRow && !bIsAfterLast; +} + +//virtual +sal_Bool SAL_CALL CachedContentResultSet + ::relative( sal_Int32 rows ) + throw( SQLException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + + if( impl_isForwardOnly() ) + throw SQLException(); + + ReacquireableGuard aGuard( m_aMutex ); + if( m_bAfterLast || impl_isKnownInvalidPosition( m_nRow ) ) + throw SQLException(); + + if( !rows ) + return sal_True; + + sal_Int32 nNewRow = m_nRow + rows; + if( nNewRow < 0 ) + nNewRow = 0; + + if( impl_isKnownValidPosition( nNewRow ) ) + { + m_nRow = nNewRow; + m_bAfterLast = sal_False; + return sal_True; + } + else + { + //known invalid new position: + if( nNewRow == 0 ) + { + m_bAfterLast = sal_False; + m_nRow = 0; + return sal_False; + } + if( m_bFinalCount && nNewRow > m_nKnownCount ) + { + m_bAfterLast = sal_True; + m_nRow = m_nKnownCount + 1; + return sal_False; + } + //unknown new position: + aGuard.clear(); + sal_Bool bValid = applyPositionToOrigin( nNewRow ); + + aGuard.reacquire(); + m_nRow = nNewRow; + m_bAfterLast = !bValid && nNewRow > 0; + return bValid; + } +} + + +//virtual +sal_Bool SAL_CALL CachedContentResultSet + ::first() + throw( SQLException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + + if( impl_isForwardOnly() ) + throw SQLException(); + + ReacquireableGuard aGuard( m_aMutex ); + if( impl_isKnownValidPosition( 1 ) ) + { + m_nRow = 1; + m_bAfterLast = sal_False; + return sal_True; + } + if( impl_isKnownInvalidPosition( 1 ) ) + { + m_nRow = 1; + m_bAfterLast = sal_False; + return sal_False; + } + //unknown position + aGuard.clear(); + + sal_Bool bValid = applyPositionToOrigin( 1 ); + + aGuard.reacquire(); + m_nRow = 1; + m_bAfterLast = sal_False; + return bValid; +} + +//virtual +sal_Bool SAL_CALL CachedContentResultSet + ::last() + throw( SQLException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + + if( impl_isForwardOnly() ) + throw SQLException(); + + ReacquireableGuard aGuard( m_aMutex ); + if( m_bFinalCount ) + { + m_nRow = m_nKnownCount; + m_bAfterLast = sal_False; + return m_nKnownCount != 0; + } + //unknown position + if( !m_xResultSetOrigin.is() ) + { + OSL_ENSURE( sal_False, "broadcaster was disposed already" ); + return sal_False; + } + aGuard.clear(); + + sal_Bool bValid = m_xResultSetOrigin->last(); + + aGuard.reacquire(); + m_bAfterLastApplied = m_bAfterLast = sal_False; + if( m_bFinalCount ) + { + m_nLastAppliedPos = m_nKnownCount; + m_nRow = m_nKnownCount; + return bValid; + } + aGuard.clear(); + + sal_Int32 nCurRow = m_xResultSetOrigin->getRow(); + + aGuard.reacquire(); + m_nLastAppliedPos = nCurRow; + m_nRow = nCurRow; + OSL_ENSURE( nCurRow >= m_nKnownCount, "position of last row < known Count, that could not be" ); + m_nKnownCount = nCurRow; + m_bFinalCount = sal_True; + return nCurRow != 0; +} + +//virtual +void SAL_CALL CachedContentResultSet + ::beforeFirst() + throw( SQLException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + + if( impl_isForwardOnly() ) + throw SQLException(); + + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + m_nRow = 0; + m_bAfterLast = sal_False; +} + +//virtual +void SAL_CALL CachedContentResultSet + ::afterLast() + throw( SQLException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + + if( impl_isForwardOnly() ) + throw SQLException(); + + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + m_nRow = 1; + m_bAfterLast = sal_True; +} + +//virtual +sal_Bool SAL_CALL CachedContentResultSet + ::isAfterLast() + throw( SQLException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + + ReacquireableGuard aGuard( m_aMutex ); + if( !m_bAfterLast ) + return sal_False; + if( m_nKnownCount ) + return m_bAfterLast; + if( m_bFinalCount ) + return sal_False; + + if( !m_xResultSetOrigin.is() ) + { + OSL_ENSURE( sal_False, "broadcaster was disposed already" ); + return sal_False; + } + aGuard.clear(); + + //find out whethter the original resultset contains rows or not + m_xResultSetOrigin->afterLast(); + + aGuard.reacquire(); + m_bAfterLastApplied = sal_True; + aGuard.clear(); + + return m_xResultSetOrigin->isAfterLast(); +} + +//virtual +sal_Bool SAL_CALL CachedContentResultSet + ::isBeforeFirst() + throw( SQLException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + + ReacquireableGuard aGuard( m_aMutex ); + if( m_bAfterLast ) + return sal_False; + if( m_nRow ) + return sal_False; + if( m_nKnownCount ) + return !m_nRow; + if( m_bFinalCount ) + return sal_False; + + if( !m_xResultSetOrigin.is() ) + { + OSL_ENSURE( sal_False, "broadcaster was disposed already" ); + return sal_False; + } + aGuard.clear(); + + //find out whethter the original resultset contains rows or not + m_xResultSetOrigin->beforeFirst(); + + aGuard.reacquire(); + m_bAfterLastApplied = sal_False; + m_nLastAppliedPos = 0; + aGuard.clear(); + + return m_xResultSetOrigin->isBeforeFirst(); +} + +//virtual +sal_Bool SAL_CALL CachedContentResultSet + ::isFirst() + throw( SQLException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + + sal_Int32 nRow = 0; + Reference< XResultSet > xResultSetOrigin; + + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + if( m_bAfterLast ) + return sal_False; + if( m_nRow != 1 ) + return sal_False; + if( m_nKnownCount ) + return m_nRow == 1; + if( m_bFinalCount ) + return sal_False; + + nRow = m_nRow; + xResultSetOrigin = m_xResultSetOrigin; + } + + //need to ask origin + { + if( applyPositionToOrigin( nRow ) ) + return xResultSetOrigin->isFirst(); + else + return sal_False; + } +} + +//virtual +sal_Bool SAL_CALL CachedContentResultSet + ::isLast() + throw( SQLException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + + sal_Int32 nRow = 0; + Reference< XResultSet > xResultSetOrigin; + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + if( m_bAfterLast ) + return sal_False; + if( m_nRow < m_nKnownCount ) + return sal_False; + if( m_bFinalCount ) + return m_nKnownCount && m_nRow == m_nKnownCount; + + nRow = m_nRow; + xResultSetOrigin = m_xResultSetOrigin; + } + + //need to ask origin + { + if( applyPositionToOrigin( nRow ) ) + return xResultSetOrigin->isLast(); + else + return sal_False; + } +} + + +//virtual +sal_Int32 SAL_CALL CachedContentResultSet + ::getRow() + throw( SQLException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + if( m_bAfterLast ) + return 0; + return m_nRow; +} + +//virtual +void SAL_CALL CachedContentResultSet + ::refreshRow() + throw( SQLException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + + //the ContentResultSet is static and will not change + //therefore we don't need to reload anything +} + +//virtual +sal_Bool SAL_CALL CachedContentResultSet + ::rowUpdated() + throw( SQLException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + + //the ContentResultSet is static and will not change + return sal_False; +} +//virtual +sal_Bool SAL_CALL CachedContentResultSet + ::rowInserted() + throw( SQLException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + + //the ContentResultSet is static and will not change + return sal_False; +} + +//virtual +sal_Bool SAL_CALL CachedContentResultSet + ::rowDeleted() + throw( SQLException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + + //the ContentResultSet is static and will not change + return sal_False; +} + +//virtual +Reference< XInterface > SAL_CALL CachedContentResultSet + ::getStatement() + throw( SQLException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + //@todo ?return anything + return Reference< XInterface >(); +} + +//----------------------------------------------------------------- +// XRow methods. ( inherited ) +//----------------------------------------------------------------- + +//virtual +sal_Bool SAL_CALL CachedContentResultSet + ::wasNull() + throw( SQLException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + impl_init_xRowOrigin(); + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + if( m_bLastReadWasFromCache ) + return m_bLastCachedReadWasNull; + if( !m_xRowOrigin.is() ) + { + OSL_ENSURE( sal_False, "broadcaster was disposed already" ); + return sal_False; + } + } + return m_xRowOrigin->wasNull(); +} + +//virtual +rtl::OUString SAL_CALL CachedContentResultSet + ::getString( sal_Int32 columnIndex ) + throw( SQLException, + RuntimeException ) +{ + XROW_GETXXX( getString, OUString ); +} + +//virtual +sal_Bool SAL_CALL CachedContentResultSet + ::getBoolean( sal_Int32 columnIndex ) + throw( SQLException, + RuntimeException ) +{ + XROW_GETXXX( getBoolean, sal_Bool ); +} + +//virtual +sal_Int8 SAL_CALL CachedContentResultSet + ::getByte( sal_Int32 columnIndex ) + throw( SQLException, + RuntimeException ) +{ + XROW_GETXXX( getByte, sal_Int8 ); +} + +//virtual +sal_Int16 SAL_CALL CachedContentResultSet + ::getShort( sal_Int32 columnIndex ) + throw( SQLException, + RuntimeException ) +{ + XROW_GETXXX( getShort, sal_Int16 ); +} + +//virtual +sal_Int32 SAL_CALL CachedContentResultSet + ::getInt( sal_Int32 columnIndex ) + throw( SQLException, + RuntimeException ) +{ + XROW_GETXXX( getInt, sal_Int32 ); +} + +//virtual +sal_Int64 SAL_CALL CachedContentResultSet + ::getLong( sal_Int32 columnIndex ) + throw( SQLException, + RuntimeException ) +{ + XROW_GETXXX( getLong, sal_Int64 ); +} + +//virtual +float SAL_CALL CachedContentResultSet + ::getFloat( sal_Int32 columnIndex ) + throw( SQLException, + RuntimeException ) +{ + XROW_GETXXX( getFloat, float ); +} + +//virtual +double SAL_CALL CachedContentResultSet + ::getDouble( sal_Int32 columnIndex ) + throw( SQLException, + RuntimeException ) +{ + XROW_GETXXX( getDouble, double ); +} + +//virtual +Sequence< sal_Int8 > SAL_CALL CachedContentResultSet + ::getBytes( sal_Int32 columnIndex ) + throw( SQLException, + RuntimeException ) +{ + XROW_GETXXX( getBytes, Sequence< sal_Int8 > ); +} + +//virtual +Date SAL_CALL CachedContentResultSet + ::getDate( sal_Int32 columnIndex ) + throw( SQLException, + RuntimeException ) +{ + XROW_GETXXX( getDate, Date ); +} + +//virtual +Time SAL_CALL CachedContentResultSet + ::getTime( sal_Int32 columnIndex ) + throw( SQLException, + RuntimeException ) +{ + XROW_GETXXX( getTime, Time ); +} + +//virtual +DateTime SAL_CALL CachedContentResultSet + ::getTimestamp( sal_Int32 columnIndex ) + throw( SQLException, + RuntimeException ) +{ + XROW_GETXXX( getTimestamp, DateTime ); +} + +//virtual +Reference< com::sun::star::io::XInputStream > + SAL_CALL CachedContentResultSet + ::getBinaryStream( sal_Int32 columnIndex ) + throw( SQLException, + RuntimeException ) +{ + XROW_GETXXX( getBinaryStream, Reference< com::sun::star::io::XInputStream > ); +} + +//virtual +Reference< com::sun::star::io::XInputStream > + SAL_CALL CachedContentResultSet + ::getCharacterStream( sal_Int32 columnIndex ) + throw( SQLException, + RuntimeException ) +{ + XROW_GETXXX( getCharacterStream, Reference< com::sun::star::io::XInputStream > ); +} + +//virtual +Any SAL_CALL CachedContentResultSet + ::getObject( sal_Int32 columnIndex, + const Reference< + com::sun::star::container::XNameAccess >& typeMap ) + throw( SQLException, + RuntimeException ) +{ + //if you change this macro please pay attention to + //define XROW_GETXXX, where this is similar implemented + + ReacquireableGuard aGuard( m_aMutex ); + sal_Int32 nRow = m_nRow; + sal_Int32 nFetchSize = m_nFetchSize; + sal_Int32 nFetchDirection = m_nFetchDirection; + if( !m_aCache.hasRow( nRow ) ) + { + if( !m_aCache.hasCausedException( nRow ) ) + { + if( !m_xFetchProvider.is() ) + { + OSL_ENSURE( sal_False, "broadcaster was disposed already" ); + return Any(); + } + aGuard.clear(); + + impl_fetchData( nRow, nFetchSize, nFetchDirection ); + } + aGuard.reacquire(); + if( !m_aCache.hasRow( nRow ) ) + { + m_bLastReadWasFromCache = sal_False; + aGuard.clear(); + applyPositionToOrigin( nRow ); + impl_init_xRowOrigin(); + return m_xRowOrigin->getObject( columnIndex, typeMap ); + } + } + //@todo: pay attention to typeMap + const Any& rValue = m_aCache.getAny( nRow, columnIndex ); + Any aRet; + m_bLastReadWasFromCache = sal_True; + m_bLastCachedReadWasNull = !( rValue >>= aRet ); + return aRet; +} + +//virtual +Reference< XRef > SAL_CALL CachedContentResultSet + ::getRef( sal_Int32 columnIndex ) + throw( SQLException, + RuntimeException ) +{ + XROW_GETXXX( getRef, Reference< XRef > ); +} + +//virtual +Reference< XBlob > SAL_CALL CachedContentResultSet + ::getBlob( sal_Int32 columnIndex ) + throw( SQLException, + RuntimeException ) +{ + XROW_GETXXX( getBlob, Reference< XBlob > ); +} + +//virtual +Reference< XClob > SAL_CALL CachedContentResultSet + ::getClob( sal_Int32 columnIndex ) + throw( SQLException, + RuntimeException ) +{ + XROW_GETXXX( getClob, Reference< XClob > ); +} + +//virtual +Reference< XArray > SAL_CALL CachedContentResultSet + ::getArray( sal_Int32 columnIndex ) + throw( SQLException, + RuntimeException ) +{ + XROW_GETXXX( getArray, Reference< XArray > ); +} + +//----------------------------------------------------------------- +// Type Converter Support +//----------------------------------------------------------------- + +const Reference< XTypeConverter >& CachedContentResultSet::getTypeConverter() +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + if ( !m_bTriedToGetTypeConverter && !m_xTypeConverter.is() ) + { + m_bTriedToGetTypeConverter = sal_True; + m_xTypeConverter = Reference< XTypeConverter >( + m_xSMgr->createInstance( + OUString::createFromAscii( + "com.sun.star.script.Converter" ) ), + UNO_QUERY ); + + OSL_ENSURE( m_xTypeConverter.is(), + "PropertyValueSet::getTypeConverter() - " + "Service 'com.sun.star.script.Converter' n/a!" ); + } + return m_xTypeConverter; +} + +//-------------------------------------------------------------------------- +//-------------------------------------------------------------------------- +// class CachedContentResultSetFactory +//-------------------------------------------------------------------------- +//-------------------------------------------------------------------------- + +CachedContentResultSetFactory::CachedContentResultSetFactory( + const Reference< XMultiServiceFactory > & rSMgr ) +{ + m_xSMgr = rSMgr; +} + +CachedContentResultSetFactory::~CachedContentResultSetFactory() +{ +} + +//-------------------------------------------------------------------------- +// CachedContentResultSetFactory XInterface methods. +//-------------------------------------------------------------------------- + +XINTERFACE_IMPL_3( CachedContentResultSetFactory, + XTypeProvider, + XServiceInfo, + XCachedContentResultSetFactory ); + +//-------------------------------------------------------------------------- +// CachedContentResultSetFactory XTypeProvider methods. +//-------------------------------------------------------------------------- + +XTYPEPROVIDER_IMPL_3( CachedContentResultSetFactory, + XTypeProvider, + XServiceInfo, + XCachedContentResultSetFactory ); + +//-------------------------------------------------------------------------- +// CachedContentResultSetFactory XServiceInfo methods. +//-------------------------------------------------------------------------- + +XSERVICEINFO_IMPL_1( CachedContentResultSetFactory, + OUString::createFromAscii( + "com.sun.star.comp.ucb.CachedContentResultSetFactory" ), + OUString::createFromAscii( + CACHED_CONTENT_RESULTSET_FACTORY_NAME ) ); + +//-------------------------------------------------------------------------- +// Service factory implementation. +//-------------------------------------------------------------------------- + +ONE_INSTANCE_SERVICE_FACTORY_IMPL( CachedContentResultSetFactory ); + +//-------------------------------------------------------------------------- +// CachedContentResultSetFactory XCachedContentResultSetFactory methods. +//-------------------------------------------------------------------------- + + //virtual +Reference< XResultSet > SAL_CALL CachedContentResultSetFactory + ::createCachedContentResultSet( + const Reference< XResultSet > & xSource, + const Reference< XContentIdentifierMapping > & xMapping ) + throw( com::sun::star::uno::RuntimeException ) +{ + Reference< XResultSet > xRet; + xRet = new CachedContentResultSet( m_xSMgr, xSource, xMapping ); + return xRet; +} + diff --git a/ucb/source/cacher/cachedcontentresultset.hxx b/ucb/source/cacher/cachedcontentresultset.hxx new file mode 100644 index 000000000000..f2ab5dce2505 --- /dev/null +++ b/ucb/source/cacher/cachedcontentresultset.hxx @@ -0,0 +1,521 @@ +/************************************************************************* + * + * 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 _CACHED_CONTENT_RESULTSET_HXX +#define _CACHED_CONTENT_RESULTSET_HXX + +#include <contentresultsetwrapper.hxx> +#include <com/sun/star/lang/XTypeProvider.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/ucb/XFetchProvider.hpp> +#include <com/sun/star/ucb/XFetchProviderForContentAccess.hpp> +#include <com/sun/star/ucb/FetchResult.hpp> +#include <com/sun/star/ucb/XContentIdentifierMapping.hpp> +#include <com/sun/star/ucb/XCachedContentResultSetFactory.hpp> + +#define CACHED_CONTENT_RESULTSET_SERVICE_NAME "com.sun.star.ucb.CachedContentResultSet" +#define CACHED_CONTENT_RESULTSET_FACTORY_NAME "com.sun.star.ucb.CachedContentResultSetFactory" + +//========================================================================= + +namespace com { namespace sun { namespace star { namespace script { + class XTypeConverter; +} } } } + +class CCRS_PropertySetInfo; +class CachedContentResultSet + : public ContentResultSetWrapper + , public com::sun::star::lang::XTypeProvider + , public com::sun::star::lang::XServiceInfo +{ + //-------------------------------------------------------------------------- + // class CCRS_Cache + + class CCRS_Cache + { + private: + com::sun::star::ucb::FetchResult* m_pResult; + com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifierMapping > + m_xContentIdentifierMapping; + com::sun::star::uno::Sequence< sal_Bool >* m_pMappedReminder; + + private: + com::sun::star::uno::Any& SAL_CALL + getRowAny( sal_Int32 nRow ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + void SAL_CALL clear(); + + + void SAL_CALL remindMapped( sal_Int32 nRow ); + sal_Bool SAL_CALL isRowMapped( sal_Int32 nRow ); + void SAL_CALL clearMappedReminder(); + com::sun::star::uno::Sequence< sal_Bool >* SAL_CALL getMappedReminder(); + + public: + CCRS_Cache( const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifierMapping > & xMapping ); + ~CCRS_Cache(); + + void SAL_CALL loadData( + const com::sun::star::ucb::FetchResult& rResult ); + + sal_Bool SAL_CALL + hasRow( sal_Int32 nRow ); + + sal_Bool SAL_CALL + hasCausedException( sal_Int32 nRow ); + + sal_Int32 SAL_CALL + getMaxRow(); + + sal_Bool SAL_CALL + hasKnownLast(); + + //--- + const com::sun::star::uno::Any& SAL_CALL + getAny( sal_Int32 nRow, sal_Int32 nColumnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + const rtl::OUString& SAL_CALL + getContentIdentifierString( sal_Int32 nRow ) + throw( com::sun::star::uno::RuntimeException ); + + const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& SAL_CALL + getContentIdentifier( sal_Int32 nRow ) + throw( com::sun::star::uno::RuntimeException ); + + const com::sun::star::uno::Reference< + com::sun::star::ucb::XContent >& SAL_CALL + getContent( sal_Int32 nRow ) + throw( com::sun::star::uno::RuntimeException ); + }; + //----------------------------------------------------------------- + //members + + com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory > + m_xSMgr; + + //different Interfaces from Origin: + com::sun::star::uno::Reference< com::sun::star::ucb::XFetchProvider > + m_xFetchProvider; //XFetchProvider-interface from m_xOrigin + + com::sun::star::uno::Reference< com::sun::star::ucb::XFetchProviderForContentAccess > + m_xFetchProviderForContentAccess; //XFetchProviderForContentAccess-interface from m_xOrigin + + //my PropertySetInfo + com::sun::star::uno::Reference< com::sun::star::beans::XPropertySetInfo > + m_xMyPropertySetInfo;//holds m_pMyPropSetInfo alive + CCRS_PropertySetInfo* m_pMyPropSetInfo; + + + // + com::sun::star::uno::Reference< com::sun::star::ucb::XContentIdentifierMapping > + m_xContentIdentifierMapping;// can be used for remote optimized ContentAccess + + //some Properties and helping variables + sal_Int32 m_nRow; + sal_Bool m_bAfterLast; // TRUE, if m_nRow is after final count; can be TRUE without knowing the exact final count + + sal_Int32 m_nLastAppliedPos; + sal_Bool m_bAfterLastApplied; + + sal_Int32 m_nKnownCount; // count we know from the Origin + sal_Bool m_bFinalCount; // TRUE if the Origin has reached final count and we got that count in m_nKnownCount + + sal_Int32 m_nFetchSize; + sal_Int32 m_nFetchDirection; + + sal_Bool m_bLastReadWasFromCache; + sal_Bool m_bLastCachedReadWasNull; + + //cache: + CCRS_Cache m_aCache; + CCRS_Cache m_aCacheContentIdentifierString; + CCRS_Cache m_aCacheContentIdentifier; + CCRS_Cache m_aCacheContent; + + +private: + //----------------------------------------------------------------- + //helping XPropertySet methods. + virtual void SAL_CALL impl_initPropertySetInfo(); + + + //----------------------------------------------------------------- + sal_Bool SAL_CALL + applyPositionToOrigin( sal_Int32 nRow ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + void SAL_CALL + impl_fetchData( sal_Int32 nRow, sal_Int32 nCount + , sal_Int32 nFetchDirection ) + throw( com::sun::star::uno::RuntimeException ); + + sal_Bool SAL_CALL + impl_isKnownValidPosition( sal_Int32 nRow ); + + sal_Bool SAL_CALL + impl_isKnownInvalidPosition( sal_Int32 nRow ); + + void SAL_CALL + impl_changeRowCount( sal_Int32 nOld, sal_Int32 nNew ); + + void SAL_CALL + impl_changeIsRowCountFinal( sal_Bool bOld, sal_Bool bNew ); + +public: + CachedContentResultSet( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory > & + xSMgr, + const com::sun::star::uno::Reference< + com::sun::star::sdbc::XResultSet > & xOrigin, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifierMapping > & + xContentIdentifierMapping ); + + virtual ~CachedContentResultSet(); + + //----------------------------------------------------------------- + // XInterface inherited + //----------------------------------------------------------------- + XINTERFACE_DECL() + //----------------------------------------------------------------- + // XTypeProvider + //----------------------------------------------------------------- + XTYPEPROVIDER_DECL() + //----------------------------------------------------------------- + // XServiceInfo + //----------------------------------------------------------------- + XSERVICEINFO_NOFACTORY_DECL() + + //----------------------------------------------------------------- + // XPropertySet inherited + //----------------------------------------------------------------- + + virtual void SAL_CALL + setPropertyValue( const rtl::OUString& aPropertyName, + const com::sun::star::uno::Any& aValue ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::beans::PropertyVetoException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::uno::Any SAL_CALL + getPropertyValue( const rtl::OUString& PropertyName ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException ); + + //----------------------------------------------------------------- + // own inherited + //----------------------------------------------------------------- + virtual void SAL_CALL + impl_disposing( const com::sun::star::lang::EventObject& Source ) + throw( com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL + impl_propertyChange( const com::sun::star::beans::PropertyChangeEvent& evt ) + throw( com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL + impl_vetoableChange( const com::sun::star::beans::PropertyChangeEvent& aEvent ) + throw( com::sun::star::beans::PropertyVetoException, + com::sun::star::uno::RuntimeException ); + + //----------------------------------------------------------------- + // XContentAccess inherited + //----------------------------------------------------------------- + virtual rtl::OUString SAL_CALL + queryContentIdentifierString() + throw( com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier > SAL_CALL + queryContentIdentifier() + throw( com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::uno::Reference< + com::sun::star::ucb::XContent > SAL_CALL + queryContent() + throw( com::sun::star::uno::RuntimeException ); + + //----------------------------------------------------------------- + // XResultSet inherited + //----------------------------------------------------------------- + virtual sal_Bool SAL_CALL + next() + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL + isBeforeFirst() + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL + isAfterLast() + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL + isFirst() + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL + isLast() + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + beforeFirst() + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + afterLast() + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL + first() + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL + last() + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + virtual sal_Int32 SAL_CALL + getRow() + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL + absolute( sal_Int32 row ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL + relative( sal_Int32 rows ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL + previous() + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + refreshRow() + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL + rowUpdated() + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL + rowInserted() + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL + rowDeleted() + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + virtual com::sun::star::uno::Reference< + com::sun::star::uno::XInterface > SAL_CALL + getStatement() + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + //----------------------------------------------------------------- + // XRow inherited + //----------------------------------------------------------------- + virtual sal_Bool SAL_CALL + wasNull() + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + virtual rtl::OUString SAL_CALL + getString( sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + virtual sal_Bool SAL_CALL + getBoolean( sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + virtual sal_Int8 SAL_CALL + getByte( sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + virtual sal_Int16 SAL_CALL + getShort( sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + virtual sal_Int32 SAL_CALL + getInt( sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + virtual sal_Int64 SAL_CALL + getLong( sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + virtual float SAL_CALL + getFloat( sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + virtual double SAL_CALL + getDouble( sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL + getBytes( sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::util::Date SAL_CALL + getDate( sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::util::Time SAL_CALL + getTime( sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::util::DateTime SAL_CALL + getTimestamp( sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::uno::Reference< + com::sun::star::io::XInputStream > SAL_CALL + getBinaryStream( sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::uno::Reference< + com::sun::star::io::XInputStream > SAL_CALL + getCharacterStream( sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::uno::Any SAL_CALL + getObject( sal_Int32 columnIndex, + const com::sun::star::uno::Reference< + com::sun::star::container::XNameAccess >& typeMap ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::uno::Reference< + com::sun::star::sdbc::XRef > SAL_CALL + getRef( sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::uno::Reference< + com::sun::star::sdbc::XBlob > SAL_CALL + getBlob( sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::uno::Reference< + com::sun::star::sdbc::XClob > SAL_CALL + getClob( sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::uno::Reference< + com::sun::star::sdbc::XArray > SAL_CALL + getArray( sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + //----------------------------------------------------------------- + // Type Converter support + //----------------------------------------------------------------- + +private: + sal_Bool m_bTriedToGetTypeConverter; + com::sun::star::uno::Reference< + com::sun::star::script::XTypeConverter > m_xTypeConverter; + + const com::sun::star::uno::Reference< + com::sun::star::script::XTypeConverter >& getTypeConverter(); +}; + +//========================================================================= + +class CachedContentResultSetFactory + : public cppu::OWeakObject + , public com::sun::star::lang::XTypeProvider + , public com::sun::star::lang::XServiceInfo + , public com::sun::star::ucb::XCachedContentResultSetFactory +{ +protected: + com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory > m_xSMgr; + +public: + + CachedContentResultSetFactory( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory > & rSMgr); + + virtual ~CachedContentResultSetFactory(); + + //----------------------------------------------------------------- + // XInterface + XINTERFACE_DECL() + + //----------------------------------------------------------------- + // XTypeProvider + XTYPEPROVIDER_DECL() + + //----------------------------------------------------------------- + // XServiceInfo + XSERVICEINFO_DECL() + + //----------------------------------------------------------------- + // XCachedContentResultSetFactory + + virtual com::sun::star::uno::Reference< + com::sun::star::sdbc::XResultSet > SAL_CALL + createCachedContentResultSet( + const com::sun::star::uno::Reference< + com::sun::star::sdbc::XResultSet > & xSource, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifierMapping > & xMapping ) + throw( com::sun::star::uno::RuntimeException ); +}; + +#endif + diff --git a/ucb/source/cacher/cachedcontentresultsetstub.cxx b/ucb/source/cacher/cachedcontentresultsetstub.cxx new file mode 100644 index 000000000000..cb0685a020f5 --- /dev/null +++ b/ucb/source/cacher/cachedcontentresultsetstub.cxx @@ -0,0 +1,631 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +#include <cachedcontentresultsetstub.hxx> +#include <com/sun/star/sdbc/FetchDirection.hpp> +#include <com/sun/star/ucb/FetchError.hpp> +#include <osl/diagnose.h> + +using namespace com::sun::star::beans; +using namespace com::sun::star::lang; +using namespace com::sun::star::sdbc; +using namespace com::sun::star::ucb; +using namespace com::sun::star::uno; +using namespace com::sun::star::util; +using namespace cppu; +using namespace rtl; + +CachedContentResultSetStub::CachedContentResultSetStub( Reference< XResultSet > xOrigin ) + : ContentResultSetWrapper( xOrigin ) + , m_nColumnCount( 0 ) + , m_bColumnCountCached( sal_False ) + , m_bNeedToPropagateFetchSize( sal_True ) + , m_bFirstFetchSizePropagationDone( sal_False ) + , m_nLastFetchSize( 1 )//this value is not important at all + , m_bLastFetchDirection( sal_True )//this value is not important at all + , m_aPropertyNameForFetchSize( OUString::createFromAscii( "FetchSize" ) ) + , m_aPropertyNameForFetchDirection( OUString::createFromAscii( "FetchDirection" ) ) +{ + impl_init(); +} + +CachedContentResultSetStub::~CachedContentResultSetStub() +{ + impl_deinit(); +} + +//-------------------------------------------------------------------------- +// XInterface methods. +//-------------------------------------------------------------------------- +XINTERFACE_COMMON_IMPL( CachedContentResultSetStub ) + +Any SAL_CALL CachedContentResultSetStub + ::queryInterface( const Type& rType ) + throw ( RuntimeException ) +{ + //list all interfaces inclusive baseclasses of interfaces + + Any aRet = ContentResultSetWrapper::queryInterface( rType ); + if( aRet.hasValue() ) + return aRet; + + aRet = cppu::queryInterface( rType + , static_cast< XTypeProvider* >( this ) + , static_cast< XServiceInfo* >( this ) + , static_cast< XFetchProvider* >( this ) + , static_cast< XFetchProviderForContentAccess* >( this ) + ); + + return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ); +} + +//-------------------------------------------------------------------------- +// own methods. ( inherited ) +//-------------------------------------------------------------------------- + +//virtual +void SAL_CALL CachedContentResultSetStub + ::impl_propertyChange( const PropertyChangeEvent& rEvt ) + throw( RuntimeException ) +{ + impl_EnsureNotDisposed(); + + //don't notify events on fetchsize and fetchdirection to the above CachedContentResultSet + //because it will ignore them anyway and we can save this remote calls + if( rEvt.PropertyName == m_aPropertyNameForFetchSize + || rEvt.PropertyName == m_aPropertyNameForFetchDirection ) + return; + + PropertyChangeEvent aEvt( rEvt ); + aEvt.Source = static_cast< XPropertySet * >( this ); + aEvt.Further = sal_False; + + impl_notifyPropertyChangeListeners( aEvt ); +} + + +//virtual +void SAL_CALL CachedContentResultSetStub + ::impl_vetoableChange( const PropertyChangeEvent& rEvt ) + throw( PropertyVetoException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + + //don't notify events on fetchsize and fetchdirection to the above CachedContentResultSet + //because it will ignore them anyway and we can save this remote calls + if( rEvt.PropertyName == m_aPropertyNameForFetchSize + || rEvt.PropertyName == m_aPropertyNameForFetchDirection ) + return; + + PropertyChangeEvent aEvt( rEvt ); + aEvt.Source = static_cast< XPropertySet * >( this ); + aEvt.Further = sal_False; + + impl_notifyVetoableChangeListeners( aEvt ); +} + +//-------------------------------------------------------------------------- +// XTypeProvider methods. +//-------------------------------------------------------------------------- + +XTYPEPROVIDER_COMMON_IMPL( CachedContentResultSetStub ) +//list all interfaces exclusive baseclasses +Sequence< Type > SAL_CALL CachedContentResultSetStub + ::getTypes() + throw( RuntimeException ) +{ + static Sequence< Type >* pTypes = NULL; + if( !pTypes ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + if( !pTypes ) + { + pTypes = new Sequence< Type >(13); + (*pTypes)[0] = CPPU_TYPE_REF( XTypeProvider ); + (*pTypes)[1] = CPPU_TYPE_REF( XServiceInfo ); + (*pTypes)[2] = CPPU_TYPE_REF( XComponent ); + (*pTypes)[3] = CPPU_TYPE_REF( XCloseable ); + (*pTypes)[4] = CPPU_TYPE_REF( XResultSetMetaDataSupplier ); + (*pTypes)[5] = CPPU_TYPE_REF( XPropertySet ); + (*pTypes)[6] = CPPU_TYPE_REF( XPropertyChangeListener ); + (*pTypes)[7] = CPPU_TYPE_REF( XVetoableChangeListener ); + (*pTypes)[8] = CPPU_TYPE_REF( XResultSet ); + (*pTypes)[9] = CPPU_TYPE_REF( XContentAccess ); + (*pTypes)[10] = CPPU_TYPE_REF( XRow ); + (*pTypes)[11] = CPPU_TYPE_REF( XFetchProvider ); + (*pTypes)[12] = CPPU_TYPE_REF( XFetchProviderForContentAccess ); + } + } + return *pTypes; + /* + static cppu::OTypeCollection * pCollection = 0; + if (!pCollection) + { + osl::MutexGuard aGuard(osl::Mutex::getGlobalMutex()); + if (!pCollection) + { + static cppu::OTypeCollection + aTheCollection( + getCppuType( + static_cast< Reference< XTypeProvider > + const * >( + 0)), + getCppuType( + static_cast< Reference< XServiceInfo > + const * >( + 0)), + getCppuType( + static_cast< Reference< XComponent > + const * >( + 0)), + getCppuType( + static_cast< Reference< XCloseable > + const * >( + 0)), + getCppuType( + static_cast< Reference< XResultSetMetaDataSupplier > + const * >( + 0)), + getCppuType( + static_cast< Reference< XPropertySet > + const * >( + 0)), + getCppuType( + static_cast< Reference< XPropertyChangeListener > + const * >( + 0)), + getCppuType( + static_cast< Reference< XVetoableChangeListener > + const * >( + 0)), + getCppuType( + static_cast< Reference< XResultSet > + const * >( + 0)), + getCppuType( + static_cast< Reference< XContentAccess > + const * >( + 0)), + getCppuType( + static_cast< Reference< XRow > + const * >( + 0)), + getCppuType( + static_cast< Reference< XFetchProvider > + const * >( + 0)), + getCppuType( + static_cast< Reference< XFetchProviderForContentAccess > + const * >( + 0)) + ); + pCollection = &aTheCollection; + } + } + return pCollection->getTypes(); + */ +} + +//-------------------------------------------------------------------------- +// XServiceInfo methods. +//-------------------------------------------------------------------------- + +XSERVICEINFO_NOFACTORY_IMPL_1( CachedContentResultSetStub, + OUString::createFromAscii( + "com.sun.star.comp.ucb.CachedContentResultSetStub" ), + OUString::createFromAscii( + CACHED_CRS_STUB_SERVICE_NAME ) ); + +//----------------------------------------------------------------- +// XFetchProvider methods. +//----------------------------------------------------------------- + +#define FETCH_XXX( impl_loadRow, loadInterface ) \ +impl_EnsureNotDisposed(); \ +if( !m_xResultSetOrigin.is() ) \ +{ \ + OSL_ENSURE( sal_False, "broadcaster was disposed already" ); \ + throw RuntimeException(); \ +} \ +impl_propagateFetchSizeAndDirection( nRowCount, bDirection ); \ +FetchResult aRet; \ +aRet.StartIndex = nRowStartPosition; \ +aRet.Orientation = bDirection; \ +aRet.FetchError = FetchError::SUCCESS; /*ENDOFDATA, EXCEPTION*/ \ +sal_Int32 nOldOriginal_Pos = m_xResultSetOrigin->getRow(); \ +if( impl_isForwardOnly() ) \ +{ \ + if( nOldOriginal_Pos != nRowStartPosition ) \ + { \ + /*@todo*/ \ + aRet.FetchError = FetchError::EXCEPTION; \ + return aRet; \ + } \ + if( nRowCount != 1 ) \ + aRet.FetchError = FetchError::EXCEPTION; \ + \ + aRet.Rows.realloc( 1 ); \ + \ + try \ + { \ + impl_loadRow( aRet.Rows[0], loadInterface ); \ + } \ + catch( SQLException& ) \ + { \ + aRet.Rows.realloc( 0 ); \ + aRet.FetchError = FetchError::EXCEPTION; \ + return aRet; \ + } \ + return aRet; \ +} \ +aRet.Rows.realloc( nRowCount ); \ +sal_Bool bOldOriginal_AfterLast = sal_False; \ +if( !nOldOriginal_Pos ) \ + bOldOriginal_AfterLast = m_xResultSetOrigin->isAfterLast(); \ +sal_Int32 nN = 1; \ +sal_Bool bValidNewPos = sal_False; \ +try \ +{ \ + try \ + { \ + /*if( nOldOriginal_Pos != nRowStartPosition )*/ \ + bValidNewPos = m_xResultSetOrigin->absolute( nRowStartPosition ); \ + } \ + catch( SQLException& ) \ + { \ + aRet.Rows.realloc( 0 ); \ + aRet.FetchError = FetchError::EXCEPTION; \ + return aRet; \ + } \ + if( !bValidNewPos ) \ + { \ + aRet.Rows.realloc( 0 ); \ + aRet.FetchError = FetchError::EXCEPTION; \ + \ + /*restore old position*/ \ + if( nOldOriginal_Pos ) \ + m_xResultSetOrigin->absolute( nOldOriginal_Pos ); \ + else if( bOldOriginal_AfterLast ) \ + m_xResultSetOrigin->afterLast(); \ + else \ + m_xResultSetOrigin->beforeFirst(); \ + \ + return aRet; \ + } \ + for( ; nN <= nRowCount; ) \ + { \ + impl_loadRow( aRet.Rows[nN-1], loadInterface ); \ + nN++; \ + if( nN <= nRowCount ) \ + { \ + if( bDirection ) \ + { \ + if( !m_xResultSetOrigin->next() ) \ + { \ + aRet.Rows.realloc( nN-1 ); \ + aRet.FetchError = FetchError::ENDOFDATA; \ + break; \ + } \ + } \ + else \ + { \ + if( !m_xResultSetOrigin->previous() ) \ + { \ + aRet.Rows.realloc( nN-1 ); \ + aRet.FetchError = FetchError::ENDOFDATA; \ + break; \ + } \ + } \ + } \ + } \ +} \ +catch( SQLException& ) \ +{ \ + aRet.Rows.realloc( nN-1 ); \ + aRet.FetchError = FetchError::EXCEPTION; \ +} \ +/*restore old position*/ \ +if( nOldOriginal_Pos ) \ + m_xResultSetOrigin->absolute( nOldOriginal_Pos ); \ +else if( bOldOriginal_AfterLast ) \ + m_xResultSetOrigin->afterLast(); \ +else \ + m_xResultSetOrigin->beforeFirst(); \ +return aRet; + +FetchResult SAL_CALL CachedContentResultSetStub + ::fetch( sal_Int32 nRowStartPosition + , sal_Int32 nRowCount, sal_Bool bDirection ) + throw( RuntimeException ) +{ + impl_init_xRowOrigin(); + FETCH_XXX( impl_getCurrentRowContent, m_xRowOrigin ); +} + +sal_Int32 SAL_CALL CachedContentResultSetStub + ::impl_getColumnCount() +{ + sal_Int32 nCount; + sal_Bool bCached; + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + nCount = m_nColumnCount; + bCached = m_bColumnCountCached; + } + if( !bCached ) + { + try + { + Reference< XResultSetMetaData > xMetaData = getMetaData(); + if( xMetaData.is() ) + nCount = xMetaData->getColumnCount(); + } + catch( SQLException& ) + { + OSL_ENSURE( sal_False, "couldn't determine the column count" ); + nCount = 0; + } + } + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + m_nColumnCount = nCount; + m_bColumnCountCached = sal_True; + return m_nColumnCount; +} + +void SAL_CALL CachedContentResultSetStub + ::impl_getCurrentRowContent( Any& rRowContent + , Reference< XRow > xRow ) + throw ( SQLException, RuntimeException ) +{ + sal_Int32 nCount = impl_getColumnCount(); + + Sequence< Any > aContent( nCount ); + for( sal_Int32 nN = 1; nN <= nCount; nN++ ) + { + aContent[nN-1] = xRow->getObject( nN, NULL ); + } + + rRowContent <<= aContent; +} + +void SAL_CALL CachedContentResultSetStub + ::impl_propagateFetchSizeAndDirection( sal_Int32 nFetchSize, sal_Bool bFetchDirection ) + throw ( RuntimeException ) +{ + //this is done only for the case, that there is another CachedContentResultSet in the chain of underlying ResulSets + + //we do not propagate the property 'FetchSize' or 'FetchDirection' via 'setPropertyValue' from the above CachedContentResultSet to save remote calls + + //if the underlying ResultSet has a property FetchSize and FetchDirection, + //we will set these properties, if the new given parameters are different from the last ones + + if( !m_bNeedToPropagateFetchSize ) + return; + + sal_Bool bNeedAction; + sal_Int32 nLastSize; + sal_Bool bLastDirection; + sal_Bool bFirstPropagationDone; + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + bNeedAction = m_bNeedToPropagateFetchSize; + nLastSize = m_nLastFetchSize; + bLastDirection = m_bLastFetchDirection; + bFirstPropagationDone = m_bFirstFetchSizePropagationDone; + } + if( bNeedAction ) + { + if( nLastSize == nFetchSize + && bLastDirection == bFetchDirection + && bFirstPropagationDone == sal_True ) + return; + + if(!bFirstPropagationDone) + { + //check wether the properties 'FetchSize' and 'FetchDirection' do exist + + Reference< XPropertySetInfo > xPropertySetInfo = getPropertySetInfo(); + sal_Bool bHasSize = xPropertySetInfo->hasPropertyByName( m_aPropertyNameForFetchSize ); + sal_Bool bHasDirection = xPropertySetInfo->hasPropertyByName( m_aPropertyNameForFetchDirection ); + + if(!bHasSize || !bHasDirection) + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + m_bNeedToPropagateFetchSize = sal_False; + return; + } + } + + sal_Bool bSetSize = ( nLastSize !=nFetchSize ) || !bFirstPropagationDone; + sal_Bool bSetDirection = ( bLastDirection !=bFetchDirection ) || !bFirstPropagationDone; + + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + m_bFirstFetchSizePropagationDone = sal_True; + m_nLastFetchSize = nFetchSize; + m_bLastFetchDirection = bFetchDirection; + } + + if( bSetSize ) + { + Any aValue; + aValue <<= nFetchSize; + try + { + setPropertyValue( m_aPropertyNameForFetchSize, aValue ); + } + catch( com::sun::star::uno::Exception& ) {} + } + if( bSetDirection ) + { + sal_Int32 nFetchDirection = FetchDirection::FORWARD; + if( !bFetchDirection ) + nFetchDirection = FetchDirection::REVERSE; + Any aValue; + aValue <<= nFetchDirection; + try + { + setPropertyValue( m_aPropertyNameForFetchDirection, aValue ); + } + catch( com::sun::star::uno::Exception& ) {} + } + + } +} + +//----------------------------------------------------------------- +// XFetchProviderForContentAccess methods. +//----------------------------------------------------------------- + +void SAL_CALL CachedContentResultSetStub + ::impl_getCurrentContentIdentifierString( Any& rAny + , Reference< XContentAccess > xContentAccess ) + throw ( RuntimeException ) +{ + rAny <<= xContentAccess->queryContentIdentifierString(); +} + +void SAL_CALL CachedContentResultSetStub + ::impl_getCurrentContentIdentifier( Any& rAny + , Reference< XContentAccess > xContentAccess ) + throw ( RuntimeException ) +{ + rAny <<= xContentAccess->queryContentIdentifier(); +} + +void SAL_CALL CachedContentResultSetStub + ::impl_getCurrentContent( Any& rAny + , Reference< XContentAccess > xContentAccess ) + throw ( RuntimeException ) +{ + rAny <<= xContentAccess->queryContent(); +} + +//virtual +FetchResult SAL_CALL CachedContentResultSetStub + ::fetchContentIdentifierStrings( sal_Int32 nRowStartPosition + , sal_Int32 nRowCount, sal_Bool bDirection ) + throw( com::sun::star::uno::RuntimeException ) +{ + impl_init_xContentAccessOrigin(); + FETCH_XXX( impl_getCurrentContentIdentifierString, m_xContentAccessOrigin ); +} + +//virtual +FetchResult SAL_CALL CachedContentResultSetStub + ::fetchContentIdentifiers( sal_Int32 nRowStartPosition + , sal_Int32 nRowCount, sal_Bool bDirection ) + throw( com::sun::star::uno::RuntimeException ) +{ + impl_init_xContentAccessOrigin(); + FETCH_XXX( impl_getCurrentContentIdentifier, m_xContentAccessOrigin ); +} + +//virtual +FetchResult SAL_CALL CachedContentResultSetStub + ::fetchContents( sal_Int32 nRowStartPosition + , sal_Int32 nRowCount, sal_Bool bDirection ) + throw( com::sun::star::uno::RuntimeException ) +{ + impl_init_xContentAccessOrigin(); + FETCH_XXX( impl_getCurrentContent, m_xContentAccessOrigin ); +} + +//-------------------------------------------------------------------------- +//-------------------------------------------------------------------------- +// class CachedContentResultSetStubFactory +//-------------------------------------------------------------------------- +//-------------------------------------------------------------------------- + +CachedContentResultSetStubFactory::CachedContentResultSetStubFactory( + const Reference< XMultiServiceFactory > & rSMgr ) +{ + m_xSMgr = rSMgr; +} + +CachedContentResultSetStubFactory::~CachedContentResultSetStubFactory() +{ +} + +//-------------------------------------------------------------------------- +// CachedContentResultSetStubFactory XInterface methods. +//-------------------------------------------------------------------------- + +XINTERFACE_IMPL_3( CachedContentResultSetStubFactory, + XTypeProvider, + XServiceInfo, + XCachedContentResultSetStubFactory ); + +//-------------------------------------------------------------------------- +// CachedContentResultSetStubFactory XTypeProvider methods. +//-------------------------------------------------------------------------- + +XTYPEPROVIDER_IMPL_3( CachedContentResultSetStubFactory, + XTypeProvider, + XServiceInfo, + XCachedContentResultSetStubFactory ); + +//-------------------------------------------------------------------------- +// CachedContentResultSetStubFactory XServiceInfo methods. +//-------------------------------------------------------------------------- + +XSERVICEINFO_IMPL_1( CachedContentResultSetStubFactory, + OUString::createFromAscii( + "com.sun.star.comp.ucb.CachedContentResultSetStubFactory" ), + OUString::createFromAscii( + CACHED_CRS_STUB_FACTORY_NAME ) ); + +//-------------------------------------------------------------------------- +// Service factory implementation. +//-------------------------------------------------------------------------- + +ONE_INSTANCE_SERVICE_FACTORY_IMPL( CachedContentResultSetStubFactory ); + +//-------------------------------------------------------------------------- +// CachedContentResultSetStubFactory XCachedContentResultSetStubFactory methods. +//-------------------------------------------------------------------------- + + //virtual +Reference< XResultSet > SAL_CALL CachedContentResultSetStubFactory + ::createCachedContentResultSetStub( + const Reference< XResultSet > & xSource ) + throw( RuntimeException ) +{ + if( xSource.is() ) + { + Reference< XResultSet > xRet; + xRet = new CachedContentResultSetStub( xSource ); + return xRet; + } + return NULL; +} + + diff --git a/ucb/source/cacher/cachedcontentresultsetstub.hxx b/ucb/source/cacher/cachedcontentresultsetstub.hxx new file mode 100644 index 000000000000..59394e232dde --- /dev/null +++ b/ucb/source/cacher/cachedcontentresultsetstub.hxx @@ -0,0 +1,202 @@ +/************************************************************************* + * + * 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 _CACHED_CONTENT_RESULTSET_STUB_HXX +#define _CACHED_CONTENT_RESULTSET_STUB_HXX + +#include <contentresultsetwrapper.hxx> +#include <com/sun/star/lang/XTypeProvider.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/ucb/XFetchProvider.hpp> +#include <com/sun/star/ucb/XFetchProviderForContentAccess.hpp> +#include <com/sun/star/ucb/XCachedContentResultSetStubFactory.hpp> + +#define CACHED_CRS_STUB_SERVICE_NAME "com.sun.star.ucb.CachedContentResultSetStub" +#define CACHED_CRS_STUB_FACTORY_NAME "com.sun.star.ucb.CachedContentResultSetStubFactory" + +//========================================================================= + +class CachedContentResultSetStub + : public ContentResultSetWrapper + , public com::sun::star::lang::XTypeProvider + , public com::sun::star::lang::XServiceInfo + , public com::sun::star::ucb::XFetchProvider + , public com::sun::star::ucb::XFetchProviderForContentAccess +{ +private: + sal_Int32 m_nColumnCount; + sal_Bool m_bColumnCountCached; + + //members to propagate fetchsize and direction: + sal_Bool m_bNeedToPropagateFetchSize; + sal_Bool m_bFirstFetchSizePropagationDone; + sal_Int32 m_nLastFetchSize; + sal_Bool m_bLastFetchDirection; + const rtl::OUString m_aPropertyNameForFetchSize; + const rtl::OUString m_aPropertyNameForFetchDirection; + + + void SAL_CALL + impl_getCurrentRowContent( + com::sun::star::uno::Any& rRowContent, + com::sun::star::uno::Reference< + com::sun::star::sdbc::XRow > xRow ) + throw ( com::sun::star::sdbc::SQLException + , com::sun::star::uno::RuntimeException ); + + sal_Int32 SAL_CALL + impl_getColumnCount(); + + void SAL_CALL + impl_getCurrentContentIdentifierString( + com::sun::star::uno::Any& rAny + , com::sun::star::uno::Reference< + com::sun::star::ucb::XContentAccess > xContentAccess ) + throw ( com::sun::star::uno::RuntimeException ); + + void SAL_CALL + impl_getCurrentContentIdentifier( + com::sun::star::uno::Any& rAny + , com::sun::star::uno::Reference< + com::sun::star::ucb::XContentAccess > xContentAccess ) + throw ( com::sun::star::uno::RuntimeException ); + + void SAL_CALL + impl_getCurrentContent( + com::sun::star::uno::Any& rAny + , com::sun::star::uno::Reference< + com::sun::star::ucb::XContentAccess > xContentAccess ) + throw ( com::sun::star::uno::RuntimeException ); + + void SAL_CALL + impl_propagateFetchSizeAndDirection( sal_Int32 nFetchSize, sal_Bool bFetchDirection ) + throw ( com::sun::star::uno::RuntimeException ); + +public: + CachedContentResultSetStub( com::sun::star::uno::Reference< + com::sun::star::sdbc::XResultSet > xOrigin ); + + virtual ~CachedContentResultSetStub(); + + + //----------------------------------------------------------------- + // XInterface inherited + //----------------------------------------------------------------- + XINTERFACE_DECL() + //----------------------------------------------------------------- + // own inherited + //----------------------------------------------------------------- + virtual void SAL_CALL + impl_propertyChange( const com::sun::star::beans::PropertyChangeEvent& evt ) + throw( com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL + impl_vetoableChange( const com::sun::star::beans::PropertyChangeEvent& aEvent ) + throw( com::sun::star::beans::PropertyVetoException, + com::sun::star::uno::RuntimeException ); + //----------------------------------------------------------------- + // XTypeProvider + //----------------------------------------------------------------- + XTYPEPROVIDER_DECL() + //----------------------------------------------------------------- + // XServiceInfo + //----------------------------------------------------------------- + XSERVICEINFO_NOFACTORY_DECL() + + //----------------------------------------------------------------- + // XFetchProvider + //----------------------------------------------------------------- + + virtual com::sun::star::ucb::FetchResult SAL_CALL + fetch( sal_Int32 nRowStartPosition + , sal_Int32 nRowCount, sal_Bool bDirection ) + throw( com::sun::star::uno::RuntimeException ); + + //----------------------------------------------------------------- + // XFetchProviderForContentAccess + //----------------------------------------------------------------- + virtual com::sun::star::ucb::FetchResult SAL_CALL + fetchContentIdentifierStrings( sal_Int32 nRowStartPosition + , sal_Int32 nRowCount, sal_Bool bDirection ) + throw( com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::ucb::FetchResult SAL_CALL + fetchContentIdentifiers( sal_Int32 nRowStartPosition + , sal_Int32 nRowCount, sal_Bool bDirection ) + throw( com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::ucb::FetchResult SAL_CALL + fetchContents( sal_Int32 nRowStartPosition + , sal_Int32 nRowCount, sal_Bool bDirection ) + throw( com::sun::star::uno::RuntimeException ); +}; + +//========================================================================= + +class CachedContentResultSetStubFactory + : public cppu::OWeakObject + , public com::sun::star::lang::XTypeProvider + , public com::sun::star::lang::XServiceInfo + , public com::sun::star::ucb::XCachedContentResultSetStubFactory +{ +protected: + com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory > m_xSMgr; + +public: + + CachedContentResultSetStubFactory( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory > & rSMgr); + + virtual ~CachedContentResultSetStubFactory(); + + //----------------------------------------------------------------- + // XInterface + XINTERFACE_DECL() + + //----------------------------------------------------------------- + // XTypeProvider + XTYPEPROVIDER_DECL() + + //----------------------------------------------------------------- + // XServiceInfo + XSERVICEINFO_DECL() + + //----------------------------------------------------------------- + // XCachedContentResultSetStubFactory + + virtual com::sun::star::uno::Reference< + com::sun::star::sdbc::XResultSet > SAL_CALL + createCachedContentResultSetStub( + const com::sun::star::uno::Reference< + com::sun::star::sdbc::XResultSet > & xSource ) + throw( com::sun::star::uno::RuntimeException ); +}; + +#endif + diff --git a/ucb/source/cacher/cacheddynamicresultset.cxx b/ucb/source/cacher/cacheddynamicresultset.cxx new file mode 100644 index 000000000000..ad7bf9f9686c --- /dev/null +++ b/ucb/source/cacher/cacheddynamicresultset.cxx @@ -0,0 +1,206 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +#include <cacheddynamicresultset.hxx> +#include <com/sun/star/sdbc/XResultSet.hpp> +#include <cachedcontentresultset.hxx> +#include <osl/diagnose.h> + +using namespace com::sun::star::lang; +using namespace com::sun::star::sdbc; +using namespace com::sun::star::ucb; +using namespace com::sun::star::uno; +using namespace rtl; + +CachedDynamicResultSet::CachedDynamicResultSet( + Reference< XDynamicResultSet > xOrigin + , const Reference< XContentIdentifierMapping > & xContentMapping + , const Reference< XMultiServiceFactory > & xSMgr ) + : DynamicResultSetWrapper( xOrigin, xSMgr ) + , m_xContentIdentifierMapping( xContentMapping ) +{ + impl_init(); +} + +CachedDynamicResultSet::~CachedDynamicResultSet() +{ + impl_deinit(); +} + +//virtual +void SAL_CALL CachedDynamicResultSet + ::impl_InitResultSetOne( const Reference< XResultSet >& xResultSet ) +{ + DynamicResultSetWrapper::impl_InitResultSetOne( xResultSet ); + OSL_ENSURE( m_xSourceResultOne.is(), "need source resultset" ); + + Reference< XResultSet > xCache( + new CachedContentResultSet( m_xSMgr, m_xSourceResultOne, m_xContentIdentifierMapping ) ); + + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + m_xMyResultOne = xCache; +} + +//virtual +void SAL_CALL CachedDynamicResultSet + ::impl_InitResultSetTwo( const Reference< XResultSet >& xResultSet ) +{ + DynamicResultSetWrapper::impl_InitResultSetTwo( xResultSet ); + OSL_ENSURE( m_xSourceResultTwo.is(), "need source resultset" ); + + Reference< XResultSet > xCache( + new CachedContentResultSet( m_xSMgr, m_xSourceResultTwo, m_xContentIdentifierMapping ) ); + + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + m_xMyResultTwo = xCache; +} + +//-------------------------------------------------------------------------- +// XInterface methods. +//-------------------------------------------------------------------------- +XINTERFACE_COMMON_IMPL( CachedDynamicResultSet ) + +Any SAL_CALL CachedDynamicResultSet + ::queryInterface( const Type& rType ) + throw ( RuntimeException ) +{ + //list all interfaces inclusive baseclasses of interfaces + + Any aRet = DynamicResultSetWrapper::queryInterface( rType ); + if( aRet.hasValue() ) + return aRet; + + aRet = cppu::queryInterface( rType, + static_cast< XTypeProvider* >( this ) + , static_cast< XServiceInfo* >( this ) + ); + return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ); +} + +//-------------------------------------------------------------------------- +// XTypeProvider methods. +//-------------------------------------------------------------------------- +//list all interfaces exclusive baseclasses +XTYPEPROVIDER_IMPL_4( CachedDynamicResultSet + , XTypeProvider + , XServiceInfo + , XDynamicResultSet + , XSourceInitialization + ); + +//-------------------------------------------------------------------------- +// XServiceInfo methods. +//-------------------------------------------------------------------------- + +XSERVICEINFO_NOFACTORY_IMPL_1( CachedDynamicResultSet, + OUString::createFromAscii( + "com.sun.star.comp.ucb.CachedDynamicResultSet" ), + OUString::createFromAscii( + CACHED_DRS_SERVICE_NAME ) ); + +//-------------------------------------------------------------------------- +// own methds. ( inherited ) +//-------------------------------------------------------------------------- +//virtual +void SAL_CALL CachedDynamicResultSet + ::impl_disposing( const EventObject& Source ) + throw( RuntimeException ) +{ + DynamicResultSetWrapper::impl_disposing( Source ); + m_xContentIdentifierMapping.clear(); +} + +//-------------------------------------------------------------------------- +//-------------------------------------------------------------------------- +// class CachedDynamicResultSetFactory +//-------------------------------------------------------------------------- +//-------------------------------------------------------------------------- + +CachedDynamicResultSetFactory::CachedDynamicResultSetFactory( + const Reference< XMultiServiceFactory > & rSMgr ) +{ + m_xSMgr = rSMgr; +} + +CachedDynamicResultSetFactory::~CachedDynamicResultSetFactory() +{ +} + +//-------------------------------------------------------------------------- +// CachedDynamicResultSetFactory XInterface methods. +//-------------------------------------------------------------------------- + +XINTERFACE_IMPL_3( CachedDynamicResultSetFactory, + XTypeProvider, + XServiceInfo, + XCachedDynamicResultSetFactory ); + +//-------------------------------------------------------------------------- +// CachedDynamicResultSetFactory XTypeProvider methods. +//-------------------------------------------------------------------------- + +XTYPEPROVIDER_IMPL_3( CachedDynamicResultSetFactory, + XTypeProvider, + XServiceInfo, + XCachedDynamicResultSetFactory ); + +//-------------------------------------------------------------------------- +// CachedDynamicResultSetFactory XServiceInfo methods. +//-------------------------------------------------------------------------- + +XSERVICEINFO_IMPL_1( CachedDynamicResultSetFactory, + OUString::createFromAscii( + "com.sun.star.comp.ucb.CachedDynamicResultSetFactory" ), + OUString::createFromAscii( + CACHED_DRS_FACTORY_NAME ) ); + +//-------------------------------------------------------------------------- +// Service factory implementation. +//-------------------------------------------------------------------------- + +ONE_INSTANCE_SERVICE_FACTORY_IMPL( CachedDynamicResultSetFactory ); + +//-------------------------------------------------------------------------- +// CachedDynamicResultSetFactory XCachedDynamicResultSetFactory methods. +//-------------------------------------------------------------------------- + +//virtual +Reference< XDynamicResultSet > SAL_CALL CachedDynamicResultSetFactory + ::createCachedDynamicResultSet( + const Reference< XDynamicResultSet > & SourceStub + , const Reference< XContentIdentifierMapping > & ContentIdentifierMapping ) + throw( RuntimeException ) +{ + Reference< XDynamicResultSet > xRet; + xRet = new CachedDynamicResultSet( SourceStub, ContentIdentifierMapping, m_xSMgr ); + return xRet; +} + + diff --git a/ucb/source/cacher/cacheddynamicresultset.hxx b/ucb/source/cacher/cacheddynamicresultset.hxx new file mode 100644 index 000000000000..ba57238e47c0 --- /dev/null +++ b/ucb/source/cacher/cacheddynamicresultset.hxx @@ -0,0 +1,137 @@ +/************************************************************************* + * + * 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 _CACHED_DYNAMIC_RESULTSET_HXX +#define _CACHED_DYNAMIC_RESULTSET_HXX + +#include <dynamicresultsetwrapper.hxx> +#include <com/sun/star/ucb/XContentIdentifierMapping.hpp> +#include <com/sun/star/ucb/XCachedDynamicResultSetFactory.hpp> + +#define CACHED_DRS_SERVICE_NAME "com.sun.star.ucb.CachedDynamicResultSet" +#define CACHED_DRS_FACTORY_NAME "com.sun.star.ucb.CachedDynamicResultSetFactory" + +//========================================================================= + +class CachedDynamicResultSet + : public DynamicResultSetWrapper + , public com::sun::star::lang::XTypeProvider + , public com::sun::star::lang::XServiceInfo +{ + com::sun::star::uno::Reference< com::sun::star::ucb::XContentIdentifierMapping > + m_xContentIdentifierMapping; + +protected: + virtual void SAL_CALL + impl_InitResultSetOne( const com::sun::star::uno::Reference< + com::sun::star::sdbc::XResultSet >& xResultSet ); + virtual void SAL_CALL + impl_InitResultSetTwo( const com::sun::star::uno::Reference< + com::sun::star::sdbc::XResultSet >& xResultSet ); + +public: + CachedDynamicResultSet( com::sun::star::uno::Reference< + com::sun::star::ucb::XDynamicResultSet > xOrigin + , const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifierMapping > & xContentMapping + , const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory > & xSMgr ); + + virtual ~CachedDynamicResultSet(); + + + //----------------------------------------------------------------- + // XInterface inherited + //----------------------------------------------------------------- + XINTERFACE_DECL() + //----------------------------------------------------------------- + // XTypeProvider + //----------------------------------------------------------------- + XTYPEPROVIDER_DECL() + //----------------------------------------------------------------- + // XServiceInfo + //----------------------------------------------------------------- + XSERVICEINFO_NOFACTORY_DECL() + + //----------------------------------------------------------------- + // own methods ( inherited ) + //----------------------------------------------------------------- + virtual void SAL_CALL + impl_disposing( const com::sun::star::lang::EventObject& Source ) + throw( com::sun::star::uno::RuntimeException ); +}; + +//========================================================================= + +class CachedDynamicResultSetFactory + : public cppu::OWeakObject + , public com::sun::star::lang::XTypeProvider + , public com::sun::star::lang::XServiceInfo + , public com::sun::star::ucb::XCachedDynamicResultSetFactory +{ +protected: + com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory > m_xSMgr; + +public: + + CachedDynamicResultSetFactory( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory > & rSMgr); + + virtual ~CachedDynamicResultSetFactory(); + + //----------------------------------------------------------------- + // XInterface + XINTERFACE_DECL() + + //----------------------------------------------------------------- + // XTypeProvider + XTYPEPROVIDER_DECL() + + //----------------------------------------------------------------- + // XServiceInfo + XSERVICEINFO_DECL() + + //----------------------------------------------------------------- + // XCachedDynamicResultSetFactory + + virtual com::sun::star::uno::Reference< + com::sun::star::ucb::XDynamicResultSet > SAL_CALL + createCachedDynamicResultSet( + const com::sun::star::uno::Reference< + com::sun::star::ucb::XDynamicResultSet > & + SourceStub + , const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifierMapping > & + ContentIdentifierMapping + ) + throw( com::sun::star::uno::RuntimeException ); +}; + +#endif + diff --git a/ucb/source/cacher/cacheddynamicresultsetstub.cxx b/ucb/source/cacher/cacheddynamicresultsetstub.cxx new file mode 100644 index 000000000000..09c5f029d4ac --- /dev/null +++ b/ucb/source/cacher/cacheddynamicresultsetstub.cxx @@ -0,0 +1,245 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +#include <cacheddynamicresultsetstub.hxx> +#include <com/sun/star/sdbc/XResultSet.hpp> +#include <cachedcontentresultsetstub.hxx> +#include <com/sun/star/ucb/ContentResultSetCapability.hpp> +#include <com/sun/star/ucb/XSortedDynamicResultSetFactory.hpp> +#include <osl/diagnose.h> + +using namespace com::sun::star::lang; +using namespace com::sun::star::sdbc; +using namespace com::sun::star::ucb; +using namespace com::sun::star::uno; +using namespace rtl; + +CachedDynamicResultSetStub::CachedDynamicResultSetStub( + Reference< XDynamicResultSet > xOrigin + , const Reference< XMultiServiceFactory > & xSMgr ) + : DynamicResultSetWrapper( xOrigin, xSMgr ) +{ + OSL_ENSURE( m_xSMgr.is(), "need Multiservicefactory to create stub" ); + impl_init(); +} + +CachedDynamicResultSetStub::~CachedDynamicResultSetStub() +{ + impl_deinit(); +} + +//virtual +void SAL_CALL CachedDynamicResultSetStub + ::impl_InitResultSetOne( const Reference< XResultSet >& xResultSet ) +{ + DynamicResultSetWrapper::impl_InitResultSetOne( xResultSet ); + OSL_ENSURE( m_xSourceResultOne.is(), "need source resultset" ); + + Reference< XResultSet > xStub( + new CachedContentResultSetStub( m_xSourceResultOne ) ); + + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + m_xMyResultOne = xStub; +} + +//virtual +void SAL_CALL CachedDynamicResultSetStub + ::impl_InitResultSetTwo( const Reference< XResultSet >& xResultSet ) +{ + DynamicResultSetWrapper::impl_InitResultSetTwo( xResultSet ); + OSL_ENSURE( m_xSourceResultTwo.is(), "need source resultset" ); + + Reference< XResultSet > xStub( + new CachedContentResultSetStub( m_xSourceResultTwo ) ); + + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + m_xMyResultTwo = xStub; +} + +//-------------------------------------------------------------------------- +// XInterface methods. +//-------------------------------------------------------------------------- +XINTERFACE_COMMON_IMPL( CachedDynamicResultSetStub ) + +Any SAL_CALL CachedDynamicResultSetStub + ::queryInterface( const Type& rType ) + throw ( RuntimeException ) +{ + //list all interfaces inclusive baseclasses of interfaces + + Any aRet = DynamicResultSetWrapper::queryInterface( rType ); + if( aRet.hasValue() ) + return aRet; + + aRet = cppu::queryInterface( rType, + static_cast< XTypeProvider* >( this ) + , static_cast< XServiceInfo* >( this ) + ); + return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ); +} + +//-------------------------------------------------------------------------- +// XTypeProvider methods. +//-------------------------------------------------------------------------- +//list all interfaces exclusive baseclasses +XTYPEPROVIDER_IMPL_5( CachedDynamicResultSetStub + , XTypeProvider + , XServiceInfo + , XDynamicResultSet + , XDynamicResultSetListener + , XSourceInitialization + ); + +//-------------------------------------------------------------------------- +// XServiceInfo methods. +//-------------------------------------------------------------------------- + +XSERVICEINFO_NOFACTORY_IMPL_1( CachedDynamicResultSetStub, + OUString::createFromAscii( + "com.sun.star.comp.ucb.CachedDynamicResultSetStub" ), + OUString::createFromAscii( + CACHED_DRS_STUB_SERVICE_NAME ) ); + +//-------------------------------------------------------------------------- +//-------------------------------------------------------------------------- +// class CachedDynamicResultSetStubFactory +//-------------------------------------------------------------------------- +//-------------------------------------------------------------------------- + +CachedDynamicResultSetStubFactory::CachedDynamicResultSetStubFactory( + const Reference< XMultiServiceFactory > & rSMgr ) +{ + m_xSMgr = rSMgr; +} + +CachedDynamicResultSetStubFactory::~CachedDynamicResultSetStubFactory() +{ +} + +//-------------------------------------------------------------------------- +// CachedDynamicResultSetStubFactory XInterface methods. +//-------------------------------------------------------------------------- + +XINTERFACE_IMPL_3( CachedDynamicResultSetStubFactory, + XTypeProvider, + XServiceInfo, + XCachedDynamicResultSetStubFactory ); + +//-------------------------------------------------------------------------- +// CachedDynamicResultSetStubFactory XTypeProvider methods. +//-------------------------------------------------------------------------- + +XTYPEPROVIDER_IMPL_3( CachedDynamicResultSetStubFactory, + XTypeProvider, + XServiceInfo, + XCachedDynamicResultSetStubFactory ); + +//-------------------------------------------------------------------------- +// CachedDynamicResultSetStubFactory XServiceInfo methods. +//-------------------------------------------------------------------------- + +XSERVICEINFO_IMPL_1( CachedDynamicResultSetStubFactory, + OUString::createFromAscii( + "com.sun.star.comp.ucb.CachedDynamicResultSetStubFactory" ), + OUString::createFromAscii( + CACHED_DRS_STUB_FACTORY_NAME ) ); + +//-------------------------------------------------------------------------- +// Service factory implementation. +//-------------------------------------------------------------------------- + +ONE_INSTANCE_SERVICE_FACTORY_IMPL( CachedDynamicResultSetStubFactory ); + +//-------------------------------------------------------------------------- +// CachedDynamicResultSetStubFactory XCachedDynamicResultSetStubFactory methods. +//-------------------------------------------------------------------------- + +//virtual +Reference< XDynamicResultSet > SAL_CALL CachedDynamicResultSetStubFactory + ::createCachedDynamicResultSetStub( + const Reference< XDynamicResultSet > & Source ) + throw( RuntimeException ) +{ + Reference< XDynamicResultSet > xRet; + xRet = new CachedDynamicResultSetStub( Source, m_xSMgr ); + return xRet; +} + +//virtual +void SAL_CALL CachedDynamicResultSetStubFactory + ::connectToCache( + const Reference< XDynamicResultSet > & Source + , const Reference< XDynamicResultSet > & TargetCache + , const Sequence< NumberedSortingInfo > & SortingInfo + , const Reference< XAnyCompareFactory > & CompareFactory + ) + throw ( ListenerAlreadySetException + , AlreadyInitializedException + , RuntimeException ) +{ + OSL_ENSURE( Source.is(), "a Source is needed" ); + OSL_ENSURE( TargetCache.is(), "a TargetCache is needed" ); + + Reference< XDynamicResultSet > xSource( Source ); + if( SortingInfo.getLength() && + !( xSource->getCapabilities() & ContentResultSetCapability::SORTED ) + ) + { + Reference< XSortedDynamicResultSetFactory > xSortFactory; + try + { + xSortFactory = Reference< XSortedDynamicResultSetFactory >( + m_xSMgr->createInstance( OUString::createFromAscii( + "com.sun.star.ucb.SortedDynamicResultSetFactory" ) ), + UNO_QUERY ); + } + catch ( Exception const & ) + { + } + + if( xSortFactory.is() ) + { + Reference< XDynamicResultSet > xSorted( + xSortFactory->createSortedDynamicResultSet( + Source, SortingInfo, CompareFactory ) ); + if( xSorted.is() ) + xSource = xSorted; + } + } + + Reference< XDynamicResultSet > xStub( + new CachedDynamicResultSetStub( xSource, m_xSMgr ) ); + + Reference< XSourceInitialization > xTarget( TargetCache, UNO_QUERY ); + OSL_ENSURE( xTarget.is(), "Target must have interface XSourceInitialization" ); + + xTarget->setSource( xStub ); +} + diff --git a/ucb/source/cacher/cacheddynamicresultsetstub.hxx b/ucb/source/cacher/cacheddynamicresultsetstub.hxx new file mode 100644 index 000000000000..33608e88f4e2 --- /dev/null +++ b/ucb/source/cacher/cacheddynamicresultsetstub.hxx @@ -0,0 +1,136 @@ +/************************************************************************* + * + * 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 _CACHED_DYNAMIC_RESULTSET_STUB_HXX +#define _CACHED_DYNAMIC_RESULTSET_STUB_HXX + +#include <dynamicresultsetwrapper.hxx> +#include <com/sun/star/ucb/XCachedDynamicResultSetStubFactory.hpp> + +#define CACHED_DRS_STUB_SERVICE_NAME "com.sun.star.ucb.CachedDynamicResultSetStub" +#define CACHED_DRS_STUB_FACTORY_NAME "com.sun.star.ucb.CachedDynamicResultSetStubFactory" + +//========================================================================= + +class CachedDynamicResultSetStub + : public DynamicResultSetWrapper + , public com::sun::star::lang::XTypeProvider + , public com::sun::star::lang::XServiceInfo +{ +protected: + virtual void SAL_CALL + impl_InitResultSetOne( const com::sun::star::uno::Reference< + com::sun::star::sdbc::XResultSet >& xResultSet ); + virtual void SAL_CALL + impl_InitResultSetTwo( const com::sun::star::uno::Reference< + com::sun::star::sdbc::XResultSet >& xResultSet ); + +public: + CachedDynamicResultSetStub( com::sun::star::uno::Reference< + com::sun::star::ucb::XDynamicResultSet > xOrigin + , const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory > & xSMgr ); + + virtual ~CachedDynamicResultSetStub(); + + + //----------------------------------------------------------------- + // XInterface inherited + //----------------------------------------------------------------- + XINTERFACE_DECL() + //----------------------------------------------------------------- + // XTypeProvider + //----------------------------------------------------------------- + XTYPEPROVIDER_DECL() + //----------------------------------------------------------------- + // XServiceInfo + //----------------------------------------------------------------- + XSERVICEINFO_NOFACTORY_DECL() +}; + +//========================================================================= + +class CachedDynamicResultSetStubFactory + : public cppu::OWeakObject + , public com::sun::star::lang::XTypeProvider + , public com::sun::star::lang::XServiceInfo + , public com::sun::star::ucb::XCachedDynamicResultSetStubFactory +{ +protected: + com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory > m_xSMgr; + +public: + + CachedDynamicResultSetStubFactory( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory > & rSMgr); + + virtual ~CachedDynamicResultSetStubFactory(); + + //----------------------------------------------------------------- + // XInterface + XINTERFACE_DECL() + + //----------------------------------------------------------------- + // XTypeProvider + XTYPEPROVIDER_DECL() + + //----------------------------------------------------------------- + // XServiceInfo + XSERVICEINFO_DECL() + + //----------------------------------------------------------------- + // XCachedDynamicResultSetStubFactory + + virtual com::sun::star::uno::Reference< + com::sun::star::ucb::XDynamicResultSet > SAL_CALL + createCachedDynamicResultSetStub( + const com::sun::star::uno::Reference< + com::sun::star::ucb::XDynamicResultSet > & Source ) + throw( com::sun::star::uno::RuntimeException ); + + + virtual void SAL_CALL connectToCache( + const com::sun::star::uno::Reference< + com::sun::star::ucb::XDynamicResultSet > & Source + , const com::sun::star::uno::Reference< + com::sun::star::ucb::XDynamicResultSet > & TargetCache + , const com::sun::star::uno::Sequence< + com::sun::star::ucb::NumberedSortingInfo > & SortingInfo + , const com::sun::star::uno::Reference< + com::sun::star::ucb::XAnyCompareFactory > & CompareFactory + ) + throw ( + com::sun::star::ucb::ListenerAlreadySetException + , com::sun::star::ucb::AlreadyInitializedException + , com::sun::star::uno::RuntimeException + ); +}; + +#endif + diff --git a/ucb/source/cacher/cacheserv.cxx b/ucb/source/cacher/cacheserv.cxx new file mode 100644 index 000000000000..f429286cfdee --- /dev/null +++ b/ucb/source/cacher/cacheserv.cxx @@ -0,0 +1,110 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <com/sun/star/registry/XRegistryKey.hpp> +#include <cachedcontentresultset.hxx> +#include <cachedcontentresultsetstub.hxx> +#include <cacheddynamicresultset.hxx> +#include <cacheddynamicresultsetstub.hxx> + +using namespace rtl; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::registry; + +//========================================================================= +extern "C" void SAL_CALL component_getImplementationEnvironment( + const sal_Char ** ppEnvTypeName, uno_Environment ** ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + +//========================================================================= +extern "C" void * SAL_CALL component_getFactory( + const sal_Char * pImplName, void * pServiceManager, void * ) +{ + void * pRet = 0; + + Reference< XMultiServiceFactory > xSMgr( + reinterpret_cast< XMultiServiceFactory * >( pServiceManager ) ); + Reference< XSingleServiceFactory > xFactory; + + ////////////////////////////////////////////////////////////////////// + // CachedContentResultSetFactory. + ////////////////////////////////////////////////////////////////////// + + if ( CachedContentResultSetFactory::getImplementationName_Static(). + compareToAscii( pImplName ) == 0 ) + { + xFactory = CachedContentResultSetFactory::createServiceFactory( xSMgr ); + } + + ////////////////////////////////////////////////////////////////////// + // CachedContentResultSetStubFactory. + ////////////////////////////////////////////////////////////////////// + + else if ( CachedContentResultSetStubFactory::getImplementationName_Static(). + compareToAscii( pImplName ) == 0 ) + { + xFactory = CachedContentResultSetStubFactory::createServiceFactory( xSMgr ); + } + + ////////////////////////////////////////////////////////////////////// + // CachedDynamicResultSetFactory. + ////////////////////////////////////////////////////////////////////// + + else if ( CachedDynamicResultSetFactory::getImplementationName_Static(). + compareToAscii( pImplName ) == 0 ) + { + xFactory = CachedDynamicResultSetFactory::createServiceFactory( xSMgr ); + } + + ////////////////////////////////////////////////////////////////////// + // CachedDynamicResultSetStubFactory. + ////////////////////////////////////////////////////////////////////// + + else if ( CachedDynamicResultSetStubFactory::getImplementationName_Static(). + compareToAscii( pImplName ) == 0 ) + { + xFactory = CachedDynamicResultSetStubFactory::createServiceFactory( xSMgr ); + } + + ////////////////////////////////////////////////////////////////////// + + if ( xFactory.is() ) + { + xFactory->acquire(); + pRet = xFactory.get(); + } + + return pRet; +} + diff --git a/ucb/source/cacher/contentresultsetwrapper.cxx b/ucb/source/cacher/contentresultsetwrapper.cxx new file mode 100644 index 000000000000..092fc3faf29f --- /dev/null +++ b/ucb/source/cacher/contentresultsetwrapper.cxx @@ -0,0 +1,1477 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +#include <contentresultsetwrapper.hxx> +#include <com/sun/star/sdbc/FetchDirection.hpp> +#include <com/sun/star/ucb/FetchError.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/sdbc/ResultSetType.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <rtl/ustring.hxx> +#include <osl/diagnose.h> + +using namespace com::sun::star::beans; +using namespace com::sun::star::lang; +using namespace com::sun::star::sdbc; +using namespace com::sun::star::ucb; +using namespace com::sun::star::uno; +using namespace com::sun::star::util; +using namespace cppu; +using namespace rtl; + +//-------------------------------------------------------------------------- +//-------------------------------------------------------------------------- +// class ContentResultSetWrapper +//-------------------------------------------------------------------------- +//-------------------------------------------------------------------------- + +ContentResultSetWrapper::ContentResultSetWrapper( + Reference< XResultSet > xOrigin ) + : m_xResultSetOrigin( xOrigin ) + , m_xRowOrigin( NULL ) + , m_xContentAccessOrigin( NULL ) + , m_xPropertySetOrigin( NULL ) + , m_xPropertySetInfo( NULL ) + , m_nForwardOnly( 2 ) + , m_xMetaDataFromOrigin( NULL ) + , m_bDisposed( sal_False ) + , m_bInDispose( sal_False ) + , m_pDisposeEventListeners( NULL ) + , m_pPropertyChangeListeners( NULL ) + , m_pVetoableChangeListeners( NULL ) +{ + m_pMyListenerImpl = new ContentResultSetWrapperListener( this ); + m_xMyListenerImpl = Reference< XPropertyChangeListener >( m_pMyListenerImpl ); + + OSL_ENSURE( m_xResultSetOrigin.is(), "XResultSet is required" ); + + //!! call impl_init() at the end of constructor of derived class +}; + + +void SAL_CALL ContentResultSetWrapper::impl_init_xRowOrigin() +{ + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + if(m_xRowOrigin.is()) + return; + } + + Reference< XRow > xOrgig = + Reference< XRow >( m_xResultSetOrigin, UNO_QUERY ); + + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + m_xRowOrigin = xOrgig; + OSL_ENSURE( m_xRowOrigin.is(), "interface XRow is required" ); + } +} + +void SAL_CALL ContentResultSetWrapper::impl_init_xContentAccessOrigin() +{ + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + if(m_xContentAccessOrigin.is()) + return; + } + + Reference< XContentAccess > xOrgig = + Reference< XContentAccess >( m_xResultSetOrigin, UNO_QUERY ); + + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + m_xContentAccessOrigin = xOrgig; + OSL_ENSURE( m_xContentAccessOrigin.is(), "interface XContentAccess is required" ); + } +} + + +void SAL_CALL ContentResultSetWrapper::impl_init_xPropertySetOrigin() +{ + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + if( m_xPropertySetOrigin.is() ) + return; + } + + Reference< XPropertySet > xOrig = + Reference< XPropertySet >( m_xResultSetOrigin, UNO_QUERY ); + + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + m_xPropertySetOrigin = xOrig; + OSL_ENSURE( m_xPropertySetOrigin.is(), "interface XPropertySet is required" ); + } +} + +void SAL_CALL ContentResultSetWrapper::impl_init() +{ + //call this at the end of constructor of derived class + // + + //listen to disposing from Origin: + Reference< XComponent > xComponentOrigin( m_xResultSetOrigin, UNO_QUERY ); + OSL_ENSURE( xComponentOrigin.is(), "interface XComponent is required" ); + xComponentOrigin->addEventListener( static_cast< XPropertyChangeListener * >( m_pMyListenerImpl ) ); +} + +ContentResultSetWrapper::~ContentResultSetWrapper() +{ + //call impl_deinit() at start of destructor of derived class + + delete m_pDisposeEventListeners; + delete m_pPropertyChangeListeners; + delete m_pVetoableChangeListeners; +}; + +void SAL_CALL ContentResultSetWrapper::impl_deinit() +{ + //call this at start of destructor of derived class + // + m_pMyListenerImpl->impl_OwnerDies(); +} + +//virtual +void SAL_CALL ContentResultSetWrapper + ::impl_initPropertySetInfo() +{ + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + if( m_xPropertySetInfo.is() ) + return; + + impl_init_xPropertySetOrigin(); + if( !m_xPropertySetOrigin.is() ) + return; + } + + Reference< XPropertySetInfo > xOrig = + m_xPropertySetOrigin->getPropertySetInfo(); + + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + m_xPropertySetInfo = xOrig; + } +} + +void SAL_CALL ContentResultSetWrapper +::impl_EnsureNotDisposed() + throw( DisposedException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + if( m_bDisposed ) + throw DisposedException(); +} + +ContentResultSetWrapper::PropertyChangeListenerContainer_Impl* SAL_CALL + ContentResultSetWrapper + ::impl_getPropertyChangeListenerContainer() +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + if ( !m_pPropertyChangeListeners ) + m_pPropertyChangeListeners = + new PropertyChangeListenerContainer_Impl( m_aContainerMutex ); + return m_pPropertyChangeListeners; +} + +ContentResultSetWrapper::PropertyChangeListenerContainer_Impl* SAL_CALL + ContentResultSetWrapper + ::impl_getVetoableChangeListenerContainer() +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + if ( !m_pVetoableChangeListeners ) + m_pVetoableChangeListeners = + new PropertyChangeListenerContainer_Impl( m_aContainerMutex ); + return m_pVetoableChangeListeners; +} + +void SAL_CALL ContentResultSetWrapper + ::impl_notifyPropertyChangeListeners( + const PropertyChangeEvent& rEvt ) +{ + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + if( !m_pPropertyChangeListeners ) + return; + } + + // Notify listeners interested especially in the changed property. + OInterfaceContainerHelper* pContainer = + m_pPropertyChangeListeners->getContainer( rEvt.PropertyName ); + if( pContainer ) + { + OInterfaceIteratorHelper aIter( *pContainer ); + while( aIter.hasMoreElements() ) + { + Reference< XPropertyChangeListener > xListener( + aIter.next(), UNO_QUERY ); + if( xListener.is() ) + xListener->propertyChange( rEvt ); + } + } + + // Notify listeners interested in all properties. + pContainer = m_pPropertyChangeListeners->getContainer( OUString() ); + if( pContainer ) + { + OInterfaceIteratorHelper aIter( *pContainer ); + while( aIter.hasMoreElements() ) + { + Reference< XPropertyChangeListener > xListener( + aIter.next(), UNO_QUERY ); + if( xListener.is() ) + xListener->propertyChange( rEvt ); + } + } +} + +void SAL_CALL ContentResultSetWrapper + ::impl_notifyVetoableChangeListeners( const PropertyChangeEvent& rEvt ) + throw( PropertyVetoException, + RuntimeException ) +{ + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + if( !m_pVetoableChangeListeners ) + return; + } + + // Notify listeners interested especially in the changed property. + OInterfaceContainerHelper* pContainer = + m_pVetoableChangeListeners->getContainer( rEvt.PropertyName ); + if( pContainer ) + { + OInterfaceIteratorHelper aIter( *pContainer ); + while( aIter.hasMoreElements() ) + { + Reference< XVetoableChangeListener > xListener( + aIter.next(), UNO_QUERY ); + if( xListener.is() ) + xListener->vetoableChange( rEvt ); + } + } + + // Notify listeners interested in all properties. + pContainer = m_pVetoableChangeListeners->getContainer( OUString() ); + if( pContainer ) + { + OInterfaceIteratorHelper aIter( *pContainer ); + while( aIter.hasMoreElements() ) + { + Reference< XVetoableChangeListener > xListener( + aIter.next(), UNO_QUERY ); + if( xListener.is() ) + xListener->vetoableChange( rEvt ); + } + } +} + +sal_Bool SAL_CALL ContentResultSetWrapper + ::impl_isForwardOnly() +{ + //m_nForwardOnly == 2 -> don't know + //m_nForwardOnly == 1 -> YES + //m_nForwardOnly == 0 -> NO + + //@todo replace this with lines in comment + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + m_nForwardOnly = 0; + return false; + + + /* + ReacquireableGuard aGuard( m_aMutex ); + if( m_nForwardOnly == 2 ) + { + aGuard.clear(); + if( !getPropertySetInfo().is() ) + { + aGuard.reacquire(); + m_nForwardOnly = 0; + return m_nForwardOnly; + } + aGuard.reacquire(); + + rtl::OUString aName = OUString::createFromAscii( "ResultSetType" ); + //find out, if we are ForwardOnly and cache the value: + + impl_init_xPropertySetOrigin(); + if( !m_xPropertySetOrigin.is() ) + { + OSL_ENSURE( sal_False, "broadcaster was disposed already" ); + m_nForwardOnly = 0; + return m_nForwardOnly; + } + + aGuard.clear(); + Any aAny = m_xPropertySetOrigin->getPropertyValue( aName ); + + aGuard.reacquire(); + long nResultSetType; + if( ( aAny >>= nResultSetType ) && + ( nResultSetType == ResultSetType::FORWARD_ONLY ) ) + m_nForwardOnly = 1; + else + m_nForwardOnly = 0; + } + return m_nForwardOnly; + */ +} + +//-------------------------------------------------------------------------- +// XInterface methods. +//-------------------------------------------------------------------------- +//list all interfaces inclusive baseclasses of interfaces +QUERYINTERFACE_IMPL_START( ContentResultSetWrapper ) + + SAL_STATIC_CAST( XComponent*, this ), + SAL_STATIC_CAST( XCloseable*, this ), + SAL_STATIC_CAST( XResultSetMetaDataSupplier*, this ), + SAL_STATIC_CAST( XPropertySet*, this ), + + SAL_STATIC_CAST( XContentAccess*, this ), + SAL_STATIC_CAST( XResultSet*, this ), + SAL_STATIC_CAST( XRow*, this ) + +QUERYINTERFACE_IMPL_END + +//-------------------------------------------------------------------------- +// XComponent methods. +//-------------------------------------------------------------------------- +// virtual +void SAL_CALL ContentResultSetWrapper + ::dispose() throw( RuntimeException ) +{ + impl_EnsureNotDisposed(); + + ReacquireableGuard aGuard( m_aMutex ); + if( m_bInDispose || m_bDisposed ) + return; + m_bInDispose = sal_True; + + if( m_xPropertySetOrigin.is() ) + { + aGuard.clear(); + try + { + m_xPropertySetOrigin->removePropertyChangeListener( + OUString(), static_cast< XPropertyChangeListener * >( m_pMyListenerImpl ) ); + } + catch( Exception& ) + { + OSL_ENSURE( sal_False, "could not remove PropertyChangeListener" ); + } + try + { + m_xPropertySetOrigin->removeVetoableChangeListener( + OUString(), static_cast< XVetoableChangeListener * >( m_pMyListenerImpl ) ); + } + catch( Exception& ) + { + OSL_ENSURE( sal_False, "could not remove VetoableChangeListener" ); + } + + Reference< XComponent > xComponentOrigin( m_xResultSetOrigin, UNO_QUERY ); + OSL_ENSURE( xComponentOrigin.is(), "interface XComponent is required" ); + xComponentOrigin->removeEventListener( static_cast< XPropertyChangeListener * >( m_pMyListenerImpl ) ); + } + + aGuard.reacquire(); + if( m_pDisposeEventListeners && m_pDisposeEventListeners->getLength() ) + { + EventObject aEvt; + aEvt.Source = static_cast< XComponent * >( this ); + + aGuard.clear(); + m_pDisposeEventListeners->disposeAndClear( aEvt ); + } + + aGuard.reacquire(); + if( m_pPropertyChangeListeners ) + { + EventObject aEvt; + aEvt.Source = static_cast< XPropertySet * >( this ); + + aGuard.clear(); + m_pPropertyChangeListeners->disposeAndClear( aEvt ); + } + + aGuard.reacquire(); + if( m_pVetoableChangeListeners ) + { + EventObject aEvt; + aEvt.Source = static_cast< XPropertySet * >( this ); + + aGuard.clear(); + m_pVetoableChangeListeners->disposeAndClear( aEvt ); + } + + aGuard.reacquire(); + m_bDisposed = sal_True; + m_bInDispose = sal_False; +} + +//-------------------------------------------------------------------------- +// virtual +void SAL_CALL ContentResultSetWrapper + ::addEventListener( const Reference< XEventListener >& Listener ) + throw( RuntimeException ) +{ + impl_EnsureNotDisposed(); + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + if ( !m_pDisposeEventListeners ) + m_pDisposeEventListeners = + new OInterfaceContainerHelper( m_aContainerMutex ); + + m_pDisposeEventListeners->addInterface( Listener ); +} + +//-------------------------------------------------------------------------- +// virtual +void SAL_CALL ContentResultSetWrapper + ::removeEventListener( const Reference< XEventListener >& Listener ) + throw( RuntimeException ) +{ + impl_EnsureNotDisposed(); + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + if ( m_pDisposeEventListeners ) + m_pDisposeEventListeners->removeInterface( Listener ); +} + +//-------------------------------------------------------------------------- +//XCloseable methods. +//-------------------------------------------------------------------------- +//virtual +void SAL_CALL ContentResultSetWrapper + ::close() + throw( SQLException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + dispose(); +} + +//-------------------------------------------------------------------------- +//XResultSetMetaDataSupplier methods. +//-------------------------------------------------------------------------- +//virtual +Reference< XResultSetMetaData > SAL_CALL ContentResultSetWrapper + ::getMetaData() + throw( SQLException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + + ReacquireableGuard aGuard( m_aMutex ); + if( !m_xMetaDataFromOrigin.is() && m_xResultSetOrigin.is() ) + { + Reference< XResultSetMetaDataSupplier > xMetaDataSupplier + = Reference< XResultSetMetaDataSupplier >( + m_xResultSetOrigin, UNO_QUERY ); + + if( xMetaDataSupplier.is() ) + { + aGuard.clear(); + + Reference< XResultSetMetaData > xMetaData + = xMetaDataSupplier->getMetaData(); + + aGuard.reacquire(); + m_xMetaDataFromOrigin = xMetaData; + } + } + return m_xMetaDataFromOrigin; +} + + +//-------------------------------------------------------------------------- +// XPropertySet methods. +//-------------------------------------------------------------------------- +// virtual +Reference< XPropertySetInfo > SAL_CALL ContentResultSetWrapper + ::getPropertySetInfo() throw( RuntimeException ) +{ + impl_EnsureNotDisposed(); + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + if( m_xPropertySetInfo.is() ) + return m_xPropertySetInfo; + } + impl_initPropertySetInfo(); + return m_xPropertySetInfo; +} +//-------------------------------------------------------------------------- +// virtual +void SAL_CALL ContentResultSetWrapper + ::setPropertyValue( const OUString& rPropertyName, const Any& rValue ) + throw( UnknownPropertyException, + PropertyVetoException, + IllegalArgumentException, + WrappedTargetException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + impl_init_xPropertySetOrigin(); + if( !m_xPropertySetOrigin.is() ) + { + OSL_ENSURE( sal_False, "broadcaster was disposed already" ); + throw UnknownPropertyException(); + } + m_xPropertySetOrigin->setPropertyValue( rPropertyName, rValue ); +} + +//-------------------------------------------------------------------------- +// virtual +Any SAL_CALL ContentResultSetWrapper + ::getPropertyValue( const OUString& rPropertyName ) + throw( UnknownPropertyException, + WrappedTargetException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + impl_init_xPropertySetOrigin(); + if( !m_xPropertySetOrigin.is() ) + { + OSL_ENSURE( sal_False, "broadcaster was disposed already" ); + throw UnknownPropertyException(); + } + return m_xPropertySetOrigin->getPropertyValue( rPropertyName ); +} + +//-------------------------------------------------------------------------- +// virtual +void SAL_CALL ContentResultSetWrapper + ::addPropertyChangeListener( + const OUString& aPropertyName, + const Reference< XPropertyChangeListener >& xListener ) + throw( UnknownPropertyException, + WrappedTargetException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + + if( !getPropertySetInfo().is() ) + { + OSL_ENSURE( sal_False, "broadcaster was disposed already" ); + throw UnknownPropertyException(); + } + + if( aPropertyName.getLength() ) + { + m_xPropertySetInfo->getPropertyByName( aPropertyName ); + //throws UnknownPropertyException, if so + } + + impl_getPropertyChangeListenerContainer(); + sal_Bool bNeedRegister = !m_pPropertyChangeListeners-> + getContainedTypes().getLength(); + m_pPropertyChangeListeners->addInterface( aPropertyName, xListener ); + if( bNeedRegister ) + { + impl_init_xPropertySetOrigin(); + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + if( !m_xPropertySetOrigin.is() ) + { + OSL_ENSURE( sal_False, "broadcaster was disposed already" ); + return; + } + } + try + { + m_xPropertySetOrigin->addPropertyChangeListener( + OUString(), static_cast< XPropertyChangeListener * >( m_pMyListenerImpl ) ); + } + catch( Exception& rEx ) + { + m_pPropertyChangeListeners->removeInterface( aPropertyName, xListener ); + throw rEx; + } + } +} + +//-------------------------------------------------------------------------- +// virtual +void SAL_CALL ContentResultSetWrapper + ::addVetoableChangeListener( + const OUString& rPropertyName, + const Reference< XVetoableChangeListener >& xListener ) + throw( UnknownPropertyException, + WrappedTargetException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + + if( !getPropertySetInfo().is() ) + { + OSL_ENSURE( sal_False, "broadcaster was disposed already" ); + throw UnknownPropertyException(); + } + if( rPropertyName.getLength() ) + { + m_xPropertySetInfo->getPropertyByName( rPropertyName ); + //throws UnknownPropertyException, if so + } + + impl_getVetoableChangeListenerContainer(); + sal_Bool bNeedRegister = !m_pVetoableChangeListeners-> + getContainedTypes().getLength(); + m_pVetoableChangeListeners->addInterface( rPropertyName, xListener ); + if( bNeedRegister ) + { + impl_init_xPropertySetOrigin(); + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + if( !m_xPropertySetOrigin.is() ) + { + OSL_ENSURE( sal_False, "broadcaster was disposed already" ); + return; + } + } + try + { + m_xPropertySetOrigin->addVetoableChangeListener( + OUString(), static_cast< XVetoableChangeListener * >( m_pMyListenerImpl ) ); + } + catch( Exception& rEx ) + { + m_pVetoableChangeListeners->removeInterface( rPropertyName, xListener ); + throw rEx; + } + } +} + +//-------------------------------------------------------------------------- +// virtual +void SAL_CALL ContentResultSetWrapper + ::removePropertyChangeListener( + const OUString& rPropertyName, + const Reference< XPropertyChangeListener >& xListener ) + throw( UnknownPropertyException, + WrappedTargetException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + + { + //noop, if no listener registered + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + if( !m_pPropertyChangeListeners ) + return; + } + OInterfaceContainerHelper* pContainer = + m_pPropertyChangeListeners->getContainer( rPropertyName ); + + if( !pContainer ) + { + if( rPropertyName.getLength() ) + { + if( !getPropertySetInfo().is() ) + throw UnknownPropertyException(); + + m_xPropertySetInfo->getPropertyByName( rPropertyName ); + //throws UnknownPropertyException, if so + } + return; //the listener was not registered + } + + m_pPropertyChangeListeners->removeInterface( rPropertyName, xListener ); + + if( !m_pPropertyChangeListeners->getContainedTypes().getLength() ) + { + impl_init_xPropertySetOrigin(); + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + if( !m_xPropertySetOrigin.is() ) + { + OSL_ENSURE( sal_False, "broadcaster was disposed already" ); + return; + } + } + try + { + m_xPropertySetOrigin->removePropertyChangeListener( + OUString(), static_cast< XPropertyChangeListener * >( m_pMyListenerImpl ) ); + } + catch( Exception& ) + { + OSL_ENSURE( sal_False, "could not remove PropertyChangeListener" ); + } + } +} + +//-------------------------------------------------------------------------- +// virtual +void SAL_CALL ContentResultSetWrapper + ::removeVetoableChangeListener( + const OUString& rPropertyName, + const Reference< XVetoableChangeListener >& xListener ) + throw( UnknownPropertyException, + WrappedTargetException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + + { + //noop, if no listener registered + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + if( !m_pVetoableChangeListeners ) + return; + } + OInterfaceContainerHelper* pContainer = + m_pVetoableChangeListeners->getContainer( rPropertyName ); + + if( !pContainer ) + { + if( rPropertyName.getLength() ) + { + if( !getPropertySetInfo().is() ) + throw UnknownPropertyException(); + + m_xPropertySetInfo->getPropertyByName( rPropertyName ); + //throws UnknownPropertyException, if so + } + return; //the listener was not registered + } + + m_pVetoableChangeListeners->removeInterface( rPropertyName, xListener ); + + if( !m_pVetoableChangeListeners->getContainedTypes().getLength() ) + { + impl_init_xPropertySetOrigin(); + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + if( !m_xPropertySetOrigin.is() ) + { + OSL_ENSURE( sal_False, "broadcaster was disposed already" ); + return; + } + } + try + { + m_xPropertySetOrigin->removeVetoableChangeListener( + OUString(), static_cast< XVetoableChangeListener * >( m_pMyListenerImpl ) ); + } + catch( Exception& ) + { + OSL_ENSURE( sal_False, "could not remove VetoableChangeListener" ); + } + } +} + +//-------------------------------------------------------------------------- +// own methods. +//-------------------------------------------------------------------------- + +//virtual +void SAL_CALL ContentResultSetWrapper + ::impl_disposing( const EventObject& ) + throw( RuntimeException ) +{ + impl_EnsureNotDisposed(); + + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + if( !m_xResultSetOrigin.is() ) + return; + + //release all references to the broadcaster: + m_xResultSetOrigin.clear(); + if(m_xRowOrigin.is()) + m_xRowOrigin.clear(); + if(m_xContentAccessOrigin.is()) + m_xContentAccessOrigin.clear(); + if(m_xPropertySetOrigin.is()) + m_xPropertySetOrigin.clear(); + m_xMetaDataFromOrigin.clear(); + if(m_xPropertySetInfo.is()) + m_xPropertySetInfo.clear(); +} + +//virtual +void SAL_CALL ContentResultSetWrapper + ::impl_propertyChange( const PropertyChangeEvent& rEvt ) + throw( RuntimeException ) +{ + impl_EnsureNotDisposed(); + + PropertyChangeEvent aEvt( rEvt ); + aEvt.Source = static_cast< XPropertySet * >( this ); + aEvt.Further = sal_False; + impl_notifyPropertyChangeListeners( aEvt ); +} + +//virtual +void SAL_CALL ContentResultSetWrapper + ::impl_vetoableChange( const PropertyChangeEvent& rEvt ) + throw( PropertyVetoException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + + PropertyChangeEvent aEvt( rEvt ); + aEvt.Source = static_cast< XPropertySet * >( this ); + aEvt.Further = sal_False; + + impl_notifyVetoableChangeListeners( aEvt ); +} + +//-------------------------------------------------------------------------- +// XContentAccess methods. ( -- position dependent ) +//-------------------------------------------------------------------------- + +// virtual +OUString SAL_CALL ContentResultSetWrapper + ::queryContentIdentifierString() + throw( RuntimeException ) +{ + impl_EnsureNotDisposed(); + impl_init_xContentAccessOrigin(); + if( !m_xContentAccessOrigin.is() ) + { + OSL_ENSURE( sal_False, "broadcaster was disposed already" ); + throw RuntimeException(); + } + return m_xContentAccessOrigin->queryContentIdentifierString(); +} + +//-------------------------------------------------------------------------- +// virtual +Reference< XContentIdentifier > SAL_CALL ContentResultSetWrapper + ::queryContentIdentifier() + throw( RuntimeException ) +{ + impl_EnsureNotDisposed(); + impl_init_xContentAccessOrigin(); + if( !m_xContentAccessOrigin.is() ) + { + OSL_ENSURE( sal_False, "broadcaster was disposed already" ); + throw RuntimeException(); + } + return m_xContentAccessOrigin->queryContentIdentifier(); +} + +//-------------------------------------------------------------------------- +// virtual +Reference< XContent > SAL_CALL ContentResultSetWrapper + ::queryContent() + throw( RuntimeException ) +{ + impl_EnsureNotDisposed(); + impl_init_xContentAccessOrigin(); + if( !m_xContentAccessOrigin.is() ) + { + OSL_ENSURE( sal_False, "broadcaster was disposed already" ); + throw RuntimeException(); + } + return m_xContentAccessOrigin->queryContent(); +} + +//----------------------------------------------------------------- +// XResultSet methods. +//----------------------------------------------------------------- +//virtual + +sal_Bool SAL_CALL ContentResultSetWrapper + ::next() + throw( SQLException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + + if( !m_xResultSetOrigin.is() ) + { + OSL_ENSURE( sal_False, "broadcaster was disposed already" ); + throw RuntimeException(); + } + return m_xResultSetOrigin->next(); +} + +//virtual +sal_Bool SAL_CALL ContentResultSetWrapper + ::previous() + throw( SQLException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + + if( !m_xResultSetOrigin.is() ) + { + OSL_ENSURE( sal_False, "broadcaster was disposed already" ); + throw RuntimeException(); + } + return m_xResultSetOrigin->previous(); +} + +//virtual +sal_Bool SAL_CALL ContentResultSetWrapper + ::absolute( sal_Int32 row ) + throw( SQLException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + + if( !m_xResultSetOrigin.is() ) + { + OSL_ENSURE( sal_False, "broadcaster was disposed already" ); + throw RuntimeException(); + } + return m_xResultSetOrigin->absolute( row ); +} + +//virtual +sal_Bool SAL_CALL ContentResultSetWrapper + ::relative( sal_Int32 rows ) + throw( SQLException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + + if( !m_xResultSetOrigin.is() ) + { + OSL_ENSURE( sal_False, "broadcaster was disposed already" ); + throw RuntimeException(); + } + return m_xResultSetOrigin->relative( rows ); +} + + +//virtual +sal_Bool SAL_CALL ContentResultSetWrapper + ::first() + throw( SQLException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + + if( !m_xResultSetOrigin.is() ) + { + OSL_ENSURE( sal_False, "broadcaster was disposed already" ); + throw RuntimeException(); + } + return m_xResultSetOrigin->first(); +} + +//virtual +sal_Bool SAL_CALL ContentResultSetWrapper + ::last() + throw( SQLException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + + if( !m_xResultSetOrigin.is() ) + { + OSL_ENSURE( sal_False, "broadcaster was disposed already" ); + throw RuntimeException(); + } + return m_xResultSetOrigin->last(); +} + +//virtual +void SAL_CALL ContentResultSetWrapper + ::beforeFirst() + throw( SQLException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + + if( !m_xResultSetOrigin.is() ) + { + OSL_ENSURE( sal_False, "broadcaster was disposed already" ); + throw RuntimeException(); + } + m_xResultSetOrigin->beforeFirst(); +} + +//virtual +void SAL_CALL ContentResultSetWrapper + ::afterLast() + throw( SQLException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + + if( !m_xResultSetOrigin.is() ) + { + OSL_ENSURE( sal_False, "broadcaster was disposed already" ); + throw RuntimeException(); + } + m_xResultSetOrigin->afterLast(); +} + +//virtual +sal_Bool SAL_CALL ContentResultSetWrapper + ::isAfterLast() + throw( SQLException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + + if( !m_xResultSetOrigin.is() ) + { + OSL_ENSURE( sal_False, "broadcaster was disposed already" ); + throw RuntimeException(); + } + return m_xResultSetOrigin->isAfterLast(); +} + +//virtual +sal_Bool SAL_CALL ContentResultSetWrapper + ::isBeforeFirst() + throw( SQLException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + + if( !m_xResultSetOrigin.is() ) + { + OSL_ENSURE( sal_False, "broadcaster was disposed already" ); + throw RuntimeException(); + } + return m_xResultSetOrigin->isBeforeFirst(); +} + +//virtual +sal_Bool SAL_CALL ContentResultSetWrapper + ::isFirst() + throw( SQLException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + + if( !m_xResultSetOrigin.is() ) + { + OSL_ENSURE( sal_False, "broadcaster was disposed already" ); + throw RuntimeException(); + } + return m_xResultSetOrigin->isFirst(); +} + +//virtual +sal_Bool SAL_CALL ContentResultSetWrapper + ::isLast() + throw( SQLException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + + if( !m_xResultSetOrigin.is() ) + { + OSL_ENSURE( sal_False, "broadcaster was disposed already" ); + throw RuntimeException(); + } + return m_xResultSetOrigin->isLast(); +} + + +//virtual +sal_Int32 SAL_CALL ContentResultSetWrapper + ::getRow() + throw( SQLException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + + if( !m_xResultSetOrigin.is() ) + { + OSL_ENSURE( sal_False, "broadcaster was disposed already" ); + throw RuntimeException(); + } + return m_xResultSetOrigin->getRow(); +} + +//virtual +void SAL_CALL ContentResultSetWrapper + ::refreshRow() + throw( SQLException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + + if( !m_xResultSetOrigin.is() ) + { + OSL_ENSURE( sal_False, "broadcaster was disposed already" ); + throw RuntimeException(); + } + m_xResultSetOrigin->refreshRow(); +} + +//virtual +sal_Bool SAL_CALL ContentResultSetWrapper + ::rowUpdated() + throw( SQLException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + + if( !m_xResultSetOrigin.is() ) + { + OSL_ENSURE( sal_False, "broadcaster was disposed already" ); + throw RuntimeException(); + } + return m_xResultSetOrigin->rowUpdated(); +} +//virtual +sal_Bool SAL_CALL ContentResultSetWrapper + ::rowInserted() + throw( SQLException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + + if( !m_xResultSetOrigin.is() ) + { + OSL_ENSURE( sal_False, "broadcaster was disposed already" ); + throw RuntimeException(); + } + return m_xResultSetOrigin->rowInserted(); +} + +//virtual +sal_Bool SAL_CALL ContentResultSetWrapper + ::rowDeleted() + throw( SQLException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + + if( !m_xResultSetOrigin.is() ) + { + OSL_ENSURE( sal_False, "broadcaster was disposed already" ); + throw RuntimeException(); + } + return m_xResultSetOrigin->rowDeleted(); +} + +//virtual +Reference< XInterface > SAL_CALL ContentResultSetWrapper + ::getStatement() + throw( SQLException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + //@todo ?return anything + return Reference< XInterface >(); +} + +//----------------------------------------------------------------- +// XRow methods. +//----------------------------------------------------------------- + +#define XROW_GETXXX( getXXX ) \ +impl_EnsureNotDisposed(); \ +impl_init_xRowOrigin(); \ +if( !m_xRowOrigin.is() ) \ +{ \ + OSL_ENSURE( sal_False, "broadcaster was disposed already" );\ + throw RuntimeException(); \ +} \ +return m_xRowOrigin->getXXX( columnIndex ); + +//virtual +sal_Bool SAL_CALL ContentResultSetWrapper + ::wasNull() + throw( SQLException, + RuntimeException ) +{ + impl_EnsureNotDisposed(); + impl_init_xRowOrigin(); + if( !m_xRowOrigin.is() ) + { + OSL_ENSURE( sal_False, "broadcaster was disposed already" ); + throw RuntimeException(); + } + return m_xRowOrigin->wasNull(); +} + +//virtual +rtl::OUString SAL_CALL ContentResultSetWrapper + ::getString( sal_Int32 columnIndex ) + throw( SQLException, + RuntimeException ) +{ + XROW_GETXXX( getString ); +} + +//virtual +sal_Bool SAL_CALL ContentResultSetWrapper + ::getBoolean( sal_Int32 columnIndex ) + throw( SQLException, + RuntimeException ) +{ + XROW_GETXXX( getBoolean ); +} + +//virtual +sal_Int8 SAL_CALL ContentResultSetWrapper + ::getByte( sal_Int32 columnIndex ) + throw( SQLException, + RuntimeException ) +{ + XROW_GETXXX( getByte ); +} + +//virtual +sal_Int16 SAL_CALL ContentResultSetWrapper + ::getShort( sal_Int32 columnIndex ) + throw( SQLException, + RuntimeException ) +{ + XROW_GETXXX( getShort ); +} + +//virtual +sal_Int32 SAL_CALL ContentResultSetWrapper + ::getInt( sal_Int32 columnIndex ) + throw( SQLException, + RuntimeException ) +{ + XROW_GETXXX( getInt ); +} + +//virtual +sal_Int64 SAL_CALL ContentResultSetWrapper + ::getLong( sal_Int32 columnIndex ) + throw( SQLException, + RuntimeException ) +{ + XROW_GETXXX( getLong ); +} + +//virtual +float SAL_CALL ContentResultSetWrapper + ::getFloat( sal_Int32 columnIndex ) + throw( SQLException, + RuntimeException ) +{ + XROW_GETXXX( getFloat ); +} + +//virtual +double SAL_CALL ContentResultSetWrapper + ::getDouble( sal_Int32 columnIndex ) + throw( SQLException, + RuntimeException ) +{ + XROW_GETXXX( getDouble ); +} + +//virtual +Sequence< sal_Int8 > SAL_CALL ContentResultSetWrapper + ::getBytes( sal_Int32 columnIndex ) + throw( SQLException, + RuntimeException ) +{ + XROW_GETXXX( getBytes ); +} + +//virtual +Date SAL_CALL ContentResultSetWrapper + ::getDate( sal_Int32 columnIndex ) + throw( SQLException, + RuntimeException ) +{ + XROW_GETXXX( getDate ); +} + +//virtual +Time SAL_CALL ContentResultSetWrapper + ::getTime( sal_Int32 columnIndex ) + throw( SQLException, + RuntimeException ) +{ + XROW_GETXXX( getTime ); +} + +//virtual +DateTime SAL_CALL ContentResultSetWrapper + ::getTimestamp( sal_Int32 columnIndex ) + throw( SQLException, + RuntimeException ) +{ + XROW_GETXXX( getTimestamp ); +} + +//virtual +Reference< com::sun::star::io::XInputStream > + SAL_CALL ContentResultSetWrapper + ::getBinaryStream( sal_Int32 columnIndex ) + throw( SQLException, + RuntimeException ) +{ + XROW_GETXXX( getBinaryStream ); +} + +//virtual +Reference< com::sun::star::io::XInputStream > + SAL_CALL ContentResultSetWrapper + ::getCharacterStream( sal_Int32 columnIndex ) + throw( SQLException, + RuntimeException ) +{ + XROW_GETXXX( getCharacterStream ); +} + +//virtual +Any SAL_CALL ContentResultSetWrapper + ::getObject( sal_Int32 columnIndex, + const Reference< + com::sun::star::container::XNameAccess >& typeMap ) + throw( SQLException, + RuntimeException ) +{ + //if you change this macro please pay attention to + //define XROW_GETXXX, where this is similar implemented + + impl_EnsureNotDisposed(); + impl_init_xRowOrigin(); + if( !m_xRowOrigin.is() ) + { + OSL_ENSURE( sal_False, "broadcaster was disposed already" ); + throw RuntimeException(); + } + return m_xRowOrigin->getObject( columnIndex, typeMap ); +} + +//virtual +Reference< XRef > SAL_CALL ContentResultSetWrapper + ::getRef( sal_Int32 columnIndex ) + throw( SQLException, + RuntimeException ) +{ + XROW_GETXXX( getRef ); +} + +//virtual +Reference< XBlob > SAL_CALL ContentResultSetWrapper + ::getBlob( sal_Int32 columnIndex ) + throw( SQLException, + RuntimeException ) +{ + XROW_GETXXX( getBlob ); +} + +//virtual +Reference< XClob > SAL_CALL ContentResultSetWrapper + ::getClob( sal_Int32 columnIndex ) + throw( SQLException, + RuntimeException ) +{ + XROW_GETXXX( getClob ); +} + +//virtual +Reference< XArray > SAL_CALL ContentResultSetWrapper + ::getArray( sal_Int32 columnIndex ) + throw( SQLException, + RuntimeException ) +{ + XROW_GETXXX( getArray ); +} + +//-------------------------------------------------------------------------- +//-------------------------------------------------------------------------- +// class ContentResultSetWrapperListener +//-------------------------------------------------------------------------- +//-------------------------------------------------------------------------- + +ContentResultSetWrapperListener::ContentResultSetWrapperListener( + ContentResultSetWrapper* pOwner ) + : m_pOwner( pOwner ) +{ +} + +ContentResultSetWrapperListener::~ContentResultSetWrapperListener() +{ +} + +//-------------------------------------------------------------------------- +// XInterface methods. +//-------------------------------------------------------------------------- +//list all interfaces inclusive baseclasses of interfaces +XINTERFACE_COMMON_IMPL( ContentResultSetWrapperListener ) +QUERYINTERFACE_IMPL_START( ContentResultSetWrapperListener ) + + static_cast< XEventListener * >( + static_cast< XPropertyChangeListener * >(this)) + , SAL_STATIC_CAST( XPropertyChangeListener*, this ) + , SAL_STATIC_CAST( XVetoableChangeListener*, this ) + +QUERYINTERFACE_IMPL_END + + +//-------------------------------------------------------------------------- +//XEventListener methods. +//-------------------------------------------------------------------------- + +//virtual +void SAL_CALL ContentResultSetWrapperListener + ::disposing( const EventObject& rEventObject ) + throw( RuntimeException ) +{ + if( m_pOwner ) + m_pOwner->impl_disposing( rEventObject ); +} + +//-------------------------------------------------------------------------- +//XPropertyChangeListener methods. +//-------------------------------------------------------------------------- + +//virtual +void SAL_CALL ContentResultSetWrapperListener + ::propertyChange( const PropertyChangeEvent& rEvt ) + throw( RuntimeException ) +{ + if( m_pOwner ) + m_pOwner->impl_propertyChange( rEvt ); +} + +//-------------------------------------------------------------------------- +//XVetoableChangeListener methods. +//-------------------------------------------------------------------------- +//virtual +void SAL_CALL ContentResultSetWrapperListener + ::vetoableChange( const PropertyChangeEvent& rEvt ) + throw( PropertyVetoException, + RuntimeException ) +{ + if( m_pOwner ) + m_pOwner->impl_vetoableChange( rEvt ); +} + +void SAL_CALL ContentResultSetWrapperListener + ::impl_OwnerDies() +{ + m_pOwner = NULL; +} + diff --git a/ucb/source/cacher/contentresultsetwrapper.hxx b/ucb/source/cacher/contentresultsetwrapper.hxx new file mode 100644 index 000000000000..b3608aca6f96 --- /dev/null +++ b/ucb/source/cacher/contentresultsetwrapper.hxx @@ -0,0 +1,587 @@ +/************************************************************************* + * + * 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 _CONTENT_RESULTSET_WRAPPER_HXX +#define _CONTENT_RESULTSET_WRAPPER_HXX + +#include <rtl/ustring.hxx> +#include <ucbhelper/macros.hxx> +#include <osl/mutex.hxx> +#include <cppuhelper/weak.hxx> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/sdbc/XCloseable.hpp> +#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp> +#include <com/sun/star/sdbc/XResultSet.hpp> +#include <com/sun/star/sdbc/XRow.hpp> +#include <com/sun/star/ucb/XContentAccess.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <cppuhelper/interfacecontainer.hxx> + +//========================================================================= + +class ContentResultSetWrapperListener; +class ContentResultSetWrapper + : public cppu::OWeakObject + , public com::sun::star::lang::XComponent + , public com::sun::star::sdbc::XCloseable + , public com::sun::star::sdbc::XResultSetMetaDataSupplier + , public com::sun::star::beans::XPropertySet + , public com::sun::star::ucb::XContentAccess + , public com::sun::star::sdbc::XResultSet + , public com::sun::star::sdbc::XRow +{ +protected: + + //-------------------------------------------------------------------------- + //class PropertyChangeListenerContainer_Impl. + + struct equalStr_Impl + { + bool operator()( const rtl::OUString& s1, const rtl::OUString& s2 ) const + { + return !!( s1 == s2 ); + } + }; + + struct hashStr_Impl + { + size_t operator()( const rtl::OUString& rName ) const + { + return rName.hashCode(); + } + }; + + typedef cppu::OMultiTypeInterfaceContainerHelperVar + < rtl::OUString , hashStr_Impl , equalStr_Impl > + PropertyChangeListenerContainer_Impl; + //-------------------------------------------------------------------------- + // class ReacquireableGuard + + class ReacquireableGuard + { + protected: + osl::Mutex* pT; + public: + + ReacquireableGuard(osl::Mutex * t) : pT(t) + { + pT->acquire(); + } + + ReacquireableGuard(osl::Mutex& t) : pT(&t) + { + pT->acquire(); + } + + /** Releases mutex. */ + ~ReacquireableGuard() + { + if (pT) + pT->release(); + } + + /** Releases mutex. */ + void clear() + { + if(pT) + { + pT->release(); + pT = NULL; + } + } + + /** Reacquire mutex. */ + void reacquire() + { + if(pT) + { + pT->acquire(); + } + } + }; + + //----------------------------------------------------------------- + //members + + //my Mutex + osl::Mutex m_aMutex; + + //different Interfaces from Origin: + com::sun::star::uno::Reference< com::sun::star::sdbc::XResultSet > + m_xResultSetOrigin; + com::sun::star::uno::Reference< com::sun::star::sdbc::XRow > + m_xRowOrigin; //XRow-interface from m_xOrigin + //!! call impl_init_xRowOrigin() bevor you access this member + com::sun::star::uno::Reference< com::sun::star::ucb::XContentAccess > + m_xContentAccessOrigin; //XContentAccess-interface from m_xOrigin + //!! call impl_init_xContentAccessOrigin() bevor you access this member + com::sun::star::uno::Reference< com::sun::star::beans::XPropertySet > + m_xPropertySetOrigin; //XPropertySet-interface from m_xOrigin + //!! call impl_init_xPropertySetOrigin() bevor you access this member + + com::sun::star::uno::Reference< com::sun::star::beans::XPropertySetInfo > + m_xPropertySetInfo; + //call impl_initPropertySetInfo() bevor you access this member + + sal_Int32 m_nForwardOnly; + +private: + com::sun::star::uno::Reference< com::sun::star::beans::XPropertyChangeListener > + m_xMyListenerImpl; + ContentResultSetWrapperListener* + m_pMyListenerImpl; + + com::sun::star::uno::Reference< com::sun::star::sdbc::XResultSetMetaData > + m_xMetaDataFromOrigin; //XResultSetMetaData from m_xOrigin + + //management of listeners + sal_Bool m_bDisposed; ///Dispose call ready. + sal_Bool m_bInDispose;///In dispose call + osl::Mutex m_aContainerMutex; + cppu::OInterfaceContainerHelper* + m_pDisposeEventListeners; + PropertyChangeListenerContainer_Impl* + m_pPropertyChangeListeners; + PropertyChangeListenerContainer_Impl* + m_pVetoableChangeListeners; + + //----------------------------------------------------------------- + //methods: +private: + PropertyChangeListenerContainer_Impl* SAL_CALL + impl_getPropertyChangeListenerContainer(); + + PropertyChangeListenerContainer_Impl* SAL_CALL + impl_getVetoableChangeListenerContainer(); + +protected: + //----------------------------------------------------------------- + + ContentResultSetWrapper( com::sun::star::uno::Reference< + com::sun::star::sdbc::XResultSet > xOrigin ); + + virtual ~ContentResultSetWrapper(); + + void SAL_CALL impl_init(); + void SAL_CALL impl_deinit(); + + //-- + + void SAL_CALL impl_init_xRowOrigin(); + void SAL_CALL impl_init_xContentAccessOrigin(); + void SAL_CALL impl_init_xPropertySetOrigin(); + + //-- + + virtual void SAL_CALL impl_initPropertySetInfo(); //helping XPropertySet + + void SAL_CALL + impl_EnsureNotDisposed() + throw( com::sun::star::lang::DisposedException, + com::sun::star::uno::RuntimeException ); + + void SAL_CALL + impl_notifyPropertyChangeListeners( + const com::sun::star::beans::PropertyChangeEvent& rEvt ); + + void SAL_CALL + impl_notifyVetoableChangeListeners( + const com::sun::star::beans::PropertyChangeEvent& rEvt ) + throw( com::sun::star::beans::PropertyVetoException, + com::sun::star::uno::RuntimeException ); + + sal_Bool SAL_CALL impl_isForwardOnly(); + +public: + + //----------------------------------------------------------------- + // XInterface + //----------------------------------------------------------------- + virtual com::sun::star::uno::Any SAL_CALL + queryInterface( const com::sun::star::uno::Type & rType ) + throw( com::sun::star::uno::RuntimeException ); + + //----------------------------------------------------------------- + // XComponent + //----------------------------------------------------------------- + virtual void SAL_CALL + dispose() throw( com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL + addEventListener( const com::sun::star::uno::Reference< + com::sun::star::lang::XEventListener >& Listener ) + throw( com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL + removeEventListener( const com::sun::star::uno::Reference< + com::sun::star::lang::XEventListener >& Listener ) + throw( com::sun::star::uno::RuntimeException ); + + //----------------------------------------------------------------- + //XCloseable + //----------------------------------------------------------------- + virtual void SAL_CALL + close() + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + //----------------------------------------------------------------- + //XResultSetMetaDataSupplier + //----------------------------------------------------------------- + virtual com::sun::star::uno::Reference< + com::sun::star::sdbc::XResultSetMetaData > SAL_CALL + getMetaData() + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + //----------------------------------------------------------------- + // XPropertySet + //----------------------------------------------------------------- + virtual com::sun::star::uno::Reference< + com::sun::star::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo() + throw( com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL + setPropertyValue( const rtl::OUString& aPropertyName, + const com::sun::star::uno::Any& aValue ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::beans::PropertyVetoException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::uno::Any SAL_CALL + getPropertyValue( const rtl::OUString& PropertyName ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL + addPropertyChangeListener( const rtl::OUString& aPropertyName, + const com::sun::star::uno::Reference< + com::sun::star::beans::XPropertyChangeListener >& xListener ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL + removePropertyChangeListener( const rtl::OUString& aPropertyName, + const com::sun::star::uno::Reference< + com::sun::star::beans::XPropertyChangeListener >& aListener ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL + addVetoableChangeListener( const rtl::OUString& PropertyName, + const com::sun::star::uno::Reference< + com::sun::star::beans::XVetoableChangeListener >& aListener ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL + removeVetoableChangeListener( const rtl::OUString& PropertyName, + const com::sun::star::uno::Reference< + com::sun::star::beans::XVetoableChangeListener >& aListener ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException ); + + //----------------------------------------------------------------- + // own methods + //----------------------------------------------------------------- + virtual void SAL_CALL + impl_disposing( const com::sun::star::lang::EventObject& Source ) + throw( com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL + impl_propertyChange( const com::sun::star::beans::PropertyChangeEvent& evt ) + throw( com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL + impl_vetoableChange( const com::sun::star::beans::PropertyChangeEvent& aEvent ) + throw( com::sun::star::beans::PropertyVetoException, + com::sun::star::uno::RuntimeException ); + + //----------------------------------------------------------------- + // XContentAccess + //----------------------------------------------------------------- + virtual rtl::OUString SAL_CALL + queryContentIdentifierString() + throw( com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier > SAL_CALL + queryContentIdentifier() + throw( com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::uno::Reference< + com::sun::star::ucb::XContent > SAL_CALL + queryContent() + throw( com::sun::star::uno::RuntimeException ); + + //----------------------------------------------------------------- + // XResultSet + //----------------------------------------------------------------- + virtual sal_Bool SAL_CALL + next() + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL + isBeforeFirst() + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL + isAfterLast() + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL + isFirst() + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL + isLast() + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + beforeFirst() + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + afterLast() + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL + first() + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL + last() + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + virtual sal_Int32 SAL_CALL + getRow() + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL + absolute( sal_Int32 row ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL + relative( sal_Int32 rows ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL + previous() + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + refreshRow() + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL + rowUpdated() + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL + rowInserted() + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL + rowDeleted() + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + virtual com::sun::star::uno::Reference< + com::sun::star::uno::XInterface > SAL_CALL + getStatement() + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + //----------------------------------------------------------------- + // XRow + //----------------------------------------------------------------- + virtual sal_Bool SAL_CALL + wasNull() + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + virtual rtl::OUString SAL_CALL + getString( sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + virtual sal_Bool SAL_CALL + getBoolean( sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + virtual sal_Int8 SAL_CALL + getByte( sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + virtual sal_Int16 SAL_CALL + getShort( sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + virtual sal_Int32 SAL_CALL + getInt( sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + virtual sal_Int64 SAL_CALL + getLong( sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + virtual float SAL_CALL + getFloat( sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + virtual double SAL_CALL + getDouble( sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL + getBytes( sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::util::Date SAL_CALL + getDate( sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::util::Time SAL_CALL + getTime( sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::util::DateTime SAL_CALL + getTimestamp( sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::uno::Reference< + com::sun::star::io::XInputStream > SAL_CALL + getBinaryStream( sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::uno::Reference< + com::sun::star::io::XInputStream > SAL_CALL + getCharacterStream( sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::uno::Any SAL_CALL + getObject( sal_Int32 columnIndex, + const com::sun::star::uno::Reference< + com::sun::star::container::XNameAccess >& typeMap ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::uno::Reference< + com::sun::star::sdbc::XRef > SAL_CALL + getRef( sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::uno::Reference< + com::sun::star::sdbc::XBlob > SAL_CALL + getBlob( sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::uno::Reference< + com::sun::star::sdbc::XClob > SAL_CALL + getClob( sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::uno::Reference< + com::sun::star::sdbc::XArray > SAL_CALL + getArray( sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); +}; + +//========================================================================= + +class ContentResultSetWrapperListener + : public cppu::OWeakObject + , public com::sun::star::beans::XPropertyChangeListener + , public com::sun::star::beans::XVetoableChangeListener +{ +protected: + ContentResultSetWrapper* m_pOwner; + +public: + ContentResultSetWrapperListener( ContentResultSetWrapper* pOwner ); + + virtual ~ContentResultSetWrapperListener(); + + //----------------------------------------------------------------- + // XInterface + //----------------------------------------------------------------- + XINTERFACE_DECL() + + //----------------------------------------------------------------- + //XEventListener + //----------------------------------------------------------------- + virtual void SAL_CALL + disposing( const com::sun::star::lang::EventObject& Source ) + throw( com::sun::star::uno::RuntimeException ); + + //----------------------------------------------------------------- + //XPropertyChangeListener + //----------------------------------------------------------------- + virtual void SAL_CALL + propertyChange( const com::sun::star::beans::PropertyChangeEvent& evt ) + throw( com::sun::star::uno::RuntimeException ); + + //----------------------------------------------------------------- + //XVetoableChangeListener + //----------------------------------------------------------------- + virtual void SAL_CALL + vetoableChange( const com::sun::star::beans::PropertyChangeEvent& aEvent ) + throw( com::sun::star::beans::PropertyVetoException, + com::sun::star::uno::RuntimeException ); + + //----------------------------------------------------------------- + // own methods: + void SAL_CALL impl_OwnerDies(); +}; + +#endif + diff --git a/ucb/source/cacher/dynamicresultsetwrapper.cxx b/ucb/source/cacher/dynamicresultsetwrapper.cxx new file mode 100644 index 000000000000..ab98c97bc4e2 --- /dev/null +++ b/ucb/source/cacher/dynamicresultsetwrapper.cxx @@ -0,0 +1,528 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +#include <dynamicresultsetwrapper.hxx> +#include <ucbhelper/macros.hxx> +#include <osl/diagnose.h> +#include <rtl/ustring.hxx> +#include <com/sun/star/ucb/ListActionType.hpp> +#include <com/sun/star/ucb/WelcomeDynamicResultSetStruct.hpp> +#include <com/sun/star/ucb/XCachedDynamicResultSetStubFactory.hpp> + +using namespace com::sun::star::lang; +using namespace com::sun::star::sdbc; +using namespace com::sun::star::ucb; +using namespace com::sun::star::uno; +using namespace cppu; +using namespace rtl; + +//-------------------------------------------------------------------------- +//-------------------------------------------------------------------------- +// class DynamicResultSetWrapper +//-------------------------------------------------------------------------- +//-------------------------------------------------------------------------- + +DynamicResultSetWrapper::DynamicResultSetWrapper( + Reference< XDynamicResultSet > xOrigin + , const Reference< XMultiServiceFactory > & xSMgr ) + + : m_bDisposed( sal_False ) + , m_bInDispose( sal_False ) + , m_pDisposeEventListeners( NULL ) + , m_xSMgr( xSMgr ) + , m_bStatic( sal_False ) + , m_bGotWelcome( sal_False ) + , m_xSource( xOrigin ) + , m_xSourceResultOne( NULL ) + , m_xSourceResultTwo( NULL ) + // , m_xSourceResultCurrent( NULL ) + // , m_bUseOne( NULL ) + , m_xMyResultOne( NULL ) + , m_xMyResultTwo( NULL ) + , m_xListener( NULL ) +{ + m_pMyListenerImpl = new DynamicResultSetWrapperListener( this ); + m_xMyListenerImpl = Reference< XDynamicResultSetListener >( m_pMyListenerImpl ); + //call impl_init() at the end of constructor of derived class +}; + +void SAL_CALL DynamicResultSetWrapper::impl_init() +{ + //call this at the end of constructor of derived class + // + + Reference< XDynamicResultSet > xSource = NULL; + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + xSource = m_xSource; + m_xSource = NULL; + } + if( xSource.is() ) + setSource( xSource ); +} + +DynamicResultSetWrapper::~DynamicResultSetWrapper() +{ + //call impl_deinit() at start of destructor of derived class + + delete m_pDisposeEventListeners; +}; + +void SAL_CALL DynamicResultSetWrapper::impl_deinit() +{ + //call this at start of destructor of derived class + // + m_pMyListenerImpl->impl_OwnerDies(); +} + +void SAL_CALL DynamicResultSetWrapper +::impl_EnsureNotDisposed() + throw( DisposedException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + if( m_bDisposed ) + throw DisposedException(); +} + +//virtual +void SAL_CALL DynamicResultSetWrapper +::impl_InitResultSetOne( const Reference< XResultSet >& xResultSet ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + OSL_ENSURE( !m_xSourceResultOne.is(), "Source ResultSet One is set already" ); + m_xSourceResultOne = xResultSet; + m_xMyResultOne = xResultSet; +} + +//virtual +void SAL_CALL DynamicResultSetWrapper +::impl_InitResultSetTwo( const Reference< XResultSet >& xResultSet ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + OSL_ENSURE( !m_xSourceResultTwo.is(), "Source ResultSet Two is set already" ); + m_xSourceResultTwo = xResultSet; + m_xMyResultTwo = xResultSet; +} + +//-------------------------------------------------------------------------- +// XInterface methods. +//-------------------------------------------------------------------------- +//list all interfaces inclusive baseclasses of interfaces +QUERYINTERFACE_IMPL_START( DynamicResultSetWrapper ) + SAL_STATIC_CAST( XComponent*, this ) //base of XDynamicResultSet + , SAL_STATIC_CAST( XDynamicResultSet*, this ) + , SAL_STATIC_CAST( XSourceInitialization*, this ) +QUERYINTERFACE_IMPL_END + +//-------------------------------------------------------------------------- +// XComponent methods. +//-------------------------------------------------------------------------- +// virtual +void SAL_CALL DynamicResultSetWrapper + ::dispose() throw( RuntimeException ) +{ + impl_EnsureNotDisposed(); + + Reference< XComponent > xSourceComponent; + { + osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); + if( m_bInDispose || m_bDisposed ) + return; + m_bInDispose = sal_True; + + xSourceComponent = Reference< XComponent >(m_xSource, UNO_QUERY); + + if( m_pDisposeEventListeners && m_pDisposeEventListeners->getLength() ) + { + EventObject aEvt; + aEvt.Source = static_cast< XComponent * >( this ); + + aGuard.clear(); + m_pDisposeEventListeners->disposeAndClear( aEvt ); + } + } + + /* //@todo ?? ( only if java collection needs to long ) + if( xSourceComponent.is() ) + xSourceComponent->dispose(); + */ + + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + m_bDisposed = sal_True; + m_bInDispose = sal_False; +} + +//-------------------------------------------------------------------------- +// virtual +void SAL_CALL DynamicResultSetWrapper + ::addEventListener( const Reference< XEventListener >& Listener ) + throw( RuntimeException ) +{ + impl_EnsureNotDisposed(); + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + if ( !m_pDisposeEventListeners ) + m_pDisposeEventListeners = + new OInterfaceContainerHelper( m_aContainerMutex ); + + m_pDisposeEventListeners->addInterface( Listener ); +} + +//-------------------------------------------------------------------------- +// virtual +void SAL_CALL DynamicResultSetWrapper + ::removeEventListener( const Reference< XEventListener >& Listener ) + throw( RuntimeException ) +{ + impl_EnsureNotDisposed(); + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + if ( m_pDisposeEventListeners ) + m_pDisposeEventListeners->removeInterface( Listener ); +} + +//-------------------------------------------------------------------------- +// own methods +//-------------------------------------------------------------------------- + +//virtual +void SAL_CALL DynamicResultSetWrapper + ::impl_disposing( const EventObject& ) + throw( RuntimeException ) +{ + impl_EnsureNotDisposed(); + + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + if( !m_xSource.is() ) + return; + + //release all references to the broadcaster: + m_xSource.clear(); + m_xSourceResultOne.clear();//?? or only when not static?? + m_xSourceResultTwo.clear();//?? + //@todo m_xMyResultOne.clear(); ??? + //@todo m_xMyResultTwo.clear(); ??? +} + +//virtual +void SAL_CALL DynamicResultSetWrapper + ::impl_notify( const ListEvent& Changes ) + throw( RuntimeException ) +{ + impl_EnsureNotDisposed(); + //@todo + /* + <p>The Listener is allowed to blockade this call, until he really want to go + to the new version. The only situation, where the listener has to return the + update call at once is, while he disposes his broadcaster or while he is + removing himsef as listener (otherwise you deadlock)!!! + */ + // handle the actions in the list + + ListEvent aNewEvent; + aNewEvent.Source = static_cast< XDynamicResultSet * >( this ); + aNewEvent.Changes = Changes.Changes; + + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + for( long i=0; !m_bGotWelcome && i<Changes.Changes.getLength(); i++ ) + { + ListAction& rAction = aNewEvent.Changes[i]; + switch( rAction.ListActionType ) + { + case ListActionType::WELCOME: + { + WelcomeDynamicResultSetStruct aWelcome; + if( rAction.ActionInfo >>= aWelcome ) + { + impl_InitResultSetOne( aWelcome.Old ); + impl_InitResultSetTwo( aWelcome.New ); + m_bGotWelcome = sal_True; + + aWelcome.Old = m_xMyResultOne; + aWelcome.New = m_xMyResultTwo; + + rAction.ActionInfo <<= aWelcome; + } + else + { + OSL_ENSURE( sal_False, "ListActionType was WELCOME but ActionInfo didn't contain a WelcomeDynamicResultSetStruct" ); + //throw RuntimeException(); + } + break; + } + } + } + OSL_ENSURE( m_bGotWelcome, "first notification was without WELCOME" ); + } + + if( !m_xListener.is() ) + m_aListenerSet.wait(); + m_xListener->notify( aNewEvent ); + + /* + m_bUseOne = !m_bUseOne; + if( m_bUseOne ) + m_xSourceResultCurrent = m_xSourceResultOne; + else + m_xSourceResultCurrent = m_xSourceResultTwo; + */ +} + +//-------------------------------------------------------------------------- +// XSourceInitialization +//-------------------------------------------------------------------------- +//virtual +void SAL_CALL DynamicResultSetWrapper + ::setSource( const Reference< XInterface > & Source ) + throw( AlreadyInitializedException, RuntimeException ) +{ + impl_EnsureNotDisposed(); + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + if( m_xSource.is() ) + { + throw AlreadyInitializedException(); + } + } + + Reference< XDynamicResultSet > xSourceDynamic( Source, UNO_QUERY ); + OSL_ENSURE( xSourceDynamic.is(), + "the given source is not of required type XDynamicResultSet" ); + + Reference< XDynamicResultSetListener > xListener = NULL; + Reference< XDynamicResultSetListener > xMyListenerImpl = NULL; + + sal_Bool bStatic = sal_False; + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + m_xSource = xSourceDynamic; + xListener = m_xListener; + bStatic = m_bStatic; + xMyListenerImpl = m_xMyListenerImpl; + } + if( xListener.is() ) + xSourceDynamic->setListener( m_xMyListenerImpl ); + else if( bStatic ) + { + Reference< XComponent > xSourceComponent( Source, UNO_QUERY ); + xSourceComponent->addEventListener( Reference< XEventListener > ::query( xMyListenerImpl ) ); + } + m_aSourceSet.set(); +} + +//-------------------------------------------------------------------------- +// XDynamicResultSet +//-------------------------------------------------------------------------- +//virtual +Reference< XResultSet > SAL_CALL DynamicResultSetWrapper + ::getStaticResultSet() + throw( ListenerAlreadySetException, RuntimeException ) +{ + impl_EnsureNotDisposed(); + + Reference< XDynamicResultSet > xSource = NULL; + Reference< XEventListener > xMyListenerImpl = NULL; + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + if( m_xListener.is() ) + throw ListenerAlreadySetException(); + + xSource = m_xSource; + m_bStatic = sal_True; + xMyListenerImpl = Reference< XEventListener > ::query( m_xMyListenerImpl ); + } + + if( xSource.is() ) + { + Reference< XComponent > xSourceComponent( xSource, UNO_QUERY ); + xSourceComponent->addEventListener( xMyListenerImpl ); + } + if( !xSource.is() ) + m_aSourceSet.wait(); + + + Reference< XResultSet > xResultSet = xSource->getStaticResultSet(); + impl_InitResultSetOne( xResultSet ); + return m_xMyResultOne; +} + +//virtual +void SAL_CALL DynamicResultSetWrapper + ::setListener( const Reference< + XDynamicResultSetListener > & Listener ) + throw( ListenerAlreadySetException, RuntimeException ) +{ + impl_EnsureNotDisposed(); + + Reference< XDynamicResultSet > xSource = NULL; + Reference< XDynamicResultSetListener > xMyListenerImpl = NULL; + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + if( m_xListener.is() ) + throw ListenerAlreadySetException(); + if( m_bStatic ) + throw ListenerAlreadySetException(); + + m_xListener = Listener; + addEventListener( Reference< XEventListener >::query( Listener ) ); + + xSource = m_xSource; + xMyListenerImpl = m_xMyListenerImpl; + } + if ( xSource.is() ) + xSource->setListener( xMyListenerImpl ); + + m_aListenerSet.set(); +} + +//virtual +void SAL_CALL DynamicResultSetWrapper + ::connectToCache( const Reference< XDynamicResultSet > & xCache ) + throw( ListenerAlreadySetException, AlreadyInitializedException, ServiceNotFoundException, RuntimeException ) +{ + impl_EnsureNotDisposed(); + + if( m_xListener.is() ) + throw ListenerAlreadySetException(); + if( m_bStatic ) + throw ListenerAlreadySetException(); + + Reference< XSourceInitialization > xTarget( xCache, UNO_QUERY ); + OSL_ENSURE( xTarget.is(), "The given Target dosn't have the required interface 'XSourceInitialization'" ); + if( xTarget.is() && m_xSMgr.is() ) + { + //@todo m_aSourceSet.wait();? + + Reference< XCachedDynamicResultSetStubFactory > xStubFactory; + try + { + xStubFactory = Reference< XCachedDynamicResultSetStubFactory >( + m_xSMgr->createInstance( + OUString::createFromAscii( + "com.sun.star.ucb.CachedDynamicResultSetStubFactory" ) ), + UNO_QUERY ); + } + catch ( Exception const & ) + { + } + + if( xStubFactory.is() ) + { + xStubFactory->connectToCache( + this, xCache, Sequence< NumberedSortingInfo > (), NULL ); + return; + } + } + OSL_ENSURE( sal_False, "could not connect to cache" ); + throw ServiceNotFoundException(); +} + +//virtual +sal_Int16 SAL_CALL DynamicResultSetWrapper + ::getCapabilities() + throw( RuntimeException ) +{ + impl_EnsureNotDisposed(); + + m_aSourceSet.wait(); + Reference< XDynamicResultSet > xSource = NULL; + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + xSource = m_xSource; + } + return xSource->getCapabilities(); +} + +//-------------------------------------------------------------------------- +//-------------------------------------------------------------------------- +// class DynamicResultSetWrapperListener +//-------------------------------------------------------------------------- +//-------------------------------------------------------------------------- + +DynamicResultSetWrapperListener::DynamicResultSetWrapperListener( + DynamicResultSetWrapper* pOwner ) + : m_pOwner( pOwner ) +{ + +} + +DynamicResultSetWrapperListener::~DynamicResultSetWrapperListener() +{ + +} + +//-------------------------------------------------------------------------- +// XInterface methods. +//-------------------------------------------------------------------------- +//list all interfaces inclusive baseclasses of interfaces +XINTERFACE_IMPL_2( DynamicResultSetWrapperListener + , XDynamicResultSetListener + , XEventListener //base of XDynamicResultSetListener + ); + +//-------------------------------------------------------------------------- +// XDynamicResultSetListener methods: +//-------------------------------------------------------------------------- +//virtual +void SAL_CALL DynamicResultSetWrapperListener + ::disposing( const EventObject& rEventObject ) + throw( RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + if( m_pOwner ) + m_pOwner->impl_disposing( rEventObject ); +} + +//virtual +void SAL_CALL DynamicResultSetWrapperListener + ::notify( const ListEvent& Changes ) + throw( RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + if( m_pOwner ) + m_pOwner->impl_notify( Changes ); +} + +//-------------------------------------------------------------------------- +// own methods: +//-------------------------------------------------------------------------- + +void SAL_CALL DynamicResultSetWrapperListener + ::impl_OwnerDies() +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + m_pOwner = NULL; +} + diff --git a/ucb/source/cacher/dynamicresultsetwrapper.hxx b/ucb/source/cacher/dynamicresultsetwrapper.hxx new file mode 100644 index 000000000000..47ff822a6ce1 --- /dev/null +++ b/ucb/source/cacher/dynamicresultsetwrapper.hxx @@ -0,0 +1,229 @@ +/************************************************************************* + * + * 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 _DYNAMIC_RESULTSET_WRAPPER_HXX +#define _DYNAMIC_RESULTSET_WRAPPER_HXX + +#include <osl/mutex.hxx> +#include <osl/conditn.hxx> +#include <ucbhelper/macros.hxx> +#include <cppuhelper/weak.hxx> +#include <com/sun/star/lang/XTypeProvider.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <cppuhelper/interfacecontainer.hxx> +#include <com/sun/star/ucb/XDynamicResultSet.hpp> +#include <com/sun/star/ucb/XSourceInitialization.hpp> + +#ifndef __com_sun_star_lang_DisposedException_idl__ +#include <com/sun/star/lang/DisposedException.hpp> +#endif +#include <com/sun/star/ucb/XDynamicResultSetListener.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> + +//#define CACHED_CRS_STUB_SERVICE_NAME "com.sun.star.ucb.CachedContentResultSetStub" +//#define CACHED_CRS_STUB_FACTORY_NAME "com.sun.star.ucb.CachedContentResultSetStubFactory" + +//========================================================================= + +class DynamicResultSetWrapperListener; +class DynamicResultSetWrapper + : public cppu::OWeakObject + , public com::sun::star::ucb::XDynamicResultSet + , public com::sun::star::ucb::XSourceInitialization +{ +private: + //management of listeners + sal_Bool m_bDisposed; ///Dispose call ready. + sal_Bool m_bInDispose;///In dispose call + osl::Mutex m_aContainerMutex; + cppu::OInterfaceContainerHelper* + m_pDisposeEventListeners; +protected: + com::sun::star::uno::Reference< com::sun::star::ucb::XDynamicResultSetListener > + m_xMyListenerImpl; + DynamicResultSetWrapperListener* + m_pMyListenerImpl; + + com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory > + m_xSMgr; + + osl::Mutex m_aMutex; + sal_Bool m_bStatic; + sal_Bool m_bGotWelcome; + + //different Interfaces from Origin: + com::sun::star::uno::Reference< com::sun::star::ucb::XDynamicResultSet > + m_xSource; + com::sun::star::uno::Reference< com::sun::star::sdbc::XResultSet > + m_xSourceResultOne; + com::sun::star::uno::Reference< com::sun::star::sdbc::XResultSet > + m_xSourceResultTwo; + //com::sun::star::uno::Reference< com::sun::star::sdbc::XResultSet > + // m_xSourceResultCurrent; + //sal_Bool m_bUseOne; + // + com::sun::star::uno::Reference< com::sun::star::sdbc::XResultSet > + m_xMyResultOne; + com::sun::star::uno::Reference< com::sun::star::sdbc::XResultSet > + m_xMyResultTwo; + // + com::sun::star::uno::Reference< com::sun::star::ucb::XDynamicResultSetListener > + m_xListener; + + osl::Condition m_aSourceSet; + osl::Condition m_aListenerSet; + +protected: + void SAL_CALL impl_init(); + void SAL_CALL impl_deinit(); + void SAL_CALL + impl_EnsureNotDisposed() + throw( com::sun::star::lang::DisposedException, + com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL + impl_InitResultSetOne( const com::sun::star::uno::Reference< + com::sun::star::sdbc::XResultSet >& xResultSet ); + virtual void SAL_CALL + impl_InitResultSetTwo( const com::sun::star::uno::Reference< + com::sun::star::sdbc::XResultSet >& xResultSet ); + +public: + + DynamicResultSetWrapper( + com::sun::star::uno::Reference< + com::sun::star::ucb::XDynamicResultSet > xOrigin + , const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory > & xSMgr ); + + virtual ~DynamicResultSetWrapper(); + + //----------------------------------------------------------------- + // XInterface + virtual com::sun::star::uno::Any SAL_CALL + queryInterface( const com::sun::star::uno::Type & rType ) + throw( com::sun::star::uno::RuntimeException ); + + //----------------------------------------------------------------- + // XDynamicResultSet + virtual com::sun::star::uno::Reference< com::sun::star::sdbc::XResultSet > SAL_CALL + getStaticResultSet() + throw( com::sun::star::ucb::ListenerAlreadySetException + , com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL + setListener( const com::sun::star::uno::Reference< + com::sun::star::ucb::XDynamicResultSetListener > & Listener ) + throw( com::sun::star::ucb::ListenerAlreadySetException + , com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL + connectToCache( const com::sun::star::uno::Reference< + com::sun::star::ucb::XDynamicResultSet > & xCache ) + throw( com::sun::star::ucb::ListenerAlreadySetException + , com::sun::star::ucb::AlreadyInitializedException + , com::sun::star::ucb::ServiceNotFoundException + , com::sun::star::uno::RuntimeException ); + + virtual sal_Int16 SAL_CALL + getCapabilities() throw( com::sun::star::uno::RuntimeException ); + + //----------------------------------------------------------------- + // XComponent ( base of XDynamicResultSet ) + virtual void SAL_CALL + dispose() throw( com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL + addEventListener( const com::sun::star::uno::Reference< + com::sun::star::lang::XEventListener >& Listener ) + throw( com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL + removeEventListener( const com::sun::star::uno::Reference< + com::sun::star::lang::XEventListener >& Listener ) + throw( com::sun::star::uno::RuntimeException ); + + //----------------------------------------------------------------- + // XSourceInitialization + + virtual void SAL_CALL + setSource( const com::sun::star::uno::Reference< + com::sun::star::uno::XInterface > & Source ) + throw( com::sun::star::ucb::AlreadyInitializedException + , com::sun::star::uno::RuntimeException ); + + //----------------------------------------------------------------- + // own methods: + virtual void SAL_CALL + impl_disposing( const com::sun::star::lang::EventObject& Source ) + throw( com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL + impl_notify( const ::com::sun::star::ucb::ListEvent& Changes ) + throw( com::sun::star::uno::RuntimeException ); +}; + +//========================================================================= + +class DynamicResultSetWrapperListener + : public cppu::OWeakObject + , public com::sun::star::ucb::XDynamicResultSetListener +{ +protected: + DynamicResultSetWrapper* m_pOwner; + osl::Mutex m_aMutex; + +public: + DynamicResultSetWrapperListener( DynamicResultSetWrapper* pOwner ); + + virtual ~DynamicResultSetWrapperListener(); + + //----------------------------------------------------------------- + // XInterface + //----------------------------------------------------------------- + XINTERFACE_DECL() + + //----------------------------------------------------------------- + // XEventListener ( base of XDynamicResultSetListener ) + //----------------------------------------------------------------- + virtual void SAL_CALL + disposing( const com::sun::star::lang::EventObject& Source ) + throw( com::sun::star::uno::RuntimeException ); + //----------------------------------------------------------------- + // XDynamicResultSetListener + virtual void SAL_CALL + notify( const ::com::sun::star::ucb::ListEvent& Changes ) + throw( com::sun::star::uno::RuntimeException ); + + //----------------------------------------------------------------- + // own methods: + void SAL_CALL impl_OwnerDies(); +}; + + +#endif + diff --git a/ucb/source/cacher/makefile.mk b/ucb/source/cacher/makefile.mk new file mode 100644 index 000000000000..24d245ec6ce8 --- /dev/null +++ b/ucb/source/cacher/makefile.mk @@ -0,0 +1,76 @@ +#************************************************************************* +# +# 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=ucb +TARGET=cached +ENABLE_EXCEPTIONS=TRUE +NO_BSYMBOLIC=TRUE + +# Version +UCB_MAJOR=1 + +.INCLUDE: settings.mk +.IF "$(L10N_framework)"=="" + +SLOFILES=\ + $(SLO)$/contentresultsetwrapper.obj \ + $(SLO)$/cachedcontentresultsetstub.obj \ + $(SLO)$/cachedcontentresultset.obj \ + $(SLO)$/dynamicresultsetwrapper.obj \ + $(SLO)$/cacheddynamicresultsetstub.obj \ + $(SLO)$/cacheddynamicresultset.obj \ + $(SLO)$/cacheserv.obj + +LIB1TARGET=$(SLB)$/_$(TARGET).lib +LIB1OBJFILES=$(SLOFILES) + +SHL1TARGET=$(TARGET)$(UCB_MAJOR) +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +SHL1STDLIBS=\ + $(CPPUHELPERLIB) \ + $(CPPULIB) \ + $(SALLIB) + +SHL1LIBS=$(LIB1TARGET) +SHL1IMPLIB=i$(TARGET) + +SHL1VERSIONMAP=$(SOLARENV)/src/component.map + +DEF1NAME=$(SHL1TARGET) +.ENDIF # L10N_framework + +.INCLUDE: target.mk + + +ALLTAR : $(MISC)/cached1.component + +$(MISC)/cached1.component .ERRREMOVE : $(SOLARENV)/bin/createcomponent.xslt \ + cached1.component + $(XSLTPROC) --nonet --stringparam uri \ + '$(COMPONENTPREFIX_BASIS_NATIVE)$(SHL1TARGETN:f)' -o $@ \ + $(SOLARENV)/bin/createcomponent.xslt cached1.component diff --git a/ucb/source/core/cmdenv.cxx b/ucb/source/core/cmdenv.cxx new file mode 100644 index 000000000000..5c0136fab063 --- /dev/null +++ b/ucb/source/core/cmdenv.cxx @@ -0,0 +1,191 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +#include "cppuhelper/factory.hxx" +#include "com/sun/star/lang/IllegalArgumentException.hpp" + +#include "cmdenv.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ +using namespace com::sun::star; +using namespace ucb_cmdenv; + +//========================================================================= +//========================================================================= +// +// UcbCommandEnvironment Implementation. +// +//========================================================================= +//========================================================================= + +UcbCommandEnvironment::UcbCommandEnvironment( + const uno::Reference< lang::XMultiServiceFactory >& /*xSMgr*/ ) +//: m_xSMgr( xSMgr ) +{ +} + +//========================================================================= +// virtual +UcbCommandEnvironment::~UcbCommandEnvironment() +{ +} + +//========================================================================= +// +// XInitialization methods. +// +//========================================================================= + +// virtual +void SAL_CALL UcbCommandEnvironment::initialize( + const uno::Sequence< uno::Any >& aArguments ) + throw( uno::Exception, + uno::RuntimeException ) +{ + if ( ( aArguments.getLength() < 2 ) || + !( aArguments[ 0 ] >>= m_xIH ) || + !( aArguments[ 1 ] >>= m_xPH )) + throw lang::IllegalArgumentException(); +} + +//========================================================================= +// +// XServiceInfo methods. +// +//========================================================================= + +// virtual +::rtl::OUString SAL_CALL UcbCommandEnvironment::getImplementationName() + throw ( uno::RuntimeException ) +{ + return getImplementationName_Static(); +} + +//========================================================================= +// virtual +sal_Bool SAL_CALL +UcbCommandEnvironment::supportsService( const ::rtl::OUString& ServiceName ) + throw ( uno::RuntimeException ) +{ + uno::Sequence< rtl::OUString > aSNL = getSupportedServiceNames(); + const rtl::OUString * pArray = aSNL.getConstArray(); + for ( sal_Int32 i = 0; i < aSNL.getLength(); i++ ) + { + if ( pArray[ i ] == ServiceName ) + return sal_True; + } + return sal_False; +} + +//========================================================================= +// virtual +uno::Sequence< ::rtl::OUString > SAL_CALL +UcbCommandEnvironment::getSupportedServiceNames() + throw ( uno::RuntimeException ) +{ + return getSupportedServiceNames_Static(); +} + +//========================================================================= +// static +rtl::OUString UcbCommandEnvironment::getImplementationName_Static() +{ + return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.comp.ucb.CommandEnvironment" ) ); +} + +//========================================================================= +// static +uno::Sequence< rtl::OUString > +UcbCommandEnvironment::getSupportedServiceNames_Static() +{ + uno::Sequence< rtl::OUString > aSNS( 1 ); + aSNS.getArray()[ 0 ] + = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.ucb.CommandEnvironment" ) ); + return aSNS; +} + +//========================================================================= +// +// XCommandInfo methods. +// +//========================================================================= + +// virtual +uno::Reference< task::XInteractionHandler > SAL_CALL +UcbCommandEnvironment::getInteractionHandler() + throw ( uno::RuntimeException ) +{ + return m_xIH; +} + +//========================================================================= +// virtual +uno::Reference< ucb::XProgressHandler > SAL_CALL +UcbCommandEnvironment::getProgressHandler() + throw ( uno::RuntimeException ) +{ + return m_xPH; +} + +//========================================================================= +// +// Service factory implementation. +// +//========================================================================= + +static uno::Reference< uno::XInterface > SAL_CALL +UcbCommandEnvironment_CreateInstance( + const uno::Reference< lang::XMultiServiceFactory> & rSMgr ) + throw( uno::Exception ) +{ + lang::XServiceInfo * pX = static_cast< lang::XServiceInfo * >( + new UcbCommandEnvironment( rSMgr ) ); + return uno::Reference< uno::XInterface >::query( pX ); +} + +//========================================================================= +// static +uno::Reference< lang::XSingleServiceFactory > +UcbCommandEnvironment::createServiceFactory( + const uno::Reference< lang::XMultiServiceFactory >& rxServiceMgr ) +{ + return uno::Reference< lang::XSingleServiceFactory >( + cppu::createSingleFactory( + rxServiceMgr, + UcbCommandEnvironment::getImplementationName_Static(), + UcbCommandEnvironment_CreateInstance, + UcbCommandEnvironment::getSupportedServiceNames_Static() ) ); +} diff --git a/ucb/source/core/cmdenv.hxx b/ucb/source/core/cmdenv.hxx new file mode 100644 index 000000000000..419ce6afb560 --- /dev/null +++ b/ucb/source/core/cmdenv.hxx @@ -0,0 +1,102 @@ +/************************************************************************* + * + * 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 INCLUDED_CMDENV_HXX +#define INCLUDED_CMDENV_HXX + +#include "cppuhelper/implbase3.hxx" + +#include "com/sun/star/lang/XInitialization.hpp" +#include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/lang/XSingleServiceFactory.hpp" +#include "com/sun/star/ucb/XCommandEnvironment.hpp" + +namespace ucb_cmdenv { + +class UcbCommandEnvironment : + public cppu::WeakImplHelper3< com::sun::star::lang::XInitialization, + com::sun::star::lang::XServiceInfo, + com::sun::star::ucb::XCommandEnvironment > +{ + com::sun::star::uno::Reference< + com::sun::star::task::XInteractionHandler > m_xIH; + com::sun::star::uno::Reference< + com::sun::star::ucb::XProgressHandler > m_xPH; + +public: + UcbCommandEnvironment( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rXSMgr ); + virtual ~UcbCommandEnvironment(); + + // XInitialization + virtual void SAL_CALL + initialize( const com::sun::star::uno::Sequence< + com::sun::star::uno::Any >& aArguments ) + throw( com::sun::star::uno::Exception, + com::sun::star::uno::RuntimeException ); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName() + throw ( com::sun::star::uno::RuntimeException ); + + virtual sal_Bool SAL_CALL + supportsService( const ::rtl::OUString& ServiceName ) + throw ( com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL + getSupportedServiceNames() + throw ( com::sun::star::uno::RuntimeException ); + + // XCommandEnvironment + virtual com::sun::star::uno::Reference< + com::sun::star::task::XInteractionHandler > SAL_CALL + getInteractionHandler() + throw ( com::sun::star::uno::RuntimeException ); + virtual com::sun::star::uno::Reference< + com::sun::star::ucb::XProgressHandler > SAL_CALL + getProgressHandler() + throw ( com::sun::star::uno::RuntimeException ); + + // Non-UNO interfaces + static rtl::OUString + getImplementationName_Static(); + static com::sun::star::uno::Sequence< rtl::OUString > + getSupportedServiceNames_Static(); + + static com::sun::star::uno::Reference< + com::sun::star::lang::XSingleServiceFactory > + createServiceFactory( const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory > & rxServiceMgr ); +private: + //com::sun::star::uno::Reference< + // com::sun::star::lang::XMultiServiceFactory > m_xSMgr; +}; + +} // namespace ucb_cmdenv + +#endif // INCLUDED_CMDENV_HXX diff --git a/ucb/source/core/exports2.dxp b/ucb/source/core/exports2.dxp new file mode 100644 index 000000000000..8091459f4d84 --- /dev/null +++ b/ucb/source/core/exports2.dxp @@ -0,0 +1,4 @@ +component_getImplementationEnvironment +component_getFactory + +_ZTIN3com3sun4star3ucb34InteractiveBadTransferURLExceptionE diff --git a/ucb/source/core/identify.cxx b/ucb/source/core/identify.cxx new file mode 100644 index 000000000000..ece9211c1ac3 --- /dev/null +++ b/ucb/source/core/identify.cxx @@ -0,0 +1,116 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ + +#include "identify.hxx" + +using namespace rtl; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::ucb; + +//========================================================================= +// +// ContentIdentifier Implementation. +// +//========================================================================= + +ContentIdentifier::ContentIdentifier( + const Reference< XMultiServiceFactory >& rxSMgr, + const OUString& ContentId ) +: m_xSMgr( rxSMgr ), + m_aContentId( ContentId ) +{ +} + +//========================================================================= +// virtual +ContentIdentifier::~ContentIdentifier() +{ +} + +//========================================================================= +// +// XInterface methods. +// +//========================================================================= + +XINTERFACE_IMPL_2( ContentIdentifier, + XTypeProvider, + XContentIdentifier ); + +//========================================================================= +// +// XTypeProvider methods. +// +//========================================================================= + +XTYPEPROVIDER_IMPL_2( ContentIdentifier, + XTypeProvider, + XContentIdentifier ); + +//========================================================================= +// +// XContentIdentifier methods. +// +//========================================================================= + +// virtual +OUString SAL_CALL ContentIdentifier::getContentIdentifier() + throw( RuntimeException ) +{ + return m_aContentId; +} + +//========================================================================= +// virtual +OUString SAL_CALL ContentIdentifier::getContentProviderScheme() + throw( RuntimeException ) +{ + if ( !m_aProviderScheme.getLength() && m_aContentId.getLength() ) + { + // The content provider scheme is the part before the first ':' + // within the content id. + sal_Int32 nPos = m_aContentId.indexOf( ':', 0 ); + if ( nPos != -1 ) + { + OUString aScheme( m_aContentId.copy( 0, nPos ) ); + m_aProviderScheme = aScheme.toAsciiLowerCase(); + } + } + + return m_aProviderScheme; +} + diff --git a/ucb/source/core/identify.hxx b/ucb/source/core/identify.hxx new file mode 100644 index 000000000000..d8ea23b1eee5 --- /dev/null +++ b/ucb/source/core/identify.hxx @@ -0,0 +1,68 @@ +/************************************************************************* + * + * 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 _IDENTIFY_HXX +#define _IDENTIFY_HXX + +#include <com/sun/star/ucb/XContentIdentifier.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XTypeProvider.hpp> +#include <rtl/ustrbuf.hxx> +#include <cppuhelper/weak.hxx> +#include <ucbhelper/macros.hxx> + +//========================================================================= + +class ContentIdentifier : + public cppu::OWeakObject, + public com::sun::star::lang::XTypeProvider, + public com::sun::star::ucb::XContentIdentifier +{ +public: + ContentIdentifier( const com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + const rtl::OUString& ContentId ); + virtual ~ContentIdentifier(); + + // XInterface + XINTERFACE_DECL() + + // XTypeProvider + XTYPEPROVIDER_DECL() + + // XContentIdentifier + virtual rtl::OUString SAL_CALL getContentIdentifier() + throw( com::sun::star::uno::RuntimeException ); + virtual rtl::OUString SAL_CALL getContentProviderScheme() + throw( com::sun::star::uno::RuntimeException ); + +private: + com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory > m_xSMgr; + rtl::OUString m_aContentId; + rtl::OUString m_aProviderScheme; +}; + +#endif /* !_IDENTIFY_HXX */ diff --git a/ucb/source/core/makefile.mk b/ucb/source/core/makefile.mk new file mode 100644 index 000000000000..6360f82320d2 --- /dev/null +++ b/ucb/source/core/makefile.mk @@ -0,0 +1,84 @@ +#************************************************************************* +# +# 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=ucb +TARGET=ucb +ENABLE_EXCEPTIONS=TRUE +NO_BSYMBOLIC=TRUE + +# Version +UCB_MAJOR=1 + +.INCLUDE: settings.mk +.IF "$(L10N_framework)"=="" + +SLOFILES=\ + $(SLO)$/identify.obj \ + $(SLO)$/ucb.obj \ + $(SLO)$/ucbserv.obj \ + $(SLO)$/ucbstore.obj \ + $(SLO)$/ucbprops.obj \ + $(SLO)$/provprox.obj \ + $(SLO)$/ucbcmds.obj \ + $(SLO)$/cmdenv.obj + +LIB1TARGET=$(SLB)$/_$(TARGET).lib +LIB1OBJFILES=$(SLOFILES) + +SHL1TARGET=$(TARGET)$(UCB_MAJOR) +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +SHL1STDLIBS=\ + $(CPPUHELPERLIB) \ + $(CPPULIB) \ + $(SALLIB) \ + $(UCBHELPERLIB) +SHL1LIBS=\ + $(LIB1TARGET) \ + $(SLB)$/regexp.lib +SHL1IMPLIB=i$(TARGET) + +.IF "$(GUI)" == "OS2" +DEF1EXPORTFILE=exports2.dxp +.ELSE +SHL1VERSIONMAP=$(SOLARENV)/src/component.map +.ENDIF + +DEF1NAME=$(SHL1TARGET) + +.ENDIF # L10N_framework + +.INCLUDE: target.mk + + +ALLTAR : $(MISC)/ucb1.component + +$(MISC)/ucb1.component .ERRREMOVE : $(SOLARENV)/bin/createcomponent.xslt \ + ucb1.component + $(XSLTPROC) --nonet --stringparam uri \ + '$(COMPONENTPREFIX_BASIS_NATIVE)$(SHL1TARGETN:f)' -o $@ \ + $(SOLARENV)/bin/createcomponent.xslt ucb1.component diff --git a/ucb/source/core/providermap.hxx b/ucb/source/core/providermap.hxx new file mode 100644 index 000000000000..a7fec30a42bf --- /dev/null +++ b/ucb/source/core/providermap.hxx @@ -0,0 +1,77 @@ +/************************************************************************* + * + * 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 _UCB_PROVIDERMAP_HXX_ +#define _UCB_PROVIDERMAP_HXX_ + +#include <list> +#include <com/sun/star/uno/Reference.h> +#include <regexpmap.hxx> + +namespace com { namespace sun { namespace star { namespace ucb { + class XContentProvider; +} } } } + +//============================================================================ +class ProviderListEntry_Impl +{ + com::sun::star::uno::Reference< + com::sun::star::ucb::XContentProvider > m_xProvider; + mutable com::sun::star::uno::Reference< + com::sun::star::ucb::XContentProvider > m_xResolvedProvider; + +private: + com::sun::star::uno::Reference< + com::sun::star::ucb::XContentProvider > resolveProvider() const; + +public: + ProviderListEntry_Impl( + const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentProvider >& xProvider ) + : m_xProvider( xProvider ) {} + + com::sun::star::uno::Reference< + com::sun::star::ucb::XContentProvider > getProvider() const + { return m_xProvider; } + inline com::sun::star::uno::Reference< + com::sun::star::ucb::XContentProvider > getResolvedProvider() const; +}; + +inline com::sun::star::uno::Reference< com::sun::star::ucb::XContentProvider > +ProviderListEntry_Impl::getResolvedProvider() const +{ + return m_xResolvedProvider.is() ? m_xResolvedProvider : resolveProvider(); +} + +//============================================================================ +typedef std::list< ProviderListEntry_Impl > ProviderList_Impl; + +//============================================================================ +typedef ucb_impl::RegexpMap< ProviderList_Impl > ProviderMap_Impl; + +#endif // _UCB_PROVIDERMAP_HXX_ + diff --git a/ucb/source/core/provprox.cxx b/ucb/source/core/provprox.cxx new file mode 100644 index 000000000000..feab9ce4f95e --- /dev/null +++ b/ucb/source/core/provprox.cxx @@ -0,0 +1,401 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" +#include <osl/diagnose.h> +#include "provprox.hxx" +#include <com/sun/star/lang/XInitialization.hpp> + +using namespace rtl; +using namespace com::sun::star::lang; +using namespace com::sun::star::ucb; +using namespace com::sun::star::uno; + +//========================================================================= +//========================================================================= +// +// UcbContentProviderProxyFactory Implementation. +// +//========================================================================= +//========================================================================= + +UcbContentProviderProxyFactory::UcbContentProviderProxyFactory( + const Reference< XMultiServiceFactory >& rxSMgr ) +: m_xSMgr( rxSMgr ) +{ +} + +//========================================================================= +// virtual +UcbContentProviderProxyFactory::~UcbContentProviderProxyFactory() +{ +} + +//========================================================================= +// +// XInterface methods. +// +//========================================================================= + +XINTERFACE_IMPL_3( UcbContentProviderProxyFactory, + XTypeProvider, + XServiceInfo, + XContentProviderFactory ); + +//========================================================================= +// +// XTypeProvider methods. +// +//========================================================================= + +XTYPEPROVIDER_IMPL_3( UcbContentProviderProxyFactory, + XTypeProvider, + XServiceInfo, + XContentProviderFactory ); + +//========================================================================= +// +// XServiceInfo methods. +// +//========================================================================= + +XSERVICEINFO_IMPL_1( UcbContentProviderProxyFactory, + OUString::createFromAscii( + "com.sun.star.comp.ucb.UcbContentProviderProxyFactory" ), + OUString::createFromAscii( + PROVIDER_FACTORY_SERVICE_NAME ) ); + +//========================================================================= +// +// Service factory implementation. +// +//========================================================================= + +ONE_INSTANCE_SERVICE_FACTORY_IMPL( UcbContentProviderProxyFactory ); + +//========================================================================= +// +// XContentProviderFactory methods. +// +//========================================================================= + +// virtual +Reference< XContentProvider > SAL_CALL +UcbContentProviderProxyFactory::createContentProvider( + const OUString& Service ) + throw( RuntimeException ) +{ + return Reference< XContentProvider >( + new UcbContentProviderProxy( m_xSMgr, Service ) ); +} + +//========================================================================= +//========================================================================= +// +// UcbContentProviderProxy Implementation. +// +//========================================================================= +//========================================================================= + +UcbContentProviderProxy::UcbContentProviderProxy( + const Reference< XMultiServiceFactory >& rxSMgr, + const OUString& Service ) +: m_aService( Service ), + m_bReplace( sal_False ), + m_bRegister( sal_False ), + m_xSMgr( rxSMgr ) +{ +} + +//========================================================================= +// virtual +UcbContentProviderProxy::~UcbContentProviderProxy() +{ +} + +//========================================================================= +// +// XInterface methods. +// +//========================================================================= + +XINTERFACE_COMMON_IMPL( UcbContentProviderProxy ); + +//============================================================================ +// virtual +Any SAL_CALL +UcbContentProviderProxy::queryInterface( const Type & rType ) + throw ( RuntimeException ) +{ + Any aRet = cppu::queryInterface( rType, + static_cast< XTypeProvider * >( this ), + static_cast< XServiceInfo * >( this ), + static_cast< XContentProvider * >( this ), + static_cast< XParameterizedContentProvider * >( this ), + static_cast< XContentProviderSupplier * >( this ) ); + + if ( !aRet.hasValue() ) + aRet = OWeakObject::queryInterface( rType ); + + if ( !aRet.hasValue() ) + { + // Get original provider an forward the call... + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + Reference< XContentProvider > xProvider = getContentProvider(); + if ( xProvider.is() ) + aRet = xProvider->queryInterface( rType ); + } + + return aRet; +} + +//========================================================================= +// +// XTypeProvider methods. +// +//========================================================================= + +XTYPEPROVIDER_COMMON_IMPL( UcbContentProviderProxy ); + +//========================================================================= + +Sequence< Type > SAL_CALL UcbContentProviderProxy::getTypes() \ + throw( RuntimeException ) +{ + // Get original provider an forward the call... + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + Reference< XTypeProvider > xProvider( getContentProvider(), UNO_QUERY ); + if ( xProvider.is() ) + { + return xProvider->getTypes(); + } + else + { + static cppu::OTypeCollection collection( + CPPU_TYPE_REF( XTypeProvider ), + CPPU_TYPE_REF( XServiceInfo ), + CPPU_TYPE_REF( XContentProvider ), + CPPU_TYPE_REF( XParameterizedContentProvider ), + CPPU_TYPE_REF( XContentProviderSupplier ) ); + return collection.getTypes(); + } +} + +//========================================================================= +// +// XServiceInfo methods. +// +//========================================================================= + +XSERVICEINFO_NOFACTORY_IMPL_1( UcbContentProviderProxy, + OUString::createFromAscii( + "com.sun.star.comp.ucb.UcbContentProviderProxy" ), + OUString::createFromAscii( + PROVIDER_PROXY_SERVICE_NAME ) ); + +//========================================================================= +// +// XContentProvider methods. +// +//========================================================================= + +// virtual +Reference< XContent > SAL_CALL UcbContentProviderProxy::queryContent( + const Reference< XContentIdentifier >& Identifier ) + throw( IllegalIdentifierException, + RuntimeException ) +{ + // Get original provider an forward the call... + + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + Reference< XContentProvider > xProvider = getContentProvider(); + if ( xProvider.is() ) + return xProvider->queryContent( Identifier ); + + return Reference< XContent >(); +} + +//========================================================================= +// virtual +sal_Int32 SAL_CALL UcbContentProviderProxy::compareContentIds( + const Reference< XContentIdentifier >& Id1, + const Reference< XContentIdentifier >& Id2 ) + throw( RuntimeException ) +{ + // Get original provider an forward the call... + + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + Reference< XContentProvider > xProvider = getContentProvider(); + if ( xProvider.is() ) + return xProvider->compareContentIds( Id1, Id2 ); + + // OSL_ENSURE( sal_False, + // "UcbContentProviderProxy::compareContentIds - No provider!" ); + + // @@@ What else? + return 0; +} + +//========================================================================= +// +// XParameterizedContentProvider methods. +// +//========================================================================= + +// virtual +Reference< XContentProvider > SAL_CALL +UcbContentProviderProxy::registerInstance( const OUString& Template, + const OUString& Arguments, + sal_Bool ReplaceExisting ) + throw( IllegalArgumentException, + RuntimeException ) +{ + // Just remember that this method was called ( and the params ). + + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + if ( !m_bRegister ) + { +// m_xTargetProvider = 0; + m_aTemplate = Template; + m_aArguments = Arguments; + m_bReplace = ReplaceExisting; + + m_bRegister = sal_True; + } + return this; +} + +//========================================================================= +// virtual +Reference< XContentProvider > SAL_CALL +UcbContentProviderProxy::deregisterInstance( const OUString& Template, + const OUString& Arguments ) + throw( IllegalArgumentException, + RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + // registerInstance called at proxy and at original? + if ( m_bRegister && m_xTargetProvider.is() ) + { + m_bRegister = sal_False; + m_xTargetProvider = 0; + + Reference< XParameterizedContentProvider > + xParamProvider( m_xProvider, UNO_QUERY ); + if ( xParamProvider.is() ) + { + try + { + xParamProvider->deregisterInstance( Template, Arguments ); + } + catch ( IllegalIdentifierException const & ) + { + OSL_ENSURE( sal_False, + "UcbContentProviderProxy::deregisterInstance - " + "Caught IllegalIdentifierException!" ); + } + } + } + + return this; +} + +//========================================================================= +// +// XContentProviderSupplier methods. +// +//========================================================================= + +// virtual +Reference< XContentProvider > SAL_CALL +UcbContentProviderProxy::getContentProvider() + throw( RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + if ( !m_xProvider.is() ) + { + try + { + m_xProvider + = Reference< XContentProvider >( + m_xSMgr->createInstance( m_aService ), UNO_QUERY ); + if(m_aArguments.compareToAscii("NoConfig") == 0) + { + Reference<XInitialization> xInit(m_xProvider,UNO_QUERY); + if(xInit.is()) { + Sequence<Any> aArgs(1); + aArgs[0] <<= m_aArguments; + xInit->initialize(aArgs); + } + } + } + catch ( RuntimeException const & ) + { + throw; + } + catch ( Exception const & ) + { + } + + // registerInstance called at proxy, but not yet at original? + if ( m_xProvider.is() && m_bRegister ) + { + Reference< XParameterizedContentProvider > + xParamProvider( m_xProvider, UNO_QUERY ); + if ( xParamProvider.is() ) + { + try + { + m_xTargetProvider + = xParamProvider->registerInstance( m_aTemplate, + m_aArguments, + m_bReplace ); + } + catch ( IllegalIdentifierException const & ) + { + OSL_ENSURE( sal_False, + "UcbContentProviderProxy::getContentProvider - " + "Caught IllegalIdentifierException!" ); + } + + OSL_ENSURE( m_xTargetProvider.is(), + "UcbContentProviderProxy::getContentProvider - " + "No provider!" ); + } + } + if ( !m_xTargetProvider.is() ) + m_xTargetProvider = m_xProvider; + } + + OSL_ENSURE( m_xProvider.is(), + "UcbContentProviderProxy::getContentProvider - No provider!" ); + return m_xTargetProvider; +} diff --git a/ucb/source/core/provprox.hxx b/ucb/source/core/provprox.hxx new file mode 100644 index 000000000000..cdc85251e96e --- /dev/null +++ b/ucb/source/core/provprox.hxx @@ -0,0 +1,166 @@ +/************************************************************************* + * + * 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 _PROVPROX_HXX +#define _PROVPROX_HXX + +#include <osl/mutex.hxx> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XTypeProvider.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/ucb/XContentProviderFactory.hpp> +#include <com/sun/star/ucb/XContentProvider.hpp> +#include <com/sun/star/ucb/XParameterizedContentProvider.hpp> +#include <com/sun/star/ucb/XContentProviderSupplier.hpp> +#include <cppuhelper/weak.hxx> +#include <ucbhelper/macros.hxx> + +//========================================================================= + +#define PROVIDER_FACTORY_SERVICE_NAME \ + "com.sun.star.ucb.ContentProviderProxyFactory" +#define PROVIDER_PROXY_SERVICE_NAME \ + "com.sun.star.ucb.ContentProviderProxy" + +//============================================================================ +// +// class UcbContentProviderProxyFactory. +// +//============================================================================ + +class UcbContentProviderProxyFactory : + public cppu::OWeakObject, + public com::sun::star::lang::XTypeProvider, + public com::sun::star::lang::XServiceInfo, + public com::sun::star::ucb::XContentProviderFactory +{ + com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory > + m_xSMgr; + +public: + UcbContentProviderProxyFactory( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr ); + virtual ~UcbContentProviderProxyFactory(); + + // XInterface + XINTERFACE_DECL() + + // XTypeProvider + XTYPEPROVIDER_DECL() + + // XServiceInfo + XSERVICEINFO_DECL() + + // XContentProviderFactory + virtual ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XContentProvider > SAL_CALL + createContentProvider( const ::rtl::OUString& Service ) + throw( ::com::sun::star::uno::RuntimeException ); +}; + +//============================================================================ +// +// class UcbContentProviderProxy. +// +//============================================================================ + +class UcbContentProviderProxy : + public cppu::OWeakObject, + public com::sun::star::lang::XTypeProvider, + public com::sun::star::lang::XServiceInfo, + public com::sun::star::ucb::XContentProviderSupplier, + public com::sun::star::ucb::XContentProvider, + public com::sun::star::ucb::XParameterizedContentProvider +{ + ::osl::Mutex m_aMutex; + ::rtl::OUString m_aService; + ::rtl::OUString m_aTemplate; + ::rtl::OUString m_aArguments; + sal_Bool m_bReplace; + sal_Bool m_bRegister; + + com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory > + m_xSMgr; + com::sun::star::uno::Reference< com::sun::star::ucb::XContentProvider > + m_xProvider; + com::sun::star::uno::Reference< com::sun::star::ucb::XContentProvider > + m_xTargetProvider; + +public: + UcbContentProviderProxy( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + const ::rtl::OUString& Service ); + virtual ~UcbContentProviderProxy(); + + // XInterface + XINTERFACE_DECL() + + // XTypeProvider + XTYPEPROVIDER_DECL() + + // XServiceInfo + XSERVICEINFO_NOFACTORY_DECL() + + // XContentProviderSupplier + virtual ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XContentProvider > SAL_CALL + getContentProvider() + throw( ::com::sun::star::uno::RuntimeException ); + + // XContentProvider + virtual ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XContent > SAL_CALL + queryContent( const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XContentIdentifier >& Identifier ) + throw( ::com::sun::star::ucb::IllegalIdentifierException, + ::com::sun::star::uno::RuntimeException ); + virtual sal_Int32 SAL_CALL + compareContentIds( const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XContentIdentifier >& Id1, + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XContentIdentifier >& Id2 ) + throw( ::com::sun::star::uno::RuntimeException ); + + // XParameterizedContentProvider + virtual ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XContentProvider > SAL_CALL + registerInstance( const ::rtl::OUString& Template, + const ::rtl::OUString& Arguments, + sal_Bool ReplaceExisting ) + throw( ::com::sun::star::lang::IllegalArgumentException, + ::com::sun::star::uno::RuntimeException ); + virtual ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XContentProvider > SAL_CALL + deregisterInstance( const ::rtl::OUString& Template, + const ::rtl::OUString& Arguments ) + throw( ::com::sun::star::lang::IllegalArgumentException, + ::com::sun::star::uno::RuntimeException ); +}; + +#endif /* !_PROVPROX_HXX */ diff --git a/ucb/source/core/ucb.cxx b/ucb/source/core/ucb.cxx new file mode 100644 index 000000000000..30f7e32f3828 --- /dev/null +++ b/ucb/source/core/ucb.cxx @@ -0,0 +1,959 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ +#include <osl/diagnose.h> +#include <cppuhelper/interfacecontainer.hxx> +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <com/sun/star/ucb/GlobalTransferCommandArgument.hpp> +#include <com/sun/star/ucb/XCommandInfo.hpp> +#include <com/sun/star/ucb/XContentProvider.hpp> +#include <com/sun/star/ucb/XContentProviderSupplier.hpp> +#include <com/sun/star/ucb/XParameterizedContentProvider.hpp> +#include <com/sun/star/ucb/XContentProviderFactory.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/container/XHierarchicalNameAccess.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/uno/Any.hxx> +#include <ucbhelper/cancelcommandexecution.hxx> +#include "identify.hxx" +#include "ucbcmds.hxx" + +#include "ucb.hxx" + +// Definitions for ProviderMap_Impl (Solaris wouldn't find explicit template +// instantiations for these in another compilation unit...): +#ifndef _UCB_REGEXPMAP_TPT_ +#include <regexpmap.tpt> +#endif + +using namespace rtl; +using namespace cppu; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::ucb; +using namespace ucb_impl; +using namespace com::sun::star; +using namespace ucbhelper; + + +#define CONFIG_CONTENTPROVIDERS_KEY \ + "/org.openoffice.ucb.Configuration/ContentProviders" + + +namespace { + +bool fillPlaceholders(rtl::OUString const & rInput, + uno::Sequence< uno::Any > const & rReplacements, + rtl::OUString * pOutput) +{ + sal_Unicode const * p = rInput.getStr(); + sal_Unicode const * pEnd = p + rInput.getLength(); + sal_Unicode const * pCopy = p; + rtl::OUStringBuffer aBuffer; + while (p != pEnd) + switch (*p++) + { + case '&': + if (pEnd - p >= 4 + && p[0] == 'a' && p[1] == 'm' && p[2] == 'p' + && p[3] == ';') + { + aBuffer.append(pCopy, p - 1 - pCopy); + aBuffer.append(sal_Unicode('&')); + p += 4; + pCopy = p; + } + else if (pEnd - p >= 3 + && p[0] == 'l' && p[1] == 't' && p[2] == ';') + { + aBuffer.append(pCopy, p - 1 - pCopy); + aBuffer.append(sal_Unicode('<')); + p += 3; + pCopy = p; + } + else if (pEnd - p >= 3 + && p[0] == 'g' && p[1] == 't' && p[2] == ';') + { + aBuffer.append(pCopy, p - 1 - pCopy); + aBuffer.append(sal_Unicode('>')); + p += 3; + pCopy = p; + } + break; + + case '<': + sal_Unicode const * q = p; + while (q != pEnd && *q != '>') + ++q; + if (q == pEnd) + break; + rtl::OUString aKey(p, q - p); + rtl::OUString aValue; + bool bFound = false; + for (sal_Int32 i = 2; i + 1 < rReplacements.getLength(); + i += 2) + { + rtl::OUString aReplaceKey; + if ((rReplacements[i] >>= aReplaceKey) + && aReplaceKey == aKey + && (rReplacements[i + 1] >>= aValue)) + { + bFound = true; + break; + } + } + if (!bFound) + return false; + aBuffer.append(pCopy, p - 1 - pCopy); + aBuffer.append(aValue); + p = q + 1; + pCopy = p; + break; + } + aBuffer.append(pCopy, pEnd - pCopy); + *pOutput = aBuffer.makeStringAndClear(); + return true; +} + +void makeAndAppendXMLName( + rtl::OUStringBuffer & rBuffer, const rtl::OUString & rIn ) +{ + sal_Int32 nCount = rIn.getLength(); + for ( sal_Int32 n = 0; n < nCount; ++n ) + { + const sal_Unicode c = rIn.getStr()[ n ]; + switch ( c ) + { + case '&': + rBuffer.appendAscii( "&" ); + break; + + case '"': + rBuffer.appendAscii( """ ); + break; + + case '\'': + rBuffer.appendAscii( "'" ); + break; + + case '<': + rBuffer.appendAscii( "<" ); + break; + + case '>': + rBuffer.appendAscii( ">" ); + break; + + default: + rBuffer.append( c ); + break; + } + } +} + +bool createContentProviderData( + const rtl::OUString & rProvider, + const uno::Reference< container::XHierarchicalNameAccess >& rxHierNameAccess, + ContentProviderData & rInfo) +{ + // Obtain service name. + rtl::OUStringBuffer aKeyBuffer (rProvider); + aKeyBuffer.appendAscii( "/ServiceName" ); + + rtl::OUString aValue; + try + { + if ( !( rxHierNameAccess->getByHierarchicalName( + aKeyBuffer.makeStringAndClear() ) >>= aValue ) ) + { + OSL_ENSURE( false, + "UniversalContentBroker::getContentProviderData - " + "Error getting item value!" ); + } + } + catch (container::NoSuchElementException &) + { + return false; + } + + rInfo.ServiceName = aValue; + + // Obtain URL Template. + aKeyBuffer.append(rProvider); + aKeyBuffer.appendAscii( "/URLTemplate" ); + + if ( !( rxHierNameAccess->getByHierarchicalName( + aKeyBuffer.makeStringAndClear() ) >>= aValue ) ) + { + OSL_ENSURE( false, + "UniversalContentBroker::getContentProviderData - " + "Error getting item value!" ); + } + + rInfo.URLTemplate = aValue; + + // Obtain Arguments. + aKeyBuffer.append(rProvider); + aKeyBuffer.appendAscii( "/Arguments" ); + + if ( !( rxHierNameAccess->getByHierarchicalName( + aKeyBuffer.makeStringAndClear() ) >>= aValue ) ) + { + OSL_ENSURE( false, + "UniversalContentBroker::getContentProviderData - " + "Error getting item value!" ); + } + + rInfo.Arguments = aValue; + return true; +} + +} + +//========================================================================= +// +// UniversalContentBroker Implementation. +// +//========================================================================= + +UniversalContentBroker::UniversalContentBroker( + const Reference< com::sun::star::lang::XMultiServiceFactory >& rXSMgr ) +: m_xSMgr( rXSMgr ), + m_pDisposeEventListeners( NULL ), + m_nInitCount( 0 ), //@@@ see initialize() method + m_nCommandId( 0 ) +{ + OSL_ENSURE( m_xSMgr.is(), + "UniversalContentBroker ctor: No service manager" ); +} + +//========================================================================= +// virtual +UniversalContentBroker::~UniversalContentBroker() +{ + delete m_pDisposeEventListeners; +} + +//========================================================================= +// +// XInterface methods. +// +//========================================================================= + +XINTERFACE_IMPL_8( UniversalContentBroker, + XTypeProvider, + XComponent, + XServiceInfo, + XInitialization, + XContentProviderManager, + XContentProvider, + XContentIdentifierFactory, + XCommandProcessor ); + +//========================================================================= +// +// XTypeProvider methods. +// +//========================================================================= + +XTYPEPROVIDER_IMPL_8( UniversalContentBroker, + XTypeProvider, + XComponent, + XServiceInfo, + XInitialization, + XContentProviderManager, + XContentProvider, + XContentIdentifierFactory, + XCommandProcessor ); + +//========================================================================= +// +// XComponent methods. +// +//========================================================================= + +// virtual +void SAL_CALL UniversalContentBroker::dispose() + throw( com::sun::star::uno::RuntimeException ) +{ + if ( m_pDisposeEventListeners && m_pDisposeEventListeners->getLength() ) + { + EventObject aEvt; + aEvt.Source = SAL_STATIC_CAST( XComponent*, this ); + m_pDisposeEventListeners->disposeAndClear( aEvt ); + } + + if ( m_xNotifier.is() ) + m_xNotifier->removeChangesListener( this ); +} + +//========================================================================= +// virtual +void SAL_CALL UniversalContentBroker::addEventListener( + const Reference< XEventListener >& Listener ) + throw( com::sun::star::uno::RuntimeException ) +{ + if ( !m_pDisposeEventListeners ) + m_pDisposeEventListeners = new OInterfaceContainerHelper( m_aMutex ); + + m_pDisposeEventListeners->addInterface( Listener ); +} + +//========================================================================= +// virtual +void SAL_CALL UniversalContentBroker::removeEventListener( + const Reference< XEventListener >& Listener ) + throw( com::sun::star::uno::RuntimeException ) +{ + if ( m_pDisposeEventListeners ) + m_pDisposeEventListeners->removeInterface( Listener ); + + // Note: Don't want to delete empty container here -> performance. +} + +//========================================================================= +// +// XServiceInfo methods. +// +//========================================================================= + +XSERVICEINFO_IMPL_1( UniversalContentBroker, + OUString::createFromAscii( + "com.sun.star.comp.ucb.UniversalContentBroker" ), + OUString::createFromAscii( + UCB_SERVICE_NAME ) ); + +//========================================================================= +// +// Service factory implementation. +// +//========================================================================= + +ONE_INSTANCE_SERVICE_FACTORY_IMPL( UniversalContentBroker ); + +//========================================================================= +// +// XInitialization methods. +// +//========================================================================= + +// virtual +void SAL_CALL UniversalContentBroker::initialize( + const com::sun::star::uno::Sequence< Any >& aArguments ) + throw( com::sun::star::uno::Exception, + com::sun::star::uno::RuntimeException ) +{ + //@@@ At the moment, there's a problem when one (non-one-instance) factory + // 'wraps' another (one-instance) factory, causing this method to be + // called several times: + m_aArguments = aArguments; + + oslInterlockedCount nCount = osl_incrementInterlockedCount(&m_nInitCount); + if (nCount == 1) + configureUcb(); + else + osl_decrementInterlockedCount(&m_nInitCount); + // make the possibility of overflow less likely... +} + +//========================================================================= +// +// XContentProviderManager methods. +// +//========================================================================= + +// virtual +Reference< XContentProvider > SAL_CALL +UniversalContentBroker::registerContentProvider( + const Reference< XContentProvider >& Provider, + const OUString& Scheme, + sal_Bool ReplaceExisting ) + throw( DuplicateProviderException, com::sun::star::uno::RuntimeException ) +{ + osl::MutexGuard aGuard(m_aMutex); + + ProviderMap_Impl::iterator aIt; + try + { + aIt = m_aProviders.find(Scheme); + } + catch (IllegalArgumentException const &) + { + return 0; //@@@ + } + + Reference< XContentProvider > xPrevious; + if (aIt == m_aProviders.end()) + { + ProviderList_Impl aList; + aList.push_front(Provider); + try + { + m_aProviders.add(Scheme, aList, false); + } + catch (IllegalArgumentException const &) + { + return 0; //@@@ + } + } + else + { + if (!ReplaceExisting) + throw DuplicateProviderException(); + + ProviderList_Impl & rList = aIt->getValue(); + xPrevious = rList.front().getProvider(); + rList.push_front(Provider); + } + + return xPrevious; +} + +//========================================================================= +// virtual +void SAL_CALL UniversalContentBroker::deregisterContentProvider( + const Reference< XContentProvider >& Provider, + const OUString& Scheme ) + throw( com::sun::star::uno::RuntimeException ) +{ + osl::MutexGuard aGuard(m_aMutex); + + ProviderMap_Impl::iterator aMapIt; + try + { + aMapIt = m_aProviders.find(Scheme); + } + catch (IllegalArgumentException const &) + { + return; //@@@ + } + + if (aMapIt != m_aProviders.end()) + { + ProviderList_Impl & rList = aMapIt->getValue(); + + ProviderList_Impl::iterator aListEnd(rList.end()); + for (ProviderList_Impl::iterator aListIt(rList.begin()); + aListIt != aListEnd; ++aListIt) + { + if ((*aListIt).getProvider() == Provider) + { + rList.erase(aListIt); + break; + } + } + + if (rList.empty()) + m_aProviders.erase(aMapIt); + } +} + +//========================================================================= +// virtual +com::sun::star::uno::Sequence< ContentProviderInfo > SAL_CALL + UniversalContentBroker::queryContentProviders() + throw( com::sun::star::uno::RuntimeException ) +{ + // Return a list with information about active(!) content providers. + + osl::MutexGuard aGuard(m_aMutex); + + com::sun::star::uno::Sequence< ContentProviderInfo > aSeq( + m_aProviders.size() ); + ContentProviderInfo* pInfo = aSeq.getArray(); + + ProviderMap_Impl::const_iterator end = m_aProviders.end(); + for (ProviderMap_Impl::const_iterator it(m_aProviders.begin()); it != end; + ++it) + { + // Note: Active provider is always the first list element. + pInfo->ContentProvider = it->getValue().front().getProvider(); + pInfo->Scheme = it->getRegexp(); + ++pInfo; + } + + return aSeq; +} + +//========================================================================= +// virtual +Reference< XContentProvider > SAL_CALL + UniversalContentBroker::queryContentProvider( const OUString& + Identifier ) + throw( com::sun::star::uno::RuntimeException ) +{ + return queryContentProvider( Identifier, sal_False ); +} + +//========================================================================= +// +// XContentProvider methods. +// +//========================================================================= + +// virtual +Reference< XContent > SAL_CALL UniversalContentBroker::queryContent( + const Reference< XContentIdentifier >& Identifier ) + throw( IllegalIdentifierException, com::sun::star::uno::RuntimeException ) +{ + ////////////////////////////////////////////////////////////////////// + // Let the content provider for the scheme given with the content + // identifier create the XContent instance. + ////////////////////////////////////////////////////////////////////// + + if ( !Identifier.is() ) + return Reference< XContent >(); + + Reference< XContentProvider > xProv = + queryContentProvider( Identifier->getContentIdentifier(), sal_True ); + if ( xProv.is() ) + return xProv->queryContent( Identifier ); + + return Reference< XContent >(); +} + +//========================================================================= +// virtual +sal_Int32 SAL_CALL UniversalContentBroker::compareContentIds( + const Reference< XContentIdentifier >& Id1, + const Reference< XContentIdentifier >& Id2 ) + throw( com::sun::star::uno::RuntimeException ) +{ + OUString aURI1( Id1->getContentIdentifier() ); + OUString aURI2( Id2->getContentIdentifier() ); + + Reference< XContentProvider > xProv1 + = queryContentProvider( aURI1, sal_True ); + Reference< XContentProvider > xProv2 + = queryContentProvider( aURI2, sal_True ); + + // When both identifiers belong to the same provider, let that provider + // compare them; otherwise, simply compare the URI strings (which must + // be different): + if ( xProv1.is() && ( xProv1 == xProv2 ) ) + return xProv1->compareContentIds( Id1, Id2 ); + else + return aURI1.compareTo( aURI2 ); +} + +//========================================================================= +// +// XContentIdentifierFactory methods. +// +//========================================================================= + +// virtual +Reference< XContentIdentifier > SAL_CALL + UniversalContentBroker::createContentIdentifier( + const OUString& ContentId ) + throw( com::sun::star::uno::RuntimeException ) +{ + ////////////////////////////////////////////////////////////////////// + // Let the content provider for the scheme given with content + // identifier create the XContentIdentifier instance, if he supports + // the XContentIdentifierFactory interface. Otherwise create standard + // implementation object for XContentIdentifier. + ////////////////////////////////////////////////////////////////////// + + Reference< XContentIdentifier > xIdentifier; + + Reference< XContentProvider > xProv + = queryContentProvider( ContentId, sal_True ); + if ( xProv.is() ) + { + Reference< XContentIdentifierFactory > xFac( xProv, UNO_QUERY ); + if ( xFac.is() ) + xIdentifier = xFac->createContentIdentifier( ContentId ); + } + + if ( !xIdentifier.is() ) + xIdentifier = new ContentIdentifier( m_xSMgr, ContentId ); + + return xIdentifier; +} + +//========================================================================= +// +// XCommandProcessor methods. +// +//========================================================================= + +// virtual +sal_Int32 SAL_CALL UniversalContentBroker::createCommandIdentifier() + throw( RuntimeException ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + // Just increase counter on every call to generate an identifier. + return ++m_nCommandId; +} + +//========================================================================= +// virtual +Any SAL_CALL UniversalContentBroker::execute( + const Command& aCommand, + sal_Int32, + const Reference< XCommandEnvironment >& Environment ) + throw( Exception, CommandAbortedException, RuntimeException ) +{ + Any aRet; + + ////////////////////////////////////////////////////////////////////// + // Note: Don't forget to adapt ucb_commands::CommandProcessorInfo + // ctor in ucbcmds.cxx when adding new commands! + ////////////////////////////////////////////////////////////////////// + + if ( ( aCommand.Handle == GETCOMMANDINFO_HANDLE ) || + aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( GETCOMMANDINFO_NAME ) ) ) + { + ////////////////////////////////////////////////////////////////// + // getCommandInfo + ////////////////////////////////////////////////////////////////// + + aRet <<= getCommandInfo(); + } + else if ( ( aCommand.Handle == GLOBALTRANSFER_HANDLE ) || + aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM(GLOBALTRANSFER_NAME ) ) ) + { + ////////////////////////////////////////////////////////////////// + // globalTransfer + ////////////////////////////////////////////////////////////////// + + GlobalTransferCommandArgument aTransferArg; + if ( !( aCommand.Argument >>= aTransferArg ) ) + { + ucbhelper::cancelCommandExecution( + makeAny( IllegalArgumentException( + rtl::OUString::createFromAscii( + "Wrong argument type!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + globalTransfer( aTransferArg, Environment ); + } + else + { + ////////////////////////////////////////////////////////////////// + // Unknown command + ////////////////////////////////////////////////////////////////// + + ucbhelper::cancelCommandExecution( + makeAny( UnsupportedCommandException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ) ) ), + Environment ); + // Unreachable + } + + return aRet; +} + +//========================================================================= +// virtual +void SAL_CALL UniversalContentBroker::abort( sal_Int32 ) + throw( RuntimeException ) +{ + // @@@ Not implemeted ( yet). +} + +//========================================================================= +// +// XChangesListener methods +// +//========================================================================= +// virtual +void SAL_CALL UniversalContentBroker::changesOccurred( const util::ChangesEvent& Event ) + throw( uno::RuntimeException ) +{ + sal_Int32 nCount = Event.Changes.getLength(); + if ( nCount ) + { + uno::Reference< container::XHierarchicalNameAccess > xHierNameAccess; + Event.Base >>= xHierNameAccess; + + OSL_ASSERT( xHierNameAccess.is() ); + + const util::ElementChange* pElementChanges + = Event.Changes.getConstArray(); + + ContentProviderDataList aData; + for ( sal_Int32 n = 0; n < nCount; ++n ) + { + const util::ElementChange& rElem = pElementChanges[ n ]; + rtl::OUString aKey; + rElem.Accessor >>= aKey; + + ContentProviderData aInfo; + + // Removal of UCPs from the configuration leads to changesOccurred + // notifications, too, but it is hard to tell for a given + // ElementChange whether it is an addition or a removal, so as a + // heuristic consider as removals those that cause a + // NoSuchElementException in createContentProviderData. + // + // For now, removal of UCPs from the configuration is simply ignored + // (and not reflected in the UCB's data structures): + if (createContentProviderData(aKey, xHierNameAccess, aInfo)) + { + aData.push_back(aInfo); + } + } + + prepareAndRegister(aData); + } +} + +//========================================================================= +// +// XEventListener methods +// +//========================================================================= +// virtual +void SAL_CALL UniversalContentBroker::disposing(const lang::EventObject&) + throw( uno::RuntimeException ) +{ + if ( m_xNotifier.is() ) + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + if ( m_xNotifier.is() ) + m_xNotifier.clear(); + } +} + +//========================================================================= +// +// Non-interface methods +// +//========================================================================= + +Reference< XContentProvider > UniversalContentBroker::queryContentProvider( + const OUString& Identifier, + sal_Bool bResolved ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + ProviderList_Impl const * pList = m_aProviders.map( Identifier ); + return pList ? bResolved ? pList->front().getResolvedProvider() + : pList->front().getProvider() + : Reference< XContentProvider >(); +} + +bool UniversalContentBroker::configureUcb() + throw (uno::RuntimeException) +{ + rtl::OUString aKey1; + rtl::OUString aKey2; + if (m_aArguments.getLength() < 2 + || !(m_aArguments[0] >>= aKey1) || !(m_aArguments[1] >>= aKey2)) + { + OSL_ENSURE(false, "UniversalContentBroker::configureUcb(): Bad arguments"); + return false; + } + + ContentProviderDataList aData; + if (!getContentProviderData(aKey1, aKey2, aData)) + { + OSL_ENSURE(false, "UniversalContentBroker::configureUcb(): No configuration"); + return false; + } + + prepareAndRegister(aData); + + return true; +} + +void UniversalContentBroker::prepareAndRegister( + const ContentProviderDataList& rData) +{ + ContentProviderDataList::const_iterator aEnd(rData.end()); + for (ContentProviderDataList::const_iterator aIt(rData.begin()); + aIt != aEnd; ++aIt) + { + rtl::OUString aProviderArguments; + if (fillPlaceholders(aIt->Arguments, + m_aArguments, + &aProviderArguments)) + { + registerAtUcb(this, + m_xSMgr, + aIt->ServiceName, + aProviderArguments, + aIt->URLTemplate, + 0); + + } + else + OSL_ENSURE(false, + "UniversalContentBroker::prepareAndRegister(): Bad argument placeholders"); + } +} + +//========================================================================= +bool UniversalContentBroker::getContentProviderData( + const rtl::OUString & rKey1, + const rtl::OUString & rKey2, + ContentProviderDataList & rListToFill ) +{ + if ( !m_xSMgr.is() || !rKey1.getLength() || !rKey2.getLength() ) + { + OSL_ENSURE( false, + "UniversalContentBroker::getContentProviderData - Invalid argument!" ); + return false; + } + + try + { + uno::Reference< lang::XMultiServiceFactory > xConfigProv( + m_xSMgr->createInstance( + rtl::OUString::createFromAscii( + "com.sun.star.configuration.ConfigurationProvider" ) ), + uno::UNO_QUERY_THROW ); + + rtl::OUStringBuffer aFullPath; + aFullPath.appendAscii( CONFIG_CONTENTPROVIDERS_KEY "/['" ); + makeAndAppendXMLName( aFullPath, rKey1 ); + aFullPath.appendAscii( "']/SecondaryKeys/['" ); + makeAndAppendXMLName( aFullPath, rKey2 ); + aFullPath.appendAscii( "']/ProviderData" ); + + uno::Sequence< uno::Any > aArguments( 1 ); + beans::PropertyValue aProperty; + aProperty.Name + = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "nodepath" ) ); + aProperty.Value <<= aFullPath.makeStringAndClear(); + aArguments[ 0 ] <<= aProperty; + + uno::Reference< uno::XInterface > xInterface( + xConfigProv->createInstanceWithArguments( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.configuration.ConfigurationAccess" ) ), + aArguments ) ); + + if ( !m_xNotifier.is() ) + { + m_xNotifier = uno::Reference< util::XChangesNotifier >( + xInterface, uno::UNO_QUERY_THROW ); + + m_xNotifier->addChangesListener( this ); + } + + uno::Reference< container::XNameAccess > xNameAccess( + xInterface, uno::UNO_QUERY_THROW ); + + uno::Sequence< rtl::OUString > aElems = xNameAccess->getElementNames(); + const rtl::OUString* pElems = aElems.getConstArray(); + sal_Int32 nCount = aElems.getLength(); + + if ( nCount > 0 ) + { + uno::Reference< container::XHierarchicalNameAccess > + xHierNameAccess( xInterface, uno::UNO_QUERY_THROW ); + + // Iterate over children. + for ( sal_Int32 n = 0; n < nCount; ++n ) + { + + try + { + + ContentProviderData aInfo; + + rtl::OUStringBuffer aElemBuffer; + aElemBuffer.appendAscii( "['" ); + makeAndAppendXMLName( aElemBuffer, pElems[ n ] ); + aElemBuffer.appendAscii( "']" ); + + OSL_VERIFY( + createContentProviderData( + aElemBuffer.makeStringAndClear(), xHierNameAccess, + aInfo)); + + rListToFill.push_back( aInfo ); + } + catch ( container::NoSuchElementException& ) + { + // getByHierarchicalName + OSL_ENSURE( false, + "UniversalContentBroker::getContentProviderData - " + "caught NoSuchElementException!" ); + } + } + } + } + catch ( uno::RuntimeException& ) + { + OSL_ENSURE( false, + "UniversalContentBroker::getContentProviderData - caught RuntimeException!" ); + return false; + } + catch ( uno::Exception& ) + { + // createInstance, createInstanceWithArguments + + OSL_ENSURE( false, + "UniversalContentBroker::getContentProviderData - caught Exception!" ); + return false; + } + + return true; +} + +//========================================================================= +// +// ProviderListEntry_Impl implementation. +// +//========================================================================= + +Reference< XContentProvider > ProviderListEntry_Impl::resolveProvider() const +{ + if ( !m_xResolvedProvider.is() ) + { + Reference< XContentProviderSupplier > xSupplier( + m_xProvider, UNO_QUERY ); + if ( xSupplier.is() ) + m_xResolvedProvider = xSupplier->getContentProvider(); + + if ( !m_xResolvedProvider.is() ) + m_xResolvedProvider = m_xProvider; + } + + return m_xResolvedProvider; +} diff --git a/ucb/source/core/ucb.hxx b/ucb/source/core/ucb.hxx new file mode 100644 index 000000000000..d2f6e4e4c41e --- /dev/null +++ b/ucb/source/core/ucb.hxx @@ -0,0 +1,220 @@ +/************************************************************************* + * + * 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 _UCB_HXX +#define _UCB_HXX + +#include <com/sun/star/ucb/XCommandProcessor.hpp> +#include <com/sun/star/ucb/XContentProvider.hpp> +#include <com/sun/star/ucb/XContentIdentifierFactory.hpp> +#include <com/sun/star/ucb/XContentProviderManager.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XTypeProvider.hpp> +#include <com/sun/star/util/XChangesListener.hpp> +#include <com/sun/star/util/XChangesNotifier.hpp> +#include <com/sun/star/container/XContainer.hpp> + +#include <rtl/ustrbuf.hxx> +#include <cppuhelper/weak.hxx> +#include <osl/mutex.hxx> +#include <osl/interlck.h> +#include <ucbhelper/macros.hxx> +#include "providermap.hxx" +#include <ucbhelper/registerucb.hxx> + +#include <vector> +//========================================================================= + +#define UCB_SERVICE_NAME "com.sun.star.ucb.UniversalContentBroker" + +//========================================================================= + +namespace cppu { class OInterfaceContainerHelper; } + +namespace com { namespace sun { namespace star { namespace ucb { + class XCommandInfo; + struct GlobalTransferCommandArgument; +} } } } + +class UniversalContentBroker : + public cppu::OWeakObject, + public com::sun::star::lang::XTypeProvider, + public com::sun::star::lang::XComponent, + public com::sun::star::lang::XServiceInfo, + public com::sun::star::lang::XInitialization, + public com::sun::star::ucb::XContentProviderManager, + public com::sun::star::ucb::XContentProvider, + public com::sun::star::ucb::XContentIdentifierFactory, + public com::sun::star::ucb::XCommandProcessor, + public com::sun::star::util::XChangesListener +{ +public: + UniversalContentBroker( const com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >& rXSMgr ); + virtual ~UniversalContentBroker(); + + // XInterface + XINTERFACE_DECL() + + // XTypeProvider + XTYPEPROVIDER_DECL() + + // XServiceInfo + XSERVICEINFO_DECL() + + // XComponent + virtual void SAL_CALL + dispose() + throw( com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + addEventListener( const com::sun::star::uno::Reference< + com::sun::star::lang::XEventListener >& Listener ) + throw( com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + removeEventListener( const com::sun::star::uno::Reference< + com::sun::star::lang::XEventListener >& Listener ) + throw( com::sun::star::uno::RuntimeException ); + + // XInitialization + virtual void SAL_CALL + initialize( const com::sun::star::uno::Sequence< + com::sun::star::uno::Any >& aArguments ) + throw( com::sun::star::uno::Exception, + com::sun::star::uno::RuntimeException ); + + // XContentProviderManager + virtual com::sun::star::uno::Reference< + com::sun::star::ucb::XContentProvider > SAL_CALL + registerContentProvider( const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentProvider >& + Provider, + const rtl::OUString& Scheme, + sal_Bool ReplaceExisting ) + throw( com::sun::star::ucb::DuplicateProviderException, + com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + deregisterContentProvider( const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentProvider >& + Provider, + const rtl::OUString& Scheme ) + throw( com::sun::star::uno::RuntimeException ); + virtual com::sun::star::uno::Sequence< + com::sun::star::ucb::ContentProviderInfo > SAL_CALL + queryContentProviders() + throw( com::sun::star::uno::RuntimeException ); + virtual com::sun::star::uno::Reference< + com::sun::star::ucb::XContentProvider > SAL_CALL + queryContentProvider( const rtl::OUString& Identifier ) + throw( com::sun::star::uno::RuntimeException ); + + // XContentProvider + virtual com::sun::star::uno::Reference< + com::sun::star::ucb::XContent > SAL_CALL + queryContent( const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& Identifier ) + throw( com::sun::star::ucb::IllegalIdentifierException, + com::sun::star::uno::RuntimeException ); + virtual sal_Int32 SAL_CALL + compareContentIds( const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& Id1, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& Id2 ) + throw( com::sun::star::uno::RuntimeException ); + + // XContentIdentifierFactory + virtual com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier > SAL_CALL + createContentIdentifier( const rtl::OUString& ContentId ) + throw( com::sun::star::uno::RuntimeException ); + + // XCommandProcessor + virtual sal_Int32 SAL_CALL + createCommandIdentifier() + throw( com::sun::star::uno::RuntimeException ); + virtual com::sun::star::uno::Any SAL_CALL + execute( const com::sun::star::ucb::Command& aCommand, + sal_Int32 CommandId, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment >& Environment ) + throw( com::sun::star::uno::Exception, + com::sun::star::ucb::CommandAbortedException, + com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + abort( sal_Int32 CommandId ) + throw( com::sun::star::uno::RuntimeException ); + + // XChangesListener + virtual void SAL_CALL changesOccurred( const com::sun::star::util::ChangesEvent& Event ) + throw( com::sun::star::uno::RuntimeException ); + + // XEventListener ( base of XChangesLisetenr ) + virtual void SAL_CALL disposing( const com::sun::star::lang::EventObject& Source ) + throw( com::sun::star::uno::RuntimeException ); + +private: + com::sun::star::uno::Reference< com::sun::star::ucb::XContentProvider > + queryContentProvider( const rtl::OUString& Identifier, + sal_Bool bResolved ); + + com::sun::star::uno::Reference< com::sun::star::ucb::XCommandInfo > + getCommandInfo(); + + void + globalTransfer( + const com::sun::star::ucb::GlobalTransferCommandArgument & rArg, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment >& xEnv ) + throw( com::sun::star::uno::Exception ); + + + bool configureUcb() + throw ( com::sun::star::uno::RuntimeException); + + bool getContentProviderData( + const rtl::OUString & rKey1, + const rtl::OUString & rKey2, + ucbhelper::ContentProviderDataList & rListToFill); + + void prepareAndRegister( const ucbhelper::ContentProviderDataList& rData); + + com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory > m_xSMgr; + + com::sun::star::uno::Reference< + com::sun::star::util::XChangesNotifier > m_xNotifier; + + com::sun::star::uno::Sequence< com::sun::star::uno::Any > m_aArguments; + ProviderMap_Impl m_aProviders; + osl::Mutex m_aMutex; + cppu::OInterfaceContainerHelper* m_pDisposeEventListeners; + oslInterlockedCount m_nInitCount; //@@@ see initialize() method + sal_Int32 m_nCommandId; +}; + +#endif /* !_UCB_HXX */ diff --git a/ucb/source/core/ucb.xml b/ucb/source/core/ucb.xml new file mode 100644 index 000000000000..1473c035ba83 --- /dev/null +++ b/ucb/source/core/ucb.xml @@ -0,0 +1,172 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE module-description PUBLIC "-//StarOffice//DTD ComponentDescription 1.0//EN" "module-description.dtd"> +<module-description xmlns:xlink="http://www.w3.org/1999/xlink"> + + <module-name> + ucb + </module-name> + + <component-description> + <author> + Kai Sommerfeld + </author> + <name> + com.sun.star.comp.ucb.UniversalContentBroker + </name> + <description> + This component provides access to a set of Contents via Content Providers. + </description> + <loader-name> + com.sun.star.loader.SharedLibrary + </loader-name> + <language> + c++ + </language> + <status value="final"/> + <supported-service> + com.sun.star.ucb.UniversalContentBroker + </supported-service> + + <service-dependency> + com.sun.star.io.Pipe + </service-dependency> + </component-description> + <component-description> + <author> + Kai Sommerfeld + </author> + <name> + com.sun.star.comp.ucb.UcbStore + </name> + <description> + This component is a factory for components managing persistent data. + </description> + <loader-name> + com.sun.star.loader.SharedLibrary + </loader-name> + <language> + c++ + </language> + <status value="final"/> + <supported-service> + com.sun.star.ucb.Store + </supported-service> + + <service-dependency> + com.sun.star.configuration.ConfigurationProvider + </service-dependency> + <service-dependency> + com.sun.star.configuration.ConfigurationAccess + </service-dependency> + <service-dependency> + com.sun.star.configuration.ConfigurationUpdateAccess + </service-dependency> + </component-description> + <component-description> + <author> + Kai Sommerfeld + </author> + <name> + com.sun.star.comp.ucb.UcbPropertiesManager + </name> + <description> + This component provides access to the meta data of the properties + known to the UCB. + </description> + <loader-name> + com.sun.star.loader.SharedLibrary + </loader-name> + <language> + c++ + </language> + <status value="final"/> + <supported-service> + com.sun.star.ucb.PropertiesManager + </supported-service> + </component-description> + <component-description> + <author> + Kai Sommerfeld + </author> + <name> + com.sun.star.comp.ucb.UcbContentProviderProxyFactory + </name> + <description> + This component is a factory for proxy objects for Content Providers. + </description> + <loader-name> + com.sun.star.loader.SharedLibrary + </loader-name> + <language> + c++ + </language> + <status value="final"/> + <supported-service> + com.sun.star.ucb.ContentProviderProxyFactory + </supported-service> + </component-description> + + <project-build-dependency> sal </project-build-dependency> + <project-build-dependency> cppu </project-build-dependency> + <project-build-dependency> cppuhelper </project-build-dependency> + <project-build-dependency> ucbhelper </project-build-dependency> + + <runtime-module-dependency> sal3 </runtime-module-dependency> + <runtime-module-dependency> cppu3 </runtime-module-dependency> + <runtime-module-dependency> cppuhelper3$(COM) </runtime-module-dependency> + <runtime-module-dependency> ucbhelper1$(COM) </runtime-module-dependency> + + <type> com.sun.star.beans.PropertyAttribute </type> + <type> com.sun.star.beans.PropertySetInfoChange </type> + <type> com.sun.star.beans.XPropertyAccess </type> + <type> com.sun.star.beans.XPropertyContainer </type> + <type> com.sun.star.beans.XPropertySetInfoChangeNotifier </type> + <type> com.sun.star.container.XHierarchicalNameAccess </type> + <type> com.sun.star.container.XNamed </type> + <type> com.sun.star.container.XNameAccess </type> + <type> com.sun.star.container.XNameContainer </type> + <type> com.sun.star.io.XActiveDataSink </type> + <type> com.sun.star.io.XOutputStream </type> + <type> com.sun.star.io.XSeekable </type> + <type> com.sun.star.lang.IllegalArgumentException </type> + <type> com.sun.star.lang.XComponent </type> + <type> com.sun.star.lang.XInitialization </type> + <type> com.sun.star.lang.XMultiServiceFactory </type> + <type> com.sun.star.lang.XServiceInfo </type> + <type> com.sun.star.lang.XSingleServiceFactory </type> + <type> com.sun.star.lang.XTypeProvider </type> + <type> com.sun.star.registry.XRegistryKey </type> + <type> com.sun.star.sdbc.XRow </type> + <type> com.sun.star.ucb.ContentInfoAttribute </type> + <type> com.sun.star.ucb.CrossReference </type> + <type> com.sun.star.ucb.DocumentHeaderField </type> + <type> com.sun.star.ucb.GlobalTransferCommandArgument </type> + <type> com.sun.star.ucb.InsertCommandArgument </type> + <type> com.sun.star.ucb.InteractiveBadTransferURLException </type> + <type> com.sun.star.ucb.NameClashException </type> + <type> com.sun.star.ucb.OpenCommandArgument2 </type> + <type> com.sun.star.ucb.OpenMode </type> + <type> com.sun.star.ucb.RecipientInfo </type> + <type> com.sun.star.ucb.RuleSet </type> + <type> com.sun.star.ucb.SendInfo </type> + <type> com.sun.star.ucb.SendMediaTypes </type> + <type> com.sun.star.ucb.TransferInfo </type> + <type> com.sun.star.ucb.UnsupportedNameClashException </type> + <type> com.sun.star.ucb.XCommandInfo </type> + <type> com.sun.star.ucb.XCommandProcessor </type> + <type> com.sun.star.ucb.XContentAccess </type> + <type> com.sun.star.ucb.XContentCreator </type> + <type> com.sun.star.ucb.XContentIdentifier </type> + <type> com.sun.star.ucb.XContentIdentifierFactory </type> + <type> com.sun.star.ucb.XContentProvider </type> + <type> com.sun.star.ucb.XContentProviderFactory </type> + <type> com.sun.star.ucb.XContentProviderManager </type> + <type> com.sun.star.ucb.XContentProviderSupplier </type> + <type> com.sun.star.ucb.XDataContainer </type> + <type> com.sun.star.ucb.XDynamicResultSet </type> + <type> com.sun.star.ucb.XParameterizedContentProvider </type> + <type> com.sun.star.ucb.XPropertySetRegistryFactory </type> + <type> com.sun.star.uno.XWeak </type> + <type> com.sun.star.util.DateTime </type> + <type> com.sun.star.util.XChangesBatch </type> +</module-description> diff --git a/ucb/source/core/ucb1.component b/ucb/source/core/ucb1.component new file mode 100644 index 000000000000..e9d408822cc9 --- /dev/null +++ b/ucb/source/core/ucb1.component @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* 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. +* +**********************************************************************--> + +<component loader="com.sun.star.loader.SharedLibrary" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.ucb.CommandEnvironment"> + <service name="com.sun.star.ucb.CommandEnvironment"/> + </implementation> + <implementation name="com.sun.star.comp.ucb.UcbContentProviderProxyFactory"> + <service name="com.sun.star.ucb.ContentProviderProxyFactory"/> + </implementation> + <implementation name="com.sun.star.comp.ucb.UcbPropertiesManager"> + <service name="com.sun.star.ucb.PropertiesManager"/> + </implementation> + <implementation name="com.sun.star.comp.ucb.UcbStore"> + <service name="com.sun.star.ucb.Store"/> + </implementation> + <implementation name="com.sun.star.comp.ucb.UniversalContentBroker"> + <service name="com.sun.star.ucb.UniversalContentBroker"/> + </implementation> +</component> diff --git a/ucb/source/core/ucbcmds.cxx b/ucb/source/core/ucbcmds.cxx new file mode 100644 index 000000000000..fd3f0f73c772 --- /dev/null +++ b/ucb/source/core/ucbcmds.cxx @@ -0,0 +1,2090 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ +#include <osl/diagnose.h> +#include <cppuhelper/implbase1.hxx> +#include <cppuhelper/exc_hlp.hxx> +#include <rtl/ustring.h> +#include <rtl/ustring.hxx> +#include <com/sun/star/uno/XInterface.hpp> +#include <com/sun/star/beans/PropertyState.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/container/XChild.hpp> +#include <com/sun/star/beans/XPropertySetInfo.hpp> +#include <com/sun/star/io/XActiveDataSink.hpp> +#include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/io/XSeekable.hpp> +#include <com/sun/star/sdbc/XRow.hpp> +#include <com/sun/star/task/XInteractionHandler.hpp> +#include <com/sun/star/ucb/CommandEnvironment.hpp> +#include <com/sun/star/ucb/CommandFailedException.hpp> +#include <com/sun/star/ucb/ContentInfoAttribute.hpp> +#include <com/sun/star/ucb/GlobalTransferCommandArgument.hpp> +#include <com/sun/star/ucb/InsertCommandArgument.hpp> +#include <com/sun/star/ucb/InteractiveBadTransferURLException.hpp> +#include <com/sun/star/ucb/NameClash.hpp> +#include <com/sun/star/ucb/NameClashException.hpp> +#include <com/sun/star/ucb/OpenCommandArgument2.hpp> +#include <com/sun/star/ucb/OpenMode.hpp> +#include <com/sun/star/ucb/TransferInfo.hpp> +#include <com/sun/star/ucb/UnsupportedNameClashException.hpp> +#include <com/sun/star/ucb/XCommandInfo.hpp> +#include <com/sun/star/ucb/XContentAccess.hpp> +#include <com/sun/star/ucb/XContentCreator.hpp> +#include <com/sun/star/ucb/XDynamicResultSet.hpp> +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/uno/Sequence.hxx> +#include <ucbhelper/cancelcommandexecution.hxx> +#include <ucbhelper/simplenameclashresolverequest.hxx> +#include "ucbcmds.hxx" +#include "ucb.hxx" + +using namespace com::sun::star; + +namespace +{ + +//========================================================================= +// +// struct TransferCommandContext. +// +//========================================================================= + +struct TransferCommandContext +{ + uno::Reference< lang::XMultiServiceFactory > xSMgr; + uno::Reference< ucb::XCommandProcessor > xProcessor; + uno::Reference< ucb::XCommandEnvironment > xEnv; + uno::Reference< ucb::XCommandEnvironment > xOrigEnv; + ucb::GlobalTransferCommandArgument aArg; + + TransferCommandContext( + const uno::Reference< lang::XMultiServiceFactory > & rxSMgr, + const uno::Reference< ucb::XCommandProcessor > & rxProcessor, + const uno::Reference< ucb::XCommandEnvironment > & rxEnv, + const uno::Reference< ucb::XCommandEnvironment > & rxOrigEnv, + const ucb::GlobalTransferCommandArgument & rArg ) + : xSMgr( rxSMgr ), xProcessor( rxProcessor ), xEnv( rxEnv ), + xOrigEnv( rxOrigEnv ), aArg( rArg ) {} +}; + +//========================================================================= +// +// class InteractionHandlerProxy. +// +//========================================================================= + +class InteractionHandlerProxy : + public cppu::WeakImplHelper1< task::XInteractionHandler > +{ + uno::Reference< task::XInteractionHandler > m_xOrig; + +public: + InteractionHandlerProxy( + const uno::Reference< task::XInteractionHandler > & xOrig ) + : m_xOrig( xOrig ) {} + + // XInteractionHandler methods. + virtual void SAL_CALL handle( + const uno::Reference< task::XInteractionRequest >& Request ) + throw ( uno::RuntimeException ); +}; + +//========================================================================= +// virtual +void SAL_CALL InteractionHandlerProxy::handle( + const uno::Reference< task::XInteractionRequest >& Request ) + throw ( uno::RuntimeException ) +{ + if ( !m_xOrig.is() ) + return; + + // Filter unwanted requests by just not handling them. + uno::Any aRequest = Request->getRequest(); + + // "transfer" + ucb::InteractiveBadTransferURLException aBadTransferURLEx; + if ( aRequest >>= aBadTransferURLEx ) + { + return; + } + else + { + // "transfer" + ucb::UnsupportedNameClashException aUnsupportedNameClashEx; + if ( aRequest >>= aUnsupportedNameClashEx ) + { + if ( aUnsupportedNameClashEx.NameClash + != ucb::NameClash::ERROR ) + return; + } + else + { + // "insert" + ucb::NameClashException aNameClashEx; + if ( aRequest >>= aNameClashEx ) + { + return; + } + else + { + // "transfer" + ucb::UnsupportedCommandException aUnsupportedCommandEx; + if ( aRequest >>= aUnsupportedCommandEx ) + { + return; + } + } + } + } + + // not filtered; let the original handler do the work. + m_xOrig->handle( Request ); +} + +//========================================================================= +// +// class ActiveDataSink. +// +//========================================================================= + +class ActiveDataSink : public cppu::WeakImplHelper1< io::XActiveDataSink > +{ + uno::Reference< io::XInputStream > m_xStream; + +public: + // XActiveDataSink methods. + virtual void SAL_CALL setInputStream( + const uno::Reference< io::XInputStream >& aStream ) + throw( uno::RuntimeException ); + virtual uno::Reference< io::XInputStream > SAL_CALL getInputStream() + throw( uno::RuntimeException ); +}; + +//========================================================================= +// virtual +void SAL_CALL ActiveDataSink::setInputStream( + const uno::Reference< io::XInputStream >& aStream ) + throw( uno::RuntimeException ) +{ + m_xStream = aStream; +} + +//========================================================================= +// virtual +uno::Reference< io::XInputStream > SAL_CALL ActiveDataSink::getInputStream() + throw( uno::RuntimeException ) +{ + return m_xStream; +} + +//========================================================================= +// +// class CommandProcessorInfo. +// +//========================================================================= + +class CommandProcessorInfo : + public cppu::WeakImplHelper1< ucb::XCommandInfo > +{ + uno::Sequence< ucb::CommandInfo > * m_pInfo; + +public: + CommandProcessorInfo(); + virtual ~CommandProcessorInfo(); + + // XCommandInfo methods + virtual uno::Sequence< ucb::CommandInfo > SAL_CALL getCommands() + throw( uno::RuntimeException ); + virtual ucb::CommandInfo SAL_CALL + getCommandInfoByName( const rtl::OUString& Name ) + throw( ucb::UnsupportedCommandException, uno::RuntimeException ); + virtual ucb::CommandInfo SAL_CALL + getCommandInfoByHandle( sal_Int32 Handle ) + throw( ucb::UnsupportedCommandException, uno::RuntimeException ); + virtual sal_Bool SAL_CALL hasCommandByName( const rtl::OUString& Name ) + throw( uno::RuntimeException ); + virtual sal_Bool SAL_CALL hasCommandByHandle( sal_Int32 Handle ) + throw( uno::RuntimeException ); +}; + +//========================================================================= +CommandProcessorInfo::CommandProcessorInfo() +{ + m_pInfo = new uno::Sequence< ucb::CommandInfo >( 2 ); + + (*m_pInfo)[ 0 ] + = ucb::CommandInfo( + rtl::OUString::createFromAscii( GETCOMMANDINFO_NAME ), // Name + GETCOMMANDINFO_HANDLE, // Handle + getCppuVoidType() ); // ArgType + (*m_pInfo)[ 1 ] + = ucb::CommandInfo( + rtl::OUString::createFromAscii( GLOBALTRANSFER_NAME ), // Name + GLOBALTRANSFER_HANDLE, // Handle + getCppuType( + static_cast< + ucb::GlobalTransferCommandArgument * >( 0 ) ) ); // ArgType +} + +//========================================================================= +// virtual +CommandProcessorInfo::~CommandProcessorInfo() +{ + delete m_pInfo; +} + +//========================================================================= +// virtual +uno::Sequence< ucb::CommandInfo > SAL_CALL +CommandProcessorInfo::getCommands() + throw( uno::RuntimeException ) +{ + return uno::Sequence< ucb::CommandInfo >( *m_pInfo ); +} + +//========================================================================= +// virtual +ucb::CommandInfo SAL_CALL +CommandProcessorInfo::getCommandInfoByName( const rtl::OUString& Name ) + throw( ucb::UnsupportedCommandException, uno::RuntimeException ) +{ + for ( sal_Int32 n = 0; n < m_pInfo->getLength(); ++n ) + { + if ( (*m_pInfo)[ n ].Name == Name ) + return ucb::CommandInfo( (*m_pInfo)[ n ] ); + } + + throw ucb::UnsupportedCommandException(); +} + +//========================================================================= +// virtual +ucb::CommandInfo SAL_CALL +CommandProcessorInfo::getCommandInfoByHandle( sal_Int32 Handle ) + throw( ucb::UnsupportedCommandException, uno::RuntimeException ) +{ + for ( sal_Int32 n = 0; n < m_pInfo->getLength(); ++n ) + { + if ( (*m_pInfo)[ n ].Handle == Handle ) + return ucb::CommandInfo( (*m_pInfo)[ n ] ); + } + + throw ucb::UnsupportedCommandException(); +} + +//========================================================================= +// virtual +sal_Bool SAL_CALL CommandProcessorInfo::hasCommandByName( + const rtl::OUString& Name ) + throw( uno::RuntimeException ) +{ + for ( sal_Int32 n = 0; n < m_pInfo->getLength(); ++n ) + { + if ( (*m_pInfo)[ n ].Name == Name ) + return sal_True; + } + + return sal_False; +} + +//========================================================================= +// virtual +sal_Bool SAL_CALL CommandProcessorInfo::hasCommandByHandle( sal_Int32 Handle ) + throw( uno::RuntimeException ) +{ + for ( sal_Int32 n = 0; n < m_pInfo->getLength(); ++n ) + { + if ( (*m_pInfo)[ n ].Handle == Handle ) + return sal_True; + } + + return sal_False; +} + +//========================================================================= +//========================================================================= +//========================================================================= + +rtl::OUString createDesiredName( + const rtl::OUString & rSourceURL, const rtl::OUString & rNewTitle ) +{ + rtl::OUString aName( rNewTitle ); + if ( aName.getLength() == 0 ) + { + // calculate name using source URL + + // @@@ It's not guaranteed that slashes contained in the URL are + // actually path separators. This depends on the fact whether the + // URL is hierarchical. Only then the slashes are path separators. + // Therefore this algorithm is not guaranteed to work! But, ATM + // I don't know a better solution. It would have been better to + // have a member for the clashing name in + // UnsupportedNameClashException... + + sal_Int32 nLastSlash = rSourceURL.lastIndexOf( '/' ); + bool bTrailingSlash = false; + if ( nLastSlash == rSourceURL.getLength() - 1 ) + { + nLastSlash = rSourceURL.lastIndexOf( '/', nLastSlash ); + bTrailingSlash = true; + } + + if ( nLastSlash != -1 ) + { + if ( bTrailingSlash ) + aName = rSourceURL.copy( + nLastSlash + 1, + rSourceURL.getLength() - nLastSlash - 2 ); + else + aName = rSourceURL.copy( nLastSlash + 1 ); + } + else + { + aName = rSourceURL; + } + + // query, fragment present? + sal_Int32 nPos = aName.indexOf( '?' ); + if ( nPos == -1 ) + nPos = aName.indexOf( '#' ); + + if ( nPos != -1 ) + aName = aName.copy( 0, nPos ); + } + return rtl::OUString( aName ); +} + +rtl::OUString createDesiredName( + const ucb::GlobalTransferCommandArgument & rArg ) +{ + return createDesiredName( rArg.SourceURL, rArg.NewTitle ); +} + +rtl::OUString createDesiredName( + const ucb::TransferInfo & rArg ) +{ + return createDesiredName( rArg.SourceURL, rArg.NewTitle ); +} + +//========================================================================= +enum NameClashContinuation { NOT_HANDLED, ABORT, OVERWRITE, NEW_NAME, UNKNOWN }; + +NameClashContinuation interactiveNameClashResolve( + const uno::Reference< ucb::XCommandEnvironment > & xEnv, + const rtl::OUString & rTargetURL, + const rtl::OUString & rClashingName, + /* [out] */ uno::Any & rException, + /* [out] */ rtl::OUString & rNewName ) +{ + rtl::Reference< ucbhelper::SimpleNameClashResolveRequest > xRequest( + new ucbhelper::SimpleNameClashResolveRequest( + rTargetURL, // target folder URL + rClashingName, // clashing name + rtl::OUString(), // no proposal for new name + sal_True /* bSupportsOverwriteData */ ) ); + + rException = xRequest->getRequest(); + if ( xEnv.is() ) + { + uno::Reference< task::XInteractionHandler > xIH + = xEnv->getInteractionHandler(); + if ( xIH.is() ) + { + + xIH->handle( xRequest.get() ); + + rtl::Reference< ucbhelper::InteractionContinuation > + xSelection( xRequest->getSelection() ); + + if ( xSelection.is() ) + { + // Handler handled the request. + uno::Reference< task::XInteractionAbort > xAbort( + xSelection.get(), uno::UNO_QUERY ); + if ( xAbort.is() ) + { + // Abort. + return ABORT; + } + else + { + uno::Reference< + ucb::XInteractionReplaceExistingData > + xReplace( + xSelection.get(), uno::UNO_QUERY ); + if ( xReplace.is() ) + { + // Try again: Replace existing data. + return OVERWRITE; + } + else + { + uno::Reference< + ucb::XInteractionSupplyName > + xSupplyName( + xSelection.get(), uno::UNO_QUERY ); + if ( xSupplyName.is() ) + { + // Try again: Use new name. + rNewName = xRequest->getNewName(); + return NEW_NAME; + } + else + { + OSL_ENSURE( sal_False, + "Unknown interaction continuation!" ); + return UNKNOWN; + } + } + } + } + } + } + return NOT_HANDLED; +} + +//========================================================================= +bool setTitle( + const uno::Reference< ucb::XCommandProcessor > & xCommandProcessor, + const uno::Reference< ucb::XCommandEnvironment > & xEnv, + const rtl::OUString & rNewTitle ) + throw( uno::RuntimeException ) +{ + try + { + uno::Sequence< beans::PropertyValue > aPropValues( 1 ); + aPropValues[ 0 ].Name + = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ); + aPropValues[ 0 ].Handle = -1; + aPropValues[ 0 ].Value = uno::makeAny( rNewTitle ); + + ucb::Command aSetPropsCommand( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ), + -1, + uno::makeAny( aPropValues ) ); + + uno::Any aResult + = xCommandProcessor->execute( aSetPropsCommand, 0, xEnv ); + + uno::Sequence< uno::Any > aErrors; + aResult >>= aErrors; + + OSL_ENSURE( aErrors.getLength() == 1, + "getPropertyValues return value invalid!" ); + + if ( aErrors[ 0 ].hasValue() ) + { + // error occured. + OSL_ENSURE( sal_False, "error setting Title property!" ); + return false; + } + } + catch ( uno::RuntimeException const & ) + { + throw; + } + catch ( uno::Exception const & ) + { + return false; + } + + return true; +} + +//========================================================================= +uno::Reference< ucb::XContent > createNew( + const TransferCommandContext & rContext, + const uno::Reference< ucb::XContent > & xTarget, + sal_Bool bSourceIsFolder, + sal_Bool bSourceIsDocument, + sal_Bool bSourceIsLink ) + throw( uno::Exception ) +{ + ////////////////////////////////////////////////////////////////////// + // + // (1) Obtain creatable types from target. + // + ////////////////////////////////////////////////////////////////////// + + // First, try it using "CreatabeleContentsInfo" property and + // "createNewContent" command -> the "new" way. + + uno::Reference< ucb::XCommandProcessor > xCommandProcessorT( + xTarget, uno::UNO_QUERY ); + if ( !xCommandProcessorT.is() ) + { + uno::Any aProps + = uno::makeAny(beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Folder")), + -1, + uno::makeAny(rContext.aArg.TargetURL), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_CREATE, + uno::Sequence< uno::Any >(&aProps, 1), + rContext.xOrigEnv, + rtl::OUString::createFromAscii( "Target is no XCommandProcessor!" ), + rContext.xProcessor ); + // Unreachable + } + + uno::Sequence< beans::Property > aPropsToObtain( 1 ); + aPropsToObtain[ 0 ].Name + = rtl::OUString::createFromAscii( "CreatableContentsInfo" ); + aPropsToObtain[ 0 ].Handle + = -1; + + ucb::Command aGetPropsCommand( + rtl::OUString::createFromAscii( "getPropertyValues" ), + -1, + uno::makeAny( aPropsToObtain ) ); + + uno::Reference< sdbc::XRow > xRow; + xCommandProcessorT->execute( aGetPropsCommand, 0, rContext.xEnv ) >>= xRow; + + uno::Sequence< ucb::ContentInfo > aTypesInfo; + bool bGotTypesInfo = false; + + if ( xRow.is() ) + { + uno::Any aValue = xRow->getObject( + 1, uno::Reference< container::XNameAccess >() ); + if ( aValue.hasValue() && ( aValue >>= aTypesInfo ) ) + { + bGotTypesInfo = true; + } + } + + uno::Reference< ucb::XContentCreator > xCreator; + + if ( !bGotTypesInfo ) + { + // Second, try it using XContentCreator interface -> the "old" way (not + // providing the chance to supply an XCommandEnvironment. + + xCreator.set( xTarget, uno::UNO_QUERY ); + + if ( !xCreator.is() ) + { + uno::Any aProps + = uno::makeAny(beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Folder")), + -1, + uno::makeAny(rContext.aArg.TargetURL), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_CREATE, + uno::Sequence< uno::Any >(&aProps, 1), + rContext.xOrigEnv, + rtl::OUString::createFromAscii( "Target is no XContentCreator!" ), + rContext.xProcessor ); + // Unreachable + } + + aTypesInfo = xCreator->queryCreatableContentsInfo(); + } + + sal_Int32 nCount = aTypesInfo.getLength(); + if ( !nCount ) + { + uno::Any aProps + = uno::makeAny(beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Folder")), + -1, + uno::makeAny(rContext.aArg.TargetURL), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_CREATE, + uno::Sequence< uno::Any >(&aProps, 1), + rContext.xOrigEnv, + rtl::OUString::createFromAscii( "No types creatable!" ), + rContext.xProcessor ); + // Unreachable + } + + ////////////////////////////////////////////////////////////////////// + // + // (2) Try to find a matching target type for the source object. + // + ////////////////////////////////////////////////////////////////////// + + uno::Reference< ucb::XContent > xNew; + for ( sal_Int32 n = 0; n < nCount; ++n ) + { + sal_Int32 nAttribs = aTypesInfo[ n ].Attributes; + sal_Bool bMatch = sal_False; + + if ( rContext.aArg.Operation == ucb::TransferCommandOperation_LINK ) + { + // Create link + + if ( nAttribs & ucb::ContentInfoAttribute::KIND_LINK ) + { + // Match! + bMatch = sal_True; + } + } + else if ( ( rContext.aArg.Operation + == ucb::TransferCommandOperation_COPY ) || + ( rContext.aArg.Operation + == ucb::TransferCommandOperation_MOVE ) ) + { + // Copy / Move + + // Is source a link? Create link in target folder then. + if ( bSourceIsLink ) + { + if ( nAttribs & ucb::ContentInfoAttribute::KIND_LINK ) + { + // Match! + bMatch = sal_True; + } + } + else + { + // (not a and not b) or (a and b) + // not( a or b) or (a and b) + // + if ( ( !!bSourceIsFolder == + !!( nAttribs + & ucb::ContentInfoAttribute::KIND_FOLDER ) ) + && + ( !!bSourceIsDocument == + !!( nAttribs + & ucb::ContentInfoAttribute::KIND_DOCUMENT ) ) + ) + { + // Match! + bMatch = sal_True; + } + } + } + else + { + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Unknown transfer operation!" ), + rContext.xProcessor, + -1 ) ), + rContext.xOrigEnv ); + // Unreachable + } + + if ( bMatch ) + { + ////////////////////////////////////////////////////////////// + // + // (3) Create a new, empty object of matched type. + // + ////////////////////////////////////////////////////////////// + + if ( !xCreator.is() ) + { + // First, try it using "CreatabeleContentsInfo" property and + // "createNewContent" command -> the "new" way. + ucb::Command aCreateNewCommand( + rtl::OUString::createFromAscii( "createNewContent" ), + -1, + uno::makeAny( aTypesInfo[ n ] ) ); + + xCommandProcessorT->execute( aCreateNewCommand, 0, rContext.xEnv ) + >>= xNew; + } + else + { + // Second, try it using XContentCreator interface -> the "old" + // way (not providing the chance to supply an XCommandEnvironment. + + xNew = xCreator->createNewContent( aTypesInfo[ n ] ); + } + + if ( !xNew.is() ) + { + uno::Any aProps + = uno::makeAny( + beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Folder")), + -1, + uno::makeAny(rContext.aArg.TargetURL), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_CREATE, + uno::Sequence< uno::Any >(&aProps, 1), + rContext.xOrigEnv, + rtl::OUString::createFromAscii( + "createNewContent failed!" ), + rContext.xProcessor ); + // Unreachable + } + break; // escape from 'for' loop + } + } // for + + return xNew; +} + +//========================================================================= +void transferProperties( + const TransferCommandContext & rContext, + const uno::Reference< ucb::XCommandProcessor > & xCommandProcessorS, + const uno::Reference< ucb::XCommandProcessor > & xCommandProcessorN ) + throw( uno::Exception ) +{ + ucb::Command aGetPropertySetInfoCommand( + rtl::OUString::createFromAscii( "getPropertySetInfo" ), + -1, + uno::Any() ); + + uno::Reference< beans::XPropertySetInfo > xInfo; + xCommandProcessorS->execute( aGetPropertySetInfoCommand, 0, rContext.xEnv ) + >>= xInfo; + + if ( !xInfo.is() ) + { + uno::Any aProps + = uno::makeAny(beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Uri")), + -1, + uno::makeAny(rContext.aArg.SourceURL), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_READ, + uno::Sequence< uno::Any >(&aProps, 1), + rContext.xOrigEnv, + rtl::OUString::createFromAscii( + "Unable to get propertyset info from source object!" ), + rContext.xProcessor ); + // Unreachable + } + + uno::Sequence< beans::Property > aAllProps = xInfo->getProperties(); + + ucb::Command aGetPropsCommand1( + rtl::OUString::createFromAscii( "getPropertyValues" ), + -1, + uno::makeAny( aAllProps ) ); + + uno::Reference< sdbc::XRow > xRow1; + xCommandProcessorS->execute( + aGetPropsCommand1, 0, rContext.xEnv ) >>= xRow1; + + if ( !xRow1.is() ) + { + uno::Any aProps + = uno::makeAny(beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Uri")), + -1, + uno::makeAny(rContext.aArg.SourceURL), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_READ, + uno::Sequence< uno::Any >(&aProps, 1), + rContext.xOrigEnv, + rtl::OUString::createFromAscii( + "Unable to get properties from source object!" ), + rContext.xProcessor ); + // Unreachable + } + + // Assemble data structure for setPropertyValues command. + + // Note: Make room for additional Title and TargetURL too. -> + 2 + uno::Sequence< beans::PropertyValue > aPropValues( + aAllProps.getLength() + 2 ); + + sal_Bool bHasTitle = ( rContext.aArg.NewTitle.getLength() == 0 ); + sal_Bool bHasTargetURL = ( rContext.aArg.Operation + != ucb::TransferCommandOperation_LINK ); + + sal_Int32 nWritePos = 0; + for ( sal_Int32 m = 0; m < aAllProps.getLength(); ++m ) + { + const beans::Property & rCurrProp = aAllProps[ m ]; + beans::PropertyValue & rCurrValue = aPropValues[ nWritePos ]; + + uno::Any aValue; + + if ( rCurrProp.Name.compareToAscii( "Title" ) == 0 ) + { + // Supply new title, if given. + if ( !bHasTitle ) + { + bHasTitle = sal_True; + aValue <<= rContext.aArg.NewTitle; + } + } + else if ( rCurrProp.Name.compareToAscii( "TargetURL" ) == 0 ) + { + // Supply source URL as link target for the new link to create. + if ( !bHasTargetURL ) + { + bHasTargetURL = sal_True; + aValue <<= rContext.aArg.SourceURL; + } + } + + if ( !aValue.hasValue() ) + { + try + { + aValue = xRow1->getObject( + m + 1, uno::Reference< container::XNameAccess >() ); + } + catch ( sdbc::SQLException const & ) + { + // Argh! But try to bring things to an end. Perhaps the + // mad property is not really important... + } + } + + if ( aValue.hasValue() ) + { + rCurrValue.Name = rCurrProp.Name; + rCurrValue.Handle = rCurrProp.Handle; + rCurrValue.Value = aValue; +// rCurrValue.State = + + nWritePos++; + } + } + + // Title needed, but not set yet? + if ( !bHasTitle && ( rContext.aArg.NewTitle.getLength() > 0 ) ) + { + aPropValues[ nWritePos ].Name + = rtl::OUString::createFromAscii( "Title" ); + aPropValues[ nWritePos ].Handle = -1; + aPropValues[ nWritePos ].Value <<= rContext.aArg.NewTitle; + + nWritePos++; + } + + // TargetURL needed, but not set yet? + if ( !bHasTargetURL && ( rContext.aArg.Operation + == ucb::TransferCommandOperation_LINK ) ) + { + aPropValues[ nWritePos ].Name + = rtl::OUString::createFromAscii( "TargetURL" ); + aPropValues[ nWritePos ].Handle = -1; + aPropValues[ nWritePos ].Value <<= rContext.aArg.SourceURL; + + nWritePos++; + } + + aPropValues.realloc( nWritePos ); + + // Set properties at new object. + + ucb::Command aSetPropsCommand( + rtl::OUString::createFromAscii( "setPropertyValues" ), + -1, + uno::makeAny( aPropValues ) ); + + xCommandProcessorN->execute( aSetPropsCommand, 0, rContext.xEnv ); + + // @@@ What to do with source props that are not supported by the + // new object? addProperty ??? +} + +//========================================================================= +uno::Reference< io::XInputStream > getInputStream( + const TransferCommandContext & rContext, + const uno::Reference< ucb::XCommandProcessor > & xCommandProcessorS ) + throw( uno::Exception ) +{ + uno::Reference< io::XInputStream > xInputStream; + + ////////////////////////////////////////////////////////////////////// + // + // (1) Try to get data as XInputStream via XActiveDataSink. + // + ////////////////////////////////////////////////////////////////////// + + try + { + uno::Reference< io::XActiveDataSink > xSink = new ActiveDataSink; + + ucb::OpenCommandArgument2 aArg; + aArg.Mode = ucb::OpenMode::DOCUMENT; + aArg.Priority = 0; // unused + aArg.Sink = xSink; + aArg.Properties = uno::Sequence< beans::Property >( 0 ); // unused + + ucb::Command aOpenCommand( + rtl::OUString::createFromAscii( "open" ), + -1, + uno::makeAny( aArg ) ); + + xCommandProcessorS->execute( aOpenCommand, 0, rContext.xEnv ); + xInputStream = xSink->getInputStream(); + } + catch ( uno::RuntimeException const & ) + { + throw; + } + catch ( uno::Exception const & ) + { + // will be handled below. + } + + if ( !xInputStream.is() ) + { + ////////////////////////////////////////////////////////////////// + // + // (2) Try to get data via XOutputStream. + // + ////////////////////////////////////////////////////////////////// + + try + { + uno::Reference< io::XOutputStream > xOutputStream( + rContext.xSMgr->createInstance( + rtl::OUString::createFromAscii( "com.sun.star.io.Pipe" ) ), + uno::UNO_QUERY ); + + if ( xOutputStream.is() ) + { + ucb::OpenCommandArgument2 aArg; + aArg.Mode = ucb::OpenMode::DOCUMENT; + aArg.Priority = 0; // unused + aArg.Sink = xOutputStream; + aArg.Properties = uno::Sequence< beans::Property >( 0 ); + + ucb::Command aOpenCommand( + rtl::OUString::createFromAscii( "open" ), + -1, + uno::makeAny( aArg ) ); + + xCommandProcessorS->execute( aOpenCommand, 0, rContext.xEnv ); + + xInputStream = uno::Reference< io::XInputStream >( + xOutputStream, uno::UNO_QUERY ); + } + } + catch ( uno::RuntimeException const & ) + { + throw; + } + catch ( uno::Exception const & ) + { + OSL_ENSURE( sal_False, "unable to get input stream from document!" ); + } + } + + return xInputStream; +} + +//========================================================================= +uno::Reference< sdbc::XResultSet > getResultSet( + const TransferCommandContext & rContext, + const uno::Reference< ucb::XCommandProcessor > & xCommandProcessorS ) + throw( uno::Exception ) +{ + uno::Reference< sdbc::XResultSet > xResultSet; + + uno::Sequence< beans::Property > aProps( 3 ); + + aProps[ 0 ].Name = rtl::OUString::createFromAscii( "IsFolder" ); + aProps[ 0 ].Handle = -1; /* unknown */ + aProps[ 1 ].Name = rtl::OUString::createFromAscii( "IsDocument" ); + aProps[ 1 ].Handle = -1; /* unknown */ + aProps[ 2 ].Name = rtl::OUString::createFromAscii( "TargetURL" ); + aProps[ 2 ].Handle = -1; /* unknown */ + + ucb::OpenCommandArgument2 aArg; + aArg.Mode = ucb::OpenMode::ALL; + aArg.Priority = 0; // unused + aArg.Sink = 0; + aArg.Properties = aProps; + + ucb::Command aOpenCommand( rtl::OUString::createFromAscii( "open" ), + -1, + uno::makeAny( aArg ) ); + try + { + uno::Reference< ucb::XDynamicResultSet > xSet; + xCommandProcessorS->execute( aOpenCommand, 0, rContext.xEnv ) >>= xSet; + + if ( xSet.is() ) + xResultSet = xSet->getStaticResultSet(); + } + catch ( uno::RuntimeException const & ) + { + throw; + } + catch ( uno::Exception const & ) + { + OSL_ENSURE( sal_False, "unable to get result set from folder!" ); + } + + return xResultSet; +} + +//========================================================================= +void handleNameClashRename( + const TransferCommandContext & rContext, + const uno::Reference< ucb::XContent > & xNew, + const uno::Reference< + ucb::XCommandProcessor > & xCommandProcessorN, + const uno::Reference< + ucb::XCommandProcessor > & xCommandProcessorS, + /* [inout] */ uno::Reference< io::XInputStream > & xInputStream ) + throw( uno::Exception ) +{ + sal_Int32 nTry = 0; + + // Obtain old title. + uno::Sequence< beans::Property > aProps( 1 ); + aProps[ 0 ].Name = rtl::OUString::createFromAscii( "Title" ); + aProps[ 0 ].Handle = -1; + + ucb::Command aGetPropsCommand( + rtl::OUString::createFromAscii( "getPropertyValues" ), + -1, + uno::makeAny( aProps ) ); + + uno::Reference< sdbc::XRow > xRow; + xCommandProcessorN->execute( aGetPropsCommand, 0, rContext.xEnv ) >>= xRow; + + if ( !xRow.is() ) + { + uno::Any aProps2 + = uno::makeAny( + beans::PropertyValue( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Uri" ) ), + -1, + uno::makeAny( + xNew->getIdentifier()->getContentIdentifier() ), + beans::PropertyState_DIRECT_VALUE ) ); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_READ, + uno::Sequence< uno::Any >( &aProps2, 1 ), + rContext.xOrigEnv, + rtl::OUString::createFromAscii( + "Unable to get properties from new object!" ), + rContext.xProcessor ); + // Unreachable + } + + rtl::OUString aOldTitle = xRow->getString( 1 ); + if ( !aOldTitle.getLength() ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( beans::UnknownPropertyException( + rtl::OUString::createFromAscii( + "Unable to get property 'Title' " + "from new object!" ), + rContext.xProcessor ) ), + rContext.xOrigEnv ); + // Unreachable + } + + // Some pseudo-intelligence for not destroying file extensions. + rtl::OUString aOldTitlePre; + rtl::OUString aOldTitlePost; + sal_Int32 nPos = aOldTitle.lastIndexOf( '.' ); + if ( nPos != -1 ) + { + aOldTitlePre = aOldTitle.copy( 0, nPos ); + aOldTitlePost = aOldTitle.copy( nPos ); + } + else + aOldTitlePre = aOldTitle; + + if ( nPos > 0 ) + aOldTitlePre += rtl::OUString::createFromAscii( "_" ); + + sal_Bool bContinue = sal_True; + do + { + nTry++; + + rtl::OUString aNewTitle = aOldTitlePre; + aNewTitle += rtl::OUString::valueOf( nTry ); + aNewTitle += aOldTitlePost; + + // Set new title + setTitle( xCommandProcessorN, rContext.xEnv, aNewTitle ); + + // Retry inserting the content. + try + { + // Previous try may have read from stream. Seek to begin (if + // optional interface XSeekable is supported) or get a new stream. + if ( xInputStream.is() ) + { + uno::Reference< io::XSeekable > xSeekable( + xInputStream, uno::UNO_QUERY ); + if ( xSeekable.is() ) + { + try + { + xSeekable->seek( 0 ); + } + catch ( lang::IllegalArgumentException const & ) + { + xInputStream.clear(); + } + catch ( io::IOException const & ) + { + xInputStream.clear(); + } + } + else + xInputStream.clear(); + + if ( !xInputStream.is() ) + { + xInputStream + = getInputStream( rContext, xCommandProcessorS ); + if ( !xInputStream.is() ) + { + uno::Any aProps2 + = uno::makeAny( + beans::PropertyValue( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "Uri" ) ), + -1, + uno::makeAny( + xNew->getIdentifier()-> + getContentIdentifier() ), + beans::PropertyState_DIRECT_VALUE ) ); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_READ, + uno::Sequence< uno::Any >( &aProps2, 1 ), + rContext.xOrigEnv, + rtl::OUString::createFromAscii( + "Got no data stream from source!" ), + rContext.xProcessor ); + // Unreachable + } + } + } + + ucb::InsertCommandArgument aArg; + aArg.Data = xInputStream; + aArg.ReplaceExisting = sal_False; + + ucb::Command aInsertCommand( + rtl::OUString::createFromAscii( "insert" ), + -1, + uno::makeAny( aArg ) ); + + xCommandProcessorN->execute( aInsertCommand, 0, rContext.xEnv ); + + // Success! + bContinue = sal_False; + } + catch ( uno::RuntimeException const & ) + { + throw; + } + catch ( uno::Exception const & ) + { + } + } + while ( bContinue && ( nTry < 50 ) ); + + if ( nTry == 50 ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( + ucb::UnsupportedNameClashException( + rtl::OUString::createFromAscii( + "Unable to resolve name clash!" ), + rContext.xProcessor, + ucb::NameClash::RENAME ) ), + rContext.xOrigEnv ); + // Unreachable + } +} + +//========================================================================= +void globalTransfer_( + const TransferCommandContext & rContext, + const uno::Reference< ucb::XContent > & xSource, + const uno::Reference< ucb::XContent > & xTarget, + const uno::Reference< sdbc::XRow > & xSourceProps ) + throw( uno::Exception ) +{ + // IsFolder: property is required. + sal_Bool bSourceIsFolder = xSourceProps->getBoolean( 1 ); + if ( !bSourceIsFolder && xSourceProps->wasNull() ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( beans::UnknownPropertyException( + rtl::OUString::createFromAscii( + "Unable to get property 'IsFolder' " + "from source object!" ), + rContext.xProcessor ) ), + rContext.xOrigEnv ); + // Unreachable + } + + // IsDocument: property is required. + sal_Bool bSourceIsDocument = xSourceProps->getBoolean( 2 ); + if ( !bSourceIsDocument && xSourceProps->wasNull() ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( beans::UnknownPropertyException( + rtl::OUString::createFromAscii( + "Unable to get property 'IsDocument' " + "from source object!" ), + rContext.xProcessor ) ), + rContext.xOrigEnv ); + // Unreachable + } + + // TargetURL: property is optional. + sal_Bool bSourceIsLink = ( xSourceProps->getString( 3 ).getLength() > 0 ); + + ////////////////////////////////////////////////////////////////////// + // + // (1) Try to find a matching target type for the source object and + // create a new, empty object of that type. + // + ////////////////////////////////////////////////////////////////////// + + uno::Reference< ucb::XContent > xNew = createNew( rContext, + xTarget, + bSourceIsFolder, + bSourceIsDocument, + bSourceIsLink ); + if ( !xNew.is() ) + { + uno::Any aProps + = uno::makeAny(beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Folder")), + -1, + uno::makeAny(rContext.aArg.TargetURL), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_CREATE, + uno::Sequence< uno::Any >(&aProps, 1), + rContext.xOrigEnv, + rtl::OUString::createFromAscii( + "No matching content type at target!" ), + rContext.xProcessor ); + // Unreachable + } + + ////////////////////////////////////////////////////////////////////// + // + // (2) Transfer property values from source to new object. + // + ////////////////////////////////////////////////////////////////////// + + uno::Reference< ucb::XCommandProcessor > xCommandProcessorN( + xNew, uno::UNO_QUERY ); + if ( !xCommandProcessorN.is() ) + { + uno::Any aProps + = uno::makeAny(beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Uri")), + -1, + uno::makeAny( + xNew->getIdentifier()-> + getContentIdentifier()), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_WRITE, + uno::Sequence< uno::Any >(&aProps, 1), + rContext.xOrigEnv, + rtl::OUString::createFromAscii( + "New content is not a XCommandProcessor!" ), + rContext.xProcessor ); + // Unreachable + } + + // Obtain all properties from source. + + uno::Reference< ucb::XCommandProcessor > xCommandProcessorS( + xSource, uno::UNO_QUERY ); + if ( !xCommandProcessorS.is() ) + { + uno::Any aProps + = uno::makeAny(beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Uri")), + -1, + uno::makeAny(rContext.aArg.SourceURL), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_READ, + uno::Sequence< uno::Any >(&aProps, 1), + rContext.xOrigEnv, + rtl::OUString::createFromAscii( + "Source content is not a XCommandProcessor!" ), + rContext.xProcessor ); + // Unreachable + } + + transferProperties( rContext, xCommandProcessorS, xCommandProcessorN ); + + ////////////////////////////////////////////////////////////////////// + // + // (3) Try to obtain a data stream from source. + // + ////////////////////////////////////////////////////////////////////// + + uno::Reference< io::XInputStream > xInputStream; + + if ( bSourceIsDocument && ( rContext.aArg.Operation + != ucb::TransferCommandOperation_LINK ) ) + xInputStream = getInputStream( rContext, xCommandProcessorS ); + + ////////////////////////////////////////////////////////////////////// + // + // (4) Try to obtain a resultset (children) from source. + // + ////////////////////////////////////////////////////////////////////// + + uno::Reference< sdbc::XResultSet > xResultSet; + + if ( bSourceIsFolder && ( rContext.aArg.Operation + != ucb::TransferCommandOperation_LINK ) ) + xResultSet = getResultSet( rContext, xCommandProcessorS ); + + ////////////////////////////////////////////////////////////////////// + // + // (5) Insert (store) new content. + // + ////////////////////////////////////////////////////////////////////// + + ucb::InsertCommandArgument aArg; + aArg.Data = xInputStream; + + switch ( rContext.aArg.NameClash ) + { + case ucb::NameClash::OVERWRITE: + aArg.ReplaceExisting = sal_True; + break; + + case ucb::NameClash::ERROR: + case ucb::NameClash::RENAME: + case ucb::NameClash::KEEP: // deprecated + case ucb::NameClash::ASK: + aArg.ReplaceExisting = sal_False; + break; + + default: + aArg.ReplaceExisting = sal_False; + OSL_ENSURE( sal_False, "Unknown nameclash directive!" ); + break; + } + + rtl::OUString aDesiredName = createDesiredName( rContext.aArg ); + + bool bRetry; + do + { + bRetry = false; + + try + { + ucb::Command aInsertCommand( + rtl::OUString::createFromAscii( "insert" ), + -1, + uno::makeAny( aArg ) ); + + xCommandProcessorN->execute( aInsertCommand, 0, rContext.xEnv ); + } + catch ( ucb::UnsupportedNameClashException const & exc ) + { + OSL_ENSURE( !aArg.ReplaceExisting, + "BUG: UnsupportedNameClashException not allowed here!" ); + + if (exc.NameClash != ucb::NameClash::ERROR) { + OSL_ENSURE( false, "BUG: NameClash::ERROR expected!" ); + } + + // No chance to solve name clashes, because I'm not able to detect + // whether there is one. + throw ucb::UnsupportedNameClashException( + rtl::OUString::createFromAscii( + "Unable to resolve name clashes, no chance to detect " + "that there is one!" ), + rContext.xProcessor, + rContext.aArg.NameClash ); + } + catch ( ucb::NameClashException const & ) + { + // The 'insert' command throws a NameClashException if the parameter + // ReplaceExisting of the command's argument was set to false and + // there exists a resource with a clashing name in the target folder + // of the operation. + + // 'insert' command has no direct support for name clashes other + // than ERROR ( ReplaceExisting == false ) and OVERWRITE + // ( ReplaceExisting == true ). So we have to implement the + // other name clash handling directives on top of the content. + + // @@@ 'insert' command should be extended that it accepts a + // name clash handling directive, exactly like 'transfer' command. + + switch ( rContext.aArg.NameClash ) + { + case ucb::NameClash::OVERWRITE: + { + ucbhelper::cancelCommandExecution( + uno::makeAny( + ucb::UnsupportedNameClashException( + rtl::OUString::createFromAscii( + "BUG: insert + replace == true MUST NOT " + "throw NameClashException." ), + rContext.xProcessor, + rContext.aArg.NameClash ) ), + rContext.xOrigEnv ); + // Unreachable + } + + case ucb::NameClash::ERROR: + throw; + + case ucb::NameClash::RENAME: + { + // "invent" a new valid title. + handleNameClashRename( rContext, + xNew, + xCommandProcessorN, + xCommandProcessorS, + xInputStream ); + break; + } + + case ucb::NameClash::ASK: + { + uno::Any aExc; + rtl::OUString aNewTitle; + NameClashContinuation eCont + = interactiveNameClashResolve( + rContext.xOrigEnv, // always use original environment! + rContext.aArg.TargetURL, // target folder URL + aDesiredName, + aExc, + aNewTitle ); + + switch ( eCont ) + { + case NOT_HANDLED: + // Not handled. + cppu::throwException( aExc ); + // break; + + case UNKNOWN: + // Handled, but not clear, how... + // fall-thru intended. + + case ABORT: + throw ucb::CommandFailedException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "abort requested via interaction " + "handler" ) ), + uno::Reference< uno::XInterface >(), + aExc ); + // break; + + case OVERWRITE: + OSL_ENSURE( aArg.ReplaceExisting == sal_False, + "Hu? ReplaceExisting already true?" + ); + aArg.ReplaceExisting = sal_True; + bRetry = true; + break; + + case NEW_NAME: + { + // set new name -> set "Title" property... + if ( setTitle( xCommandProcessorN, + rContext.xEnv, + aNewTitle ) ) + { + // remember suggested title... + aDesiredName = aNewTitle; + + // ... and try again. + bRetry = true; + } + else + { + // error setting title. Abort. + throw ucb::CommandFailedException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "error setting Title property!" + ) ), + uno::Reference< uno::XInterface >(), + aExc ); + } + break; + } + } + + OSL_ENSURE( bRetry, "bRetry must be true here!!!" ); + } + break; + + case ucb::NameClash::KEEP: // deprecated + default: + { + ucbhelper::cancelCommandExecution( + uno::makeAny( + ucb::UnsupportedNameClashException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "default action, don't know how to " + "handle name clash" ) ), + rContext.xProcessor, + rContext.aArg.NameClash ) ), + rContext.xOrigEnv ); + // Unreachable + } + } + } + } + while ( bRetry ); + + ////////////////////////////////////////////////////////////////////// + // + // (6) Process children of source. + // + ////////////////////////////////////////////////////////////////////// + + if ( xResultSet.is() ) + { + try + { + // Iterate over children... + + uno::Reference< sdbc::XRow > xChildRow( + xResultSet, uno::UNO_QUERY ); + + if ( !xChildRow.is() ) + { + uno::Any aProps + = uno::makeAny( + beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Uri")), + -1, + uno::makeAny(rContext.aArg.SourceURL), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_READ, + uno::Sequence< uno::Any >(&aProps, 1), + rContext.xOrigEnv, + rtl::OUString::createFromAscii( + "Unable to get properties from children of source!" ), + rContext.xProcessor ); + // Unreachable + } + + uno::Reference< ucb::XContentAccess > xChildAccess( + xResultSet, uno::UNO_QUERY ); + + if ( !xChildAccess.is() ) + { + uno::Any aProps + = uno::makeAny( + beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Uri")), + -1, + uno::makeAny(rContext.aArg.SourceURL), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_READ, + uno::Sequence< uno::Any >(&aProps, 1), + rContext.xOrigEnv, + rtl::OUString::createFromAscii( + "Unable to get children of source!" ), + rContext.xProcessor ); + // Unreachable + } + + if ( xResultSet->first() ) + { + ucb::GlobalTransferCommandArgument aTransArg( + rContext.aArg.Operation, // Operation + rtl::OUString(), // SourceURL; filled later + xNew->getIdentifier() + ->getContentIdentifier(), // TargetURL + rtl::OUString(), // NewTitle; + rContext.aArg.NameClash ); // NameClash + + TransferCommandContext aSubCtx( + rContext.xSMgr, + rContext.xProcessor, + rContext.xEnv, + rContext.xOrigEnv, + aTransArg ); + do + { + uno::Reference< ucb::XContent > xChild + = xChildAccess->queryContent(); + if ( xChild.is() ) + { + // Recursion! + + aSubCtx.aArg.SourceURL + = xChild->getIdentifier()->getContentIdentifier(); + + globalTransfer_( aSubCtx, + xChild, + xNew, + xChildRow ); + } + } + while ( xResultSet->next() ); + } + } + catch ( sdbc::SQLException const & ) + { + } + } + + try { + uno::Reference< ucb::XCommandProcessor > xcp( + xTarget, uno::UNO_QUERY ); + + uno::Any aAny; + uno::Reference< ucb::XCommandInfo > xci; + if(xcp.is()) + aAny = + xcp->execute( + ucb::Command( + rtl::OUString::createFromAscii("getCommandInfo"), + -1, + uno::Any()), + 0, + rContext.xEnv ); + + const rtl::OUString cmdName = + rtl::OUString::createFromAscii("flush"); + if((aAny >>= xci) && xci->hasCommandByName(cmdName)) + xcp->execute( + ucb::Command( + cmdName, + -1, + uno::Any()) , + 0, + rContext.xEnv ); + } + catch( uno::Exception const & ) + { + } +} + +} /* namescpace */ + +//========================================================================= +// +// UniversalContentBroker implementation ( XCommandProcessor commands ). +// +//========================================================================= + +uno::Reference< ucb::XCommandInfo > +UniversalContentBroker::getCommandInfo() +{ + return uno::Reference< ucb::XCommandInfo >( new CommandProcessorInfo() ); +} + +//========================================================================= +void UniversalContentBroker::globalTransfer( + const ucb::GlobalTransferCommandArgument & rArg, + const uno::Reference< ucb::XCommandEnvironment > & xEnv ) + throw( uno::Exception ) +{ + // Use own command environment with own interaction handler intercepting + // some interaction requests that shall not be handled by the user-supplied + // interaction handler. + uno::Reference< ucb::XCommandEnvironment > xLocalEnv; + if (xEnv.is()) + { + uno::Reference< beans::XPropertySet > const xProps( + m_xSMgr, uno::UNO_QUERY_THROW ); + uno::Reference< uno::XComponentContext > xCtx; + xCtx.set( xProps->getPropertyValue( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ) ) ), + uno::UNO_QUERY_THROW ); + + xLocalEnv.set( ucb::CommandEnvironment::create( + xCtx, + new InteractionHandlerProxy( xEnv->getInteractionHandler() ), + xEnv->getProgressHandler() ) ); + } + + ////////////////////////////////////////////////////////////////////// + // + // (1) Try to transfer the content using 'transfer' command. + // + ////////////////////////////////////////////////////////////////////// + + uno::Reference< ucb::XContent > xTarget; + uno::Reference< ucb::XContentIdentifier > xId + = createContentIdentifier( rArg.TargetURL ); + if ( xId.is() ) + { + try + { + xTarget = queryContent( xId ); + } + catch ( ucb::IllegalIdentifierException const & ) + { + } + } + + if ( !xTarget.is() ) + { + uno::Any aProps + = uno::makeAny(beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Uri")), + -1, + uno::makeAny(rArg.TargetURL), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_READ, + uno::Sequence< uno::Any >(&aProps, 1), + xEnv, + rtl::OUString::createFromAscii( + "Can't instanciate target object!" ), + this ); + // Unreachable + } + + if ( ( rArg.Operation == ucb::TransferCommandOperation_COPY ) || + ( rArg.Operation == ucb::TransferCommandOperation_MOVE ) ) + { + uno::Reference< ucb::XCommandProcessor > xCommandProcessor( + xTarget, uno::UNO_QUERY ); + if ( !xCommandProcessor.is() ) + { + uno::Any aProps + = uno::makeAny( + beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Uri")), + -1, + uno::makeAny(rArg.TargetURL), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_READ, + uno::Sequence< uno::Any >(&aProps, 1), + xEnv, + rtl::OUString::createFromAscii( + "Target content is not a XCommandProcessor!" ), + this ); + // Unreachable + } + + ucb::TransferInfo aTransferArg( + ( rArg.Operation + == ucb::TransferCommandOperation_MOVE ), // MoveData + rArg.SourceURL, // SourceURL + rArg.NewTitle, // NewTitle + rArg.NameClash ); // NameClash + + bool bRetry; + do + { + bRetry = false; + + try + { + ucb::Command aCommand( + rtl::OUString::createFromAscii( "transfer" ), // Name + -1, // Handle + uno::makeAny( aTransferArg ) ); // Argument + + xCommandProcessor->execute( aCommand, 0, xLocalEnv ); + + // Command succeeded. We're done. + return; + } + catch ( ucb::InteractiveBadTransferURLException const & ) + { + // Source URL is not supported by target. Try to transfer + // the content "manually". + } + catch ( ucb::UnsupportedCommandException const & ) + { + // 'transfer' command is not supported by commandprocessor. + // Try to transfer manually. + } + catch ( ucb::UnsupportedNameClashException const & exc ) + { + OSL_ENSURE( aTransferArg.NameClash == exc.NameClash, + "nameclash mismatch!" ); + if ( exc.NameClash == ucb::NameClash::ASK ) + { + // Try to detect a name clash by invoking "transfer" with + // NameClash::ERROR. + try + { + ucb::TransferInfo aTransferArg1( + aTransferArg.MoveData, + aTransferArg.SourceURL, + aTransferArg.NewTitle, + ucb::NameClash::ERROR ); + + ucb::Command aCommand1( + rtl::OUString::createFromAscii( "transfer" ), + -1, + uno::makeAny( aTransferArg1 ) ); + + xCommandProcessor->execute( aCommand1, 0, xLocalEnv ); + + // Command succeeded. We're done. + return; + } + catch ( ucb::UnsupportedNameClashException const & ) + { + // No chance to solve name clashes, because I'm not + // able to detect whether there is one. + throw exc; // Not just 'throw;'! + } + catch ( ucb::NameClashException const & ) + { + // There's a clash. Use interaction handler to solve it. + + uno::Any aExc; + rtl::OUString aNewTitle; + NameClashContinuation eCont + = interactiveNameClashResolve( + xEnv, // always use original environment! + rArg.TargetURL, // target folder URL + createDesiredName( + aTransferArg ), // clashing name + aExc, + aNewTitle ); + + switch ( eCont ) + { + case NOT_HANDLED: + // Not handled. + cppu::throwException( aExc ); +// break; + + case UNKNOWN: + // Handled, but not clear, how... + // fall-thru intended. + + case ABORT: + throw ucb::CommandFailedException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "abort requested via interaction " + "handler" ) ), + uno::Reference< uno::XInterface >(), + aExc ); +// break; + + case OVERWRITE: + aTransferArg.NameClash + = ucb::NameClash::OVERWRITE; + bRetry = true; + break; + + case NEW_NAME: + aTransferArg.NewTitle = aNewTitle; + bRetry = true; + break; + } + + OSL_ENSURE( bRetry, "bRetry must be true here!!!" ); + } + } + else + { + throw; + } + } + } + while ( bRetry ); + } + + ////////////////////////////////////////////////////////////////////// + // + // (2) Try to transfer the content "manually". + // + ////////////////////////////////////////////////////////////////////// + + uno::Reference< ucb::XContent > xSource; + try + { + uno::Reference< ucb::XContentIdentifier > xId2 + = createContentIdentifier( rArg.SourceURL ); + if ( xId2.is() ) + xSource = queryContent( xId2 ); + } + catch ( ucb::IllegalIdentifierException const & ) + { + // Error handling via "if ( !xSource.is() )" below. + } + + if ( !xSource.is() ) + { + uno::Any aProps + = uno::makeAny(beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Uri")), + -1, + uno::makeAny(rArg.SourceURL), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_READ, + uno::Sequence< uno::Any >(&aProps, 1), + xEnv, + rtl::OUString::createFromAscii( + "Can't instanciate source object!" ), + this ); + // Unreachable + } + + uno::Reference< ucb::XCommandProcessor > xCommandProcessor( + xSource, uno::UNO_QUERY ); + if ( !xCommandProcessor.is() ) + { + uno::Any aProps + = uno::makeAny(beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Uri")), + -1, + uno::makeAny(rArg.SourceURL), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_READ, + uno::Sequence< uno::Any >(&aProps, 1), + xEnv, + rtl::OUString::createFromAscii( + "Source content is not a XCommandProcessor!" ), + this ); + // Unreachable + } + + // Obtain interesting property values from source... + + uno::Sequence< beans::Property > aProps( 4 ); + + aProps[ 0 ].Name = rtl::OUString::createFromAscii( "IsFolder" ); + aProps[ 0 ].Handle = -1; /* unknown */ + aProps[ 1 ].Name = rtl::OUString::createFromAscii( "IsDocument" ); + aProps[ 1 ].Handle = -1; /* unknown */ + aProps[ 2 ].Name = rtl::OUString::createFromAscii( "TargetURL" ); + aProps[ 2 ].Handle = -1; /* unknown */ + aProps[ 3 ].Name = rtl::OUString::createFromAscii( "BaseURI" ); + aProps[ 3 ].Handle = -1; /* unknown */ + + ucb::Command aGetPropsCommand( + rtl::OUString::createFromAscii( "getPropertyValues" ), + -1, + uno::makeAny( aProps ) ); + + uno::Reference< sdbc::XRow > xRow; + xCommandProcessor->execute( aGetPropsCommand, 0, xLocalEnv ) >>= xRow; + + if ( !xRow.is() ) + { + uno::Any aProps2 + = uno::makeAny(beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Uri")), + -1, + uno::makeAny(rArg.SourceURL), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_READ, + uno::Sequence< uno::Any >(&aProps2, 1), + xEnv, + rtl::OUString::createFromAscii( + "Unable to get properties from source object!" ), + this ); + // Unreachable + } + + TransferCommandContext aTransferCtx( + m_xSMgr, this, xLocalEnv, xEnv, rArg ); + + if ( rArg.NewTitle.getLength() == 0 ) + { + // BaseURI: property is optional. + rtl::OUString aBaseURI( xRow->getString( 4 ) ); + if ( aBaseURI.getLength() ) + { + aTransferCtx.aArg.NewTitle + = createDesiredName( aBaseURI, rtl::OUString() ); + } + } + + // Do it! + globalTransfer_( aTransferCtx, xSource, xTarget, xRow ); + + ////////////////////////////////////////////////////////////////////// + // + // (3) Delete source, if operation is MOVE. + // + ////////////////////////////////////////////////////////////////////// + + if ( rArg.Operation == ucb::TransferCommandOperation_MOVE ) + { + try + { + ucb::Command aCommand( + rtl::OUString::createFromAscii( "delete" ), // Name + -1, // Handle + uno::makeAny( sal_Bool( sal_True ) ) ); // Argument + + xCommandProcessor->execute( aCommand, 0, xLocalEnv ); + } + catch ( uno::Exception const & ) + { + OSL_ENSURE( sal_False, "Cannot delete source object!" ); + throw; + } + } +} diff --git a/ucb/source/core/ucbcmds.hxx b/ucb/source/core/ucbcmds.hxx new file mode 100644 index 000000000000..7e50bcceef93 --- /dev/null +++ b/ucb/source/core/ucbcmds.hxx @@ -0,0 +1,43 @@ +/************************************************************************* + * + * 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 _UCBCMDS_HXX +#define _UCBCMDS_HXX + +////////////////////////////////////////////////////////////////////////// +// +// Definitions for the commands supported by the UCB. +// +////////////////////////////////////////////////////////////////////////// + +#define GETCOMMANDINFO_NAME "getCommandInfo" +#define GETCOMMANDINFO_HANDLE 1024 + +#define GLOBALTRANSFER_NAME "globalTransfer" +#define GLOBALTRANSFER_HANDLE 1025 + +#endif /* !_UCBCMDS_HXX */ diff --git a/ucb/source/core/ucbprops.cxx b/ucb/source/core/ucbprops.cxx new file mode 100644 index 000000000000..564383fd528a --- /dev/null +++ b/ucb/source/core/ucbprops.cxx @@ -0,0 +1,477 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" +#include <osl/diagnose.h> +#include <com/sun/star/uno/Type.hxx> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/ucb/CrossReference.hpp> +#include <com/sun/star/util/DateTime.hpp> +#include <com/sun/star/ucb/DocumentHeaderField.hpp> +#include <com/sun/star/ucb/RecipientInfo.hpp> +#include <com/sun/star/ucb/RuleSet.hpp> +#include <com/sun/star/ucb/SendInfo.hpp> +#include <com/sun/star/ucb/SendMediaTypes.hpp> +#include <com/sun/star/ucb/XDataContainer.hpp> +#include "ucbprops.hxx" + +using namespace rtl; +using namespace com::sun::star::beans; +using namespace com::sun::star::lang; +using namespace com::sun::star::ucb; +using namespace com::sun::star::uno; +using namespace com::sun::star::util; + +//========================================================================= +// +// struct PropertyTableEntry +// +//========================================================================= + +struct PropertyTableEntry +{ + const char* pName; + sal_Int32 nHandle; + sal_Int16 nAttributes; + const com::sun::star::uno::Type& (*pGetCppuType)(); +}; + +////////////////////////////////////////////////////////////////////////// +// +// CPPU type access functions. +// +////////////////////////////////////////////////////////////////////////// + +static const com::sun::star::uno::Type& OUString_getCppuType() +{ + return getCppuType( static_cast< const rtl::OUString * >( 0 ) ); +} + +static const com::sun::star::uno::Type& sal_uInt16_getCppuType() +{ + // ! uInt -> Int, because of Java !!! + return getCppuType( static_cast< const sal_Int16 * >( 0 ) ); +} + +static const com::sun::star::uno::Type& sal_uInt32_getCppuType() +{ + // ! uInt -> Int, because of Java !!! + return getCppuType( static_cast< const sal_Int32 * >( 0 ) ); +} + +static const com::sun::star::uno::Type& sal_uInt64_getCppuType() +{ + // ! uInt -> Int, because of Java !!! + return getCppuType( static_cast< const sal_Int64 * >( 0 ) ); +} + +static const com::sun::star::uno::Type& enum_getCppuType() +{ + // ! enum -> Int, because of Java !!! + return getCppuType( static_cast< const sal_Int16 * >( 0 ) ); +} + +static const com::sun::star::uno::Type& sal_Bool_getCppuType() +{ + return getCppuBooleanType(); +} + +static const com::sun::star::uno::Type& byte_getCppuType() +{ + return getCppuType( static_cast< const sal_Int8 * >( 0 ) ); +} + +static const com::sun::star::uno::Type& Sequence_CrossReference_getCppuType() +{ + return getCppuType( + static_cast< com::sun::star::uno::Sequence< + com::sun::star::ucb::CrossReference > * >( 0 ) ); +} + +static const com::sun::star::uno::Type& DateTime_getCppuType() +{ + return getCppuType( + static_cast< com::sun::star::util::DateTime * >( 0 ) ); +} + +static const com::sun::star::uno::Type& Sequence_byte_getCppuType() +{ + return getCppuType( + static_cast< com::sun::star::uno::Sequence< sal_Int8 > * >( 0 ) ); +} + +static const com::sun::star::uno::Type& Sequence_DocumentHeaderField_getCppuType() +{ + return getCppuType( + static_cast< com::sun::star::uno::Sequence< + com::sun::star::ucb::DocumentHeaderField > * >( 0 ) ); +} + +static const com::sun::star::uno::Type& XDataContainer_getCppuType() +{ + return getCppuType( + static_cast< com::sun::star::uno::Reference< + com::sun::star::ucb::XDataContainer > * >( 0 ) ); +} + +static const com::sun::star::uno::Type& Sequence_RecipientInfo_getCppuType() +{ + return getCppuType( + static_cast< com::sun::star::uno::Sequence< + com::sun::star::ucb::RecipientInfo > * >( 0 ) ); +} + +static const com::sun::star::uno::Type& RuleSet_getCppuType() +{ + return getCppuType( + static_cast< com::sun::star::ucb::RuleSet * >( 0 ) ); +} + +static const com::sun::star::uno::Type& Sequence_SendInfo_getCppuType() +{ + return getCppuType( + static_cast< com::sun::star::uno::Sequence< + com::sun::star::ucb::SendInfo > * >( 0 ) ); +} + +static const com::sun::star::uno::Type& Sequence_SendMediaTypes_getCppuType() +{ + return getCppuType( + static_cast< com::sun::star::uno::Sequence< + com::sun::star::ucb::SendMediaTypes > * >( 0 ) ); +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// A table with all well-known UCB properties. +////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#define ATTR_DEFAULT ( PropertyAttribute::BOUND | PropertyAttribute::MAYBEVOID | PropertyAttribute::MAYBEDEFAULT ) + +static PropertyTableEntry __aPropertyTable[] = +{ + { "Account", -1 /* WID_ACCOUNT */, ATTR_DEFAULT, &OUString_getCppuType }, + { "AutoUpdateInterval", -1 /* WID_AUTOUPDATE_INTERVAL */, ATTR_DEFAULT, &sal_uInt32_getCppuType }, + { "ConfirmEmpty", -1 /* WID_TRASHCAN_FLAG_CONFIRMEMPTY */, + ATTR_DEFAULT, &sal_Bool_getCppuType }, + { "ConnectionLimit", -1 /* WID_HTTP_CONNECTION_LIMIT */, ATTR_DEFAULT, &byte_getCppuType }, + { "ConnectionMode", -1 /* WID_CONNECTION_MODE */, ATTR_DEFAULT, &enum_getCppuType }, + { "ContentCountLimit", -1 /* WID_SHOW_MSGS_TIMELIMIT */, ATTR_DEFAULT, &sal_uInt16_getCppuType }, + { "ContentType", -1 /* WID_CONTENT_TYPE */, ATTR_DEFAULT, &OUString_getCppuType }, + { "Cookie", -1 /* WID_HTTP_COOKIE */, ATTR_DEFAULT, &OUString_getCppuType }, + { "CrossReferences", -1 /* WID_NEWS_XREFLIST */, ATTR_DEFAULT, &Sequence_CrossReference_getCppuType }, + { "DateCreated", -1 /* WID_DATE_CREATED */, ATTR_DEFAULT, &DateTime_getCppuType }, + { "DateModified", -1 /* WID_DATE_MODIFIED */, ATTR_DEFAULT, &DateTime_getCppuType }, + { "DeleteOnServer", -1 /* WID_DELETE_ON_SERVER */, ATTR_DEFAULT, &sal_Bool_getCppuType }, + { "DocumentBody", -1 /* WID_DOCUMENT_BODY */, ATTR_DEFAULT, &Sequence_byte_getCppuType }, + { "DocumentCount", -1 /* WID_TOTALCONTENTCOUNT */, ATTR_DEFAULT | PropertyAttribute::READONLY, + &sal_uInt32_getCppuType }, + { "DocumentCountMarked", + -1 /* WID_MARKED_DOCUMENT_COUNT */, ATTR_DEFAULT | PropertyAttribute::READONLY, + &sal_uInt32_getCppuType }, + { "DocumentHeader", -1 /* WID_DOCUMENT_HEADER */, ATTR_DEFAULT, &Sequence_DocumentHeaderField_getCppuType }, + { "DocumentStoreMode", -1 /* WID_MESSAGE_STOREMODE */, ATTR_DEFAULT, &enum_getCppuType }, + { "DocumentViewMode", -1 /* WID_MESSAGEVIEW_MODE */, ATTR_DEFAULT, &enum_getCppuType }, + { "FTPAccount", -1 /* WID_FTP_ACCOUNT */, ATTR_DEFAULT, &OUString_getCppuType }, + { "Flags", -1 /* WID_FSYS_FLAGS */, ATTR_DEFAULT, &sal_uInt32_getCppuType }, + { "FolderCount", -1 /* WID_FOLDER_COUNT */, ATTR_DEFAULT | PropertyAttribute::READONLY, + &sal_uInt32_getCppuType }, + { "FolderViewMode", -1 /* WID_FOLDERVIEW_MODE */, ATTR_DEFAULT, &enum_getCppuType }, + { "FreeSpace", -1 /* WID_FSYS_DISKSPACE_LEFT */, ATTR_DEFAULT | PropertyAttribute::READONLY, + &sal_uInt64_getCppuType }, + { "HasDocuments", -1 /* WID_FLAG_HAS_MESSAGES */, ATTR_DEFAULT | PropertyAttribute::READONLY, + &sal_Bool_getCppuType }, + { "HasFolders", -1 /* WID_FLAG_HAS_FOLDER */, ATTR_DEFAULT | PropertyAttribute::READONLY, + &sal_Bool_getCppuType }, + { "IsAutoDelete", -1 /* WID_TRASHCAN_FLAG_AUTODELETE */, + ATTR_DEFAULT, &sal_Bool_getCppuType }, + { "IsAutoUpdate", -1 /* WID_UPDATE_ENABLED */, ATTR_DEFAULT, &sal_Bool_getCppuType }, + { "IsDocument", -1 /* WID_FLAG_IS_MESSAGE */, ATTR_DEFAULT | PropertyAttribute::READONLY, + &sal_Bool_getCppuType }, + { "IsFolder", -1 /* WID_FLAG_IS_FOLDER */, ATTR_DEFAULT | PropertyAttribute::READONLY, + &sal_Bool_getCppuType }, + { "IsKeepExpired", -1 /* WID_HTTP_KEEP_EXPIRED */, ATTR_DEFAULT, &sal_Bool_getCppuType }, + { "IsLimitedContentCount", + -1 /* WID_SHOW_MSGS_HAS_TIMELIMIT */, + ATTR_DEFAULT, &sal_Bool_getCppuType }, + { "IsMarked", -1 /* WID_IS_MARKED */, ATTR_DEFAULT, &sal_Bool_getCppuType }, + { "IsRead", -1 /* WID_IS_READ */, ATTR_DEFAULT, &sal_Bool_getCppuType }, + { "IsReadOnly", -1 /* WID_FLAG_READONLY */, ATTR_DEFAULT, &sal_Bool_getCppuType }, + { "IsSubscribed", -1 /* WID_FLAG_SUBSCRIBED */, ATTR_DEFAULT, &sal_Bool_getCppuType }, +// { "IsThreaded", -1 /* WID_THREADED */, ATTR_DEFAULT, &sal_Bool_getCppuType }, + { "IsTimeLimitedStore", -1 /* WID_STORE_MSGS_HAS_TIMELIMIT */, + ATTR_DEFAULT, &sal_Bool_getCppuType }, + { "Keywords", -1 /* WID_KEYWORDS */, ATTR_DEFAULT, &OUString_getCppuType }, + { "LocalBase", -1 /* WID_LOCALBASE */, ATTR_DEFAULT, &OUString_getCppuType }, + { "MessageBCC", -1 /* WID_BCC */, ATTR_DEFAULT, &OUString_getCppuType }, + { "MessageBody", -1 /* WID_MESSAGEBODY */, ATTR_DEFAULT, &XDataContainer_getCppuType }, + { "MessageCC", -1 /* WID_CC */, ATTR_DEFAULT, &OUString_getCppuType }, + { "MessageFrom", -1 /* WID_FROM */, ATTR_DEFAULT, &OUString_getCppuType }, + { "MessageId", -1 /* WID_MESSAGE_ID */, ATTR_DEFAULT, &OUString_getCppuType }, + { "MessageInReplyTo", -1 /* WID_IN_REPLY_TO */, ATTR_DEFAULT, &OUString_getCppuType }, + { "MessageReplyTo", -1 /* WID_REPLY_TO */, ATTR_DEFAULT, &OUString_getCppuType }, + { "MessageTo", -1 /* WID_TO */, ATTR_DEFAULT, &OUString_getCppuType }, + { "NewsGroups", -1 /* WID_NEWSGROUPS */, ATTR_DEFAULT, &OUString_getCppuType }, + { "NoCacheList", -1 /* WID_HTTP_NOCACHE_LIST */, ATTR_DEFAULT, &OUString_getCppuType }, + { "Origin", -1 /* WID_TRASH_ORIGIN */, ATTR_DEFAULT | PropertyAttribute::READONLY, + &OUString_getCppuType }, + { "OutgoingMessageRecipients", + -1 /* WID_RECIPIENTLIST */, ATTR_DEFAULT, &Sequence_RecipientInfo_getCppuType }, + { "OutgoingMessageState", + -1 /* WID_OUTMSGINTERNALSTATE */, ATTR_DEFAULT | PropertyAttribute::READONLY, + &enum_getCppuType }, + { "OutgoingMessageViewMode", + -1 /* WID_SENTMESSAGEVIEW_MODE */, + ATTR_DEFAULT, &enum_getCppuType }, +// { "OwnURL", -1 /* WID_OWN_URL */, ATTR_DEFAULT, &OUString_getCppuType }, + { "Password", -1 /* WID_PASSWORD */, ATTR_DEFAULT, &OUString_getCppuType }, +// { "PresentationURL", -1 /* WID_REAL_URL */, ATTR_DEFAULT | PropertyAttribute::READONLY, +// &OUString_getCppuType }, + { "Priority", -1 /* WID_PRIORITY */, ATTR_DEFAULT, &enum_getCppuType }, + { "References", -1 /* WID_REFERENCES */, ATTR_DEFAULT, &OUString_getCppuType }, + { "Referer", -1 /* WID_HTTP_REFERER */, ATTR_DEFAULT, &OUString_getCppuType }, + { "Rules", -1 /* WID_RULES */, ATTR_DEFAULT, &RuleSet_getCppuType }, + { "SearchCriteria", -1 /* WID_SEARCH_CRITERIA */, ATTR_DEFAULT, &RuleSet_getCppuType }, + { "SearchIndirections", -1 /* WID_SEARCH_INDIRECTIONS */, ATTR_DEFAULT, &sal_Bool_getCppuType }, + { "SearchLocations", -1 /* WID_SEARCH_LOCATIONS */, ATTR_DEFAULT, &OUString_getCppuType }, + { "SearchRecursive", -1 /* WID_SEARCH_RECURSIVE */, ATTR_DEFAULT, &sal_Bool_getCppuType }, + { "SeenCount", -1 /* WID_SEENCONTENTCOUNT */, ATTR_DEFAULT | PropertyAttribute::READONLY, + &sal_uInt32_getCppuType }, + { "SendCopyTarget", -1 /* WID_SEND_COPY_TARGET */, ATTR_DEFAULT, &Sequence_SendInfo_getCppuType }, + { "SendFormats", -1 /* WID_SEND_FORMATS */, ATTR_DEFAULT, &Sequence_SendMediaTypes_getCppuType }, + { "SendFroms", -1 /* WID_SEND_FROM_DEFAULT */, ATTR_DEFAULT, &Sequence_SendInfo_getCppuType }, + { "SendPasswords", -1 /* WID_SEND_PASSWORD */, ATTR_DEFAULT, &Sequence_SendInfo_getCppuType }, + { "SendProtocolPrivate",-1 /* WID_SEND_PRIVATE_PROT_ID */, ATTR_DEFAULT, &sal_uInt16_getCppuType }, + { "SendProtocolPublic", -1 /* WID_SEND_PUBLIC_PROT_ID */, ATTR_DEFAULT, &sal_uInt16_getCppuType }, + { "SendReplyTos", -1 /* WID_SEND_REPLY_TO_DEFAULT */, ATTR_DEFAULT, &Sequence_SendInfo_getCppuType }, + { "SendServerNames", -1 /* WID_SEND_SERVERNAME */, ATTR_DEFAULT, &Sequence_SendInfo_getCppuType }, + { "SendUserNames", -1 /* WID_SEND_USERNAME */, ATTR_DEFAULT, &Sequence_SendInfo_getCppuType }, + { "SendVIMPostOfficePath", + -1 /* WID_SEND_VIM_POPATH */, ATTR_DEFAULT, &OUString_getCppuType }, + { "ServerBase", -1 /* WID_SERVERBASE */, ATTR_DEFAULT, &OUString_getCppuType }, + { "ServerName", -1 /* WID_SERVERNAME */, ATTR_DEFAULT, &OUString_getCppuType }, + { "ServerPort", -1 /* WID_SERVERPORT */, ATTR_DEFAULT, &sal_uInt16_getCppuType }, + { "Size", -1 /* WID_DOCUMENT_SIZE */, ATTR_DEFAULT | PropertyAttribute::READONLY, + &sal_uInt64_getCppuType }, + { "SizeLimit", -1 /* WID_SIZE_LIMIT */, ATTR_DEFAULT, &sal_uInt64_getCppuType }, + { "SubscribedCount", -1 /* WID_SUBSCRNEWSGROUPCOUNT */, ATTR_DEFAULT | PropertyAttribute::READONLY, + &sal_uInt32_getCppuType }, + { "SynchronizePolicy", -1 /* WID_WHO_IS_MASTER */, ATTR_DEFAULT, &enum_getCppuType }, + { "TargetFrames", -1 /* WID_TARGET_FRAMES */, ATTR_DEFAULT, &OUString_getCppuType }, + { "TargetURL", -1 /* WID_TARGET_URL */, ATTR_DEFAULT, &OUString_getCppuType }, +// { "ThreadingInfo", -1 /* WID_THREADING */, ATTR_DEFAULT, &Sequence_ThreadingInfo_getCppuType }, + { "TimeLimitStore", -1 /* WID_STORE_MSGS_TIMELIMIT */, ATTR_DEFAULT, &sal_uInt16_getCppuType }, + { "Title", -1 /* WID_TITLE */, ATTR_DEFAULT, &OUString_getCppuType }, + { "UpdateOnOpen", -1 /* WID_FLAG_UPDATE_ON_OPEN */, ATTR_DEFAULT, &sal_Bool_getCppuType }, + { "UseOutBoxPrivateProtocolSettings", + -1 /* WID_SEND_PRIVATE_OUTBOXPROPS */, + ATTR_DEFAULT, &sal_Bool_getCppuType }, + { "UseOutBoxPublicProtocolSettings", + -1 /* WID_SEND_PUBLIC_OUTBOXPROPS */, + ATTR_DEFAULT, &sal_Bool_getCppuType }, + { "UserName", -1 /* WID_USERNAME */, ATTR_DEFAULT, &OUString_getCppuType }, + { "UserSortCriterium", -1 /* WID_USER_SORT_CRITERIUM */, ATTR_DEFAULT, &OUString_getCppuType }, + { "VIMPostOfficePath", -1 /* WID_VIM_POPATH */, ATTR_DEFAULT, &OUString_getCppuType }, + { "VerificationMode", -1 /* WID_HTTP_VERIFY_MODE */, ATTR_DEFAULT, &enum_getCppuType }, + + ////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // EOT. + ////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + { 0, 0, 0, 0 } +}; + +//========================================================================= +//========================================================================= +// +// UcbPropertiesManager Implementation. +// +//========================================================================= +//========================================================================= + +UcbPropertiesManager::UcbPropertiesManager( + const Reference< XMultiServiceFactory >& ) +: m_pProps( 0 ) +{ +} + +//========================================================================= +// virtual +UcbPropertiesManager::~UcbPropertiesManager() +{ + delete m_pProps; +} + +//========================================================================= +// +// XInterface methods. +// +//========================================================================= + +XINTERFACE_IMPL_3( UcbPropertiesManager, + XTypeProvider, + XServiceInfo, + XPropertySetInfo ); + +//========================================================================= +// +// XTypeProvider methods. +// +//========================================================================= + +XTYPEPROVIDER_IMPL_3( UcbPropertiesManager, + XTypeProvider, + XServiceInfo, + XPropertySetInfo ); + +//========================================================================= +// +// XServiceInfo methods. +// +//========================================================================= + +XSERVICEINFO_IMPL_1( UcbPropertiesManager, + OUString::createFromAscii( + "com.sun.star.comp.ucb.UcbPropertiesManager" ), + OUString::createFromAscii( + PROPERTIES_MANAGER_SERVICE_NAME ) ); + +//========================================================================= +// +// Service factory implementation. +// +//========================================================================= + +ONE_INSTANCE_SERVICE_FACTORY_IMPL( UcbPropertiesManager ); + +//========================================================================= +// +// XPropertySetInfo methods. +// +//========================================================================= + +// virtual +Sequence< Property > SAL_CALL UcbPropertiesManager::getProperties() + throw( RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + if ( !m_pProps ) + { + m_pProps = new Sequence< Property >( 128 ); + Property* pProps = m_pProps->getArray(); + sal_Int32 nPos = 0; + sal_Int32 nSize = m_pProps->getLength(); + + ////////////////////////////////////////////////////////////////// + // Get info for well-known properties. + ////////////////////////////////////////////////////////////////// + + const PropertyTableEntry* pCurr = &__aPropertyTable[ 0 ]; + while ( pCurr->pName ) + { + if ( nSize <= nPos ) + { + OSL_ENSURE( sal_False, + "UcbPropertiesManager::getProperties - " + "Initial size of property sequence too small!" ); + + m_pProps->realloc( 128 ); + nSize += 128; + } + + Property& rProp = pProps[ nPos ]; + + rProp.Name = OUString::createFromAscii( pCurr->pName ); + rProp.Handle = pCurr->nHandle; + rProp.Type = pCurr->pGetCppuType(); + rProp.Attributes = pCurr->nAttributes; + + nPos++; + pCurr++; + } + + if ( nPos > 0 ) + { + m_pProps->realloc( nPos ); + nSize = m_pProps->getLength(); + } + } + return *m_pProps; +} + +//========================================================================= +// virtual +Property SAL_CALL UcbPropertiesManager::getPropertyByName( const OUString& aName ) + throw( UnknownPropertyException, RuntimeException ) +{ + Property aProp; + if ( queryProperty( aName, aProp ) ) + return aProp; + + throw UnknownPropertyException(); +} + +//========================================================================= +// virtual +sal_Bool SAL_CALL UcbPropertiesManager::hasPropertyByName( const OUString& Name ) + throw( RuntimeException ) +{ + Property aProp; + return queryProperty( Name, aProp ); +} + +//========================================================================= +// +// Non-Interface methods. +// +//========================================================================= + +sal_Bool UcbPropertiesManager::queryProperty( + const OUString& rName, Property& rProp ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + getProperties(); + + const Property* pProps = m_pProps->getConstArray(); + sal_Int32 nCount = m_pProps->getLength(); + for ( sal_Int32 n = 0; n < nCount; ++n ) + { + const Property& rCurrProp = pProps[ n ]; + if ( rCurrProp.Name == rName ) + { + rProp = rCurrProp; + return sal_True; + } + } + + return sal_False; +} + diff --git a/ucb/source/core/ucbprops.hxx b/ucb/source/core/ucbprops.hxx new file mode 100644 index 000000000000..7908fa6af90c --- /dev/null +++ b/ucb/source/core/ucbprops.hxx @@ -0,0 +1,93 @@ +/************************************************************************* + * + * 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 _UCBPROPS_HXX +#define _UCBPROPS_HXX + +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XTypeProvider.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/beans/XPropertySetInfo.hpp> +#include <cppuhelper/weak.hxx> +#include <osl/mutex.hxx> +#include <ucbhelper/macros.hxx> + +//========================================================================= + +#define PROPERTIES_MANAGER_SERVICE_NAME "com.sun.star.ucb.PropertiesManager" + +//============================================================================ +// +// class UcbPropertiesManager. +// +//============================================================================ + +class UcbPropertiesManager : + public cppu::OWeakObject, + public com::sun::star::lang::XTypeProvider, + public com::sun::star::lang::XServiceInfo, + public com::sun::star::beans::XPropertySetInfo +{ + com::sun::star::uno::Sequence< com::sun::star::beans::Property >* + m_pProps; + osl::Mutex m_aMutex; + +private: + sal_Bool queryProperty( const rtl::OUString& rName, + com::sun::star::beans::Property& rProp ); + +public: + UcbPropertiesManager( const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& + rxSMgr ); + virtual ~UcbPropertiesManager(); + + // XInterface + XINTERFACE_DECL() + + // XTypeProvider + XTYPEPROVIDER_DECL() + + // XServiceInfo + XSERVICEINFO_DECL() + + // XPropertySetInfo + virtual com::sun::star::uno::Sequence< + com::sun::star::beans::Property > SAL_CALL + getProperties() + throw( com::sun::star::uno::RuntimeException ); + virtual com::sun::star::beans::Property SAL_CALL + getPropertyByName( const rtl::OUString& aName ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL + hasPropertyByName( const rtl::OUString& Name ) + throw( com::sun::star::uno::RuntimeException ); +}; + +#endif /* !_UCBPROPS_HXX */ + diff --git a/ucb/source/core/ucbserv.cxx b/ucb/source/core/ucbserv.cxx new file mode 100644 index 000000000000..a4e5bdc1dccf --- /dev/null +++ b/ucb/source/core/ucbserv.cxx @@ -0,0 +1,121 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include "ucb.hxx" +#include "ucbstore.hxx" +#include "ucbprops.hxx" +#include "provprox.hxx" +#include "cmdenv.hxx" + +using namespace rtl; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; + +//========================================================================= +extern "C" void SAL_CALL component_getImplementationEnvironment( + const sal_Char ** ppEnvTypeName, uno_Environment ** ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + +//========================================================================= +extern "C" void * SAL_CALL component_getFactory( + const sal_Char * pImplName, void * pServiceManager, void * ) +{ + void * pRet = 0; + + Reference< XMultiServiceFactory > xSMgr( + reinterpret_cast< XMultiServiceFactory * >( pServiceManager ) ); + Reference< XSingleServiceFactory > xFactory; + + ////////////////////////////////////////////////////////////////////// + // Universal Content Broker. + ////////////////////////////////////////////////////////////////////// + + if ( UniversalContentBroker::getImplementationName_Static(). + compareToAscii( pImplName ) == 0 ) + { + xFactory = UniversalContentBroker::createServiceFactory( xSMgr ); + } + + ////////////////////////////////////////////////////////////////////// + // UCB Store. + ////////////////////////////////////////////////////////////////////// + + else if ( UcbStore::getImplementationName_Static(). + compareToAscii( pImplName ) == 0 ) + { + xFactory = UcbStore::createServiceFactory( xSMgr ); + } + + ////////////////////////////////////////////////////////////////////// + // UCB PropertiesManager. + ////////////////////////////////////////////////////////////////////// + + else if ( UcbPropertiesManager::getImplementationName_Static(). + compareToAscii( pImplName ) == 0 ) + { + xFactory = UcbPropertiesManager::createServiceFactory( xSMgr ); + } + + ////////////////////////////////////////////////////////////////////// + // UCP Proxy Factory. + ////////////////////////////////////////////////////////////////////// + + else if ( UcbContentProviderProxyFactory::getImplementationName_Static(). + compareToAscii( pImplName ) == 0 ) + { + xFactory + = UcbContentProviderProxyFactory::createServiceFactory( xSMgr ); + } + + ////////////////////////////////////////////////////////////////////// + // Command Environment. + ////////////////////////////////////////////////////////////////////// + + else if ( ucb_cmdenv::UcbCommandEnvironment::getImplementationName_Static(). + compareToAscii( pImplName ) == 0 ) + { + xFactory + = ucb_cmdenv::UcbCommandEnvironment::createServiceFactory( xSMgr ); + } + + ////////////////////////////////////////////////////////////////////// + + if ( xFactory.is() ) + { + xFactory->acquire(); + pRet = xFactory.get(); + } + + return pRet; +} + diff --git a/ucb/source/core/ucbstore.cxx b/ucb/source/core/ucbstore.cxx new file mode 100644 index 000000000000..cd5cb7856d7a --- /dev/null +++ b/ucb/source/core/ucbstore.cxx @@ -0,0 +1,2770 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ + +#include <list> +#include <hash_map> +#include <osl/diagnose.h> +#include <rtl/ustrbuf.hxx> +#include <cppuhelper/interfacecontainer.hxx> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/beans/PropertySetInfoChange.hpp> +#include <com/sun/star/container/XHierarchicalNameAccess.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/container/XNameReplace.hpp> +#include <com/sun/star/util/XChangesBatch.hpp> +#include "ucbstore.hxx" + +using namespace com::sun::star::beans; +using namespace com::sun::star::container; +using namespace com::sun::star::lang; +using namespace com::sun::star::ucb; +using namespace com::sun::star::uno; +using namespace com::sun::star::util; +using namespace cppu; +using namespace rtl; + +//========================================================================= +rtl::OUString makeHierarchalNameSegment( const rtl::OUString & rIn ) +{ + rtl::OUStringBuffer aBuffer; + aBuffer.appendAscii( "['" ); + + sal_Int32 nCount = rIn.getLength(); + for ( sal_Int32 n = 0; n < nCount; ++n ) + { + const sal_Unicode c = rIn.getStr()[ n ]; + switch ( c ) + { + case '&': + aBuffer.appendAscii( "&" ); + break; + + case '"': + aBuffer.appendAscii( """ ); + break; + + case '\'': + aBuffer.appendAscii( "'" ); + break; + + case '<': + aBuffer.appendAscii( "<" ); + break; + + case '>': + aBuffer.appendAscii( ">" ); + break; + + default: + aBuffer.append( c ); + break; + } + } + + aBuffer.appendAscii( "']" ); + return rtl::OUString( aBuffer.makeStringAndClear() ); +} + +//========================================================================= + +#define STORE_CONTENTPROPERTIES_KEY "/org.openoffice.ucb.Store/ContentProperties" + +// describe path of cfg entry +#define CFGPROPERTY_NODEPATH "nodepath" +// true->async. update; false->sync. update +#define CFGPROPERTY_LAZYWRITE "lazywrite" + +//========================================================================= + +struct equalString_Impl +{ + bool operator()( const OUString& s1, const OUString& s2 ) const + { + return !!( s1 == s2 ); + } +}; + +struct hashString_Impl +{ + size_t operator()( const OUString & rName ) const + { + return rName.hashCode(); + } +}; + +//========================================================================= +// +// PropertySetMap_Impl. +// +//========================================================================= + +typedef std::hash_map +< + OUString, + PersistentPropertySet*, + hashString_Impl, + equalString_Impl +> +PropertySetMap_Impl; + +//========================================================================= +// +// class PropertySetInfo_Impl +// +//========================================================================= + +class PropertySetInfo_Impl : + public OWeakObject, public XTypeProvider, public XPropertySetInfo +{ + Reference< XMultiServiceFactory > m_xSMgr; + Sequence< Property >* m_pProps; + PersistentPropertySet* m_pOwner; + +public: + PropertySetInfo_Impl( const Reference< XMultiServiceFactory >& rxSMgr, + PersistentPropertySet* pOwner ); + virtual ~PropertySetInfo_Impl(); + + // XInterface + XINTERFACE_DECL() + + // XTypeProvider + XTYPEPROVIDER_DECL() + + // XPropertySetInfo + virtual Sequence< Property > SAL_CALL getProperties() + throw( RuntimeException ); + virtual Property SAL_CALL getPropertyByName( const OUString& aName ) + throw( UnknownPropertyException, RuntimeException ); + virtual sal_Bool SAL_CALL hasPropertyByName( const OUString& Name ) + throw( RuntimeException ); + + // Non-interface methods. + void reset() { delete m_pProps; m_pProps = 0; } +}; + +//========================================================================= +// +// UcbStore_Impl. +// +//========================================================================= + +struct UcbStore_Impl +{ + osl::Mutex m_aMutex; + Sequence< Any > m_aInitArgs; + Reference< XPropertySetRegistry > m_xTheRegistry; +}; + +//========================================================================= +//========================================================================= +//========================================================================= +// +// UcbStore Implementation. +// +//========================================================================= +//========================================================================= +//========================================================================= + +UcbStore::UcbStore( const Reference< XMultiServiceFactory >& rXSMgr ) +: m_xSMgr( rXSMgr ), + m_pImpl( new UcbStore_Impl() ) +{ +} + +//========================================================================= +// virtual +UcbStore::~UcbStore() +{ + delete m_pImpl; +} + +//========================================================================= +// +// XInterface methods. +// +//========================================================================= + +XINTERFACE_IMPL_4( UcbStore, + XTypeProvider, + XServiceInfo, + XPropertySetRegistryFactory, + XInitialization ); + +//========================================================================= +// +// XTypeProvider methods. +// +//========================================================================= + +XTYPEPROVIDER_IMPL_4( UcbStore, + XTypeProvider, + XServiceInfo, + XPropertySetRegistryFactory, + XInitialization ); + +//========================================================================= +// +// XServiceInfo methods. +// +//========================================================================= + +XSERVICEINFO_IMPL_1( UcbStore, + OUString::createFromAscii( + "com.sun.star.comp.ucb.UcbStore" ), + OUString::createFromAscii( + STORE_SERVICE_NAME ) ); + +//========================================================================= +// +// Service factory implementation. +// +//========================================================================= + +ONE_INSTANCE_SERVICE_FACTORY_IMPL( UcbStore ); + +//========================================================================= +// +// XPropertySetRegistryFactory methods. +// +//========================================================================= + +// virtual +Reference< XPropertySetRegistry > SAL_CALL +UcbStore::createPropertySetRegistry( const OUString& ) + throw( RuntimeException ) +{ + // The URL parameter is ignored by this interface implementation. It always + // uses the configuration server as storage medium. + + if ( !m_pImpl->m_xTheRegistry.is() ) + { + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + if ( !m_pImpl->m_xTheRegistry.is() ) + m_pImpl->m_xTheRegistry = new PropertySetRegistry( m_xSMgr, getInitArgs() ); + } + + return m_pImpl->m_xTheRegistry; +} + +//========================================================================= +// +// XInitialization methods. +// +//========================================================================= + +// virtual +void SAL_CALL UcbStore::initialize( const Sequence< Any >& aArguments ) + throw( Exception, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + m_pImpl->m_aInitArgs = aArguments; +} + +//========================================================================= +const Sequence< Any >& UcbStore::getInitArgs() const +{ + return m_pImpl->m_aInitArgs; +} + +//========================================================================= +// +// PropertySetRegistry_Impl. +// +//========================================================================= + +struct PropertySetRegistry_Impl +{ + const Sequence< Any > m_aInitArgs; + PropertySetMap_Impl m_aPropSets; + Reference< XMultiServiceFactory > m_xConfigProvider; + Reference< XInterface > m_xRootReadAccess; + Reference< XInterface > m_xRootWriteAccess; + osl::Mutex m_aMutex; + sal_Bool m_bTriedToGetRootReadAccess; // #82494# + sal_Bool m_bTriedToGetRootWriteAccess; // #82494# + + PropertySetRegistry_Impl( const Sequence< Any > &rInitArgs ) + : m_aInitArgs( rInitArgs ), + m_bTriedToGetRootReadAccess( sal_False ), + m_bTriedToGetRootWriteAccess( sal_False ) + { + } +}; + +//========================================================================= +//========================================================================= +//========================================================================= +// +// PropertySetRegistry Implementation. +// +//========================================================================= +//========================================================================= +//========================================================================= + +PropertySetRegistry::PropertySetRegistry( + const Reference< XMultiServiceFactory >& rXSMgr, + const Sequence< Any > &rInitArgs ) +: m_xSMgr( rXSMgr ), + m_pImpl( new PropertySetRegistry_Impl( rInitArgs ) ) +{ +} + +//========================================================================= +// virtual +PropertySetRegistry::~PropertySetRegistry() +{ + delete m_pImpl; +} + +//========================================================================= +// +// XInterface methods. +// +//========================================================================= + +XINTERFACE_IMPL_5( PropertySetRegistry, + XTypeProvider, + XServiceInfo, + XPropertySetRegistry, + XElementAccess, /* base of XNameAccess */ + XNameAccess ); + +//========================================================================= +// +// XTypeProvider methods. +// +//========================================================================= + +XTYPEPROVIDER_IMPL_4( PropertySetRegistry, + XTypeProvider, + XServiceInfo, + XPropertySetRegistry, + XNameAccess ); + +//========================================================================= +// +// XServiceInfo methods. +// +//========================================================================= + +XSERVICEINFO_NOFACTORY_IMPL_1( PropertySetRegistry, + OUString::createFromAscii( + "com.sun.star.comp.ucb.PropertySetRegistry" ), + OUString::createFromAscii( + PROPSET_REG_SERVICE_NAME ) ); + +//========================================================================= +// +// XPropertySetRegistry methods. +// +//========================================================================= + +// virtual +Reference< XPersistentPropertySet > SAL_CALL +PropertySetRegistry::openPropertySet( const OUString& key, sal_Bool create ) + throw( RuntimeException ) +{ + if ( key.getLength() ) + { + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + PropertySetMap_Impl& rSets = m_pImpl->m_aPropSets; + + PropertySetMap_Impl::const_iterator it = rSets.find( key ); + if ( it != rSets.end() ) + { + // Already instanciated. + return Reference< XPersistentPropertySet >( (*it).second ); + } + else + { + // Create new instance. + Reference< XNameAccess > xRootNameAccess( + getRootConfigReadAccess(), UNO_QUERY ); + if ( xRootNameAccess.is() ) + { + // Propertyset in registry? + if ( xRootNameAccess->hasByName( key ) ) + { + // Yep! + return Reference< XPersistentPropertySet >( + new PersistentPropertySet( + m_xSMgr, *this, key ) ); + } + else if ( create ) + { + // No. Create entry for propertyset. + + Reference< XSingleServiceFactory > xFac( + getConfigWriteAccess( OUString() ), UNO_QUERY ); + Reference< XChangesBatch > xBatch( xFac, UNO_QUERY ); + Reference< XNameContainer > xContainer( xFac, UNO_QUERY ); + + OSL_ENSURE( xFac.is(), + "PropertySetRegistry::openPropertySet - " + "No factory!" ); + + OSL_ENSURE( xBatch.is(), + "PropertySetRegistry::openPropertySet - " + "No batch!" ); + + OSL_ENSURE( xContainer.is(), + "PropertySetRegistry::openPropertySet - " + "No conteiner!" ); + + if ( xFac.is() && xBatch.is() && xContainer.is() ) + { + try + { + // Create new "Properties" config item. + Reference< XNameReplace > xNameReplace( + xFac->createInstance(), UNO_QUERY ); + + if ( xNameReplace.is() ) + { + // Fill new item... + +// // Set Values +// xNameReplace->replaceByName( +// OUString::createFromAscii( "Values" ), +// makeAny( ... ) ); + + // Insert new item. + xContainer->insertByName( + key, makeAny( xNameReplace ) ); + // Commit changes. + xBatch->commitChanges(); + + return Reference< XPersistentPropertySet >( + new PersistentPropertySet( + m_xSMgr, *this, key ) ); + } + } + catch ( IllegalArgumentException& ) + { + // insertByName + + OSL_ENSURE( sal_False, + "PropertySetRegistry::openPropertySet - " + "caught IllegalArgumentException!" ); + } + catch ( ElementExistException& ) + { + // insertByName + + OSL_ENSURE( sal_False, + "PropertySetRegistry::openPropertySet - " + "caught ElementExistException!" ); + } + catch ( WrappedTargetException& ) + { + // insertByName, commitChanges + + OSL_ENSURE( sal_False, + "PropertySetRegistry::openPropertySet - " + "caught WrappedTargetException!" ); + } + catch ( RuntimeException& ) + { + OSL_ENSURE( sal_False, + "PropertySetRegistry::openPropertySet - " + "caught RuntimeException!" ); + } + catch ( Exception& ) + { + // createInstance + + OSL_ENSURE( sal_False, + "PropertySetRegistry::openPropertySet - " + "caught Exception!" ); + } + } + } + else + { + // No entry. Fail, but no error. + return Reference< XPersistentPropertySet >(); + } + } + + OSL_ENSURE( sal_False, + "PropertySetRegistry::openPropertySet - Error!" ); + } + } + + return Reference< XPersistentPropertySet >(); +} + +//========================================================================= +// virtual +void SAL_CALL PropertySetRegistry::removePropertySet( const OUString& key ) + throw( RuntimeException ) +{ + if ( !key.getLength() ) + return; + + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + Reference< XNameAccess > xRootNameAccess( + getRootConfigReadAccess(), UNO_QUERY ); + if ( xRootNameAccess.is() ) + { + // Propertyset in registry? + if ( !xRootNameAccess->hasByName( key ) ) + return; + Reference< XChangesBatch > xBatch( + getConfigWriteAccess( OUString() ), UNO_QUERY ); + Reference< XNameContainer > xContainer( xBatch, UNO_QUERY ); + + OSL_ENSURE( xBatch.is(), + "PropertySetRegistry::removePropertySet - " + "No batch!" ); + + OSL_ENSURE( xContainer.is(), + "PropertySetRegistry::removePropertySet - " + "No conteiner!" ); + + if ( xBatch.is() && xContainer.is() ) + { + try + { + // Remove item. + xContainer->removeByName( key ); + // Commit changes. + xBatch->commitChanges(); + + // Success. + return; + } + catch ( NoSuchElementException& ) + { + // removeByName + + OSL_ENSURE( sal_False, + "PropertySetRegistry::removePropertySet - " + "caught NoSuchElementException!" ); + return; + } + catch ( WrappedTargetException& ) + { + // commitChanges + + OSL_ENSURE( sal_False, + "PropertySetRegistry::removePropertySet - " + "caught WrappedTargetException!" ); + return; + } + } + + return; + } + + OSL_ENSURE( sal_False, "PropertySetRegistry::removePropertySet - Error!" ); +} + +//========================================================================= +// +// XElementAccess methods. +// +//========================================================================= + +// virtual +com::sun::star::uno::Type SAL_CALL PropertySetRegistry::getElementType() + throw( RuntimeException ) +{ + return getCppuType( ( Reference< XPersistentPropertySet > * ) 0 ); +} + +//========================================================================= +// virtual +sal_Bool SAL_CALL PropertySetRegistry::hasElements() + throw( RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + Reference< XElementAccess > xElemAccess( + getRootConfigReadAccess(), UNO_QUERY ); + if ( xElemAccess.is() ) + return xElemAccess->hasElements(); + + return sal_False; +} + +//========================================================================= +// +// XNameAccess methods. +// +//========================================================================= + +// virtual +Any SAL_CALL PropertySetRegistry::getByName( const OUString& aName ) + throw( NoSuchElementException, WrappedTargetException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + Reference< XNameAccess > xNameAccess( + getRootConfigReadAccess(), UNO_QUERY ); + if ( xNameAccess.is() ) + { + + try + { + return xNameAccess->getByName( aName ); + } + catch ( NoSuchElementException& ) + { + // getByName + } + catch ( WrappedTargetException& ) + { + // getByName + } + } + + return Any(); +} + +//========================================================================= +// virtual +Sequence< OUString > SAL_CALL PropertySetRegistry::getElementNames() + throw( RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + Reference< XNameAccess > xNameAccess( + getRootConfigReadAccess(), UNO_QUERY ); + if ( xNameAccess.is() ) + { + return xNameAccess->getElementNames(); + } + return Sequence< OUString >( 0 ); +} + +//========================================================================= +// virtual +sal_Bool SAL_CALL PropertySetRegistry::hasByName( const OUString& aName ) + throw( RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + Reference< XNameAccess > xNameAccess( + getRootConfigReadAccess(), UNO_QUERY ); + if ( xNameAccess.is() ) + { + return xNameAccess->hasByName( aName ); + } + + return sal_False; +} + +//========================================================================= +void PropertySetRegistry::add( PersistentPropertySet* pSet ) +{ + OUString key( pSet->getKey() ); + + if ( key.getLength() ) + { + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + m_pImpl->m_aPropSets[ key ] = pSet; + } +} + +//========================================================================= +void PropertySetRegistry::remove( PersistentPropertySet* pSet ) +{ + OUString key( pSet->getKey() ); + + if ( key.getLength() ) + { + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + PropertySetMap_Impl& rSets = m_pImpl->m_aPropSets; + + PropertySetMap_Impl::iterator it = rSets.find( key ); + if ( it != rSets.end() ) + { + // Found. + rSets.erase( it ); + } + } +} + +//========================================================================= +void PropertySetRegistry::renamePropertySet( const OUString& rOldKey, + const OUString& rNewKey ) +{ + if ( rOldKey == rNewKey ) + return; + + Reference< XNameAccess > xRootNameAccess( + getConfigWriteAccess( OUString() ), UNO_QUERY ); + if ( xRootNameAccess.is() ) + { + // Old key present? + if ( xRootNameAccess->hasByName( rOldKey ) ) + { + // New key not present? + if ( xRootNameAccess->hasByName( rNewKey ) ) + { + OSL_ENSURE( sal_False, + "PropertySetRegistry::renamePropertySet - " + "New key exists!" ); + return; + } + Reference< XSingleServiceFactory > xFac( + xRootNameAccess, UNO_QUERY ); + Reference< XChangesBatch > xBatch( xFac, UNO_QUERY ); + Reference< XNameContainer > xContainer( xFac, UNO_QUERY ); + + OSL_ENSURE( xFac.is(), + "PropertySetRegistry::renamePropertySet - " + "No factory!" ); + + OSL_ENSURE( xBatch.is(), + "PropertySetRegistry::renamePropertySet - " + "No batch!" ); + + OSL_ENSURE( xContainer.is(), + "PropertySetRegistry::renamePropertySet - " + "No container!" ); + + if ( xFac.is() && xBatch.is() && xContainer.is() ) + { + ////////////////////////////////////////////////////// + // Create new "Properties" config item. + ////////////////////////////////////////////////////// + + try + { + Reference< XNameReplace > xNameReplace( + xFac->createInstance(), UNO_QUERY ); + + if ( xNameReplace.is() ) + { + // Insert new item. + xContainer->insertByName( + rNewKey, makeAny( xNameReplace ) ); + // Commit changes. + xBatch->commitChanges(); + } + } + catch ( IllegalArgumentException& ) + { + // insertByName + + OSL_ENSURE( sal_False, + "PropertySetRegistry::renamePropertySet - " + "caught IllegalArgumentException!" ); + return; + } + catch ( ElementExistException& ) + { + // insertByName + + OSL_ENSURE( sal_False, + "PropertySetRegistry::renamePropertySet - " + "caught ElementExistException!" ); + return; + } + catch ( WrappedTargetException& ) + { + // insertByName, commitChanges + + OSL_ENSURE( sal_False, + "PropertySetRegistry::renamePropertySet - " + "caught WrappedTargetException!" ); + return; + } + catch ( RuntimeException& ) + { + OSL_ENSURE( sal_False, + "PropertySetRegistry::renamePropertySet - " + "caught RuntimeException!" ); + return; + } + catch ( Exception& ) + { + // createInstance + + OSL_ENSURE( sal_False, + "PropertySetRegistry::renamePropertySet - " + "caught Exception!" ); + return; + } + + ////////////////////////////////////////////////////// + // Copy data... + ////////////////////////////////////////////////////// + + Reference< XHierarchicalNameAccess > xRootHierNameAccess( + xRootNameAccess, UNO_QUERY ); + if ( !xRootHierNameAccess.is() ) + { + OSL_ENSURE( sal_False, + "PropertySetRegistry::renamePropertySet - " + "No hierarchical name access!" ); + return; + } + + try + { + rtl::OUString aOldValuesKey + = makeHierarchalNameSegment( rOldKey ); + aOldValuesKey += OUString::createFromAscii( "/Values" ); + + Reference< XNameAccess > xOldNameAccess; + xRootHierNameAccess->getByHierarchicalName( + aOldValuesKey ) + >>= xOldNameAccess; + if ( !xOldNameAccess.is() ) + { + OSL_ENSURE( sal_False, + "PersistentPropertySet::renamePropertySet - " + "No old name access!" ); + return; + } + + // Obtain property names. + Sequence< OUString > aElems + = xOldNameAccess->getElementNames(); + sal_Int32 nCount = aElems.getLength(); + if ( nCount ) + { + rtl::OUString aNewValuesKey + = makeHierarchalNameSegment( rNewKey ); + aNewValuesKey += OUString::createFromAscii( "/Values" ); + + Reference< XSingleServiceFactory > xNewFac; + xRootHierNameAccess->getByHierarchicalName( + aNewValuesKey ) + >>= xNewFac; + if ( !xNewFac.is() ) + { + OSL_ENSURE( sal_False, + "PersistentPropertySet::renamePropertySet - " + "No new factory!" ); + return; + } + + Reference< XNameContainer > xNewContainer( + xNewFac, UNO_QUERY ); + if ( !xNewContainer.is() ) + { + OSL_ENSURE( sal_False, + "PersistentPropertySet::renamePropertySet - " + "No new container!" ); + return; + } + + aOldValuesKey += OUString::createFromAscii( "/" ); + + OUString aHandleKey + = OUString::createFromAscii( "/Handle" ); + OUString aValueKey + = OUString::createFromAscii( "/Value" ); + OUString aStateKey + = OUString::createFromAscii( "/State" ); + OUString aAttrKey + = OUString::createFromAscii( "/Attributes" ); + + for ( sal_Int32 n = 0; n < nCount; ++n ) + { + const OUString& rPropName = aElems[ n ]; + + // Create new item. + Reference< XNameReplace > xNewPropNameReplace( + xNewFac->createInstance(), UNO_QUERY ); + + if ( !xNewPropNameReplace.is() ) + { + OSL_ENSURE( sal_False, + "PersistentPropertySet::renamePropertySet - " + "No new prop name replace!" ); + return; + } + + // Fill new item... + + // Set Values + OUString aKey = aOldValuesKey; + aKey += makeHierarchalNameSegment( rPropName ); + + // ... handle + OUString aNewKey1 = aKey; + aNewKey1 += aHandleKey; + Any aAny = + xRootHierNameAccess->getByHierarchicalName( + aNewKey1 ); + xNewPropNameReplace->replaceByName( + OUString::createFromAscii( "Handle" ), + aAny ); + + // ... value + aNewKey1 = aKey; + aNewKey1 += aValueKey; + aAny = + xRootHierNameAccess->getByHierarchicalName( + aNewKey1 ); + xNewPropNameReplace->replaceByName( + OUString::createFromAscii( "Value" ), + aAny ); + + // ... state + aNewKey1 = aKey; + aNewKey1 += aStateKey; + aAny = + xRootHierNameAccess->getByHierarchicalName( + aNewKey1 ); + xNewPropNameReplace->replaceByName( + OUString::createFromAscii( "State" ), + aAny ); + + // ... attributes + aNewKey1 = aKey; + aNewKey1 += aAttrKey; + aAny = + xRootHierNameAccess->getByHierarchicalName( + aNewKey1 ); + xNewPropNameReplace->replaceByName( + OUString::createFromAscii( "Attributes" ), + aAny ); + + // Insert new item. + xNewContainer->insertByName( + rPropName, makeAny( xNewPropNameReplace ) ); + + // Commit changes. + xBatch->commitChanges(); + } + } + } + catch ( IllegalArgumentException& ) + { + // insertByName, replaceByName + + OSL_ENSURE( sal_False, + "PropertySetRegistry::renamePropertySet - " + "caught IllegalArgumentException!" ); + return; + } + catch ( ElementExistException& ) + { + // insertByName + + OSL_ENSURE( sal_False, + "PropertySetRegistry::renamePropertySet - " + "caught ElementExistException!" ); + return; + } + catch ( WrappedTargetException& ) + { + // insertByName, replaceByName, commitChanges + + OSL_ENSURE( sal_False, + "PropertySetRegistry::renamePropertySet - " + "caught WrappedTargetException!" ); + return; + } + catch ( NoSuchElementException& ) + { + // getByHierarchicalName, replaceByName + + OSL_ENSURE( sal_False, + "PropertySetRegistry::renamePropertySet - " + "caught NoSuchElementException!" ); + return; + } + catch ( RuntimeException& ) + { + OSL_ENSURE( sal_False, + "PropertySetRegistry::renamePropertySet - " + "caught RuntimeException!" ); + return; + } + catch ( Exception& ) + { + // createInstance + + OSL_ENSURE( sal_False, + "PropertySetRegistry::renamePropertySet - " + "caught Exception!" ); + return; + } + + ////////////////////////////////////////////////////// + // Remove old entry... + ////////////////////////////////////////////////////// + + try + { + // Remove item. + xContainer->removeByName( rOldKey ); + // Commit changes. + xBatch->commitChanges(); + + // Success. + return; + } + catch ( NoSuchElementException& ) + { + // removeByName + + OSL_ENSURE( sal_False, + "PropertySetRegistry::renamePropertySet - " + "caught NoSuchElementException!" ); + return; + } + catch ( WrappedTargetException& ) + { + // commitChanges + + OSL_ENSURE( sal_False, + "PropertySetRegistry::renamePropertySet - " + "caught WrappedTargetException!" ); + return; + } + } + } + } + + OSL_ENSURE( sal_False, "PropertySetRegistry::renamePropertySet - Error!" ); +} + +//========================================================================= +Reference< XMultiServiceFactory > PropertySetRegistry::getConfigProvider() +{ + if ( !m_pImpl->m_xConfigProvider.is() ) + { + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + if ( !m_pImpl->m_xConfigProvider.is() ) + { + const Sequence< Any >& rInitArgs = m_pImpl->m_aInitArgs; + + if ( rInitArgs.getLength() > 0 ) + { + // Extract config provider from service init args. + rInitArgs[ 0 ] >>= m_pImpl->m_xConfigProvider; + + OSL_ENSURE( m_pImpl->m_xConfigProvider.is(), + "PropertySetRegistry::getConfigProvider - " + "No config provider!" ); + } + else + { + try + { + m_pImpl->m_xConfigProvider + = Reference< XMultiServiceFactory >( + m_xSMgr->createInstance( + OUString::createFromAscii( + "com.sun.star.configuration." + "ConfigurationProvider" ) ), + UNO_QUERY ); + + OSL_ENSURE( m_pImpl->m_xConfigProvider.is(), + "PropertySetRegistry::getConfigProvider - " + "No config provider!" ); + + } + catch ( Exception& ) + { + OSL_ENSURE( sal_False, + "PropertySetRegistry::getConfigProvider - " + "caught exception!" ); + } + } + } + } + + return m_pImpl->m_xConfigProvider; +} + +//========================================================================= +Reference< XInterface > PropertySetRegistry::getRootConfigReadAccess() +{ + try + { + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( !m_pImpl->m_xRootReadAccess.is() ) + { + if ( m_pImpl->m_bTriedToGetRootReadAccess ) // #82494# + { + OSL_ENSURE( sal_False, + "PropertySetRegistry::getRootConfigReadAccess - " + "Unable to read any config data! -> #82494#" ); + return Reference< XInterface >(); + } + + getConfigProvider(); + + if ( m_pImpl->m_xConfigProvider.is() ) + { + Sequence< Any > aArguments( 1 ); + PropertyValue aProperty; + aProperty.Name + = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + CFGPROPERTY_NODEPATH ) ); + aProperty.Value + <<= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + STORE_CONTENTPROPERTIES_KEY ) ); + aArguments[ 0 ] <<= aProperty; + + m_pImpl->m_bTriedToGetRootReadAccess = sal_True; + + m_pImpl->m_xRootReadAccess = + m_pImpl->m_xConfigProvider->createInstanceWithArguments( + OUString::createFromAscii( + "com.sun.star.configuration.ConfigurationAccess" ), + aArguments ); + + if ( m_pImpl->m_xRootReadAccess.is() ) + return m_pImpl->m_xRootReadAccess; + } + } + else + return m_pImpl->m_xRootReadAccess; + } + catch ( RuntimeException& ) + { + throw; + } + catch ( Exception& ) + { + // createInstance, createInstanceWithArguments + + OSL_ENSURE( sal_False, + "PropertySetRegistry::getRootConfigReadAccess - caught Exception!" ); + return Reference< XInterface >(); + } + + OSL_ENSURE( sal_False, + "PropertySetRegistry::getRootConfigReadAccess - Error!" ); + return Reference< XInterface >(); +} + +//========================================================================= +Reference< XInterface > PropertySetRegistry::getConfigWriteAccess( + const OUString& rPath ) +{ + try + { + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( !m_pImpl->m_xRootWriteAccess.is() ) + { + if ( m_pImpl->m_bTriedToGetRootWriteAccess ) // #82494# + { + OSL_ENSURE( sal_False, + "PropertySetRegistry::getConfigWriteAccess - " + "Unable to write any config data! -> #82494#" ); + return Reference< XInterface >(); + } + + getConfigProvider(); + + if ( m_pImpl->m_xConfigProvider.is() ) + { + Sequence< Any > aArguments( 2 ); + PropertyValue aProperty; + + aProperty.Name + = OUString( RTL_CONSTASCII_USTRINGPARAM( + CFGPROPERTY_NODEPATH ) ); + aProperty.Value + <<= OUString( RTL_CONSTASCII_USTRINGPARAM( + STORE_CONTENTPROPERTIES_KEY ) ); + aArguments[ 0 ] <<= aProperty; + + aProperty.Name + = OUString( RTL_CONSTASCII_USTRINGPARAM( + CFGPROPERTY_LAZYWRITE ) ); + aProperty.Value <<= sal_True; + aArguments[ 1 ] <<= aProperty; + + m_pImpl->m_bTriedToGetRootWriteAccess = sal_True; + + m_pImpl->m_xRootWriteAccess = + m_pImpl->m_xConfigProvider->createInstanceWithArguments( + OUString::createFromAscii( + "com.sun.star.configuration.ConfigurationUpdateAccess" ), + aArguments ); + + OSL_ENSURE( m_pImpl->m_xRootWriteAccess.is(), + "PropertySetRegistry::getConfigWriteAccess - " + "No config update access!" ); + } + } + + if ( m_pImpl->m_xRootWriteAccess.is() ) + { + if ( rPath.getLength() ) + { + Reference< XHierarchicalNameAccess > xNA( + m_pImpl->m_xRootWriteAccess, UNO_QUERY ); + if ( xNA.is() ) + { + Reference< XInterface > xInterface; + xNA->getByHierarchicalName( rPath ) >>= xInterface; + + if ( xInterface.is() ) + return xInterface; + } + } + else + return m_pImpl->m_xRootWriteAccess; + } + } + catch ( RuntimeException& ) + { + throw; + } + catch ( NoSuchElementException& ) + { + // getByHierarchicalName + + OSL_ENSURE( sal_False, + "PropertySetRegistry::getConfigWriteAccess - " + "caught NoSuchElementException!" ); + return Reference< XInterface >(); + } + catch ( Exception& ) + { + // createInstance, createInstanceWithArguments + + OSL_ENSURE( sal_False, + "PropertySetRegistry::getConfigWriteAccess - " + "caught Exception!" ); + return Reference< XInterface >(); + } + + OSL_ENSURE( sal_False, + "PropertySetRegistry::getConfigWriteAccess - Error!" ); + return Reference< XInterface >(); +} + +//========================================================================= +// +// PropertyListeners_Impl. +// +//========================================================================= + +typedef OMultiTypeInterfaceContainerHelperVar +< + OUString, + hashString_Impl, + equalString_Impl +> PropertyListeners_Impl; + +//========================================================================= +// +// PersistentPropertySet_Impl. +// +//========================================================================= + +struct PersistentPropertySet_Impl +{ + PropertySetRegistry* m_pCreator; + PropertySetInfo_Impl* m_pInfo; + OUString m_aKey; + OUString m_aFullKey; + osl::Mutex m_aMutex; + OInterfaceContainerHelper* m_pDisposeEventListeners; + OInterfaceContainerHelper* m_pPropSetChangeListeners; + PropertyListeners_Impl* m_pPropertyChangeListeners; + + PersistentPropertySet_Impl( PropertySetRegistry& rCreator, + const OUString& rKey ) + : m_pCreator( &rCreator ), m_pInfo( NULL ), m_aKey( rKey ), + m_pDisposeEventListeners( NULL ), m_pPropSetChangeListeners( NULL ), + m_pPropertyChangeListeners( NULL ) + { + m_pCreator->acquire(); + } + + ~PersistentPropertySet_Impl() + { + m_pCreator->release(); + + if ( m_pInfo ) + m_pInfo->release(); + + delete m_pDisposeEventListeners; + delete m_pPropSetChangeListeners; + delete m_pPropertyChangeListeners; + } +}; + +//========================================================================= +//========================================================================= +//========================================================================= +// +// PersistentPropertySet Implementation. +// +//========================================================================= +//========================================================================= +//========================================================================= + +PersistentPropertySet::PersistentPropertySet( + const Reference< XMultiServiceFactory >& rXSMgr, + PropertySetRegistry& rCreator, + const OUString& rKey ) +: m_xSMgr( rXSMgr ), + m_pImpl( new PersistentPropertySet_Impl( rCreator, rKey ) ) +{ + // register at creator. + rCreator.add( this ); +} + +//========================================================================= +// virtual +PersistentPropertySet::~PersistentPropertySet() +{ + // deregister at creator. + m_pImpl->m_pCreator->remove( this ); + + delete m_pImpl; +} + +//========================================================================= +// +// XInterface methods. +// +//========================================================================= + +XINTERFACE_IMPL_9( PersistentPropertySet, + XTypeProvider, + XServiceInfo, + XComponent, + XPropertySet, /* base of XPersistentPropertySet */ + XNamed, + XPersistentPropertySet, + XPropertyContainer, + XPropertySetInfoChangeNotifier, + XPropertyAccess ); + +//========================================================================= +// +// XTypeProvider methods. +// +//========================================================================= + +XTYPEPROVIDER_IMPL_8( PersistentPropertySet, + XTypeProvider, + XServiceInfo, + XComponent, + XPersistentPropertySet, + XNamed, + XPropertyContainer, + XPropertySetInfoChangeNotifier, + XPropertyAccess ); + +//========================================================================= +// +// XServiceInfo methods. +// +//========================================================================= + +XSERVICEINFO_NOFACTORY_IMPL_1( PersistentPropertySet, + OUString::createFromAscii( + "com.sun.star.comp.ucb.PersistentPropertySet" ), + OUString::createFromAscii( + PERS_PROPSET_SERVICE_NAME ) ); + +//========================================================================= +// +// XComponent methods. +// +//========================================================================= + +// virtual +void SAL_CALL PersistentPropertySet::dispose() + throw( RuntimeException ) +{ + if ( m_pImpl->m_pDisposeEventListeners && + m_pImpl->m_pDisposeEventListeners->getLength() ) + { + EventObject aEvt; + aEvt.Source = static_cast< XComponent * >( this ); + m_pImpl->m_pDisposeEventListeners->disposeAndClear( aEvt ); + } + + if ( m_pImpl->m_pPropSetChangeListeners && + m_pImpl->m_pPropSetChangeListeners->getLength() ) + { + EventObject aEvt; + aEvt.Source = static_cast< XPropertySetInfoChangeNotifier * >( this ); + m_pImpl->m_pPropSetChangeListeners->disposeAndClear( aEvt ); + } + + if ( m_pImpl->m_pPropertyChangeListeners ) + { + EventObject aEvt; + aEvt.Source = static_cast< XPropertySet * >( this ); + m_pImpl->m_pPropertyChangeListeners->disposeAndClear( aEvt ); + } +} + +//========================================================================= +// virtual +void SAL_CALL PersistentPropertySet::addEventListener( + const Reference< XEventListener >& Listener ) + throw( RuntimeException ) +{ + if ( !m_pImpl->m_pDisposeEventListeners ) + m_pImpl->m_pDisposeEventListeners = + new OInterfaceContainerHelper( m_pImpl->m_aMutex ); + + m_pImpl->m_pDisposeEventListeners->addInterface( Listener ); +} + +//========================================================================= +// virtual +void SAL_CALL PersistentPropertySet::removeEventListener( + const Reference< XEventListener >& Listener ) + throw( RuntimeException ) +{ + if ( m_pImpl->m_pDisposeEventListeners ) + m_pImpl->m_pDisposeEventListeners->removeInterface( Listener ); + + // Note: Don't want to delete empty container here -> performance. +} + +//========================================================================= +// +// XPropertySet methods. +// +//========================================================================= + +// virtual +Reference< XPropertySetInfo > SAL_CALL + PersistentPropertySet::getPropertySetInfo() + throw( RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + PropertySetInfo_Impl*& rpInfo = m_pImpl->m_pInfo; + if ( !rpInfo ) + { + rpInfo = new PropertySetInfo_Impl( m_xSMgr, this ); + rpInfo->acquire(); + } + return Reference< XPropertySetInfo >( rpInfo ); +} + +//========================================================================= +// virtual +void SAL_CALL PersistentPropertySet::setPropertyValue( + const OUString& aPropertyName, const Any& aValue ) + throw( UnknownPropertyException, + PropertyVetoException, + IllegalArgumentException, + WrappedTargetException, + RuntimeException ) +{ + if ( !aPropertyName.getLength() ) + throw UnknownPropertyException(); + + osl::ClearableGuard< osl::Mutex > aCGuard( m_pImpl->m_aMutex ); + + Reference< XHierarchicalNameAccess > xRootHierNameAccess( + m_pImpl->m_pCreator->getRootConfigReadAccess(), UNO_QUERY ); + if ( xRootHierNameAccess.is() ) + { + OUString aFullPropName( getFullKey() ); + aFullPropName += OUString::createFromAscii( "/" ); + aFullPropName += makeHierarchalNameSegment( aPropertyName ); + + // Does property exist? + if ( xRootHierNameAccess->hasByHierarchicalName( aFullPropName ) ) + { + Reference< XNameReplace > xNameReplace( + m_pImpl->m_pCreator->getConfigWriteAccess( + aFullPropName ), UNO_QUERY ); + Reference< XChangesBatch > xBatch( + m_pImpl->m_pCreator->getConfigWriteAccess( + OUString() ), UNO_QUERY ); + + if ( xNameReplace.is() && xBatch.is() ) + { + try + { + // Obtain old value + OUString aValueName = aFullPropName; + aValueName += OUString::createFromAscii( "/Value" ); + Any aOldValue + = xRootHierNameAccess->getByHierarchicalName( + aValueName ); + // Check value type. + if ( aOldValue.getValueType() != aValue.getValueType() ) + { + aCGuard.clear(); + throw IllegalArgumentException(); + } + + // Write value + xNameReplace->replaceByName( + OUString::createFromAscii( "Value" ), + aValue ); + + // Write state ( Now it is a directly set value ) + xNameReplace->replaceByName( + OUString::createFromAscii( "State" ), + makeAny( + sal_Int32( + PropertyState_DIRECT_VALUE ) ) ); + + // Commit changes. + xBatch->commitChanges(); + + PropertyChangeEvent aEvt; + if ( m_pImpl->m_pPropertyChangeListeners ) + { + // Obtain handle + aValueName = aFullPropName; + aValueName += OUString::createFromAscii( "/Handle" ); + sal_Int32 nHandle = -1; + xRootHierNameAccess->getByHierarchicalName( aValueName ) + >>= nHandle; + + aEvt.Source = (OWeakObject*)this; + aEvt.PropertyName = aPropertyName; + aEvt.PropertyHandle = nHandle; + aEvt.Further = sal_False; + aEvt.OldValue = aOldValue; + aEvt.NewValue = aValue; + + // Callback follows! + aCGuard.clear(); + + notifyPropertyChangeEvent( aEvt ); + } + return; + } + catch ( IllegalArgumentException& ) + { + // replaceByName + } + catch ( NoSuchElementException& ) + { + // getByHierarchicalName, replaceByName + } + catch ( WrappedTargetException& ) + { + // replaceByName, commitChanges + } + } + } + } + + throw UnknownPropertyException(); +} + +//========================================================================= +// virtual +Any SAL_CALL PersistentPropertySet::getPropertyValue( + const OUString& PropertyName ) + throw( UnknownPropertyException, + WrappedTargetException, + RuntimeException ) +{ + if ( !PropertyName.getLength() ) + throw UnknownPropertyException(); + + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + Reference< XHierarchicalNameAccess > xNameAccess( + m_pImpl->m_pCreator->getRootConfigReadAccess(), UNO_QUERY ); + if ( xNameAccess.is() ) + { + OUString aFullPropName( getFullKey() ); + aFullPropName += OUString::createFromAscii( "/" ); + aFullPropName += makeHierarchalNameSegment( PropertyName ); + aFullPropName += OUString::createFromAscii( "/Value" ); + try + { + return xNameAccess->getByHierarchicalName( aFullPropName ); + } + catch ( NoSuchElementException& ) + { + throw UnknownPropertyException(); + } + } + + throw UnknownPropertyException(); +} + +//========================================================================= +// virtual +void SAL_CALL PersistentPropertySet::addPropertyChangeListener( + const OUString& aPropertyName, + const Reference< XPropertyChangeListener >& xListener ) + throw( UnknownPropertyException, + WrappedTargetException, + RuntimeException ) +{ +// load(); + + if ( !m_pImpl->m_pPropertyChangeListeners ) + m_pImpl->m_pPropertyChangeListeners = + new PropertyListeners_Impl( m_pImpl->m_aMutex ); + + m_pImpl->m_pPropertyChangeListeners->addInterface( + aPropertyName, xListener ); +} + +//========================================================================= +// virtual +void SAL_CALL PersistentPropertySet::removePropertyChangeListener( + const OUString& aPropertyName, + const Reference< XPropertyChangeListener >& aListener ) + throw( UnknownPropertyException, + WrappedTargetException, + RuntimeException ) +{ +// load(); + + if ( m_pImpl->m_pPropertyChangeListeners ) + m_pImpl->m_pPropertyChangeListeners->removeInterface( + aPropertyName, aListener ); + + // Note: Don't want to delete empty container here -> performance. +} + +//========================================================================= +// virtual +void SAL_CALL PersistentPropertySet::addVetoableChangeListener( + const OUString&, + const Reference< XVetoableChangeListener >& ) + throw( UnknownPropertyException, + WrappedTargetException, + RuntimeException ) +{ +// load(); +// OSL_ENSURE( sal_False, +// "PersistentPropertySet::addVetoableChangeListener - N.Y.I." ); +} + +//========================================================================= +// virtual +void SAL_CALL PersistentPropertySet::removeVetoableChangeListener( + const OUString&, + const Reference< XVetoableChangeListener >& ) + throw( UnknownPropertyException, + WrappedTargetException, + RuntimeException ) +{ +// load(); +// OSL_ENSURE( sal_False, +// "PersistentPropertySet::removeVetoableChangeListener - N.Y.I." ); +} + +//========================================================================= +// +// XPersistentPropertySet methods. +// +//========================================================================= + +// virtual +Reference< XPropertySetRegistry > SAL_CALL PersistentPropertySet::getRegistry() + throw( RuntimeException ) +{ + return Reference< XPropertySetRegistry >( m_pImpl->m_pCreator ); +} + +//========================================================================= +// virtual +OUString SAL_CALL PersistentPropertySet::getKey() + throw( RuntimeException ) +{ + return m_pImpl->m_aKey; +} + +//========================================================================= +// +// XNamed methods. +// +//========================================================================= + +// virtual +rtl::OUString SAL_CALL PersistentPropertySet::getName() + throw( RuntimeException ) +{ + // same as getKey() + return m_pImpl->m_aKey; +} + +//========================================================================= +// virtual +void SAL_CALL PersistentPropertySet::setName( const OUString& aName ) + throw( RuntimeException ) +{ + if ( aName != m_pImpl->m_aKey ) + m_pImpl->m_pCreator->renamePropertySet( m_pImpl->m_aKey, aName ); +} + +//========================================================================= +// +// XPropertyContainer methods. +// +//========================================================================= + +// virtual +void SAL_CALL PersistentPropertySet::addProperty( + const OUString& Name, sal_Int16 Attributes, const Any& DefaultValue ) + throw( PropertyExistException, + IllegalTypeException, + IllegalArgumentException, + RuntimeException ) +{ + if ( !Name.getLength() ) + throw IllegalArgumentException(); + + // @@@ What other types can't be written to config server? + + // Check type class ( Not all types can be written to storage ) + TypeClass eTypeClass = DefaultValue.getValueTypeClass(); + if ( eTypeClass == TypeClass_INTERFACE ) + throw IllegalTypeException(); + + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + // Property already in set? + + OUString aFullValuesName; + + Reference< XHierarchicalNameAccess > xRootHierNameAccess( + m_pImpl->m_pCreator->getRootConfigReadAccess(), UNO_QUERY ); + if ( xRootHierNameAccess.is() ) + { + aFullValuesName = getFullKey(); + OUString aFullPropName = aFullValuesName; + aFullPropName += OUString::createFromAscii( "/" ); + aFullPropName += makeHierarchalNameSegment( Name ); + + if ( xRootHierNameAccess->hasByHierarchicalName( aFullPropName ) ) + { + // Already in set. + throw PropertyExistException(); + } + } + + // Property is always removeable. + Attributes |= PropertyAttribute::REMOVEABLE; + + // Add property. + + Reference< XSingleServiceFactory > xFac( + m_pImpl->m_pCreator->getConfigWriteAccess( aFullValuesName ), + UNO_QUERY ); + Reference< XNameContainer > xContainer( xFac, UNO_QUERY ); + Reference< XChangesBatch > xBatch( + m_pImpl->m_pCreator->getConfigWriteAccess( OUString() ), + UNO_QUERY ); + + OSL_ENSURE( xFac.is(), + "PersistentPropertySet::addProperty - No factory!" ); + + OSL_ENSURE( xBatch.is(), + "PersistentPropertySet::addProperty - No batch!" ); + + OSL_ENSURE( xContainer.is(), + "PersistentPropertySet::addProperty - No container!" ); + + if ( xFac.is() && xBatch.is() && xContainer.is() ) + { + try + { + // Create new "PropertyValue" config item. + Reference< XNameReplace > xNameReplace( + xFac->createInstance(), UNO_QUERY ); + + if ( xNameReplace.is() ) + { + // Fill new item... + + // Set handle + xNameReplace->replaceByName( + OUString::createFromAscii( "Handle" ), + makeAny( sal_Int32( -1 ) ) ); + + // Set default value + xNameReplace->replaceByName( + OUString::createFromAscii( "Value" ), + DefaultValue ); + + // Set state ( always "default" ) + xNameReplace->replaceByName( + OUString::createFromAscii( "State" ), + makeAny( + sal_Int32( + PropertyState_DEFAULT_VALUE ) ) ); + + // Set attributes + xNameReplace->replaceByName( + OUString::createFromAscii( "Attributes" ), + makeAny( sal_Int32( Attributes ) ) ); + + // Insert new item. + xContainer->insertByName( Name, makeAny( xNameReplace ) ); + + // Commit changes. + xBatch->commitChanges(); + + // Property set info is invalid. + if ( m_pImpl->m_pInfo ) + m_pImpl->m_pInfo->reset(); + + // Notify propertyset info change listeners. + if ( m_pImpl->m_pPropSetChangeListeners && + m_pImpl->m_pPropSetChangeListeners->getLength() ) + { + PropertySetInfoChangeEvent evt( + static_cast< OWeakObject * >( this ), + Name, + -1, + PropertySetInfoChange::PROPERTY_INSERTED ); + notifyPropertySetInfoChange( evt ); + } + + // Success. + return; + } + } + catch ( IllegalArgumentException& ) + { + // insertByName + + OSL_ENSURE( sal_False, + "PersistentPropertySet::addProperty - " + "caught IllegalArgumentException!" ); + return; + } + catch ( ElementExistException& ) + { + // insertByName + + OSL_ENSURE( sal_False, + "PersistentPropertySet::addProperty - " + "caught ElementExistException!" ); + return; + } + catch ( WrappedTargetException& ) + { + // replaceByName, insertByName, commitChanges + + OSL_ENSURE( sal_False, + "PersistentPropertySet::addProperty - " + "caught WrappedTargetException!" ); + return; + } + catch ( RuntimeException& ) + { + throw; + } + catch ( Exception& ) + { + // createInstance + + OSL_ENSURE( sal_False, + "PersistentPropertySet::addProperty - " + "caught Exception!" ); + return; + } + } + + OSL_ENSURE( sal_False, + "PersistentPropertySet::addProperty - Error!" ); +} + +//========================================================================= +// virtual +void SAL_CALL PersistentPropertySet::removeProperty( const OUString& Name ) + throw( UnknownPropertyException, + NotRemoveableException, + RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + OUString aFullValuesName; + OUString aFullPropName; + + Reference< XHierarchicalNameAccess > xRootHierNameAccess( + m_pImpl->m_pCreator->getRootConfigReadAccess(), UNO_QUERY ); + if ( xRootHierNameAccess.is() ) + { + aFullValuesName = getFullKey(); + aFullPropName = aFullValuesName; + aFullPropName += OUString::createFromAscii( "/" ); + aFullPropName += makeHierarchalNameSegment( Name ); + + // Property in set? + if ( !xRootHierNameAccess->hasByHierarchicalName( aFullPropName ) ) + throw UnknownPropertyException(); + + // Property removeable? + try + { + OUString aFullAttrName = aFullPropName; + aFullAttrName += OUString::createFromAscii( "/Attributes" ); + + sal_Int32 nAttribs = 0; + if ( xRootHierNameAccess->getByHierarchicalName( aFullAttrName ) + >>= nAttribs ) + { + if ( !( nAttribs & PropertyAttribute::REMOVEABLE ) ) + { + // Not removeable! + throw NotRemoveableException(); + } + } + else + { + OSL_ENSURE( sal_False, + "PersistentPropertySet::removeProperty - " + "No attributes!" ); + return; + } + } + catch ( NoSuchElementException& ) + { + // getByHierarchicalName + + OSL_ENSURE( sal_False, + "PersistentPropertySet::removeProperty - " + "caught NoSuchElementException!" ); + } + + // Remove property... + + Reference< XNameContainer > xContainer( + m_pImpl->m_pCreator->getConfigWriteAccess( aFullValuesName ), + UNO_QUERY ); + Reference< XChangesBatch > xBatch( + m_pImpl->m_pCreator->getConfigWriteAccess( OUString() ), + UNO_QUERY ); + + OSL_ENSURE( xBatch.is(), + "PersistentPropertySet::removeProperty - No batch!" ); + + OSL_ENSURE( xContainer.is(), + "PersistentPropertySet::removeProperty - No container!" ); + + if ( xBatch.is() && xContainer.is() ) + { + try + { + sal_Int32 nHandle = -1; + + if ( m_pImpl->m_pPropSetChangeListeners && + m_pImpl->m_pPropSetChangeListeners->getLength() ) + { + // Obtain property handle ( needed for propertysetinfo + // change event )... + + try + { + OUString aFullHandleName = aFullPropName; + aFullHandleName + += OUString::createFromAscii( "/Handle" ); + + if ( ! ( xRootHierNameAccess->getByHierarchicalName( + aFullHandleName ) >>= nHandle ) ) + nHandle = -1; + + } + catch ( NoSuchElementException& ) + { + // getByHierarchicalName + + OSL_ENSURE( sal_False, + "PersistentPropertySet::removeProperty - " + "caught NoSuchElementException!" ); + nHandle = -1; + } + } + + xContainer->removeByName( Name ); + xBatch->commitChanges(); + + // Property set info is invalid. + if ( m_pImpl->m_pInfo ) + m_pImpl->m_pInfo->reset(); + + // Notify propertyset info change listeners. + if ( m_pImpl->m_pPropSetChangeListeners && + m_pImpl->m_pPropSetChangeListeners->getLength() ) + { + PropertySetInfoChangeEvent evt( + static_cast< OWeakObject * >( this ), + Name, + nHandle, + PropertySetInfoChange::PROPERTY_REMOVED ); + notifyPropertySetInfoChange( evt ); + } + + // Success. + return; + } + catch ( NoSuchElementException& ) + { + // removeByName + + OSL_ENSURE( sal_False, + "PersistentPropertySet::removeProperty - " + "caught NoSuchElementException!" ); + return; + } + catch ( WrappedTargetException& ) + { + // commitChanges + + OSL_ENSURE( sal_False, + "PersistentPropertySet::removeProperty - " + "caught WrappedTargetException!" ); + return; + } + } + } + + OSL_ENSURE( sal_False, + "PersistentPropertySet::removeProperty - Error!" ); +} + +//========================================================================= +// +// XPropertySetInfoChangeNotifier methods. +// +//========================================================================= + +// virtual +void SAL_CALL PersistentPropertySet::addPropertySetInfoChangeListener( + const Reference< XPropertySetInfoChangeListener >& Listener ) + throw( RuntimeException ) +{ + if ( !m_pImpl->m_pPropSetChangeListeners ) + m_pImpl->m_pPropSetChangeListeners = + new OInterfaceContainerHelper( m_pImpl->m_aMutex ); + + m_pImpl->m_pPropSetChangeListeners->addInterface( Listener ); +} + +//========================================================================= +// virtual +void SAL_CALL PersistentPropertySet::removePropertySetInfoChangeListener( + const Reference< XPropertySetInfoChangeListener >& Listener ) + throw( RuntimeException ) +{ + if ( m_pImpl->m_pPropSetChangeListeners ) + m_pImpl->m_pPropSetChangeListeners->removeInterface( Listener ); +} + +//========================================================================= +// +// XPropertyAccess methods. +// +//========================================================================= + +// virtual +Sequence< PropertyValue > SAL_CALL PersistentPropertySet::getPropertyValues() + throw( RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + Reference< XHierarchicalNameAccess > xRootHierNameAccess( + m_pImpl->m_pCreator->getRootConfigReadAccess(), UNO_QUERY ); + if ( xRootHierNameAccess.is() ) + { + try + { + Reference< XNameAccess > xNameAccess; + xRootHierNameAccess->getByHierarchicalName(getFullKey()) + >>= xNameAccess; + if ( xNameAccess.is() ) + { + // Obtain property names. + + Sequence< OUString > aElems = xNameAccess->getElementNames(); + + sal_Int32 nCount = aElems.getLength(); + if ( nCount ) + { + Reference< XHierarchicalNameAccess > xHierNameAccess( + xNameAccess, UNO_QUERY ); + + OSL_ENSURE( xHierNameAccess.is(), + "PersistentPropertySet::getPropertyValues - " + "No hierarchical name access!" ); + + if ( xHierNameAccess.is() ) + { + Sequence< PropertyValue > aValues( nCount ); + + const OUString aHandleName + = OUString::createFromAscii( "/Handle" ); + const OUString aValueName + = OUString::createFromAscii( "/Value" ); + const OUString aStateName + = OUString::createFromAscii( "/State" ); + + for ( sal_Int32 n = 0; n < nCount; ++n ) + { + PropertyValue& rValue = aValues[ n ]; + OUString rName = aElems[ n ]; + OUString aXMLName + = makeHierarchalNameSegment( rName ); + + // Set property name. + + rValue.Name = rName; + + try + { + // Obtain and set property handle + OUString aHierName = aXMLName; + aHierName += aHandleName; + Any aKeyValue + = xHierNameAccess->getByHierarchicalName( + aHierName ); + + if ( !( aKeyValue >>= rValue.Handle ) ) + OSL_ENSURE( sal_False, + "PersistentPropertySet::getPropertyValues - " + "Error getting property handle!" ); + } + catch ( NoSuchElementException& ) + { + // getByHierarchicalName + + OSL_ENSURE( sal_False, + "PersistentPropertySet::getPropertyValues - " + "NoSuchElementException!" ); + } + + try + { + // Obtain and set property value + OUString aHierName = aXMLName; + aHierName += aValueName; + rValue.Value + = xHierNameAccess->getByHierarchicalName( + aHierName ); + + // Note: The value may be void if addProperty + // was called with a default value + // of type void. + } + catch ( NoSuchElementException& ) + { + // getByHierarchicalName + + OSL_ENSURE( sal_False, + "PersistentPropertySet::getPropertyValues - " + "NoSuchElementException!" ); + } + + try + { + // Obtain and set property state + OUString aHierName = aXMLName; + aHierName += aStateName; + Any aKeyValue + = xHierNameAccess->getByHierarchicalName( + aHierName ); + + sal_Int32 nState = 0; + if ( !( aKeyValue >>= nState ) ) + OSL_ENSURE( sal_False, + "PersistentPropertySet::getPropertyValues - " + "Error getting property state!" ); + else + rValue.State = PropertyState( nState ); + } + catch ( NoSuchElementException& ) + { + // getByHierarchicalName + + OSL_ENSURE( sal_False, + "PersistentPropertySet::getPropertyValues - " + "NoSuchElementException!" ); + } + } + + return aValues; + } + } + } + } + catch ( NoSuchElementException& ) + { + // getByHierarchicalName + } + } + + return Sequence< PropertyValue >( 0 ); +} + +//========================================================================= +// virtual +void SAL_CALL PersistentPropertySet::setPropertyValues( + const Sequence< PropertyValue >& aProps ) + throw( UnknownPropertyException, + PropertyVetoException, + IllegalArgumentException, + WrappedTargetException, + RuntimeException ) +{ + sal_Int32 nCount = aProps.getLength(); + if ( !nCount ) + return; + + osl::ClearableGuard< osl::Mutex > aCGuard( m_pImpl->m_aMutex ); + + Reference< XHierarchicalNameAccess > xRootHierNameAccess( + m_pImpl->m_pCreator->getRootConfigReadAccess(), UNO_QUERY ); + if ( xRootHierNameAccess.is() ) + { + const PropertyValue* pNewValues = aProps.getConstArray(); + + typedef std::list< PropertyChangeEvent > Events; + Events aEvents; + + OUString aFullPropNamePrefix( getFullKey() ); + aFullPropNamePrefix += OUString::createFromAscii( "/" ); + + // Iterate over given property value sequence. + for ( sal_Int32 n = 0; n < nCount; ++n ) + { + const PropertyValue& rNewValue = pNewValues[ n ]; + const OUString& rName = rNewValue.Name; + + OUString aFullPropName = aFullPropNamePrefix; + aFullPropName += makeHierarchalNameSegment( rName ); + + // Does property exist? + if ( xRootHierNameAccess->hasByHierarchicalName( aFullPropName ) ) + { + Reference< XNameReplace > xNameReplace( + m_pImpl->m_pCreator->getConfigWriteAccess( + aFullPropName ), UNO_QUERY ); + Reference< XChangesBatch > xBatch( + m_pImpl->m_pCreator->getConfigWriteAccess( + OUString() ), UNO_QUERY ); + + if ( xNameReplace.is() && xBatch.is() ) + { + try + { + // Write handle + xNameReplace->replaceByName( + OUString::createFromAscii( "Handle" ), + makeAny( rNewValue.Handle ) ); + + // Save old value + OUString aValueName = aFullPropName; + aValueName += OUString::createFromAscii( "/Value" ); + Any aOldValue + = xRootHierNameAccess->getByHierarchicalName( + aValueName ); + // Write value + xNameReplace->replaceByName( + OUString::createFromAscii( "Value" ), + rNewValue.Value ); + + // Write state ( Now it is a directly set value ) + xNameReplace->replaceByName( + OUString::createFromAscii( "State" ), + makeAny( + sal_Int32( + PropertyState_DIRECT_VALUE ) ) ); + + // Commit changes. + xBatch->commitChanges(); + + if ( m_pImpl->m_pPropertyChangeListeners ) + { + PropertyChangeEvent aEvt; + aEvt.Source = (OWeakObject*)this; + aEvt.PropertyName = rNewValue.Name; + aEvt.PropertyHandle = rNewValue.Handle; + aEvt.Further = sal_False; + aEvt.OldValue = aOldValue; + aEvt.NewValue = rNewValue.Value; + + aEvents.push_back( aEvt ); + } + } + catch ( IllegalArgumentException& ) + { + // replaceByName + } + catch ( NoSuchElementException& ) + { + // getByHierarchicalName, replaceByName + } + catch ( WrappedTargetException& ) + { + // replaceByName, commitChanges + } + } + } + } + + // Callback follows! + aCGuard.clear(); + + if ( m_pImpl->m_pPropertyChangeListeners ) + { + // Notify property changes. + Events::const_iterator it = aEvents.begin(); + Events::const_iterator end = aEvents.end(); + + while ( it != end ) + { + notifyPropertyChangeEvent( (*it) ); + it++; + } + } + + return; + } + + OSL_ENSURE( sal_False, + "PersistentPropertySet::setPropertyValues - Nothing set!" ); +} + +//========================================================================= +// +// Non-interface methods +// +//========================================================================= + +void PersistentPropertySet::notifyPropertyChangeEvent( + const PropertyChangeEvent& rEvent ) const +{ + // Get "normal" listeners for the property. + OInterfaceContainerHelper* pContainer = + m_pImpl->m_pPropertyChangeListeners->getContainer( + rEvent.PropertyName ); + if ( pContainer && pContainer->getLength() ) + { + OInterfaceIteratorHelper aIter( *pContainer ); + while ( aIter.hasMoreElements() ) + { + // Propagate event. + Reference< XPropertyChangeListener > xListener( + aIter.next(), UNO_QUERY ); + if ( xListener.is() ) + xListener->propertyChange( rEvent ); + } + } + + // Get "normal" listeners for all properties. + OInterfaceContainerHelper* pNoNameContainer = + m_pImpl->m_pPropertyChangeListeners->getContainer( OUString() ); + if ( pNoNameContainer && pNoNameContainer->getLength() ) + { + OInterfaceIteratorHelper aIter( *pNoNameContainer ); + while ( aIter.hasMoreElements() ) + { + // Propagate event. + Reference< XPropertyChangeListener > xListener( + aIter.next(), UNO_QUERY ); + if ( xListener.is() ) + xListener->propertyChange( rEvent ); + } + } +} + +//========================================================================= +void PersistentPropertySet::notifyPropertySetInfoChange( + const PropertySetInfoChangeEvent& evt ) const +{ + if ( !m_pImpl->m_pPropSetChangeListeners ) + return; + + // Notify event listeners. + OInterfaceIteratorHelper aIter( *( m_pImpl->m_pPropSetChangeListeners ) ); + while ( aIter.hasMoreElements() ) + { + // Propagate event. + Reference< XPropertySetInfoChangeListener > + xListener( aIter.next(), UNO_QUERY ); + if ( xListener.is() ) + xListener->propertySetInfoChange( evt ); + } +} + +//========================================================================= +const OUString& PersistentPropertySet::getFullKey() +{ + if ( !m_pImpl->m_aFullKey.getLength() ) + { + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + if ( !m_pImpl->m_aFullKey.getLength() ) + { + m_pImpl->m_aFullKey + = makeHierarchalNameSegment( m_pImpl->m_aKey ); + m_pImpl->m_aFullKey + += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/Values" ) ); + } + } + + return m_pImpl->m_aFullKey; +} + +//========================================================================= +PropertySetRegistry& PersistentPropertySet::getPropertySetRegistry() +{ + return *m_pImpl->m_pCreator; +} + +//========================================================================= +//========================================================================= +// +// PropertySetInfo_Impl Implementation. +// +//========================================================================= +//========================================================================= + +PropertySetInfo_Impl::PropertySetInfo_Impl( + const Reference< XMultiServiceFactory >& rxSMgr, + PersistentPropertySet* pOwner ) +: m_xSMgr( rxSMgr ), + m_pProps( NULL ), + m_pOwner( pOwner ) +{ +} + +//========================================================================= +// virtual +PropertySetInfo_Impl::~PropertySetInfo_Impl() +{ + delete m_pProps; + + // !!! Do not delete m_pOwner !!! +} + +//========================================================================= +// +// XInterface methods. +// +//========================================================================= + +XINTERFACE_IMPL_2( PropertySetInfo_Impl, + XTypeProvider, + XPropertySetInfo ); + +//========================================================================= +// +// XTypeProvider methods. +// +//========================================================================= + +XTYPEPROVIDER_IMPL_2( PropertySetInfo_Impl, + XTypeProvider, + XPropertySetInfo ); + +//========================================================================= +// +// XPropertySetInfo methods. +// +//========================================================================= + +// virtual +Sequence< Property > SAL_CALL PropertySetInfo_Impl::getProperties() + throw( RuntimeException ) +{ + if ( !m_pProps ) + { + Reference< XHierarchicalNameAccess > xRootHierNameAccess( + m_pOwner->getPropertySetRegistry().getRootConfigReadAccess(), + UNO_QUERY ); + if ( xRootHierNameAccess.is() ) + { + try + { + Reference< XNameAccess > xNameAccess; + xRootHierNameAccess->getByHierarchicalName( + m_pOwner->getFullKey() ) + >>= xNameAccess; + if ( xNameAccess.is() ) + { + // Obtain property names. + + Sequence< OUString > aElems + = xNameAccess->getElementNames(); + + sal_uInt32 nCount = aElems.getLength(); + Sequence< Property >* pPropSeq + = new Sequence< Property >( nCount ); + + if ( nCount ) + { + Reference< XHierarchicalNameAccess > xHierNameAccess( + xNameAccess, UNO_QUERY ); + + OSL_ENSURE( xHierNameAccess.is(), + "PropertySetInfo_Impl::getProperties - " + "No hierarchical name access!" ); + + if ( xHierNameAccess.is() ) + { + const OUString aHandleName + = OUString::createFromAscii( "/Handle" ); + const OUString aValueName + = OUString::createFromAscii( "/Value" ); + const OUString aAttrName + = OUString::createFromAscii( "/Attributes" ); + + Property* pProps = pPropSeq->getArray(); + + for ( sal_uInt32 n = 0; n < nCount; ++n ) + { + Property& rProp = pProps[ n ]; + OUString rName = aElems[ n ]; + OUString aXMLName + = makeHierarchalNameSegment( rName ); + + // Set property name. + + rProp.Name = rName; + + try + { + // Obtain and set property handle + rtl::OUString aHierName = aXMLName; + aHierName += aHandleName; + Any aKeyValue + = xHierNameAccess->getByHierarchicalName( + aHierName ); + + if ( !( aKeyValue >>= rProp.Handle ) ) + OSL_ENSURE( sal_False, + "PropertySetInfo_Impl::getProperties - " + "Error getting property handle!" ); + } + catch ( NoSuchElementException& ) + { + // getByHierarchicalName + + OSL_ENSURE( sal_False, + "PropertySetInfo_Impl::getProperties - " + "NoSuchElementException!" ); + } + + try + { + // Obtain and set property type + rtl::OUString aHierName = aXMLName; + aHierName += aValueName; + Any aKeyValue + = xHierNameAccess->getByHierarchicalName( + aHierName ); + + // Note: The type may be void if addProperty + // was called with a default value + // of type void. + + rProp.Type = aKeyValue.getValueType(); + } + catch ( NoSuchElementException& ) + { + // getByHierarchicalName + + OSL_ENSURE( sal_False, + "PropertySetInfo_Impl::getProperties - " + "NoSuchElementException!" ); + } + + try + { + // Obtain and set property attributes + rtl::OUString aHierName = aXMLName; + aHierName += aAttrName; + Any aKeyValue + = xHierNameAccess->getByHierarchicalName( + aHierName ); + + sal_Int32 nAttribs = 0; + if ( aKeyValue >>= nAttribs ) + rProp.Attributes + = sal_Int16( nAttribs ); + else + OSL_ENSURE( sal_False, + "PropertySetInfo_Impl::getProperties - " + "Error getting property attributes!" ); + } + catch ( NoSuchElementException& ) + { + // getByHierarchicalName + + OSL_ENSURE( sal_False, + "PropertySetInfo_Impl::getProperties - " + "NoSuchElementException!" ); + } + } + } + } + + // Success. + m_pProps = pPropSeq; + return *m_pProps; + } + } + catch ( NoSuchElementException& ) + { + // getByHierarchicalName + } + } + + OSL_ENSURE( sal_False, "PropertySetInfo_Impl::getProperties - Error!" ); + m_pProps = new Sequence< Property >( 0 ); + } + + return *m_pProps; +} + +//========================================================================= +// virtual +Property SAL_CALL PropertySetInfo_Impl::getPropertyByName( + const OUString& aName ) + throw( UnknownPropertyException, RuntimeException ) +{ + Reference< XHierarchicalNameAccess > xRootHierNameAccess( + m_pOwner->getPropertySetRegistry().getRootConfigReadAccess(), + UNO_QUERY ); + if ( xRootHierNameAccess.is() ) + { + OUString aFullPropName( m_pOwner->getFullKey() ); + aFullPropName += OUString::createFromAscii( "/" ); + aFullPropName += makeHierarchalNameSegment( aName ); + + // Does property exist? + if ( !xRootHierNameAccess->hasByHierarchicalName( aFullPropName ) ) + throw UnknownPropertyException(); + + try + { + Property aProp; + + // Obtain handle. + OUString aKey = aFullPropName; + aKey += OUString::createFromAscii( "/Handle" ); + + if ( !( xRootHierNameAccess->getByHierarchicalName( aKey ) + >>= aProp.Handle ) ) + { + OSL_ENSURE( sal_False, + "PropertySetInfo_Impl::getPropertyByName - " + "No handle!" ); + return Property(); + } + + // Obtain Value and extract type. + aKey = aFullPropName; + aKey += OUString::createFromAscii( "/Value" ); + + Any aValue = xRootHierNameAccess->getByHierarchicalName( aKey ); + if ( !aValue.hasValue() ) + { + OSL_ENSURE( sal_False, + "PropertySetInfo_Impl::getPropertyByName - " + "No Value!" ); + return Property(); + } + + aProp.Type = aValue.getValueType(); + + // Obtain Attributes. + aKey = aFullPropName; + aKey += OUString::createFromAscii( "/Attributes" ); + + sal_Int32 nAttribs = 0; + if ( xRootHierNameAccess->getByHierarchicalName( aKey ) + >>= nAttribs ) + aProp.Attributes = sal_Int16( nAttribs ); + else + { + OSL_ENSURE( sal_False, + "PropertySetInfo_Impl::getPropertyByName - " + "No attributes!" ); + return Property(); + } + + // set name. + aProp.Name = aName; + + // Success. + return aProp; + } + catch ( NoSuchElementException& ) + { + // getByHierarchicalName + + OSL_ENSURE( sal_False, + "PropertySetInfo_Impl::getPropertyByName - " + "caught NoSuchElementException!" ); + } + + } + + OSL_ENSURE( sal_False, "PropertySetInfo_Impl::getPropertyByName - Error!" ); + return Property(); +} + +//========================================================================= +// virtual +sal_Bool SAL_CALL PropertySetInfo_Impl::hasPropertyByName( + const OUString& Name ) + throw( RuntimeException ) +{ + Reference< XHierarchicalNameAccess > xRootHierNameAccess( + m_pOwner->getPropertySetRegistry().getRootConfigReadAccess(), + UNO_QUERY ); + if ( xRootHierNameAccess.is() ) + { + OUString aFullPropName( m_pOwner->getFullKey() ); + aFullPropName += OUString::createFromAscii( "/" ); + aFullPropName += makeHierarchalNameSegment( Name ); + + return xRootHierNameAccess->hasByHierarchicalName( aFullPropName ); + } + + return sal_False; +} + diff --git a/ucb/source/core/ucbstore.hxx b/ucb/source/core/ucbstore.hxx new file mode 100644 index 000000000000..7a7a76cb1b99 --- /dev/null +++ b/ucb/source/core/ucbstore.hxx @@ -0,0 +1,345 @@ +/************************************************************************* + * + * 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 _UCBSTORE_HXX +#define _UCBSTORE_HXX + +#include <com/sun/star/lang/XTypeProvider.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/container/XNamed.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/ucb/XPropertySetRegistryFactory.hpp> +#include <com/sun/star/ucb/XPropertySetRegistry.hpp> +#include <com/sun/star/ucb/XPersistentPropertySet.hpp> +#include <com/sun/star/beans/XPropertyContainer.hpp> +#include <com/sun/star/beans/XPropertySetInfoChangeNotifier.hpp> +#include <com/sun/star/beans/XPropertyAccess.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <cppuhelper/weak.hxx> +#include <ucbhelper/macros.hxx> + +//========================================================================= + +#define STORE_SERVICE_NAME "com.sun.star.ucb.Store" +#define PROPSET_REG_SERVICE_NAME "com.sun.star.ucb.PropertySetRegistry" +#define PERS_PROPSET_SERVICE_NAME "com.sun.star.ucb.PersistentPropertySet" + +//========================================================================= + +struct UcbStore_Impl; + +class UcbStore : + public cppu::OWeakObject, + public com::sun::star::lang::XTypeProvider, + public com::sun::star::lang::XServiceInfo, + public com::sun::star::ucb::XPropertySetRegistryFactory, + public com::sun::star::lang::XInitialization +{ + com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory > m_xSMgr; + UcbStore_Impl* m_pImpl; + +public: + UcbStore( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rXSMgr ); + virtual ~UcbStore(); + + // XInterface + XINTERFACE_DECL() + + // XTypeProvider + XTYPEPROVIDER_DECL() + + // XServiceInfo + XSERVICEINFO_DECL() + + // XPropertySetRegistryFactory + virtual com::sun::star::uno::Reference< + com::sun::star::ucb::XPropertySetRegistry > SAL_CALL + createPropertySetRegistry( const rtl::OUString& URL ) + throw( com::sun::star::uno::RuntimeException ); + + // XInitialization + virtual void SAL_CALL + initialize( const ::com::sun::star::uno::Sequence< + ::com::sun::star::uno::Any >& aArguments ) + throw( ::com::sun::star::uno::Exception, + ::com::sun::star::uno::RuntimeException ); + + const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& + getInitArgs() const; +}; + +//========================================================================= + +struct PropertySetRegistry_Impl; +class PersistentPropertySet; + +class PropertySetRegistry : + public cppu::OWeakObject, + public com::sun::star::lang::XTypeProvider, + public com::sun::star::lang::XServiceInfo, + public com::sun::star::ucb::XPropertySetRegistry, + public com::sun::star::container::XNameAccess +{ + friend class PersistentPropertySet; + + com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory > m_xSMgr; + PropertySetRegistry_Impl* m_pImpl; + +private: + com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory > + getConfigProvider(); + + void add ( PersistentPropertySet* pSet ); + void remove( PersistentPropertySet* pSet ); + + void renamePropertySet( const rtl::OUString& rOldKey, + const rtl::OUString& rNewKey ); + +public: + PropertySetRegistry( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rXSMgr, + const ::com::sun::star::uno::Sequence< + ::com::sun::star::uno::Any >& rInitArgs); + virtual ~PropertySetRegistry(); + + // XInterface + XINTERFACE_DECL() + + // XTypeProvider + XTYPEPROVIDER_DECL() + + // XServiceInfo + XSERVICEINFO_NOFACTORY_DECL() + + // XPropertySetRegistry + virtual com::sun::star::uno::Reference< + com::sun::star::ucb::XPersistentPropertySet > SAL_CALL + openPropertySet( const rtl::OUString& key, sal_Bool create ) + throw( com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + removePropertySet( const rtl::OUString& key ) + throw( com::sun::star::uno::RuntimeException ); + + // XElementAccess ( XNameAccess is derived from it ) + virtual com::sun::star::uno::Type SAL_CALL + getElementType() + throw( com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL + hasElements() + throw( com::sun::star::uno::RuntimeException ); + + // XNameAccess + virtual com::sun::star::uno::Any SAL_CALL + getByName( const rtl::OUString& aName ) + throw( com::sun::star::container::NoSuchElementException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException ); + virtual com::sun::star::uno::Sequence< rtl::OUString > SAL_CALL + getElementNames() + throw( com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL + hasByName( const rtl::OUString& aName ) + throw( com::sun::star::uno::RuntimeException ); + + // Non-interface methods + com::sun::star::uno::Reference< com::sun::star::uno::XInterface > + getRootConfigReadAccess(); + com::sun::star::uno::Reference< com::sun::star::uno::XInterface > + getConfigWriteAccess( const rtl::OUString& rPath ); +}; + +//========================================================================= + +struct PersistentPropertySet_Impl; + +class PersistentPropertySet : + public cppu::OWeakObject, + public com::sun::star::lang::XTypeProvider, + public com::sun::star::lang::XServiceInfo, + public com::sun::star::lang::XComponent, + public com::sun::star::ucb::XPersistentPropertySet, + public com::sun::star::container::XNamed, + public com::sun::star::beans::XPropertyContainer, + public com::sun::star::beans::XPropertySetInfoChangeNotifier, + public com::sun::star::beans::XPropertyAccess +{ + com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory > m_xSMgr; + PersistentPropertySet_Impl* m_pImpl; + +private: + void notifyPropertyChangeEvent( + const com::sun::star::beans::PropertyChangeEvent& rEvent ) const; + void notifyPropertySetInfoChange( + const com::sun::star::beans::PropertySetInfoChangeEvent& evt ) const; + +public: + PersistentPropertySet( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rXSMgr, + PropertySetRegistry& rCreator, + const rtl::OUString& rKey ); + virtual ~PersistentPropertySet(); + + // XInterface + XINTERFACE_DECL() + + // XTypeProvider + XTYPEPROVIDER_DECL() + + // XServiceInfo + XSERVICEINFO_NOFACTORY_DECL() + + // XComponent + virtual void SAL_CALL + dispose() + throw( com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + addEventListener( const com::sun::star::uno::Reference< + com::sun::star::lang::XEventListener >& Listener ) + throw( com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + removeEventListener( const com::sun::star::uno::Reference< + com::sun::star::lang::XEventListener >& Listener ) + throw( com::sun::star::uno::RuntimeException ); + + // XPropertySet + virtual com::sun::star::uno::Reference< + com::sun::star::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo() + throw( com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + setPropertyValue( const rtl::OUString& aPropertyName, + const com::sun::star::uno::Any& aValue ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::beans::PropertyVetoException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException ); + virtual com::sun::star::uno::Any SAL_CALL + getPropertyValue( const rtl::OUString& PropertyName ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + addPropertyChangeListener( const rtl::OUString& aPropertyName, + const com::sun::star::uno::Reference< + com::sun::star::beans::XPropertyChangeListener >& xListener ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + removePropertyChangeListener( const rtl::OUString& aPropertyName, + const com::sun::star::uno::Reference< + com::sun::star::beans::XPropertyChangeListener >& aListener ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + addVetoableChangeListener( const rtl::OUString& PropertyName, + const com::sun::star::uno::Reference< + com::sun::star::beans::XVetoableChangeListener >& aListener ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + removeVetoableChangeListener( const rtl::OUString& PropertyName, + const com::sun::star::uno::Reference< + com::sun::star::beans::XVetoableChangeListener >& aListener ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException ); + + // XPersistentPropertySet + virtual com::sun::star::uno::Reference< + com::sun::star::ucb::XPropertySetRegistry > SAL_CALL + getRegistry() + throw( com::sun::star::uno::RuntimeException ); + virtual rtl::OUString SAL_CALL + getKey() + throw( com::sun::star::uno::RuntimeException ); + + // XNamed + virtual rtl::OUString SAL_CALL + getName() + throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + setName( const ::rtl::OUString& aName ) + throw( ::com::sun::star::uno::RuntimeException ); + + // XPropertyContainer + virtual void SAL_CALL + addProperty( const rtl::OUString& Name, + sal_Int16 Attributes, + const com::sun::star::uno::Any& DefaultValue ) + throw( com::sun::star::beans::PropertyExistException, + com::sun::star::beans::IllegalTypeException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + removeProperty( const rtl::OUString& Name ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::beans::NotRemoveableException, + com::sun::star::uno::RuntimeException ); + + // XPropertySetInfoChangeNotifier + virtual void SAL_CALL + addPropertySetInfoChangeListener( const com::sun::star::uno::Reference< + com::sun::star::beans::XPropertySetInfoChangeListener >& Listener ) + throw( com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + removePropertySetInfoChangeListener( const com::sun::star::uno::Reference< + com::sun::star::beans::XPropertySetInfoChangeListener >& Listener ) + throw( com::sun::star::uno::RuntimeException ); + + // XPropertyAccess + virtual com::sun::star::uno::Sequence< + com::sun::star::beans::PropertyValue > SAL_CALL + getPropertyValues() + throw( com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + setPropertyValues( const com::sun::star::uno::Sequence< + com::sun::star::beans::PropertyValue >& aProps ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::beans::PropertyVetoException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException ); + + // Non-interface methods. + PropertySetRegistry& getPropertySetRegistry(); + const rtl::OUString& getFullKey(); +}; + +#endif /* !_UCBSTORE_HXX */ diff --git a/ucb/source/inc/regexp.hxx b/ucb/source/inc/regexp.hxx new file mode 100644 index 000000000000..ddfed2994108 --- /dev/null +++ b/ucb/source/inc/regexp.hxx @@ -0,0 +1,84 @@ +/************************************************************************* + * + * 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 _UCB_REGEXP_HXX_ +#define _UCB_REGEXP_HXX_ + +#include <rtl/ustring.hxx> + +//============================================================================ +namespace ucb_impl { + +class Regexp +{ +public: + enum Kind + { + KIND_PREFIX, + KIND_AUTHORITY, + KIND_DOMAIN + }; + + inline bool operator ==(Regexp const & rOther) const; + + inline bool isDefault() const + { return m_eKind == KIND_PREFIX && m_aPrefix.getLength() == 0; } + + inline Kind getKind() const { return m_eKind; } + + bool matches(rtl::OUString const & rString, rtl::OUString * pTranslation, + bool * pTranslated) const; + + rtl::OUString getRegexp(bool bReverse) const; + + static Regexp parse(rtl::OUString const & rRegexp); + +private: + Kind m_eKind; + rtl::OUString m_aPrefix; + rtl::OUString m_aInfix; + rtl::OUString m_aReversePrefix; + bool m_bEmptyDomain; + bool m_bTranslation; + + inline Regexp(Kind eTheKind, rtl::OUString const & rThePrefix, + bool bTheEmptyDomain, rtl::OUString const & rTheInfix, + bool bTheTranslation, + rtl::OUString const & rTheReversePrefix); +}; + +inline bool Regexp::operator ==(Regexp const & rOther) const +{ + return m_eKind == rOther.m_eKind + && m_aPrefix == rOther.m_aPrefix + && m_aInfix == rOther.m_aInfix; +} + +} + +#endif // _UCB_REGEXP_HXX_ + diff --git a/ucb/source/inc/regexpmap.hxx b/ucb/source/inc/regexpmap.hxx new file mode 100644 index 000000000000..3bff4e619073 --- /dev/null +++ b/ucb/source/inc/regexpmap.hxx @@ -0,0 +1,188 @@ +/************************************************************************* + * + * 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 _UCB_REGEXPMAP_HXX_ +#define _UCB_REGEXPMAP_HXX_ + +#include <rtl/ustring.hxx> +#include <sal/types.h> + +namespace ucb_impl { + +template< typename Val > class RegexpMap; +template< typename Val > class RegexpMapIter; + +//============================================================================ +template< typename Val > +class RegexpMapEntry +{ +public: + inline RegexpMapEntry(rtl::OUString const & rTheRegexp, + Val * pTheValue): + m_aRegexp(rTheRegexp), m_pValue(pTheValue) {} + + rtl::OUString getRegexp() const { return m_aRegexp; } + + Val const & getValue() const { return *m_pValue; } + + Val & getValue() { return *m_pValue; } + +private: + rtl::OUString m_aRegexp; + Val * m_pValue; +}; + +//============================================================================ +template< typename Val > class RegexpMapIterImpl; + // MSC doesn't like this to be a private RegexpMapConstIter member + // class... + +template< typename Val > +class RegexpMapConstIter +{ + friend class RegexpMap< Val >; // to access m_pImpl, ctor + friend class RegexpMapIter< Val >; // to access m_pImpl, ctor + +public: + RegexpMapConstIter(); + + RegexpMapConstIter(RegexpMapConstIter const & rOther); + + ~RegexpMapConstIter(); + + RegexpMapConstIter & operator =(RegexpMapConstIter const & rOther); + + RegexpMapConstIter & operator ++(); + + RegexpMapConstIter operator ++(int); + + RegexpMapEntry< Val > const & operator *() const; + + RegexpMapEntry< Val > const * operator ->() const; + + bool equals(RegexpMapConstIter const & rOther) const; + // for free operator ==(), operator !=() + +private: + RegexpMapIterImpl< Val > * m_pImpl; + + RegexpMapConstIter(RegexpMapIterImpl< Val > * pTheImpl); +}; + +//============================================================================ +template< typename Val > +class RegexpMapIter: public RegexpMapConstIter< Val > +{ + friend class RegexpMap< Val >; // to access ctor + +public: + RegexpMapIter() {} + + RegexpMapIter & operator ++(); + + RegexpMapIter operator ++(int); + + RegexpMapEntry< Val > & operator *(); + + RegexpMapEntry< Val > const & operator *() const; + + RegexpMapEntry< Val > * operator ->(); + + RegexpMapEntry< Val > const * operator ->() const; + +private: + RegexpMapIter(RegexpMapIterImpl< Val > * pTheImpl); +}; + +//============================================================================ +template< typename Val > struct RegexpMapImpl; + // MSC doesn't like this to be a RegexpMap member class... + +template< typename Val > +class RegexpMap +{ +public: + typedef sal_uInt32 size_type; + typedef RegexpMapIter< Val > iterator; + typedef RegexpMapConstIter< Val > const_iterator; + + RegexpMap(); + + RegexpMap(RegexpMap const & rOther); + + ~RegexpMap(); + + RegexpMap & operator =(RegexpMap const & rOther); + + bool add(rtl::OUString const & rKey, Val const & rValue, bool bOverwrite, + rtl::OUString * pReverse = 0); + // throws com::sun::star::lang::IllegalArgumentException + + iterator find(rtl::OUString const & rKey, rtl::OUString * pReverse = 0); + // throws com::sun::star::lang::IllegalArgumentException + + void erase(iterator const & rPos); + + iterator begin(); + + const_iterator begin() const; + + iterator end(); + + const_iterator end() const; + + bool empty() const; + + size_type size() const; + + Val const * map(rtl::OUString const & rString, + rtl::OUString * pTranslation = 0, bool * pTranslated = 0) + const; + +private: + RegexpMapImpl< Val > * m_pImpl; +}; + +} + +//============================================================================ +template< typename Val > +inline bool operator ==(ucb_impl::RegexpMapConstIter< Val > const & rIter1, + ucb_impl::RegexpMapConstIter< Val > const & rIter2) +{ + return rIter1.equals(rIter2); +} + +template< typename Val > +inline bool operator !=(ucb_impl::RegexpMapConstIter< Val > const & rIter1, + ucb_impl::RegexpMapConstIter< Val > const & rIter2) +{ + return !rIter1.equals(rIter2); +} + +#endif // _UCB_REGEXPMAP_HXX_ + diff --git a/ucb/source/inc/regexpmap.tpt b/ucb/source/inc/regexpmap.tpt new file mode 100644 index 000000000000..9d4a7fb69c82 --- /dev/null +++ b/ucb/source/inc/regexpmap.tpt @@ -0,0 +1,564 @@ +/************************************************************************* + * + * 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 _UCB_REGEXPMAP_TPT_ +#define _UCB_REGEXPMAP_TPT_ + +#ifndef _UCB_REGEXPMAP_HXX_ +#include <regexpmap.hxx> +#endif + +#include <list> + +#ifndef _RTL_USTRING_HXX_ +#include <rtl/ustring.hxx> +#endif + +#ifndef _UCB_REGEXP_HXX_ +#include "regexp.hxx" +#endif + +using namespace ucb_impl; + +namespace ucb_impl { + +//============================================================================ + +template< typename Val > +struct Entry +{ + Regexp m_aRegexp; + Val m_aValue; + + inline Entry(Regexp const & rTheRegexp, Val const & rTheValue): + m_aRegexp(rTheRegexp), m_aValue(rTheValue) {} +}; + +//============================================================================ +template< typename Val > class List: public std::list< Entry< Val > > {}; + +//============================================================================ +// +// RegexpMapIterImpl +// +//============================================================================ + +template< typename Val > +class RegexpMapIterImpl +{ +public: + typedef RegexpMapImpl< Val > MapImpl; + typedef typename List< Val >::iterator ListIterator; + + // Solaris needs these for the ctor... + + inline RegexpMapIterImpl(); + + inline RegexpMapIterImpl(MapImpl * pTheMap, int nTheList, + ListIterator aTheIndex); + + RegexpMapIterImpl(RegexpMapImpl< Val > * pTheMap, bool bBegin); + + bool operator ==(RegexpMapIterImpl const & rOther) const; + + RegexpMapImpl< Val > const * getMap() const { return m_pMap; } + + int getList() const { return m_nList; } + + typename List< Val >::iterator const & getIndex() const { return m_aIndex; } + + void next(); + + RegexpMapEntry< Val > & get(); + +private: + mutable RegexpMapEntry< Val > m_aEntry; + typename List< Val >::iterator m_aIndex; + RegexpMapImpl< Val > * m_pMap; + int m_nList; + mutable bool m_bEntrySet; + + void setEntry() const; +}; + +} + +template< typename Val > +inline RegexpMapIterImpl< Val >::RegexpMapIterImpl(): + m_aEntry(rtl::OUString(), 0), + m_pMap(0), + m_nList(-1), + m_bEntrySet(false) +{} + +template< typename Val > +inline RegexpMapIterImpl< Val >::RegexpMapIterImpl(MapImpl * pTheMap, + int nTheList, + ListIterator aTheIndex): + m_aEntry(rtl::OUString(), 0), + m_aIndex(aTheIndex), + m_pMap(pTheMap), + m_nList(nTheList), + m_bEntrySet(false) +{} + +//============================================================================ +template< typename Val > +void RegexpMapIterImpl< Val >::setEntry() const +{ + if (!m_bEntrySet) + { + Entry< Val > const & rTheEntry + = m_nList == -1 ? *m_pMap->m_pDefault : *m_aIndex; + m_aEntry + = RegexpMapEntry< Val >(rTheEntry.m_aRegexp.getRegexp(false), + const_cast< Val * >(&rTheEntry.m_aValue)); + m_bEntrySet = true; + } +} + +//============================================================================ +template< typename Val > +RegexpMapIterImpl< Val >::RegexpMapIterImpl(RegexpMapImpl< Val > * pTheMap, + bool bBegin): + m_aEntry(rtl::OUString(), 0), + m_pMap(pTheMap), + m_bEntrySet(false) +{ + if (bBegin) + { + m_nList = -1; + m_aIndex = typename List< Val >::iterator(); + if (!m_pMap->m_pDefault) + next(); + } + else + { + m_nList = Regexp::KIND_DOMAIN; + m_aIndex = m_pMap->m_aList[Regexp::KIND_DOMAIN].end(); + } +} + +//============================================================================ +template< typename Val > +bool RegexpMapIterImpl< Val >::operator ==(RegexpMapIterImpl const & rOther) + const +{ + return m_pMap == rOther.m_pMap + && m_nList == rOther.m_nList + && m_aIndex == rOther.m_aIndex; +} + +//============================================================================ +template< typename Val > +void RegexpMapIterImpl< Val >::next() +{ + switch (m_nList) + { + case Regexp::KIND_DOMAIN: + if (m_aIndex == m_pMap->m_aList[m_nList].end()) + return; + default: + ++m_aIndex; + if (m_nList == Regexp::KIND_DOMAIN + || m_aIndex != m_pMap->m_aList[m_nList].end()) + break; + case -1: + do + { + ++m_nList; + m_aIndex = m_pMap->m_aList[m_nList].begin(); + } + while (m_nList < Regexp::KIND_DOMAIN + && m_aIndex == m_pMap->m_aList[m_nList].end()); + break; + } + m_bEntrySet = false; +} + +//============================================================================ +template< typename Val > +RegexpMapEntry< Val > & RegexpMapIterImpl< Val >::get() +{ + setEntry(); + return m_aEntry; +} + +//============================================================================ +// +// RegexpMapConstIter +// +//============================================================================ + +template< typename Val > +RegexpMapConstIter< Val >::RegexpMapConstIter(RegexpMapIterImpl< Val > * + pTheImpl): + m_pImpl(pTheImpl) +{} + +//============================================================================ +template< typename Val > +RegexpMapConstIter< Val >::RegexpMapConstIter(): + m_pImpl(new RegexpMapIterImpl< Val >) +{} + +//============================================================================ +template< typename Val > +RegexpMapConstIter< Val >::RegexpMapConstIter(RegexpMapConstIter const & + rOther): + m_pImpl(new RegexpMapIterImpl< Val >(*rOther.m_pImpl)) +{} + +//============================================================================ +template< typename Val > +RegexpMapConstIter< Val >::~RegexpMapConstIter() +{ + delete m_pImpl; +} + +//============================================================================ +template< typename Val > +RegexpMapConstIter< Val > & +RegexpMapConstIter< Val >::operator =(RegexpMapConstIter const & rOther) +{ + *m_pImpl = *rOther.m_pImpl; + return *this; +} + +//============================================================================ +template< typename Val > +RegexpMapConstIter< Val > & RegexpMapConstIter< Val >::operator ++() +{ + m_pImpl->next(); + return *this; +} + +//============================================================================ +template< typename Val > +RegexpMapConstIter< Val > RegexpMapConstIter< Val >::operator ++(int) +{ + RegexpMapConstIter aTemp(*this); + m_pImpl->next(); + return aTemp; +} + +//============================================================================ +template< typename Val > +RegexpMapEntry< Val > const & RegexpMapConstIter< Val >::operator *() const +{ + return m_pImpl->get(); +} + +//============================================================================ +template< typename Val > +RegexpMapEntry< Val > const * RegexpMapConstIter< Val >::operator ->() const +{ + return &m_pImpl->get(); +} + +//============================================================================ +template< typename Val > +bool RegexpMapConstIter< Val >::equals(RegexpMapConstIter const & rOther) + const +{ + return *m_pImpl == *rOther.m_pImpl; +} + +//============================================================================ +// +// RegexpMapIter +// +//============================================================================ + +template< typename Val > +RegexpMapIter< Val >::RegexpMapIter(RegexpMapIterImpl< Val > * pTheImpl): + RegexpMapConstIter< Val >(pTheImpl) +{} + +//============================================================================ +template< typename Val > +RegexpMapIter< Val > & RegexpMapIter< Val >::operator ++() +{ + this->m_pImpl->next(); + return *this; +} + +//============================================================================ +template< typename Val > +RegexpMapIter< Val > RegexpMapIter< Val >::operator ++(int) +{ + RegexpMapIter aTemp(*this); + this->m_pImpl->next(); + return aTemp; +} + +//============================================================================ +template< typename Val > +RegexpMapEntry< Val > & RegexpMapIter< Val >::operator *() +{ + return this->m_pImpl->get(); +} + +//============================================================================ +template< typename Val > +RegexpMapEntry< Val > const & RegexpMapIter< Val >::operator *() const +{ + return this->m_pImpl->get(); +} + +//============================================================================ +template< typename Val > +RegexpMapEntry< Val > * RegexpMapIter< Val >::operator ->() +{ + return &this->m_pImpl->get(); +} + +//============================================================================ +template< typename Val > +RegexpMapEntry< Val > const * RegexpMapIter< Val >::operator ->() const +{ + return &this->m_pImpl->get(); +} + +//============================================================================ +// +// RegexpMap +// +//============================================================================ + +namespace ucb_impl { + +template< typename Val > +struct RegexpMapImpl +{ + List< Val > m_aList[Regexp::KIND_DOMAIN + 1]; + Entry< Val > * m_pDefault; + + RegexpMapImpl(): m_pDefault(0) {} + + ~RegexpMapImpl() { delete m_pDefault; } +}; + +} + +//============================================================================ +template< typename Val > +RegexpMap< Val >::RegexpMap(): + m_pImpl(new RegexpMapImpl< Val >) +{} + +//============================================================================ +template< typename Val > +RegexpMap< Val >::RegexpMap(RegexpMap const & rOther): + m_pImpl(new RegexpMapImpl< Val >(*rOther.m_pImpl)) +{} + +//============================================================================ +template< typename Val > +RegexpMap< Val >::~RegexpMap() +{ + delete m_pImpl; +} + +//============================================================================ +template< typename Val > +RegexpMap< Val > & RegexpMap< Val >::operator =(RegexpMap const & rOther) +{ + *m_pImpl = *rOther.m_pImpl; + return *this; +} + +//============================================================================ +template< typename Val > +bool RegexpMap< Val >::add(rtl::OUString const & rKey, Val const & rValue, + bool bOverwrite, rtl::OUString * pReverse) +{ + Regexp aRegexp(Regexp::parse(rKey)); + + if (aRegexp.isDefault()) + { + if (m_pImpl->m_pDefault) + { + if (!bOverwrite) + return false; + delete m_pImpl->m_pDefault; + } + m_pImpl->m_pDefault = new Entry< Val >(aRegexp, rValue); + } + else + { + List< Val > & rTheList = m_pImpl->m_aList[aRegexp.getKind()]; + + typename List< Val >::iterator aEnd(rTheList.end()); + for (typename List< Val >::iterator aIt(rTheList.begin()); aIt != aEnd; ++aIt) + { + if (aIt->m_aRegexp == aRegexp) + { + if (bOverwrite) + { + rTheList.erase(aIt); + break; + } + else + return false; + } + } + + rTheList.push_back(Entry< Val >(aRegexp, rValue)); + } + + if (pReverse) + *pReverse = aRegexp.getRegexp(true); + + return true; +} + +//============================================================================ +template< typename Val > +typename RegexpMap< Val >::iterator RegexpMap< Val >::find(rtl::OUString const & rKey, + rtl::OUString * pReverse) +{ + Regexp aRegexp(Regexp::parse(rKey)); + + if (pReverse) + *pReverse = aRegexp.getRegexp(true); + + if (aRegexp.isDefault()) + { + if (m_pImpl->m_pDefault) + return RegexpMapIter< Val >(new RegexpMapIterImpl< Val >(m_pImpl, + true)); + } + else + { + List< Val > & rTheList = m_pImpl->m_aList[aRegexp.getKind()]; + + typename List< Val > ::iterator aEnd(rTheList.end()); + for (typename List< Val >::iterator aIt(rTheList.begin()); aIt != aEnd; ++aIt) + if (aIt->m_aRegexp == aRegexp) + return RegexpMapIter< Val >(new RegexpMapIterImpl< Val >( + m_pImpl, + aRegexp.getKind(), aIt)); + } + + return RegexpMapIter< Val >(new RegexpMapIterImpl< Val >(m_pImpl, false)); +} + +//============================================================================ +template< typename Val > +void RegexpMap< Val >::erase(iterator const & rPos) +{ + if (rPos.m_pImpl->getMap() == m_pImpl) + { + if (rPos.m_pImpl->getList() == -1) + { + if (m_pImpl->m_pDefault) + { + delete m_pImpl->m_pDefault; + m_pImpl->m_pDefault = 0; + } + } + else + m_pImpl->m_aList[rPos.m_pImpl->getList()]. + erase(rPos.m_pImpl->getIndex()); + } +} + +//============================================================================ +template< typename Val > +typename RegexpMap< Val >::iterator RegexpMap< Val >::begin() +{ + return RegexpMapIter< Val >(new RegexpMapIterImpl< Val >(m_pImpl, true)); +} + +//============================================================================ +template< typename Val > +typename RegexpMap< Val >::const_iterator RegexpMap< Val >::begin() const +{ + return RegexpMapConstIter< Val >(new RegexpMapIterImpl< Val >(m_pImpl, + true)); +} + +//============================================================================ +template< typename Val > +typename RegexpMap< Val >::iterator RegexpMap< Val >::end() +{ + return RegexpMapIter< Val >(new RegexpMapIterImpl< Val >(m_pImpl, false)); +} + +//============================================================================ +template< typename Val > +typename RegexpMap< Val >::const_iterator RegexpMap< Val >::end() const +{ + return RegexpMapConstIter< Val >(new RegexpMapIterImpl< Val >(m_pImpl, + false)); +} + +//============================================================================ +template< typename Val > +bool RegexpMap< Val >::empty() const +{ + return !m_pImpl->m_pDefault + && m_pImpl->m_aList[Regexp::KIND_PREFIX].empty() + && m_pImpl->m_aList[Regexp::KIND_AUTHORITY].empty() + && m_pImpl->m_aList[Regexp::KIND_DOMAIN].empty(); +} + +//============================================================================ +template< typename Val > +typename RegexpMap< Val >::size_type RegexpMap< Val >::size() const +{ + return (m_pImpl->m_pDefault ? 1 : 0) + + m_pImpl->m_aList[Regexp::KIND_PREFIX].size() + + m_pImpl->m_aList[Regexp::KIND_AUTHORITY].size() + + m_pImpl->m_aList[Regexp::KIND_DOMAIN].size(); +} + +//============================================================================ +template< typename Val > +Val const * RegexpMap< Val >::map(rtl::OUString const & rString, + rtl::OUString * pTranslation, + bool * pTranslated) const +{ + for (int n = Regexp::KIND_DOMAIN; n >= Regexp::KIND_PREFIX; --n) + { + List< Val > const & rTheList = m_pImpl->m_aList[n]; + + typename List< Val >::const_iterator aEnd(rTheList.end()); + for (typename List< Val >::const_iterator aIt(rTheList.begin()); aIt != aEnd; + ++aIt) + if (aIt->m_aRegexp.matches(rString, pTranslation, pTranslated)) + return &aIt->m_aValue; + } + if (m_pImpl->m_pDefault + && m_pImpl->m_pDefault->m_aRegexp.matches(rString, pTranslation, + pTranslated)) + return &m_pImpl->m_pDefault->m_aValue; + return 0; +} + +#endif // _UCB_REGEXPMAP_TPT_ diff --git a/ucb/source/regexp/makefile.mk b/ucb/source/regexp/makefile.mk new file mode 100644 index 000000000000..e748f054ea13 --- /dev/null +++ b/ucb/source/regexp/makefile.mk @@ -0,0 +1,41 @@ +#************************************************************************* +# +# 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=ucb +TARGET=regexp +AUTOSEG=true +ENABLE_EXCEPTIONS=true + +.INCLUDE : settings.mk +.IF "$(L10N_framework)"=="" + +SLOFILES=\ + $(SLO)$/regexp.obj +.ENDIF # L10N_framework + +.INCLUDE : target.mk diff --git a/ucb/source/regexp/regexp.cxx b/ucb/source/regexp/regexp.cxx new file mode 100644 index 000000000000..f784532d31b3 --- /dev/null +++ b/ucb/source/regexp/regexp.cxx @@ -0,0 +1,473 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" +#include <regexp.hxx> + +#include <cstddef> + +#include "osl/diagnose.h" +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <rtl/ustrbuf.hxx> +#include <rtl/ustring.hxx> + +namespace unnamed_ucb_regexp {} using namespace unnamed_ucb_regexp; + // unnamed namespaces don't work well yet... + +using namespace com::sun::star; +using namespace ucb_impl; + +//============================================================================ +// +// Regexp +// +//============================================================================ + +inline Regexp::Regexp(Kind eTheKind, rtl::OUString const & rThePrefix, + bool bTheEmptyDomain, rtl::OUString const & rTheInfix, + bool bTheTranslation, + rtl::OUString const & rTheReversePrefix): + m_eKind(eTheKind), + m_aPrefix(rThePrefix), + m_aInfix(rTheInfix), + m_aReversePrefix(rTheReversePrefix), + m_bEmptyDomain(bTheEmptyDomain), + m_bTranslation(bTheTranslation) +{ + OSL_ASSERT(m_eKind == KIND_DOMAIN + || !m_bEmptyDomain && m_aInfix.getLength() == 0); + OSL_ASSERT(m_bTranslation || m_aReversePrefix.getLength() == 0); +} + +//============================================================================ +namespace unnamed_ucb_regexp { + +bool matchStringIgnoreCase(sal_Unicode const ** pBegin, + sal_Unicode const * pEnd, + rtl::OUString const & rString) +{ + sal_Unicode const * p = *pBegin; + + sal_Unicode const * q = rString.getStr(); + sal_Unicode const * qEnd = q + rString.getLength(); + + if (pEnd - p < qEnd - q) + return false; + + while (q != qEnd) + { + sal_Unicode c1 = *p++; + sal_Unicode c2 = *q++; + if (c1 >= 'a' && c1 <= 'z') + c1 -= 'a' - 'A'; + if (c2 >= 'a' && c2 <= 'z') + c2 -= 'a' - 'A'; + if (c1 != c2) + return false; + } + + *pBegin = p; + return true; +} + +} + +bool Regexp::matches(rtl::OUString const & rString, + rtl::OUString * pTranslation, bool * pTranslated) const +{ + sal_Unicode const * pBegin = rString.getStr(); + sal_Unicode const * pEnd = pBegin + rString.getLength(); + + bool bMatches = false; + + sal_Unicode const * p = pBegin; + if (matchStringIgnoreCase(&p, pEnd, m_aPrefix)) + { + sal_Unicode const * pBlock1Begin = p; + sal_Unicode const * pBlock1End = pEnd; + + sal_Unicode const * pBlock2Begin = 0; + sal_Unicode const * pBlock2End = 0; + + switch (m_eKind) + { + case KIND_PREFIX: + bMatches = true; + break; + + case KIND_AUTHORITY: + bMatches = p == pEnd || *p == '/' || *p == '?' || *p == '#'; + break; + + case KIND_DOMAIN: + if (!m_bEmptyDomain) + { + if (p == pEnd || *p == '/' || *p == '?' || *p == '#') + break; + ++p; + } + for (;;) + { + sal_Unicode const * q = p; + if (matchStringIgnoreCase(&q, pEnd, m_aInfix) + && (q == pEnd || *q == '/' || *q == '?' || *q == '#')) + { + bMatches = true; + pBlock1End = p; + pBlock2Begin = q; + pBlock2End = pEnd; + break; + } + + if (p == pEnd) + break; + + sal_Unicode c = *p++; + if (c == '/' || c == '?' || c == '#') + break; + } + break; + } + + if (bMatches) + { + if (m_bTranslation) + { + if (pTranslation) + { + rtl::OUStringBuffer aBuffer(m_aReversePrefix); + aBuffer.append(pBlock1Begin, pBlock1End - pBlock1Begin); + aBuffer.append(m_aInfix); + aBuffer.append(pBlock2Begin, pBlock2End - pBlock2Begin); + *pTranslation = aBuffer.makeStringAndClear(); + } + if (pTranslated) + *pTranslated = true; + } + else + { + if (pTranslation) + *pTranslation = rString; + if (pTranslated) + *pTranslated = false; + } + } + } + + return bMatches; +} + +//============================================================================ +namespace unnamed_ucb_regexp { + +inline bool isAlpha(sal_Unicode c) +{ + return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); +} + +inline bool isDigit(sal_Unicode c) +{ + return c >= '0' && c <= '9'; +} + +bool isScheme(rtl::OUString const & rString, bool bColon) +{ + // Return true if rString matches <scheme> (plus a trailing ":" if bColon + // is true) from RFC 2396: + sal_Unicode const * p = rString.getStr(); + sal_Unicode const * pEnd = p + rString.getLength(); + if (p != pEnd && isAlpha(*p)) + for (++p;;) + { + if (p == pEnd) + return !bColon; + sal_Unicode c = *p++; + if (!(isAlpha(c) || isDigit(c) + || c == '+' || c == '-' || c == '.')) + return bColon && c == ':' && p == pEnd; + } + return false; +} + +void appendStringLiteral(rtl::OUStringBuffer * pBuffer, + rtl::OUString const & rString) +{ + OSL_ASSERT(pBuffer); + + pBuffer->append(sal_Unicode('"')); + sal_Unicode const * p = rString.getStr(); + sal_Unicode const * pEnd = p + rString.getLength(); + while (p != pEnd) + { + sal_Unicode c = *p++; + if (c == '"' || c == '\\') + pBuffer->append(sal_Unicode('\\')); + pBuffer->append(c); + } + pBuffer->append(sal_Unicode('"')); +} + +} + +rtl::OUString Regexp::getRegexp(bool bReverse) const +{ + if (m_bTranslation) + { + rtl::OUStringBuffer aBuffer; + if (bReverse) + { + if (m_aReversePrefix.getLength() != 0) + appendStringLiteral(&aBuffer, m_aReversePrefix); + } + else + { + if (m_aPrefix.getLength() != 0) + appendStringLiteral(&aBuffer, m_aPrefix); + } + switch (m_eKind) + { + case KIND_PREFIX: + aBuffer.appendAscii(RTL_CONSTASCII_STRINGPARAM("(.*)")); + break; + + case KIND_AUTHORITY: + aBuffer. + appendAscii(RTL_CONSTASCII_STRINGPARAM("(([/?#].*)?)")); + break; + + case KIND_DOMAIN: + aBuffer.appendAscii(RTL_CONSTASCII_STRINGPARAM("([^/?#]")); + aBuffer.append(sal_Unicode(m_bEmptyDomain ? '*' : '+')); + if (m_aInfix.getLength() != 0) + appendStringLiteral(&aBuffer, m_aInfix); + aBuffer. + appendAscii(RTL_CONSTASCII_STRINGPARAM("([/?#].*)?)")); + break; + } + aBuffer.appendAscii(RTL_CONSTASCII_STRINGPARAM("->")); + if (bReverse) + { + if (m_aPrefix.getLength() != 0) + appendStringLiteral(&aBuffer, m_aPrefix); + } + else + { + if (m_aReversePrefix.getLength() != 0) + appendStringLiteral(&aBuffer, m_aReversePrefix); + } + aBuffer.appendAscii(RTL_CONSTASCII_STRINGPARAM("\\1")); + return aBuffer.makeStringAndClear(); + } + else if (m_eKind == KIND_PREFIX && isScheme(m_aPrefix, true)) + return m_aPrefix.copy(0, m_aPrefix.getLength() - 1); + else + { + rtl::OUStringBuffer aBuffer; + if (m_aPrefix.getLength() != 0) + appendStringLiteral(&aBuffer, m_aPrefix); + switch (m_eKind) + { + case KIND_PREFIX: + aBuffer.appendAscii(RTL_CONSTASCII_STRINGPARAM(".*")); + break; + + case KIND_AUTHORITY: + aBuffer.appendAscii(RTL_CONSTASCII_STRINGPARAM("([/?#].*)?")); + break; + + case KIND_DOMAIN: + aBuffer.appendAscii(RTL_CONSTASCII_STRINGPARAM("[^/?#]")); + aBuffer.append(sal_Unicode(m_bEmptyDomain ? '*' : '+')); + if (m_aInfix.getLength() != 0) + appendStringLiteral(&aBuffer, m_aInfix); + aBuffer.appendAscii(RTL_CONSTASCII_STRINGPARAM("([/?#].*)?")); + break; + } + return aBuffer.makeStringAndClear(); + } +} + +//============================================================================ +namespace unnamed_ucb_regexp { + +bool matchString(sal_Unicode const ** pBegin, sal_Unicode const * pEnd, + sal_Char const * pString, size_t nStringLength) +{ + sal_Unicode const * p = *pBegin; + + sal_uChar const * q = reinterpret_cast< sal_uChar const * >(pString); + sal_uChar const * qEnd = q + nStringLength; + + if (pEnd - p < qEnd - q) + return false; + + while (q != qEnd) + { + sal_Unicode c1 = *p++; + sal_Unicode c2 = *q++; + if (c1 != c2) + return false; + } + + *pBegin = p; + return true; +} + +bool scanStringLiteral(sal_Unicode const ** pBegin, sal_Unicode const * pEnd, + rtl::OUString * pString) +{ + sal_Unicode const * p = *pBegin; + + if (p == pEnd || *p++ != '"') + return false; + + rtl::OUStringBuffer aBuffer; + for (;;) + { + if (p == pEnd) + return false; + sal_Unicode c = *p++; + if (c == '"') + break; + if (c == '\\') + { + if (p == pEnd) + return false; + c = *p++; + if (c != '"' && c != '\\') + return false; + } + aBuffer.append(c); + } + + *pBegin = p; + *pString = aBuffer.makeStringAndClear(); + return true; +} + +} + +Regexp Regexp::parse(rtl::OUString const & rRegexp) +{ + // Detect an input of '<scheme>' as an abbreviation of '"<scheme>:".*' + // where <scheme> is as defined in RFC 2396: + if (isScheme(rRegexp, false)) + return Regexp(Regexp::KIND_PREFIX, + rRegexp + + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(":")), + false, + rtl::OUString(), + false, + rtl::OUString()); + + sal_Unicode const * p = rRegexp.getStr(); + sal_Unicode const * pEnd = p + rRegexp.getLength(); + + rtl::OUString aPrefix; + scanStringLiteral(&p, pEnd, &aPrefix); + + if (p == pEnd) + throw lang::IllegalArgumentException(); + + if (matchString(&p, pEnd, RTL_CONSTASCII_STRINGPARAM(".*"))) + { + if (p != pEnd) + throw lang::IllegalArgumentException(); + + return Regexp(Regexp::KIND_PREFIX, aPrefix, false, rtl::OUString(), + false, rtl::OUString()); + } + else if (matchString(&p, pEnd, RTL_CONSTASCII_STRINGPARAM("(.*)->"))) + { + rtl::OUString aReversePrefix; + scanStringLiteral(&p, pEnd, &aReversePrefix); + + if (!matchString(&p, pEnd, RTL_CONSTASCII_STRINGPARAM("\\1")) + || p != pEnd) + throw lang::IllegalArgumentException(); + + return Regexp(Regexp::KIND_PREFIX, aPrefix, false, rtl::OUString(), + true, aReversePrefix); + } + else if (matchString(&p, pEnd, RTL_CONSTASCII_STRINGPARAM("([/?#].*)?"))) + { + if (p != pEnd) + throw lang::IllegalArgumentException(); + + return Regexp(Regexp::KIND_AUTHORITY, aPrefix, false, rtl::OUString(), + false, rtl::OUString()); + } + else if (matchString(&p, pEnd, + RTL_CONSTASCII_STRINGPARAM("(([/?#].*)?)->"))) + { + rtl::OUString aReversePrefix; + if (!(scanStringLiteral(&p, pEnd, &aReversePrefix) + && matchString(&p, pEnd, RTL_CONSTASCII_STRINGPARAM("\\1")) + && p == pEnd)) + throw lang::IllegalArgumentException(); + + return Regexp(Regexp::KIND_AUTHORITY, aPrefix, false, rtl::OUString(), + true, aReversePrefix); + } + else + { + bool bOpen = false; + if (p != pEnd && *p == '(') + { + ++p; + bOpen = true; + } + + if (!matchString(&p, pEnd, RTL_CONSTASCII_STRINGPARAM("[^/?#]"))) + throw lang::IllegalArgumentException(); + + if (p == pEnd || (*p != '*' && *p != '+')) + throw lang::IllegalArgumentException(); + bool bEmptyDomain = *p++ == '*'; + + rtl::OUString aInfix; + scanStringLiteral(&p, pEnd, &aInfix); + + if (!matchString(&p, pEnd, RTL_CONSTASCII_STRINGPARAM("([/?#].*)?"))) + throw lang::IllegalArgumentException(); + + rtl::OUString aReversePrefix; + if (bOpen + && !(matchString(&p, pEnd, RTL_CONSTASCII_STRINGPARAM(")->")) + && scanStringLiteral(&p, pEnd, &aReversePrefix) + && matchString(&p, pEnd, RTL_CONSTASCII_STRINGPARAM("\\1")))) + throw lang::IllegalArgumentException(); + + if (p != pEnd) + throw lang::IllegalArgumentException(); + + return Regexp(Regexp::KIND_DOMAIN, aPrefix, bEmptyDomain, aInfix, + bOpen, aReversePrefix); + } +} + diff --git a/ucb/source/sorter/makefile.mk b/ucb/source/sorter/makefile.mk new file mode 100644 index 000000000000..008e39b4bce3 --- /dev/null +++ b/ucb/source/sorter/makefile.mk @@ -0,0 +1,71 @@ +#************************************************************************* +# +# 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=ucb +TARGET=srtrs +ENABLE_EXCEPTIONS=TRUE + +# Version +UCB_MAJOR=1 + +.INCLUDE: settings.mk +.IF "$(L10N_framework)"=="" + +SLOFILES=\ + $(SLO)$/sortdynres.obj \ + $(SLO)$/sortresult.obj \ + $(SLO)$/sortmain.obj + +LIB1TARGET=$(SLB)$/_$(TARGET).lib +LIB1OBJFILES=$(SLOFILES) + +SHL1TARGET=$(TARGET)$(UCB_MAJOR) +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +SHL1STDLIBS=\ + $(CPPUHELPERLIB) \ + $(CPPULIB) \ + $(SALLIB) + +SHL1LIBS=$(LIB1TARGET) +SHL1IMPLIB=i$(TARGET) + +SHL1VERSIONMAP=$(SOLARENV)/src/component.map + +DEF1NAME=$(SHL1TARGET) +.ENDIF # L10N_framework + +.INCLUDE: target.mk + + +ALLTAR : $(MISC)/srtrs1.component + +$(MISC)/srtrs1.component .ERRREMOVE : $(SOLARENV)/bin/createcomponent.xslt \ + srtrs1.component + $(XSLTPROC) --nonet --stringparam uri \ + '$(COMPONENTPREFIX_BASIS_NATIVE)$(SHL1TARGETN:f)' -o $@ \ + $(SOLARENV)/bin/createcomponent.xslt srtrs1.component diff --git a/ucb/source/sorter/sortdynres.cxx b/ucb/source/sorter/sortdynres.cxx new file mode 100644 index 000000000000..2fc38ee46a42 --- /dev/null +++ b/ucb/source/sorter/sortdynres.cxx @@ -0,0 +1,628 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +#include <vector> +#include <sortdynres.hxx> +#include <cppuhelper/interfacecontainer.hxx> +#include <com/sun/star/ucb/ContentResultSetCapability.hpp> +#include <com/sun/star/ucb/ListActionType.hpp> +#include <com/sun/star/ucb/WelcomeDynamicResultSetStruct.hpp> +#include <com/sun/star/ucb/XCachedDynamicResultSetStubFactory.hpp> +#include <com/sun/star/ucb/XSourceInitialization.hpp> + +//----------------------------------------------------------------------------- +using namespace com::sun::star::beans; +using namespace com::sun::star::lang; +using namespace com::sun::star::sdbc; +using namespace com::sun::star::ucb; +using namespace com::sun::star::uno; +using namespace cppu; +using namespace rtl; + +//========================================================================= + +// The mutex to synchronize access to containers. +static osl::Mutex& getContainerMutex() +{ + static osl::Mutex* pMutex = NULL; + if( !pMutex ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + if( !pMutex ) + { + static osl::Mutex aMutex; + pMutex = &aMutex; + } + } + + return *pMutex; +} + +//========================================================================= +// +// SortedDynamicResultSet +// +//========================================================================= + +SortedDynamicResultSet::SortedDynamicResultSet( + const Reference < XDynamicResultSet > &xOriginal, + const Sequence < NumberedSortingInfo > &aOptions, + const Reference < XAnyCompareFactory > &xCompFac, + const Reference < XMultiServiceFactory > &xSMgr ) +{ + mpDisposeEventListeners = NULL; + mpOwnListener = new SortedDynamicResultSetListener( this ); + + mxOwnListener = Reference< XDynamicResultSetListener >( mpOwnListener ); + + mxOriginal = xOriginal; + maOptions = aOptions; + mxCompFac = xCompFac; + mxSMgr = xSMgr; + + mpOne = NULL; + mpTwo = NULL; + + mbGotWelcome = sal_False; + mbUseOne = sal_True; + mbStatic = sal_False; +} + +//-------------------------------------------------------------------------- +SortedDynamicResultSet::~SortedDynamicResultSet() +{ + mpOwnListener->impl_OwnerDies(); + mxOwnListener.clear(); + + delete mpDisposeEventListeners; + + mxOne.clear(); + mxTwo.clear(); + mxOriginal.clear(); + + mpOne = NULL; + mpTwo = NULL; +} + +//-------------------------------------------------------------------------- +// XInterface methods. +//-------------------------------------------------------------------------- + +XINTERFACE_IMPL_4( SortedDynamicResultSet, + XTypeProvider, + XServiceInfo, + XComponent, /* base class of XDynamicResultSet */ + XDynamicResultSet ); + +//-------------------------------------------------------------------------- +// XTypeProvider methods. +//-------------------------------------------------------------------------- + +XTYPEPROVIDER_IMPL_3( SortedDynamicResultSet, + XTypeProvider, + XServiceInfo, + XDynamicResultSet ); + +//-------------------------------------------------------------------------- +// XServiceInfo methods. +//-------------------------------------------------------------------------- + +XSERVICEINFO_NOFACTORY_IMPL_1( SortedDynamicResultSet, + OUString::createFromAscii( + "com.sun.star.comp.ucb.SortedDynamicResultSet" ), + OUString::createFromAscii( + DYNAMIC_RESULTSET_SERVICE_NAME ) ); + +//-------------------------------------------------------------------------- +// XComponent methods. +//-------------------------------------------------------------------------- +void SAL_CALL SortedDynamicResultSet::dispose() + throw( RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( mpDisposeEventListeners && mpDisposeEventListeners->getLength() ) + { + EventObject aEvt; + aEvt.Source = static_cast< XComponent * >( this ); + mpDisposeEventListeners->disposeAndClear( aEvt ); + } + + mxOne.clear(); + mxTwo.clear(); + mxOriginal.clear(); + + mpOne = NULL; + mpTwo = NULL; + mbUseOne = sal_True; +} + +//-------------------------------------------------------------------------- +void SAL_CALL SortedDynamicResultSet::addEventListener( + const Reference< XEventListener >& Listener ) + throw( RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( !mpDisposeEventListeners ) + mpDisposeEventListeners = + new OInterfaceContainerHelper( getContainerMutex() ); + + mpDisposeEventListeners->addInterface( Listener ); +} + +//-------------------------------------------------------------------------- +void SAL_CALL SortedDynamicResultSet::removeEventListener( + const Reference< XEventListener >& Listener ) + throw( RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( mpDisposeEventListeners ) + mpDisposeEventListeners->removeInterface( Listener ); +} + +//-------------------------------------------------------------------------- +// XDynamicResultSet methods. +// ------------------------------------------------------------------------------ +Reference< XResultSet > SAL_CALL +SortedDynamicResultSet::getStaticResultSet() + throw( ListenerAlreadySetException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( mxListener.is() ) + throw ListenerAlreadySetException(); + + mbStatic = sal_True; + + if ( mxOriginal.is() ) + { + mpOne = new SortedResultSet( mxOriginal->getStaticResultSet() ); + mxOne = mpOne; + mpOne->Initialize( maOptions, mxCompFac ); + } + + return mxOne; +} + +// ------------------------------------------------------------------------------ +void SAL_CALL +SortedDynamicResultSet::setListener( const Reference< XDynamicResultSetListener >& Listener ) + throw( ListenerAlreadySetException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( mxListener.is() ) + throw ListenerAlreadySetException(); + + addEventListener( Reference< XEventListener >::query( Listener ) ); + + mxListener = Listener; + + if ( mxOriginal.is() ) + mxOriginal->setListener( mxOwnListener ); +} + +// ------------------------------------------------------------------------------ +void SAL_CALL +SortedDynamicResultSet::connectToCache( + const Reference< XDynamicResultSet > & xCache ) + throw( ListenerAlreadySetException, + AlreadyInitializedException, + ServiceNotFoundException, + RuntimeException ) +{ + if( mxListener.is() ) + throw ListenerAlreadySetException(); + + if( mbStatic ) + throw ListenerAlreadySetException(); + + Reference< XSourceInitialization > xTarget( xCache, UNO_QUERY ); + if( xTarget.is() && mxSMgr.is() ) + { + Reference< XCachedDynamicResultSetStubFactory > xStubFactory; + try + { + xStubFactory = Reference< XCachedDynamicResultSetStubFactory >( + mxSMgr->createInstance( + OUString::createFromAscii( + "com.sun.star.ucb.CachedDynamicResultSetStubFactory" ) ), + UNO_QUERY ); + } + catch ( Exception const & ) + { + } + + if( xStubFactory.is() ) + { + xStubFactory->connectToCache( + this, xCache, Sequence< NumberedSortingInfo > (), NULL ); + return; + } + } + throw ServiceNotFoundException(); +} + +// ------------------------------------------------------------------------------ +sal_Int16 SAL_CALL +SortedDynamicResultSet::getCapabilities() + throw( RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + sal_Int16 nCaps = 0; + + if ( mxOriginal.is() ) + nCaps = mxOriginal->getCapabilities(); + + nCaps |= ContentResultSetCapability::SORTED; + + return nCaps; +} + +//-------------------------------------------------------------------------- +// XDynamicResultSetListener methods. +// ------------------------------------------------------------------------------ + +/** In the first notify-call the listener gets the two + <type>XResultSet</type>s and has to hold them. The <type>XResultSet</type>s + are implementations of the service <type>ContentResultSet</type>. + + <p>The notified new <type>XResultSet</type> will stay valid after returning + notification. The old one will become invalid after returning notification. + + <p>While in notify-call the listener is allowed to read old and new version, + except in the first call, where only the new Resultset is valid. + + <p>The Listener is allowed to blockade this call, until he really want to go + to the new version. The only situation, where the listener has to return the + update call at once is, while he disposes his broadcaster or while he is + removing himsef as listener (otherwise you deadlock)!!! +*/ +void SAL_CALL +SortedDynamicResultSet::impl_notify( const ListEvent& Changes ) + throw( RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + sal_Bool bHasNew = sal_False; + sal_Bool bHasModified = sal_False; + + SortedResultSet *pCurSet = NULL; + + // mxNew und mxOld vertauschen und anschliessend die Tabellen von Old + // nach New kopieren + if ( mbGotWelcome ) + { + if ( mbUseOne ) + { + mbUseOne = sal_False; + mpTwo->CopyData( mpOne ); + pCurSet = mpTwo; + } + else + { + mbUseOne = sal_True; + mpOne->CopyData( mpTwo ); + pCurSet = mpOne; + } + } + + Any aRet; + + try { + aRet = pCurSet->getPropertyValue( OUString::createFromAscii( "IsRowCountFinal" ) ); + } + catch ( UnknownPropertyException ) {} + catch ( WrappedTargetException ) {} + + long nOldCount = pCurSet->GetCount(); + sal_Bool bWasFinal = false; + + aRet >>= bWasFinal; + + // handle the actions in the list + for ( long i=0; i<Changes.Changes.getLength(); i++ ) + { + const ListAction aAction = Changes.Changes[i]; + switch ( aAction.ListActionType ) + { + case ListActionType::WELCOME: + { + WelcomeDynamicResultSetStruct aWelcome; + if ( aAction.ActionInfo >>= aWelcome ) + { + mpTwo = new SortedResultSet( aWelcome.Old ); + mxTwo = mpTwo; + mpOne = new SortedResultSet( aWelcome.New ); + mxOne = mpOne; + mpOne->Initialize( maOptions, mxCompFac ); + mbGotWelcome = sal_True; + mbUseOne = sal_True; + pCurSet = mpOne; + + aWelcome.Old = mxTwo; + aWelcome.New = mxOne; + + ListAction *pWelcomeAction = new ListAction; + pWelcomeAction->ActionInfo <<= aWelcome; + pWelcomeAction->Position = 0; + pWelcomeAction->Count = 0; + pWelcomeAction->ListActionType = ListActionType::WELCOME; + + maActions.Insert( pWelcomeAction ); + } + else + { + // throw RuntimeException(); + } + break; + } + case ListActionType::INSERTED: + { + pCurSet->InsertNew( aAction.Position, aAction.Count ); + bHasNew = sal_True; + break; + } + case ListActionType::REMOVED: + { + pCurSet->Remove( aAction.Position, + aAction.Count, + &maActions ); + break; + } + case ListActionType::MOVED: + { + long nOffset = 0; + if ( aAction.ActionInfo >>= nOffset ) + { + pCurSet->Move( aAction.Position, + aAction.Count, + nOffset ); + } + break; + } + case ListActionType::PROPERTIES_CHANGED: + { + pCurSet->SetChanged( aAction.Position, aAction.Count ); + bHasModified = sal_True; + break; + } + default: break; + } + } + + if ( bHasModified ) + pCurSet->ResortModified( &maActions ); + + if ( bHasNew ) + pCurSet->ResortNew( &maActions ); + + // send the new actions with a notify to the listeners + SendNotify(); + + // check for propertyChangeEvents + pCurSet->CheckProperties( nOldCount, bWasFinal ); +} + +//----------------------------------------------------------------- +// XEventListener +//----------------------------------------------------------------- +void SAL_CALL +SortedDynamicResultSet::impl_disposing( const EventObject& ) + throw( RuntimeException ) +{ + mxListener.clear(); + mxOriginal.clear(); +} + +// ------------------------------------------------------------------------------ +// private methods +// ------------------------------------------------------------------------------ +void SortedDynamicResultSet::SendNotify() +{ + long nCount = maActions.Count(); + + if ( nCount && mxListener.is() ) + { + Sequence< ListAction > aActionList( maActions.Count() ); + ListAction *pActionList = aActionList.getArray(); + + for ( long i=0; i<nCount; i++ ) + { + pActionList[ i ] = *(maActions.GetAction( i )); + } + + ListEvent aNewEvent; + aNewEvent.Changes = aActionList; + + mxListener->notify( aNewEvent ); + } + + // clean up + maActions.Clear(); +} + +//========================================================================= +// +// SortedDynamicResultSetFactory +// +//========================================================================= +SortedDynamicResultSetFactory::SortedDynamicResultSetFactory( + const Reference< XMultiServiceFactory > & rSMgr ) +{ + mxSMgr = rSMgr; +} + +//-------------------------------------------------------------------------- +SortedDynamicResultSetFactory::~SortedDynamicResultSetFactory() +{ +} + +//-------------------------------------------------------------------------- +// XInterface methods. +//-------------------------------------------------------------------------- + +XINTERFACE_IMPL_3( SortedDynamicResultSetFactory, + XTypeProvider, + XServiceInfo, + XSortedDynamicResultSetFactory ); + +//-------------------------------------------------------------------------- +// XTypeProvider methods. +//-------------------------------------------------------------------------- + +XTYPEPROVIDER_IMPL_3( SortedDynamicResultSetFactory, + XTypeProvider, + XServiceInfo, + XSortedDynamicResultSetFactory ); + +//-------------------------------------------------------------------------- +// XServiceInfo methods. +//-------------------------------------------------------------------------- + +XSERVICEINFO_IMPL_1( SortedDynamicResultSetFactory, + OUString::createFromAscii( + "com.sun.star.comp.ucb.SortedDynamicResultSetFactory" ), + OUString::createFromAscii( + DYNAMIC_RESULTSET_FACTORY_NAME ) ); + +//-------------------------------------------------------------------------- +// Service factory implementation. +//-------------------------------------------------------------------------- + +ONE_INSTANCE_SERVICE_FACTORY_IMPL( SortedDynamicResultSetFactory ); + +//-------------------------------------------------------------------------- +// SortedDynamicResultSetFactory methods. +//-------------------------------------------------------------------------- +Reference< XDynamicResultSet > SAL_CALL +SortedDynamicResultSetFactory::createSortedDynamicResultSet( + const Reference< XDynamicResultSet > & Source, + const Sequence< NumberedSortingInfo > & Info, + const Reference< XAnyCompareFactory > & CompareFactory ) + throw( RuntimeException ) +{ + Reference< XDynamicResultSet > xRet; + xRet = new SortedDynamicResultSet( Source, Info, CompareFactory, mxSMgr ); + return xRet; +} + +//========================================================================= +// +// EventList +// +//========================================================================= + +void EventList::Clear() +{ + for ( std::deque< LISTACTION* >::size_type i = 0; + i < maData.size(); ++i ) + { + delete maData[i]; + } + + maData.clear(); +} + +//-------------------------------------------------------------------------- +void EventList::AddEvent( long nType, long nPos, long nCount ) +{ + ListAction *pAction = new ListAction; + pAction->Position = nPos; + pAction->Count = nCount; + pAction->ListActionType = nType; + + Insert( pAction ); +} + +//================================================================= +// +// SortedDynamicResultSetListener +// +//================================================================= + +SortedDynamicResultSetListener::SortedDynamicResultSetListener( + SortedDynamicResultSet *mOwner ) +{ + mpOwner = mOwner; +} + +//----------------------------------------------------------------- +SortedDynamicResultSetListener::~SortedDynamicResultSetListener() +{ +} + +//----------------------------------------------------------------- +// XInterface methods. +//----------------------------------------------------------------- + +XINTERFACE_IMPL_2( SortedDynamicResultSetListener, + XEventListener, /* base class of XDynamicResultSetListener */ + XDynamicResultSetListener ); + +//----------------------------------------------------------------- +// XEventListener ( base of XDynamicResultSetListener ) +//----------------------------------------------------------------- +void SAL_CALL +SortedDynamicResultSetListener::disposing( const EventObject& Source ) + throw( RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( mpOwner ) + mpOwner->impl_disposing( Source ); +} + +//----------------------------------------------------------------- +// XDynamicResultSetListener +//----------------------------------------------------------------- +void SAL_CALL +SortedDynamicResultSetListener::notify( const ListEvent& Changes ) + throw( RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( mpOwner ) + mpOwner->impl_notify( Changes ); +} + +//----------------------------------------------------------------- +// own methods: +//----------------------------------------------------------------- +void SAL_CALL +SortedDynamicResultSetListener::impl_OwnerDies() +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + mpOwner = NULL; +} + diff --git a/ucb/source/sorter/sortdynres.hxx b/ucb/source/sorter/sortdynres.hxx new file mode 100644 index 000000000000..fe026d40a3f7 --- /dev/null +++ b/ucb/source/sorter/sortdynres.hxx @@ -0,0 +1,257 @@ +/************************************************************************* + * + * 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 _SORTDYNRES_HXX +#define _SORTDYNRES_HXX + +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XTypeProvider.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/ucb/NumberedSortingInfo.hpp> +#include <com/sun/star/sdbc/XResultSet.hpp> +#include <com/sun/star/ucb/XDynamicResultSet.hpp> +#include <com/sun/star/ucb/XDynamicResultSetListener.hpp> +#include <com/sun/star/ucb/ListenerAlreadySetException.hpp> +#include <com/sun/star/ucb/XSortedDynamicResultSetFactory.hpp> +#include <cppuhelper/weak.hxx> +#include <osl/mutex.hxx> +#include <ucbhelper/macros.hxx> +#include "sortresult.hxx" + +namespace cppu { + class OInterfaceContainerHelper; +} + +//----------------------------------------------------------------------------- + +#define NUMBERED_SORTINGINFO com::sun::star::ucb::NumberedSortingInfo +#define RUNTIMEEXCEPTION com::sun::star::uno::RuntimeException +#define REFERENCE com::sun::star::uno::Reference +#define SEQUENCE com::sun::star::uno::Sequence +#define EVENTOBJECT com::sun::star::lang::EventObject +#define XEVENTLISTENER com::sun::star::lang::XEventListener +#define XMULTISERVICEFACTORY com::sun::star::lang::XMultiServiceFactory +#define XRESULTSET com::sun::star::sdbc::XResultSet +#define SQLEXCEPTION com::sun::star::sdbc::SQLException +#define XANYCOMPAREFACTORY com::sun::star::ucb::XAnyCompareFactory +#define XDYNAMICRESULTSET com::sun::star::ucb::XDynamicResultSet +#define XDYNAMICRESULTSETLISTENER com::sun::star::ucb::XDynamicResultSetListener +#define LISTENERALREADYSETEXCEPTION com::sun::star::ucb::ListenerAlreadySetException + +#define DYNAMIC_RESULTSET_SERVICE_NAME "com.sun.star.ucb.SortedDynamicResultSet" +#define DYNAMIC_RESULTSET_FACTORY_NAME "com.sun.star.ucb.SortedDynamicResultSetFactory" + +//----------------------------------------------------------------------------- +class SortedDynamicResultSetListener; + +class SortedDynamicResultSet: + public cppu::OWeakObject, + public com::sun::star::lang::XTypeProvider, + public com::sun::star::lang::XServiceInfo, + public com::sun::star::ucb::XDynamicResultSet +{ + cppu::OInterfaceContainerHelper *mpDisposeEventListeners; + + REFERENCE < XDYNAMICRESULTSETLISTENER > mxListener; + REFERENCE < XDYNAMICRESULTSETLISTENER > mxOwnListener; + + REFERENCE < XRESULTSET > mxOne; + REFERENCE < XRESULTSET > mxTwo; + REFERENCE < XDYNAMICRESULTSET > mxOriginal; + SEQUENCE < NUMBERED_SORTINGINFO > maOptions; + REFERENCE < XANYCOMPAREFACTORY > mxCompFac; + REFERENCE < XMULTISERVICEFACTORY > mxSMgr; + + SortedResultSet* mpOne; + SortedResultSet* mpTwo; + SortedDynamicResultSetListener* mpOwnListener; + + EventList maActions; + osl::Mutex maMutex; + sal_Bool mbGotWelcome :1; + sal_Bool mbUseOne :1; + sal_Bool mbStatic :1; + +private: + + void SendNotify(); + +public: + SortedDynamicResultSet( const REFERENCE < XDYNAMICRESULTSET > &xOriginal, + const SEQUENCE < NUMBERED_SORTINGINFO > &aOptions, + const REFERENCE < XANYCOMPAREFACTORY > &xCompFac, + const REFERENCE < XMULTISERVICEFACTORY > &xSMgr ); + + ~SortedDynamicResultSet(); + + //----------------------------------------------------------------- + // XInterface + //----------------------------------------------------------------- + XINTERFACE_DECL() + + //----------------------------------------------------------------- + // XTypeProvider + //----------------------------------------------------------------- + XTYPEPROVIDER_DECL() + + //----------------------------------------------------------------- + // XServiceInfo + //----------------------------------------------------------------- + XSERVICEINFO_NOFACTORY_DECL() + + //----------------------------------------------------------------- + // XComponent + //----------------------------------------------------------------- + virtual void SAL_CALL + dispose() throw( RUNTIME_EXCEPTION ); + + virtual void SAL_CALL + addEventListener( const REFERENCE< XEVENTLISTENER >& Listener ) + throw( RUNTIME_EXCEPTION ); + + virtual void SAL_CALL + removeEventListener( const REFERENCE< XEVENTLISTENER >& Listener ) + throw( RUNTIME_EXCEPTION ); + + //----------------------------------------------------------------- + // XDynamicResultSet + //----------------------------------------------------------------- + virtual REFERENCE< XRESULTSET > SAL_CALL + getStaticResultSet( ) + throw( LISTENERALREADYSETEXCEPTION, RUNTIMEEXCEPTION ); + + virtual void SAL_CALL + setListener( const REFERENCE< XDYNAMICRESULTSETLISTENER >& Listener ) + throw( LISTENERALREADYSETEXCEPTION, RUNTIMEEXCEPTION ); + + virtual void SAL_CALL + connectToCache( const REFERENCE< XDYNAMICRESULTSET > & xCache ) + throw( LISTENERALREADYSETEXCEPTION, + com::sun::star::ucb::AlreadyInitializedException, + com::sun::star::ucb::ServiceNotFoundException, + RUNTIMEEXCEPTION ); + + virtual sal_Int16 SAL_CALL + getCapabilities() + throw( RUNTIMEEXCEPTION ); + + //----------------------------------------------------------------- + // own methods: + //----------------------------------------------------------------- + virtual void SAL_CALL + impl_disposing( const EVENTOBJECT& Source ) + throw( RUNTIMEEXCEPTION ); + + virtual void SAL_CALL + impl_notify( const ::com::sun::star::ucb::ListEvent& Changes ) + throw( RUNTIMEEXCEPTION ); +}; + +//----------------------------------------------------------------------------- + +class SortedDynamicResultSetListener: + public cppu::OWeakObject, + public com::sun::star::ucb::XDynamicResultSetListener +{ + SortedDynamicResultSet *mpOwner; + osl::Mutex maMutex; + +public: + SortedDynamicResultSetListener( SortedDynamicResultSet *mOwner ); + ~SortedDynamicResultSetListener(); + + //----------------------------------------------------------------- + // XInterface + //----------------------------------------------------------------- + XINTERFACE_DECL() + + //----------------------------------------------------------------- + // XEventListener ( base of XDynamicResultSetListener ) + //----------------------------------------------------------------- + virtual void SAL_CALL + disposing( const EVENTOBJECT& Source ) + throw( RUNTIMEEXCEPTION ); + + //----------------------------------------------------------------- + // XDynamicResultSetListener + //----------------------------------------------------------------- + virtual void SAL_CALL + notify( const ::com::sun::star::ucb::ListEvent& Changes ) + throw( RUNTIMEEXCEPTION ); + + //----------------------------------------------------------------- + // own methods: + //----------------------------------------------------------------- + void SAL_CALL impl_OwnerDies(); +}; + +//----------------------------------------------------------------------------- + +class SortedDynamicResultSetFactory: + public cppu::OWeakObject, + public com::sun::star::lang::XTypeProvider, + public com::sun::star::lang::XServiceInfo, + public com::sun::star::ucb::XSortedDynamicResultSetFactory +{ + + REFERENCE< XMULTISERVICEFACTORY > mxSMgr; + +public: + + SortedDynamicResultSetFactory( + const REFERENCE< XMULTISERVICEFACTORY > & rSMgr); + + ~SortedDynamicResultSetFactory(); + + //----------------------------------------------------------------- + // XInterface + //----------------------------------------------------------------- + XINTERFACE_DECL() + + //----------------------------------------------------------------- + // XTypeProvider + //----------------------------------------------------------------- + XTYPEPROVIDER_DECL() + + //----------------------------------------------------------------- + // XServiceInfo + //----------------------------------------------------------------- + XSERVICEINFO_DECL() + + //----------------------------------------------------------------- + // XSortedDynamicResultSetFactory + + virtual REFERENCE< XDYNAMICRESULTSET > SAL_CALL + createSortedDynamicResultSet( + const REFERENCE< XDYNAMICRESULTSET > & Source, + const SEQUENCE< NUMBERED_SORTINGINFO > & Info, + const REFERENCE< XANYCOMPAREFACTORY > & CompareFactory ) + throw( RUNTIMEEXCEPTION ); +}; + +#endif diff --git a/ucb/source/sorter/sortmain.cxx b/ucb/source/sorter/sortmain.cxx new file mode 100644 index 000000000000..5ad9a529e1f2 --- /dev/null +++ b/ucb/source/sorter/sortmain.cxx @@ -0,0 +1,75 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" +#include <sortdynres.hxx> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> + +using namespace rtl; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; + +//========================================================================= +extern "C" void SAL_CALL component_getImplementationEnvironment( + const sal_Char ** ppEnvTypeName, uno_Environment ** ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + +//========================================================================= +extern "C" void * SAL_CALL component_getFactory( + const sal_Char * pImplName, void * pServiceManager, void * ) +{ + void * pRet = 0; + + Reference< XMultiServiceFactory > xSMgr( + reinterpret_cast< XMultiServiceFactory * >( pServiceManager ) ); + Reference< XSingleServiceFactory > xFactory; + + ////////////////////////////////////////////////////////////////////// + // SortedDynamicResultSetFactory. + ////////////////////////////////////////////////////////////////////// + + if ( SortedDynamicResultSetFactory::getImplementationName_Static(). + compareToAscii( pImplName ) == 0 ) + { + xFactory = SortedDynamicResultSetFactory::createServiceFactory( xSMgr ); + } + + ////////////////////////////////////////////////////////////////////// + + if ( xFactory.is() ) + { + xFactory->acquire(); + pRet = xFactory.get(); + } + + return pRet; +} + diff --git a/ucb/source/sorter/sortresult.cxx b/ucb/source/sorter/sortresult.cxx new file mode 100644 index 000000000000..6e546950a23a --- /dev/null +++ b/ucb/source/sorter/sortresult.cxx @@ -0,0 +1,2070 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +#include <vector> +#include <sortresult.hxx> +#include <cppuhelper/interfacecontainer.hxx> +#include <com/sun/star/sdbc/DataType.hpp> +#include <com/sun/star/sdbc/XResultSetMetaData.hpp> +#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp> +#include <com/sun/star/ucb/ListActionType.hpp> +#include <com/sun/star/ucb/XAnyCompare.hpp> +#include <com/sun/star/ucb/XAnyCompareFactory.hpp> +#include <osl/diagnose.h> + +//----------------------------------------------------------------------------- +using namespace com::sun::star::beans; +using namespace com::sun::star::container; +using namespace com::sun::star::io; +using namespace com::sun::star::lang; +using namespace com::sun::star::sdbc; +using namespace com::sun::star::ucb; +using namespace com::sun::star::uno; +using namespace com::sun::star::util; +using namespace cppu; +using namespace rtl; + +//========================================================================= + +// The mutex to synchronize access to containers. +static osl::Mutex& getContainerMutex() +{ + static osl::Mutex* pMutex = NULL; + if( !pMutex ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + if( !pMutex ) + { + static osl::Mutex aMutex; + pMutex = &aMutex; + } + } + + return *pMutex; +} + +//========================================================================== + +struct SortInfo +{ + sal_Bool mbUseOwnCompare; + sal_Bool mbAscending; + sal_Bool mbCaseSensitive; + sal_Int32 mnColumn; + sal_Int32 mnType; + SortInfo* mpNext; + Reference < XAnyCompare > mxCompareFunction; +}; + +//----------------------------------------------------------------------------- + +struct SortListData +{ + sal_Bool mbModified; + long mnCurPos; + long mnOldPos; + + SortListData( long nPos, sal_Bool bModified = sal_False ); +}; + +//============================================================================ +// +// class SRSPropertySetInfo. +// +//============================================================================ + +class SRSPropertySetInfo : + public OWeakObject, + public XTypeProvider, + public XPropertySetInfo +{ + Property maProps[2]; + +private: + +public: + SRSPropertySetInfo(); + virtual ~SRSPropertySetInfo(); + + // XInterface + XINTERFACE_DECL() + + // XTypeProvider + XTYPEPROVIDER_DECL() + + // XPropertySetInfo + virtual Sequence< Property > SAL_CALL getProperties() + throw( RuntimeException ); + virtual Property SAL_CALL getPropertyByName( const OUString& aName ) + throw( UnknownPropertyException, RuntimeException ); + virtual sal_Bool SAL_CALL hasPropertyByName( const OUString& Name ) + throw( RuntimeException ); +}; + +//========================================================================= +// +// PropertyChangeListenerContainer_Impl. +// +//========================================================================= + +struct equalStr_Impl +{ + bool operator()( const OUString& s1, const OUString& s2 ) const + { + return !!( s1 == s2 ); + } +}; + +struct hashStr_Impl +{ + size_t operator()( const OUString& rName ) const + { + return rName.hashCode(); + } +}; + +typedef OMultiTypeInterfaceContainerHelperVar +< + OUString, + hashStr_Impl, + equalStr_Impl +> PropertyChangeListenerContainer_Impl; + +//========================================================================= +// +// class PropertyChangeListeners_Impl +// +//========================================================================= + +class PropertyChangeListeners_Impl : public PropertyChangeListenerContainer_Impl +{ +public: + PropertyChangeListeners_Impl() + : PropertyChangeListenerContainer_Impl( getContainerMutex() ) {} +}; + +//========================================================================== +SortedResultSet::SortedResultSet( Reference< XResultSet > aResult ) +{ + mpDisposeEventListeners = NULL; + mpPropChangeListeners = NULL; + mpVetoChangeListeners = NULL; + mpPropSetInfo = NULL; + + mxOriginal = aResult; + mpSortInfo = NULL; + mnLastSort = 0; + mnCurEntry = 0; + mnCount = 0; + mbIsCopy = sal_False; +} + +//-------------------------------------------------------------------------- +SortedResultSet::~SortedResultSet() +{ + mxOriginal.clear(); + mxOther.clear(); + + if ( !mbIsCopy ) + { + SortInfo *pInfo = mpSortInfo; + while ( pInfo ) + { + mpSortInfo = pInfo->mpNext; + delete pInfo; + pInfo = mpSortInfo; + } + } + + mpSortInfo = NULL; + + if ( mpPropSetInfo ) + mpPropSetInfo->release(); + + delete mpPropChangeListeners; + delete mpVetoChangeListeners; +} + +//-------------------------------------------------------------------------- +// XInterface methods. +//-------------------------------------------------------------------------- + +XINTERFACE_IMPL_9( SortedResultSet, + XTypeProvider, + XServiceInfo, + XComponent, + XContentAccess, + XResultSet, + XRow, + XCloseable, + XResultSetMetaDataSupplier, + XPropertySet ); + +//-------------------------------------------------------------------------- +// XTypeProvider methods. +//-------------------------------------------------------------------------- + +XTYPEPROVIDER_IMPL_9( SortedResultSet, + XTypeProvider, + XServiceInfo, + XComponent, + XContentAccess, + XResultSet, + XRow, + XCloseable, + XResultSetMetaDataSupplier, + XPropertySet ); + +//-------------------------------------------------------------------------- +// XServiceInfo methods. +//-------------------------------------------------------------------------- + +XSERVICEINFO_NOFACTORY_IMPL_1( SortedResultSet, + OUString::createFromAscii( + "com.sun.star.comp.ucb.SortedResultSet" ), + OUString::createFromAscii( + RESULTSET_SERVICE_NAME ) ); + +//-------------------------------------------------------------------------- +// XComponent methods. +//-------------------------------------------------------------------------- +void SAL_CALL SortedResultSet::dispose() + throw( RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( mpDisposeEventListeners && mpDisposeEventListeners->getLength() ) + { + EventObject aEvt; + aEvt.Source = static_cast< XComponent * >( this ); + mpDisposeEventListeners->disposeAndClear( aEvt ); + } + + if ( mpPropChangeListeners ) + { + EventObject aEvt; + aEvt.Source = static_cast< XPropertySet * >( this ); + mpPropChangeListeners->disposeAndClear( aEvt ); + } + + if ( mpVetoChangeListeners ) + { + EventObject aEvt; + aEvt.Source = static_cast< XPropertySet * >( this ); + mpVetoChangeListeners->disposeAndClear( aEvt ); + } + + mxOriginal.clear(); + mxOther.clear(); +} + +//-------------------------------------------------------------------------- +void SAL_CALL SortedResultSet::addEventListener( + const Reference< XEventListener >& Listener ) + throw( RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( !mpDisposeEventListeners ) + mpDisposeEventListeners = + new OInterfaceContainerHelper( getContainerMutex() ); + + mpDisposeEventListeners->addInterface( Listener ); +} + +//-------------------------------------------------------------------------- +void SAL_CALL SortedResultSet::removeEventListener( + const Reference< XEventListener >& Listener ) + throw( RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( mpDisposeEventListeners ) + mpDisposeEventListeners->removeInterface( Listener ); +} + +//-------------------------------------------------------------------------- +// XContentAccess methods. +//-------------------------------------------------------------------------- + +OUString SAL_CALL +SortedResultSet::queryContentIdentifierString() + throw( RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XContentAccess >::query(mxOriginal)->queryContentIdentifierString(); +} + +//-------------------------------------------------------------------------- +Reference< XContentIdentifier > SAL_CALL +SortedResultSet::queryContentIdentifier() + throw( RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XContentAccess >::query(mxOriginal)->queryContentIdentifier(); +} + +//-------------------------------------------------------------------------- +Reference< XContent > SAL_CALL +SortedResultSet::queryContent() + throw( RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XContentAccess >::query(mxOriginal)->queryContent(); +} + + +//-------------------------------------------------------------------------- +// XResultSet methods. +//-------------------------------------------------------------------------- +sal_Bool SAL_CALL SortedResultSet::next() + throw ( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + mnCurEntry++; + + if ( mnCurEntry > 0 ) + { + if ( mnCurEntry <= mnCount ) + { + sal_Int32 nIndex = maS2O[ mnCurEntry ]; + return mxOriginal->absolute( nIndex ); + } + else + { + mnCurEntry = mnCount + 1; + } + } + return sal_False; +} + +//------------------------------------------------------------------------- +sal_Bool SAL_CALL SortedResultSet::isBeforeFirst() + throw ( SQLException, RuntimeException ) +{ + if ( mnCurEntry ) + return sal_False; + else + return sal_True; +} + +//------------------------------------------------------------------------- +sal_Bool SAL_CALL SortedResultSet::isAfterLast() + throw ( SQLException, RuntimeException ) +{ + if ( mnCurEntry > mnCount ) + return sal_True; + else + return sal_False; +} + +//------------------------------------------------------------------------- +sal_Bool SAL_CALL SortedResultSet::isFirst() + throw ( SQLException, RuntimeException ) +{ + if ( mnCurEntry == 1 ) + return sal_True; + else + return sal_False; +} + +//------------------------------------------------------------------------- +sal_Bool SAL_CALL SortedResultSet::isLast() + throw ( SQLException, RuntimeException ) +{ + if ( mnCurEntry == mnCount ) + return sal_True; + else + return sal_False; +} + +//------------------------------------------------------------------------- +void SAL_CALL SortedResultSet::beforeFirst() + throw ( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + mnCurEntry = 0; + mxOriginal->beforeFirst(); +} + +//------------------------------------------------------------------------- +void SAL_CALL SortedResultSet::afterLast() + throw ( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + mnCurEntry = mnCount+1; + mxOriginal->afterLast(); +} + +//------------------------------------------------------------------------- +sal_Bool SAL_CALL SortedResultSet::first() + throw ( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( mnCount ) + { + mnCurEntry = 1; + sal_Int32 nIndex = maS2O[ mnCurEntry ]; + return mxOriginal->absolute( nIndex ); + } + else + { + mnCurEntry = 0; + return sal_False; + } +} + +//------------------------------------------------------------------------- +sal_Bool SAL_CALL SortedResultSet::last() + throw ( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( mnCount ) + { + mnCurEntry = mnCount; + sal_Int32 nIndex = maS2O[ mnCurEntry ]; + return mxOriginal->absolute( nIndex ); + } + else + { + mnCurEntry = 0; + return sal_False; + } +} + +//------------------------------------------------------------------------- +sal_Int32 SAL_CALL SortedResultSet::getRow() + throw ( SQLException, RuntimeException ) +{ + return mnCurEntry; +} + +//------------------------------------------------------------------------- +/** + moves the cursor to the given row number in the result set. + <p>If the row number is positive, the cursor moves to the given row + number with respect to the beginning of the result set. The first + row is row 1, the second is row 2, and so on. + <p>If the given row number is negative, the cursor moves to an + absolute row position with respect to the end of the result set. + For example, calling <code>moveToPosition(-1)</code> positions the + cursor on the last row, <code>moveToPosition(-2)</code> indicates the + next-to-last row, and so on. + <p>An attempt to position the cursor beyond the first/last row in the + result set leaves the cursor before/after the first/last row, + respectively. + <p>Note: Calling <code>moveToPosition(1)</code> is the same + as calling <code>moveToFirst()</code>. Calling + <code>moveToPosition(-1)</code> is the same as calling + <code>moveToLast()</code>. + @param row + is the number of rows to move. Could be negative. + @returns + <sal_True/> if the cursor is on a row; <sal_False/> otherwise + @throws SQLException + if a database access error occurs or if row is 0, or the result set + type is FORWARD_ONLY. + */ +sal_Bool SAL_CALL SortedResultSet::absolute( sal_Int32 row ) + throw ( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + sal_Int32 nIndex; + + if ( row > 0 ) + { + if ( row <= mnCount ) + { + mnCurEntry = row; + nIndex = maS2O[ mnCurEntry ]; + return mxOriginal->absolute( nIndex ); + } + else + { + mnCurEntry = mnCount + 1; + return sal_False; + } + } + else if ( row == 0 ) + { + throw SQLException(); + } + else + { + if ( mnCount + row + 1 > 0 ) + { + mnCurEntry = mnCount + row + 1; + nIndex = maS2O[ mnCurEntry ]; + return mxOriginal->absolute( nIndex ); + } + else + { + mnCurEntry = 0; + return sal_False; + } + } +} + +//------------------------------------------------------------------------- +/** + moves the cursor a relative number of rows, either positive or negative. + <p> + Attempting to move beyond the first/last row in the result set positions + the cursor before/after the first/last row. Calling + <code>moveRelative(0)</code> is valid, but does not change the cursor + position. + <p>Note: Calling <code>moveRelative(1)</code> is different from calling + <code>moveNext()</code> because is makes sense to call + <code>moveNext()</code> when there is no current row, for example, + when the cursor is positioned before the first row or after the last + row of the result set. + @param rows + is the number of rows to move. Could be negative. + @returns + <sal_True/> if the cursor is on a valid row; <sal_False/> if it is off + the result set. + @throws SQLException + if a database access error occurs or if there is no + current row, or the result set type is FORWARD_ONLY. + */ +sal_Bool SAL_CALL SortedResultSet::relative( sal_Int32 rows ) + throw ( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( ( mnCurEntry <= 0 ) || ( mnCurEntry > mnCount ) ) + { + throw SQLException(); + } + + if ( rows == 0 ) + return sal_True; + + sal_Int32 nTmp = mnCurEntry + rows; + + if ( nTmp <= 0 ) + { + mnCurEntry = 0; + return sal_False; + } + else if ( nTmp > mnCount ) + { + mnCurEntry = mnCount + 1; + return sal_False; + } + else + { + mnCurEntry = nTmp; + nTmp = maS2O[ mnCurEntry ]; + return mxOriginal->absolute( nTmp ); + } +} + +//------------------------------------------------------------------------- +/** + moves the cursor to the previous row in the result set. + <p>Note: <code>previous()</code> is not the same as + <code>relative(-1)</code> because it makes sense to call + <code>previous()</code> when there is no current row. + @returns <sal_True/> if the cursor is on a valid row; <sal_False/> if it is off + the result set. + @throws SQLException + if a database access error occurs or the result set type + is FORWARD_ONLY. + */ +sal_Bool SAL_CALL SortedResultSet::previous() + throw ( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + mnCurEntry -= 1; + + if ( mnCurEntry > 0 ) + { + if ( mnCurEntry <= mnCount ) + { + sal_Int32 nIndex = maS2O[ mnCurEntry ]; + return mxOriginal->absolute( nIndex ); + } + } + else + mnCurEntry = 0; + + return sal_False; +} + +//------------------------------------------------------------------------- +void SAL_CALL SortedResultSet::refreshRow() + throw ( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( ( mnCurEntry <= 0 ) || ( mnCurEntry > mnCount ) ) + { + throw SQLException(); + } + + mxOriginal->refreshRow(); +} + +//------------------------------------------------------------------------- +sal_Bool SAL_CALL SortedResultSet::rowUpdated() + throw ( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( ( mnCurEntry <= 0 ) || ( mnCurEntry > mnCount ) ) + { + throw SQLException(); + } + + return mxOriginal->rowUpdated(); +} + +//------------------------------------------------------------------------- +sal_Bool SAL_CALL SortedResultSet::rowInserted() + throw ( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( ( mnCurEntry <= 0 ) || ( mnCurEntry > mnCount ) ) + { + throw SQLException(); + } + + return mxOriginal->rowInserted(); +} + +//------------------------------------------------------------------------- +sal_Bool SAL_CALL SortedResultSet::rowDeleted() + throw ( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( ( mnCurEntry <= 0 ) || ( mnCurEntry > mnCount ) ) + { + throw SQLException(); + } + + return mxOriginal->rowDeleted(); +} + +//------------------------------------------------------------------------- +Reference< XInterface > SAL_CALL SortedResultSet::getStatement() + throw ( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( ( mnCurEntry <= 0 ) || ( mnCurEntry > mnCount ) ) + { + throw SQLException(); + } + + return mxOriginal->getStatement(); +} + +//-------------------------------------------------------------------------- +// XRow methods. +//-------------------------------------------------------------------------- + +sal_Bool SAL_CALL SortedResultSet::wasNull() + throw( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->wasNull(); +} + +//------------------------------------------------------------------------- +OUString SAL_CALL SortedResultSet::getString( sal_Int32 columnIndex ) + throw( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getString( columnIndex ); +} + +//------------------------------------------------------------------------- +sal_Bool SAL_CALL SortedResultSet::getBoolean( sal_Int32 columnIndex ) + throw( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getBoolean( columnIndex ); +} + +//------------------------------------------------------------------------- +sal_Int8 SAL_CALL SortedResultSet::getByte( sal_Int32 columnIndex ) + throw( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getByte( columnIndex ); +} + +//------------------------------------------------------------------------- +sal_Int16 SAL_CALL SortedResultSet::getShort( sal_Int32 columnIndex ) + throw( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getShort( columnIndex ); +} + +//------------------------------------------------------------------------- +sal_Int32 SAL_CALL SortedResultSet::getInt( sal_Int32 columnIndex ) + throw( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getInt( columnIndex ); +} +//------------------------------------------------------------------------- +sal_Int64 SAL_CALL SortedResultSet::getLong( sal_Int32 columnIndex ) + throw( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getLong( columnIndex ); +} + +//------------------------------------------------------------------------- +float SAL_CALL SortedResultSet::getFloat( sal_Int32 columnIndex ) + throw( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getFloat( columnIndex ); +} + +//------------------------------------------------------------------------- +double SAL_CALL SortedResultSet::getDouble( sal_Int32 columnIndex ) + throw( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getDouble( columnIndex ); +} + +//------------------------------------------------------------------------- +Sequence< sal_Int8 > SAL_CALL SortedResultSet::getBytes( sal_Int32 columnIndex ) + throw( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getBytes( columnIndex ); +} + +//------------------------------------------------------------------------- +Date SAL_CALL SortedResultSet::getDate( sal_Int32 columnIndex ) + throw( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getDate( columnIndex ); +} + +//------------------------------------------------------------------------- +Time SAL_CALL SortedResultSet::getTime( sal_Int32 columnIndex ) + throw( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getTime( columnIndex ); +} + +//------------------------------------------------------------------------- +DateTime SAL_CALL SortedResultSet::getTimestamp( sal_Int32 columnIndex ) + throw( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getTimestamp( columnIndex ); +} + +//------------------------------------------------------------------------- +Reference< XInputStream > SAL_CALL +SortedResultSet::getBinaryStream( sal_Int32 columnIndex ) + throw( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getBinaryStream( columnIndex ); +} + +//------------------------------------------------------------------------- +Reference< XInputStream > SAL_CALL +SortedResultSet::getCharacterStream( sal_Int32 columnIndex ) + throw( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getCharacterStream( columnIndex ); +} + +//------------------------------------------------------------------------- +Any SAL_CALL SortedResultSet::getObject( sal_Int32 columnIndex, + const Reference< XNameAccess >& typeMap ) + throw( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getObject( columnIndex, + typeMap); +} + +//------------------------------------------------------------------------- +Reference< XRef > SAL_CALL SortedResultSet::getRef( sal_Int32 columnIndex ) + throw( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getRef( columnIndex ); +} + +//------------------------------------------------------------------------- +Reference< XBlob > SAL_CALL SortedResultSet::getBlob( sal_Int32 columnIndex ) + throw( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getBlob( columnIndex ); +} + +//------------------------------------------------------------------------- +Reference< XClob > SAL_CALL SortedResultSet::getClob( sal_Int32 columnIndex ) + throw( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getClob( columnIndex ); +} + +//------------------------------------------------------------------------- +Reference< XArray > SAL_CALL SortedResultSet::getArray( sal_Int32 columnIndex ) + throw( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getArray( columnIndex ); +} + + +//-------------------------------------------------------------------------- +// XCloseable methods. +//-------------------------------------------------------------------------- + +void SAL_CALL SortedResultSet::close() + throw( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + Reference< XCloseable >::query(mxOriginal)->close(); +} + +//-------------------------------------------------------------------------- +// XResultSetMetaDataSupplier methods. +//-------------------------------------------------------------------------- + +Reference< XResultSetMetaData > SAL_CALL SortedResultSet::getMetaData() + throw( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XResultSetMetaDataSupplier >::query(mxOriginal)->getMetaData(); +} + + +//-------------------------------------------------------------------------- +// XPropertySet methods. +//-------------------------------------------------------------------------- + +Reference< XPropertySetInfo > SAL_CALL +SortedResultSet::getPropertySetInfo() throw( RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( !mpPropSetInfo ) + { + mpPropSetInfo = new SRSPropertySetInfo(); + mpPropSetInfo->acquire(); + } + + return Reference< XPropertySetInfo >( mpPropSetInfo ); +} + +//-------------------------------------------------------------------------- +void SAL_CALL SortedResultSet::setPropertyValue( + const OUString& PropertyName, + const Any& ) + throw( UnknownPropertyException, + PropertyVetoException, + IllegalArgumentException, + WrappedTargetException, + RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( ( PropertyName.compareToAscii( "RowCount" ) == 0 ) || + ( PropertyName.compareToAscii( "IsRowCountFinal" ) == 0 ) ) + throw IllegalArgumentException(); + else + throw UnknownPropertyException(); +} + +//-------------------------------------------------------------------------- +Any SAL_CALL SortedResultSet::getPropertyValue( const OUString& PropertyName ) + throw( UnknownPropertyException, + WrappedTargetException, + RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + Any aRet; + + if ( PropertyName.compareToAscii( "RowCount" ) == 0 ) + { + aRet <<= maS2O.Count(); + } + else if ( PropertyName.compareToAscii( "IsRowCountFinal" ) == 0 ) + { + sal_uInt32 nOrgCount = 0; + sal_Bool bOrgFinal = false; + Any aOrgRet; + + aRet <<= (sal_Bool) sal_False; + + aOrgRet = Reference< XPropertySet >::query(mxOriginal)-> + getPropertyValue( PropertyName ); + aOrgRet >>= bOrgFinal; + + if ( bOrgFinal ) + { + aOrgRet = Reference< XPropertySet >::query(mxOriginal)-> + getPropertyValue( OUString::createFromAscii( "RowCount" ) ); + aOrgRet >>= nOrgCount; + if ( nOrgCount == maS2O.Count() ) + aRet <<= (sal_Bool) sal_True; + } + } + else + throw UnknownPropertyException(); + + return aRet; +} + +//-------------------------------------------------------------------------- +void SAL_CALL SortedResultSet::addPropertyChangeListener( + const OUString& PropertyName, + const Reference< XPropertyChangeListener >& Listener ) + throw( UnknownPropertyException, + WrappedTargetException, + RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( !mpPropChangeListeners ) + mpPropChangeListeners = + new PropertyChangeListeners_Impl(); + + mpPropChangeListeners->addInterface( PropertyName, Listener ); +} + +//-------------------------------------------------------------------------- +void SAL_CALL SortedResultSet::removePropertyChangeListener( + const OUString& PropertyName, + const Reference< XPropertyChangeListener >& Listener ) + throw( UnknownPropertyException, + WrappedTargetException, + RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( mpPropChangeListeners ) + mpPropChangeListeners->removeInterface( PropertyName, Listener ); +} + +//-------------------------------------------------------------------------- +void SAL_CALL SortedResultSet::addVetoableChangeListener( + const OUString& PropertyName, + const Reference< XVetoableChangeListener >& Listener ) + throw( UnknownPropertyException, + WrappedTargetException, + RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( !mpVetoChangeListeners ) + mpVetoChangeListeners = + new PropertyChangeListeners_Impl(); + + mpVetoChangeListeners->addInterface( PropertyName, Listener ); +} + +//-------------------------------------------------------------------------- +void SAL_CALL SortedResultSet::removeVetoableChangeListener( + const OUString& PropertyName, + const Reference< XVetoableChangeListener >& Listener ) + throw( UnknownPropertyException, + WrappedTargetException, + RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( mpVetoChangeListeners ) + mpVetoChangeListeners->removeInterface( PropertyName, Listener ); +} + +//-------------------------------------------------------------------------- +// private methods +//-------------------------------------------------------------------------- +long SortedResultSet::CompareImpl( Reference < XResultSet > xResultOne, + Reference < XResultSet > xResultTwo, + long nIndexOne, long nIndexTwo, + SortInfo* pSortInfo ) + + throw( SQLException, RuntimeException ) +{ + Reference < XRow > xRowOne = Reference< XRow >::query( xResultOne ); + Reference < XRow > xRowTwo = Reference< XRow >::query( xResultTwo ); + + long nCompare = 0; + long nColumn = pSortInfo->mnColumn; + + switch ( pSortInfo->mnType ) + { + case DataType::BIT : + case DataType::TINYINT : + case DataType::SMALLINT : + case DataType::INTEGER : + { + sal_Int32 aOne = 0; + sal_Int32 aTwo = 0; + + if ( xResultOne->absolute( nIndexOne ) ) + aOne = xRowOne->getInt( nColumn ); + if ( xResultTwo->absolute( nIndexTwo ) ) + aTwo = xRowTwo->getInt( nColumn ); + + if ( aOne < aTwo ) + nCompare = -1; + else if ( aOne == aTwo ) + nCompare = 0; + else + nCompare = 1; + + break; + } + case DataType::BIGINT : + { + sal_Int64 aOne = 0; + sal_Int64 aTwo = 0; + + if ( xResultOne->absolute( nIndexOne ) ) + aOne = xRowOne->getLong( nColumn ); + if ( xResultTwo->absolute( nIndexTwo ) ) + aTwo = xRowTwo->getLong( nColumn ); + + if ( aOne < aTwo ) + nCompare = -1; + else if ( aOne == aTwo ) + nCompare = 0; + else + nCompare = 1; + + break; + } + case DataType::CHAR : + case DataType::VARCHAR : + case DataType::LONGVARCHAR : + { + OUString aOne, aTwo; + + if ( xResultOne->absolute( nIndexOne ) ) + aOne = xRowOne->getString( nColumn ); + if ( xResultTwo->absolute( nIndexTwo ) ) + aTwo = xRowTwo->getString( nColumn ); + + if ( ! pSortInfo->mbCaseSensitive ) + { + aOne = aOne.toAsciiLowerCase(); + aTwo = aTwo.toAsciiLowerCase(); + } + + nCompare = aOne.compareTo( aTwo ); + break; + } + case DataType::DATE : + { + Date aOne, aTwo; + sal_Int32 nTmp; + + if ( xResultOne->absolute( nIndexOne ) ) + aOne = xRowOne->getDate( nColumn ); + if ( xResultTwo->absolute( nIndexTwo ) ) + aTwo = xRowTwo->getDate( nColumn ); + + nTmp = (sal_Int32) aTwo.Year - (sal_Int32) aOne.Year; + if ( !nTmp ) { + nTmp = (sal_Int32) aTwo.Month - (sal_Int32) aOne.Month; + if ( !nTmp ) + nTmp = (sal_Int32) aTwo.Day - (sal_Int32) aOne.Day; + } + + if ( nTmp < 0 ) + nCompare = -1; + else if ( nTmp == 0 ) + nCompare = 0; + else + nCompare = 1; + + break; + } + case DataType::TIME : + { + Time aOne, aTwo; + sal_Int32 nTmp; + + if ( xResultOne->absolute( nIndexOne ) ) + aOne = xRowOne->getTime( nColumn ); + if ( xResultTwo->absolute( nIndexTwo ) ) + aTwo = xRowTwo->getTime( nColumn ); + + nTmp = (sal_Int32) aTwo.Hours - (sal_Int32) aOne.Hours; + if ( !nTmp ) { + nTmp = (sal_Int32) aTwo.Minutes - (sal_Int32) aOne.Minutes; + if ( !nTmp ) { + nTmp = (sal_Int32) aTwo.Seconds - (sal_Int32) aOne.Seconds; + if ( !nTmp ) + nTmp = (sal_Int32) aTwo.HundredthSeconds + - (sal_Int32) aOne.HundredthSeconds; + }} + + if ( nTmp < 0 ) + nCompare = -1; + else if ( nTmp == 0 ) + nCompare = 0; + else + nCompare = 1; + + break; + } + case DataType::TIMESTAMP : + { + DateTime aOne, aTwo; + sal_Int32 nTmp; + + if ( xResultOne->absolute( nIndexOne ) ) + aOne = xRowOne->getTimestamp( nColumn ); + if ( xResultTwo->absolute( nIndexTwo ) ) + aTwo = xRowTwo->getTimestamp( nColumn ); + + nTmp = (sal_Int32) aTwo.Year - (sal_Int32) aOne.Year; + if ( !nTmp ) { + nTmp = (sal_Int32) aTwo.Month - (sal_Int32) aOne.Month; + if ( !nTmp ) { + nTmp = (sal_Int32) aTwo.Day - (sal_Int32) aOne.Day; + if ( !nTmp ) { + nTmp = (sal_Int32) aTwo.Hours - (sal_Int32) aOne.Hours; + if ( !nTmp ) { + nTmp = (sal_Int32) aTwo.Minutes - (sal_Int32) aOne.Minutes; + if ( !nTmp ) { + nTmp = (sal_Int32) aTwo.Seconds - (sal_Int32) aOne.Seconds; + if ( !nTmp ) + nTmp = (sal_Int32) aTwo.HundredthSeconds + - (sal_Int32) aOne.HundredthSeconds; + }}}}} + + if ( nTmp < 0 ) + nCompare = -1; + else if ( nTmp == 0 ) + nCompare = 0; + else + nCompare = 1; + + break; + } + case DataType::REAL : + { + float aOne = 0; + float aTwo = 0; + + if ( xResultOne->absolute( nIndexOne ) ) + aOne = xRowOne->getFloat( nColumn ); + if ( xResultTwo->absolute( nIndexTwo ) ) + aTwo = xRowTwo->getFloat( nColumn ); + + if ( aOne < aTwo ) + nCompare = -1; + else if ( aOne == aTwo ) + nCompare = 0; + else + nCompare = 1; + + break; + } + case DataType::FLOAT : + case DataType::DOUBLE : + { + double aOne = 0; + double aTwo = 0; + + if ( xResultOne->absolute( nIndexOne ) ) + aOne = xRowOne->getDouble( nColumn ); + if ( xResultTwo->absolute( nIndexTwo ) ) + aTwo = xRowTwo->getDouble( nColumn ); + + if ( aOne < aTwo ) + nCompare = -1; + else if ( aOne == aTwo ) + nCompare = 0; + else + nCompare = 1; + + break; + } + default: + { + OSL_ENSURE( sal_False, "DataType not supported for compare!" ); + } + } + + return nCompare; +} + +//-------------------------------------------------------------------------- +long SortedResultSet::CompareImpl( Reference < XResultSet > xResultOne, + Reference < XResultSet > xResultTwo, + long nIndexOne, long nIndexTwo ) + throw( SQLException, RuntimeException ) +{ + long nCompare = 0; + SortInfo* pInfo = mpSortInfo; + + while ( !nCompare && pInfo ) + { + if ( pInfo->mbUseOwnCompare ) + { + nCompare = CompareImpl( xResultOne, xResultTwo, + nIndexOne, nIndexTwo, pInfo ); + } + else + { + Any aOne, aTwo; + + Reference < XRow > xRowOne = + Reference< XRow >::query( xResultOne ); + Reference < XRow > xRowTwo = + Reference< XRow >::query( xResultTwo ); + + if ( xResultOne->absolute( nIndexOne ) ) + aOne = xRowOne->getObject( pInfo->mnColumn, NULL ); + if ( xResultTwo->absolute( nIndexTwo ) ) + aTwo = xRowTwo->getObject( pInfo->mnColumn, NULL ); + + nCompare = pInfo->mxCompareFunction->compare( aOne, aTwo ); + } + + if ( ! pInfo->mbAscending ) + nCompare = - nCompare; + + pInfo = pInfo->mpNext; + } + + return nCompare; +} + +//-------------------------------------------------------------------------- +long SortedResultSet::Compare( SortListData *pOne, + SortListData *pTwo ) + throw( SQLException, RuntimeException ) +{ + long nIndexOne; + long nIndexTwo; + + Reference < XResultSet > xResultOne; + Reference < XResultSet > xResultTwo; + + if ( pOne->mbModified ) + { + xResultOne = mxOther; + nIndexOne = pOne->mnOldPos; + } + else + { + xResultOne = mxOriginal; + nIndexOne = pOne->mnCurPos; + } + + if ( pTwo->mbModified ) + { + xResultTwo = mxOther; + nIndexTwo = pTwo->mnOldPos; + } + else + { + xResultTwo = mxOriginal; + nIndexTwo = pTwo->mnCurPos; + } + + long nCompare; + nCompare = CompareImpl( xResultOne, xResultTwo, + nIndexOne, nIndexTwo ); + return nCompare; +} + +//-------------------------------------------------------------------------- +long SortedResultSet::FindPos( SortListData *pEntry, + long _nStart, long _nEnd ) + throw( SQLException, RuntimeException ) +{ + if ( _nStart > _nEnd ) + return _nStart + 1; + + long nStart = _nStart; + long nEnd = _nEnd; + long nMid = 0, nCompare = 0; + + SortListData *pMid; + + while ( nStart <= nEnd ) + { + nMid = ( nEnd - nStart ) / 2 + nStart; + pMid = maS2O.GetData( nMid ); + nCompare = Compare( pEntry, pMid ); + + if ( !nCompare ) + nCompare = ((long) pEntry ) - ( (long) pMid ); + + if ( nCompare < 0 ) // pEntry < pMid + nEnd = nMid - 1; + else + nStart = nMid + 1; + } + + if ( nCompare < 0 ) // pEntry < pMid + return nMid; + else + return nMid+1; +} + +//-------------------------------------------------------------------------- +void SortedResultSet::PropertyChanged( const PropertyChangeEvent& rEvt ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( !mpPropChangeListeners ) + return; + + // Notify listeners interested especially in the changed property. + OInterfaceContainerHelper* pPropsContainer = + mpPropChangeListeners->getContainer( rEvt.PropertyName ); + if ( pPropsContainer ) + { + OInterfaceIteratorHelper aIter( *pPropsContainer ); + while ( aIter.hasMoreElements() ) + { + Reference< XPropertyChangeListener > xListener( + aIter.next(), UNO_QUERY ); + if ( xListener.is() ) + xListener->propertyChange( rEvt ); + } + } + + // Notify listeners interested in all properties. + pPropsContainer = mpPropChangeListeners->getContainer( OUString() ); + if ( pPropsContainer ) + { + OInterfaceIteratorHelper aIter( *pPropsContainer ); + while ( aIter.hasMoreElements() ) + { + Reference< XPropertyChangeListener > xListener( + aIter.next(), UNO_QUERY ); + if ( xListener.is() ) + xListener->propertyChange( rEvt ); + } + } +} + +//------------------------------------------------------------------------- + +//-------------------------------------------------------------------------- +// public methods +//-------------------------------------------------------------------------- + +void SortedResultSet::CopyData( SortedResultSet *pSource ) +{ + const SortedEntryList *pSrcS2O = pSource->GetS2OList(); + const SimpleList *pSrcO2S = pSource->GetO2SList(); + + long i, nCount; + + maS2O.Clear(); + maO2S.Clear(); + maModList.Clear(); + + maS2O.Insert( NULL, 0 ); + maO2S.Insert( 0, (sal_uInt32) 0 ); // value, pos + + nCount = pSrcS2O->Count(); + + for ( i=1; i<nCount; i++ ) + { + maS2O.Insert( new SortListData( (*pSrcS2O)[ i ] ), i ); + maO2S.Insert( pSrcO2S->GetObject( i ), (sal_uInt32) i ); + } + + mnLastSort = maS2O.Count(); + mxOther = pSource->GetResultSet(); + + if ( !mpSortInfo ) + { + mpSortInfo = pSource->GetSortInfo(); + mbIsCopy = sal_True; + } +} + +//-------------------------------------------------------------------------- +void SortedResultSet::Initialize( + const Sequence < NumberedSortingInfo > &xSortInfo, + const Reference< XAnyCompareFactory > &xCompFactory ) +{ + BuildSortInfo( mxOriginal, xSortInfo, xCompFactory ); + // Insert dummy at pos 0 + SortListData *pData = new SortListData( 0 ); + maS2O.Insert( pData, 0 ); + + long nIndex = 1; + + // now fetch all the elements from the original result set, + // get there new position in the sorted result set and insert + // an entry in the sorted to original mapping list + try { + while ( mxOriginal->absolute( nIndex ) ) + { + pData = new SortListData( nIndex ); + long nPos = FindPos( pData, 1, nIndex-1 ); + + maS2O.Insert( pData, nPos ); + + nIndex++; + } + } + catch ( SQLException ) { OSL_ENSURE( sal_False, "SortedResultSet::Initialize() : Got unexpected SQLException" ); } + + // when we have fetched all the elements, we can create the + // original to sorted mapping list from the s2o list + maO2S.Clear(); + maO2S.Insert( NULL, (sal_uInt32) 0 ); + + // insert some dummy entries first and replace then + // the entries with the right ones + sal_uInt32 i; + + for ( i=1; i<maS2O.Count(); i++ ) + maO2S.Insert( (void*) 0, i ); // Insert( data, pos ) + for ( i=1; i<maS2O.Count(); i++ ) + maO2S.Replace( (void*) i, maS2O[ i ] ); // Insert( data, pos ) + + mnCount = maS2O.Count() - 1; +} + +//-------------------------------------------------------------------------- +void SortedResultSet::CheckProperties( long nOldCount, sal_Bool bWasFinal ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( !mpPropChangeListeners ) + return; + + try { + // check for propertyChangeEvents + if ( nOldCount != GetCount() ) + { + sal_Bool bIsFinal = sal_False; + PropertyChangeEvent aEvt; + + aEvt.PropertyName = OUString::createFromAscii( "RowCount" ); + aEvt.Further = sal_False; + aEvt.PropertyHandle = -1; + aEvt.OldValue <<= nOldCount; + aEvt.NewValue <<= GetCount(); + + PropertyChanged( aEvt ); + + OUString aName = OUString::createFromAscii( "IsRowCountFinal" ); + Any aRet = getPropertyValue( aName ); + if ( (aRet >>= bIsFinal) && bIsFinal != bWasFinal ) + { + aEvt.PropertyName = aName; + aEvt.Further = sal_False; + aEvt.PropertyHandle = -1; + aEvt.OldValue <<= (sal_Bool) bWasFinal; + aEvt.NewValue <<= (sal_Bool) bIsFinal; + PropertyChanged( aEvt ); + } + } + } + catch ( UnknownPropertyException ) {} + catch ( WrappedTargetException ) {} +} + +//------------------------------------------------------------------------- +void SortedResultSet::InsertNew( long nPos, long nCount ) +{ + // in der maS2O Liste alle Einträge, die >= nPos sind, um nCount + // erhöhen + SortListData *pData; + long i, nEnd; + + nEnd = maS2O.Count(); + for ( i=1; i<=nEnd; i++ ) + { + pData = maS2O.GetData( i ); + if ( pData->mnCurPos >= nPos ) + { + pData->mnCurPos += nCount; + } + } + + // und die neuen einträge hinten an die maS2O Liste anhängen bzw + // an der Position nPos in der maO2S Liste einfügen + for ( i=0; i<nCount; i++ ) + { + nEnd += 1; + pData = new SortListData( nEnd ); + + maS2O.Insert( pData, nEnd ); // Insert( Wert, Position ) + maO2S.Insert( (void*)nEnd, (sal_uInt32)(nPos+i) ); // Insert( Wert, Position ) + } + + mnCount += nCount; +} + +//------------------------------------------------------------------------- +void SortedResultSet::Remove( long nPos, long nCount, EventList *pEvents ) +{ + sal_uInt32 i, j; + long nOldLastSort; + + // correct mnLastSort first + nOldLastSort = mnLastSort; + if ( nPos <= mnLastSort ) + { + if ( nPos + nCount - 1 <= mnLastSort ) + mnLastSort -= nCount; + else + mnLastSort = nPos - 1; + } + + // remove the entries from the lists and correct the positions + // in the original2sorted list + for ( i=0; i < (sal_uInt32) nCount; i++ ) + { + long nSortPos = (long) maO2S.GetObject( nPos ); + maO2S.Remove( (sal_uInt32) nPos ); + + for ( j=1; j<=maO2S.Count(); j++ ) + { + long nVal = (long) maO2S.GetObject( j ); + if ( nVal > nSortPos ) + { + --nVal; + maO2S.Replace( (void*) nVal, j ); + } + } + + SortListData *pData = maS2O.Remove( nSortPos ); + if ( pData->mbModified ) + maModList.Remove( (void*) pData ); + delete pData; + + // generate remove Event, but not for new entries + if ( nSortPos <= nOldLastSort ) + pEvents->AddEvent( ListActionType::REMOVED, nSortPos, 1 ); + } + + // correct the positions in the sorted list + for ( i=1; i<= maS2O.Count(); i++ ) + { + SortListData *pData = maS2O.GetData( i ); + if ( pData->mnCurPos > nPos ) + pData->mnCurPos -= nCount; + } + + mnCount -= nCount; +} + +//------------------------------------------------------------------------- +void SortedResultSet::Move( long nPos, long nCount, long nOffset ) +{ + if ( !nOffset ) + return; + + long i, nSortPos, nTo; + SortListData *pData; + + for ( i=0; i<nCount; i++ ) + { + nSortPos = (long) maO2S.GetObject( nPos+i ); + pData = maS2O.GetData( nSortPos ); + pData->mnCurPos += nOffset; + } + + if ( nOffset < 0 ) + { + for ( i=nPos+nOffset; i<nPos; i++ ) + { + nSortPos = (long) maO2S.GetObject( i ); + pData = maS2O.GetData( nSortPos ); + pData->mnCurPos += nCount; + } + } + else + { + long nStart = nPos + nCount; + long nEnd = nStart + nOffset; + for ( i=nStart; i<nEnd; i++ ) + { + nSortPos = (long) maO2S.GetObject( i ); + pData = maS2O.GetData( nSortPos ); + pData->mnCurPos -= nCount; + } + } + + // remember the to be moved entries + long *pTmpArr = new long[ nCount ]; + for ( i=0; i<nCount; i++ ) + pTmpArr[i] = (long)maO2S.GetObject( (sal_uInt32)( nPos+i ) ); + + // now move the entries, which are in the way + if ( nOffset < 0 ) + { + // be carefully here, because nOffset is negative here, so an + // addition is a subtraction + long nFrom = nPos - 1; + nTo = nPos + nCount - 1; + + // same for i here + for ( i=0; i>nOffset; i-- ) + { + long nVal = (long) maO2S.GetObject( (sal_uInt32)( nFrom+i ) ); + maO2S.Replace( (void*) nVal, (sal_uInt32)( nTo+i ) ); + } + + } + else + { + long nStart = nPos + nCount; + for ( i=0; i<nOffset; i++ ) + { + long nVal = (long) maO2S.GetObject( (sal_uInt32)( nStart+i ) ); + maO2S.Replace( (void*) nVal, (sal_uInt32)( nPos+i ) ); + } + } + + // finally put the remembered entries at there new location + nTo = nPos + nOffset; + for ( i=0; i<nCount; i++ ) + { + maO2S.Replace( (void*)pTmpArr[ i ], (sal_uInt32)( nTo+i ) ); + } + + delete [] pTmpArr; +} + +//-------------------------------------------------------------------------- +void SortedResultSet::BuildSortInfo( + Reference< XResultSet > aResult, + const Sequence < NumberedSortingInfo > &xSortInfo, + const Reference< XAnyCompareFactory > &xCompFactory ) +{ + Reference < XResultSetMetaDataSupplier > xMeta ( aResult, UNO_QUERY ); + + if ( ! xMeta.is() ) + { + OSL_ENSURE( sal_False, "No MetaData, No Sorting!" ); + return; + } + + Reference < XResultSetMetaData > xData = xMeta->getMetaData(); + const NumberedSortingInfo *pSortInfo = xSortInfo.getConstArray(); + + sal_Int32 nColumn; + OUString aPropName; + SortInfo *pInfo; + + for ( long i=xSortInfo.getLength(); i > 0; ) + { + --i; + nColumn = pSortInfo[ i ].ColumnIndex; + aPropName = xData->getColumnName( nColumn ); + pInfo = new SortInfo; + + if ( xCompFactory.is() ) + pInfo->mxCompareFunction = xCompFactory->createAnyCompareByName( + aPropName ); + + if ( pInfo->mxCompareFunction.is() ) + { + pInfo->mbUseOwnCompare = sal_False; + pInfo->mnType = 0; + } + else + { + pInfo->mbUseOwnCompare = sal_True; + pInfo->mnType = xData->getColumnType( nColumn ); + } + + pInfo->mnColumn = nColumn; + pInfo->mbAscending = pSortInfo[ i ].Ascending; + pInfo->mbCaseSensitive = xData->isCaseSensitive( nColumn ); + pInfo->mpNext = mpSortInfo; + mpSortInfo = pInfo; + } +} + +//------------------------------------------------------------------------- +void SortedResultSet::SetChanged( long nPos, long nCount ) +{ + for ( long i=0; i<nCount; i++ ) + { + long nSortPos = (long) maO2S.GetObject( nPos ); + if ( nSortPos < mnLastSort ) + { + SortListData *pData = maS2O.GetData( nSortPos ); + if ( ! pData->mbModified ) + { + pData->mbModified = sal_True; + maModList.Append( pData ); + } + } + nPos += 1; + } +} + +//------------------------------------------------------------------------- +void SortedResultSet::ResortModified( EventList* pList ) +{ + sal_uInt32 i, j; + long nCompare, nCurPos, nNewPos; + long nStart, nEnd, nOffset, nVal; + SortListData *pData; + ListAction *pAction; + + try { + for ( i=0; i<maModList.Count(); i++ ) + { + pData = (SortListData*) maModList.GetObject( i ); + nCompare = CompareImpl( mxOther, mxOriginal, + pData->mnOldPos, pData->mnCurPos ); + pData->mbModified = sal_False; + if ( nCompare != 0 ) + { + nCurPos = (long) maO2S.GetObject( (sal_uInt32) pData->mnCurPos ); + if ( nCompare < 0 ) + { + nNewPos = FindPos( pData, 1, nCurPos-1 ); + nStart = nNewPos; + nEnd = nCurPos; + nOffset = 1; + } + else + { + nNewPos = FindPos( pData, nCurPos+1, mnLastSort ); + nStart = nCurPos; + nEnd = mnLastSort; + nOffset = -1; + } + + if ( nNewPos != nCurPos ) + { + // correct the lists! + maS2O.Remove( (sal_uInt32) nCurPos ); + maS2O.Insert( pData, nNewPos ); + for ( j=1; j<maO2S.Count(); j++ ) + { + nVal = (long) maO2S.GetObject( (sal_uInt32)( j ) ); + if ( ( nStart <= nVal ) && ( nVal <= nEnd ) ) + { + nVal += nOffset; + maO2S.Replace( (void*) (nVal), (sal_uInt32)( j ) ); + } + } + + maO2S.Replace( (void*) nNewPos, (sal_uInt32) pData->mnCurPos ); + + pAction = new ListAction; + pAction->Position = nCurPos; + pAction->Count = 1; + pAction->ListActionType = ListActionType::MOVED; + pAction->ActionInfo <<= nNewPos-nCurPos; + pList->Insert( pAction ); + } + pList->AddEvent( ListActionType::PROPERTIES_CHANGED, + nNewPos, 1 ); + } + } + } + catch ( SQLException ) { OSL_ENSURE( sal_False, "SortedResultSet::ResortModified() : Got unexpected SQLException" ); } + + maModList.Clear(); +} + +//------------------------------------------------------------------------- +void SortedResultSet::ResortNew( EventList* pList ) +{ + long i, j, nNewPos, nVal; + SortListData *pData; + + try { + for ( i = mnLastSort; i<(long)maS2O.Count(); i++ ) + { + pData = (SortListData*) maModList.GetObject( i ); + nNewPos = FindPos( pData, 1, mnLastSort ); + if ( nNewPos != i ) + { + maS2O.Remove( (sal_uInt32) i ); + maS2O.Insert( pData, nNewPos ); + // maO2S liste korigieren + for ( j=1; j<(long)maO2S.Count(); j++ ) + { + nVal = (long) maO2S.GetObject( (sal_uInt32)( j ) ); + if ( nVal >= nNewPos ) + maO2S.Replace( (void*) (nVal+1), (sal_uInt32)( j ) ); + } + maO2S.Replace( (void*) nNewPos, (sal_uInt32) pData->mnCurPos ); + } + mnLastSort++; + pList->AddEvent( ListActionType::INSERTED, nNewPos, 1 ); + } + } + catch ( SQLException ) { OSL_ENSURE( sal_False, "SortedResultSet::ResortNew() : Got unexpected SQLException" ); } +} + +//------------------------------------------------------------------------- +// +// SortListData +// +//------------------------------------------------------------------------- +SortListData::SortListData( long nPos, sal_Bool bModified ) +{ + mbModified = bModified; + mnCurPos = nPos; + mnOldPos = nPos; +}; + + +//========================================================================= +void SortedEntryList::Clear() +{ + for ( std::deque< LISTACTION* >::size_type i = 0; + i < maData.size(); ++i ) + { + delete maData[i]; + } + + maData.clear(); +} + +//------------------------------------------------------------------------- +void SortedEntryList::Insert( SortListData *pEntry, long nPos ) +{ + if ( nPos < (long) maData.size() ) + maData.insert( maData.begin() + nPos, pEntry ); + else + maData.push_back( pEntry ); +} + +//------------------------------------------------------------------------- +SortListData* SortedEntryList::Remove( long nPos ) +{ + SortListData *pData; + + if ( nPos < (long) maData.size() ) + { + pData = maData[ nPos ]; + maData.erase( maData.begin() + nPos ); + } + else + pData = NULL; + + return pData; +} + +//------------------------------------------------------------------------- +SortListData* SortedEntryList::GetData( long nPos ) +{ + SortListData *pData; + + if ( nPos < (long) maData.size() ) + pData = maData[ nPos ]; + else + pData = NULL; + + return pData; +} + +//------------------------------------------------------------------------- +long SortedEntryList::operator [] ( long nPos ) const +{ + SortListData *pData; + + if ( nPos < (long) maData.size() ) + pData = maData[ nPos ]; + else + pData = NULL; + + if ( pData ) + if ( ! pData->mbModified ) + return pData->mnCurPos; + else + { + OSL_ENSURE( sal_False, "SortedEntryList: Can't get value for modified entry!"); + return 0; + } + else + { + OSL_ENSURE( sal_False, "SortedEntryList: invalid pos!"); + return 0; + } +} + +//------------------------------------------------------------------------- +//------------------------------------------------------------------------- +//------------------------------------------------------------------------- +void SimpleList::Remove( sal_uInt32 nPos ) +{ + if ( nPos < (sal_uInt32) maData.size() ) + { + maData.erase( maData.begin() + nPos ); + } +} + +//------------------------------------------------------------------------- +void SimpleList::Remove( void* pData ) +{ + sal_Bool bFound = sal_False; + sal_uInt32 i; + + for ( i = 0; i < (sal_uInt32) maData.size(); i++ ) + { + if ( maData[ i ] == pData ) + { + bFound = sal_True; + break; + } + } + + if ( bFound ) + maData.erase( maData.begin() + i ); +} + +//------------------------------------------------------------------------- +void SimpleList::Insert( void* pData, sal_uInt32 nPos ) +{ + if ( nPos < (sal_uInt32) maData.size() ) + maData.insert( maData.begin() + nPos, pData ); + else + maData.push_back( pData ); +} + +//------------------------------------------------------------------------- +void* SimpleList::GetObject( sal_uInt32 nPos ) const +{ + if ( nPos < (sal_uInt32) maData.size() ) + return maData[ nPos ]; + else + return NULL; +} + +//------------------------------------------------------------------------- +void SimpleList::Replace( void* pData, sal_uInt32 nPos ) +{ + if ( nPos < (sal_uInt32) maData.size() ) + maData[ nPos ] = pData; +} + +//------------------------------------------------------------------------- +// +// class SRSPropertySetInfo. +// +//------------------------------------------------------------------------- + +SRSPropertySetInfo::SRSPropertySetInfo() +{ + maProps[0].Name = OUString::createFromAscii( "RowCount" ); + maProps[0].Handle = -1; + maProps[0].Type = ::getCppuType( (const OUString*) NULL ); + maProps[0].Attributes = -1; + + maProps[1].Name = OUString::createFromAscii( "IsRowCountFinal" ); + maProps[1].Handle = -1; + maProps[1].Type = ::getBooleanCppuType(); + maProps[1].Attributes = -1; +} + +//------------------------------------------------------------------------- +SRSPropertySetInfo::~SRSPropertySetInfo() +{} + +//------------------------------------------------------------------------- +// XInterface methods. +//------------------------------------------------------------------------- + +XINTERFACE_IMPL_2( SRSPropertySetInfo, + XTypeProvider, + XPropertySetInfo ); + +//------------------------------------------------------------------------- +// XTypeProvider methods. +//------------------------------------------------------------------------- + +XTYPEPROVIDER_IMPL_2( SRSPropertySetInfo, + XTypeProvider, + XPropertySetInfo ); + +//------------------------------------------------------------------------- +// XPropertySetInfo methods. +//------------------------------------------------------------------------- +Sequence< Property > SAL_CALL +SRSPropertySetInfo::getProperties() throw( RuntimeException ) +{ + return Sequence < Property > ( maProps, 2 ); +} + +//------------------------------------------------------------------------- +Property SAL_CALL +SRSPropertySetInfo::getPropertyByName( const OUString& Name ) + throw( UnknownPropertyException, RuntimeException ) +{ + if ( Name.compareToAscii( "RowCount" ) == 0 ) + return maProps[0]; + else if ( Name.compareToAscii( "IsRowCountFinal" ) == 0 ) + return maProps[1]; + else + throw UnknownPropertyException(); +} + +//------------------------------------------------------------------------- +sal_Bool SAL_CALL +SRSPropertySetInfo::hasPropertyByName( const OUString& Name ) + throw( RuntimeException ) +{ + if ( Name.compareToAscii( "RowCount" ) == 0 ) + return sal_True; + else if ( Name.compareToAscii( "IsRowCountFinal" ) == 0 ) + return sal_True; + else + return sal_False; +} + diff --git a/ucb/source/sorter/sortresult.hxx b/ucb/source/sorter/sortresult.hxx new file mode 100644 index 000000000000..3817152f3d6c --- /dev/null +++ b/ucb/source/sorter/sortresult.hxx @@ -0,0 +1,455 @@ +/************************************************************************* + * + * 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 _SORTRESULT_HXX +#define _SORTRESULT_HXX + +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XTypeProvider.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/sdbc/XCloseable.hpp> +#include <com/sun/star/sdbc/XResultSet.hpp> +#include <com/sun/star/sdbc/XResultSetMetaData.hpp> +#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp> +#include <com/sun/star/sdbc/XRow.hpp> +#include <com/sun/star/ucb/XContentAccess.hpp> +#include <com/sun/star/ucb/NumberedSortingInfo.hpp> +#include <com/sun/star/ucb/XAnyCompareFactory.hpp> +#include <com/sun/star/ucb/ListAction.hpp> +#include <cppuhelper/weak.hxx> +#include <osl/mutex.hxx> + +#include <deque> +#include <ucbhelper/macros.hxx> + +namespace cppu { + class OInterfaceContainerHelper; +} + +//----------------------------------------------------------------------------- +struct SortInfo; +struct SortListData; +class SRSPropertySetInfo; +class PropertyChangeListeners_Impl; + +//----------------------------------------------------------------------------- +class SortedEntryList +{ + std::deque < SortListData* > maData; + +public: + SortedEntryList(){} + ~SortedEntryList(){ Clear(); } + + sal_uInt32 Count() const { return (sal_uInt32) maData.size(); } + + void Clear(); + void Insert( SortListData *pEntry, long nPos ); + SortListData* Remove( long nPos ); + SortListData* GetData( long nPos ); + + long operator [] ( long nPos ) const; +}; + +//----------------------------------------------------------------------------- +#define LISTACTION com::sun::star::ucb::ListAction + +class EventList +{ + std::deque < LISTACTION* > maData; + +public: + EventList(){} + ~EventList(){ Clear(); } + + sal_uInt32 Count() { return (sal_uInt32) maData.size(); } + + void AddEvent( long nType, long nPos, long nCount ); + void Insert( LISTACTION *pAction ) { maData.push_back( pAction ); } + void Clear(); + LISTACTION* GetAction( long nIndex ) { return maData[ nIndex ]; } +}; + +//----------------------------------------------------------------------------- + +class SimpleList +{ + std::deque < void* > maData; + +public: + SimpleList(){} + ~SimpleList(){ Clear(); } + + sal_uInt32 Count() { return (sal_uInt32) maData.size(); } + void Clear() { maData.clear(); } + + void Remove( sal_uInt32 nPos ); + void Remove( void* pData ); + + void Append( void* pData ) + { maData.push_back( pData ); } + void Insert( void* pData, sal_uInt32 nPos ); + void* GetObject( sal_uInt32 nPos ) const; + void Replace( void* pData, sal_uInt32 nPos ); +}; + +//----------------------------------------------------------------------------- + +#define PROPERTYCHANGEEVENT com::sun::star::beans::PropertyChangeEvent +#define RUNTIME_EXCEPTION com::sun::star::uno::RuntimeException +#define REFERENCE com::sun::star::uno::Reference +#define SEQUENCE com::sun::star::uno::Sequence +#define XEVENTLISTENER com::sun::star::lang::XEventListener +#define XRESULTSET com::sun::star::sdbc::XResultSet +#define SQLEXCEPTION com::sun::star::sdbc::SQLException +#define XRESULTSETMETADATA com::sun::star::sdbc::XResultSetMetaData +#define NUMBERED_SORTINGINFO com::sun::star::ucb::NumberedSortingInfo +#define XANYCOMPAREFACTORY com::sun::star::ucb::XAnyCompareFactory + +#define RESULTSET_SERVICE_NAME "com.sun.star.ucb.SortedResultSet" + +//----------------------------------------------------------------------------- + +class SortedResultSet: + public cppu::OWeakObject, + public com::sun::star::lang::XTypeProvider, + public com::sun::star::lang::XServiceInfo, + public com::sun::star::lang::XComponent, + public com::sun::star::ucb::XContentAccess, + public XRESULTSET, + public com::sun::star::sdbc::XRow, + public com::sun::star::sdbc::XCloseable, + public com::sun::star::sdbc::XResultSetMetaDataSupplier, + public com::sun::star::beans::XPropertySet +{ + cppu::OInterfaceContainerHelper *mpDisposeEventListeners; + PropertyChangeListeners_Impl *mpPropChangeListeners; + PropertyChangeListeners_Impl *mpVetoChangeListeners; + + REFERENCE < XRESULTSET > mxOriginal; + REFERENCE < XRESULTSET > mxOther; + + SRSPropertySetInfo* mpPropSetInfo; + SortInfo* mpSortInfo; + osl::Mutex maMutex; + SortedEntryList maS2O; // maps the sorted entries to the original ones + SimpleList maO2S; // maps the original Entries to the sorted ones + SimpleList maModList; // keeps track of modified entries + long mnLastSort; // index of the last sorted entry; + long mnCurEntry; // index of the current entry + long mnCount; // total count of the elements + sal_Bool mbIsCopy; + + +private: + + long FindPos( SortListData *pEntry, long nStart, long nEnd ) + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + long Compare( SortListData *pOne, + SortListData *pTwo ) + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + void BuildSortInfo( REFERENCE< XRESULTSET > aResult, + const SEQUENCE < NUMBERED_SORTINGINFO > &xSortInfo, + const REFERENCE< XANYCOMPAREFACTORY > &xCompFac ); + long CompareImpl( REFERENCE < XRESULTSET > xResultOne, + REFERENCE < XRESULTSET > xResultTwo, + long nIndexOne, long nIndexTwo, + SortInfo* pSortInfo ) + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + long CompareImpl( REFERENCE < XRESULTSET > xResultOne, + REFERENCE < XRESULTSET > xResultTwo, + long nIndexOne, long nIndexTwo ) + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + void PropertyChanged( const PROPERTYCHANGEEVENT& rEvt ); + +public: + SortedResultSet( REFERENCE< XRESULTSET > aResult ); + ~SortedResultSet(); + + const SortedEntryList* GetS2OList() const { return &maS2O; } + const SimpleList* GetO2SList() const { return &maO2S; } + REFERENCE < XRESULTSET > GetResultSet() const { return mxOriginal; } + SortInfo* GetSortInfo() const { return mpSortInfo; } + long GetCount() const { return mnCount; } + + void CopyData( SortedResultSet* pSource ); + void Initialize( const SEQUENCE < NUMBERED_SORTINGINFO > &xSortInfo, + const REFERENCE< XANYCOMPAREFACTORY > &xCompFac ); + void CheckProperties( long nOldCount, sal_Bool bWasFinal ); + + void InsertNew( long nPos, long nCount ); + void SetChanged( long nPos, long nCount ); + void Remove( long nPos, long nCount, EventList *pList ); + void Move( long nPos, long nCount, long nOffset ); + + void ResortModified( EventList* pList ); + void ResortNew( EventList* pList ); + + // XInterface + XINTERFACE_DECL() + + // XTypeProvider + XTYPEPROVIDER_DECL() + + // XServiceInfo + XSERVICEINFO_NOFACTORY_DECL() + + // XComponent + virtual void SAL_CALL + dispose() throw( RUNTIME_EXCEPTION ); + + virtual void SAL_CALL + addEventListener( const REFERENCE< XEVENTLISTENER >& Listener ) + throw( RUNTIME_EXCEPTION ); + + virtual void SAL_CALL + removeEventListener( const REFERENCE< XEVENTLISTENER >& Listener ) + throw( RUNTIME_EXCEPTION ); + + // XContentAccess + virtual rtl::OUString SAL_CALL + queryContentIdentifierString() + throw( RUNTIME_EXCEPTION ); + virtual REFERENCE< + com::sun::star::ucb::XContentIdentifier > SAL_CALL + queryContentIdentifier() + throw( RUNTIME_EXCEPTION ); + virtual REFERENCE< + com::sun::star::ucb::XContent > SAL_CALL + queryContent() + throw( RUNTIME_EXCEPTION ); + + // XResultSet + virtual sal_Bool SAL_CALL + next() + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + virtual sal_Bool SAL_CALL + isBeforeFirst() + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + virtual sal_Bool SAL_CALL + isAfterLast() + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + virtual sal_Bool SAL_CALL + isFirst() + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + virtual sal_Bool SAL_CALL + isLast() + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + virtual void SAL_CALL + beforeFirst() + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + virtual void SAL_CALL + afterLast() + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + virtual sal_Bool SAL_CALL + first() + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + virtual sal_Bool SAL_CALL + last() + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + virtual sal_Int32 SAL_CALL + getRow() + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + virtual sal_Bool SAL_CALL + absolute( sal_Int32 row ) + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + virtual sal_Bool SAL_CALL + relative( sal_Int32 rows ) + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + virtual sal_Bool SAL_CALL + previous() + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + virtual void SAL_CALL + refreshRow() + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + virtual sal_Bool SAL_CALL + rowUpdated() + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + virtual sal_Bool SAL_CALL + rowInserted() + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + virtual sal_Bool SAL_CALL + rowDeleted() + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + virtual REFERENCE< + com::sun::star::uno::XInterface > SAL_CALL + getStatement() + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + + // XRow + virtual sal_Bool SAL_CALL + wasNull() throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + + virtual rtl::OUString SAL_CALL + getString( sal_Int32 columnIndex ) + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + + virtual sal_Bool SAL_CALL + getBoolean( sal_Int32 columnIndex ) + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + + virtual sal_Int8 SAL_CALL + getByte( sal_Int32 columnIndex ) + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + + virtual sal_Int16 SAL_CALL + getShort( sal_Int32 columnIndex ) + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + + virtual sal_Int32 SAL_CALL + getInt( sal_Int32 columnIndex ) + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + + virtual sal_Int64 SAL_CALL + getLong( sal_Int32 columnIndex ) + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + + virtual float SAL_CALL + getFloat( sal_Int32 columnIndex ) + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + + virtual double SAL_CALL + getDouble( sal_Int32 columnIndex ) + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + + virtual com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL + getBytes( sal_Int32 columnIndex ) + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + + virtual com::sun::star::util::Date SAL_CALL + getDate( sal_Int32 columnIndex ) + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + + virtual com::sun::star::util::Time SAL_CALL + getTime( sal_Int32 columnIndex ) + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + + virtual com::sun::star::util::DateTime SAL_CALL + getTimestamp( sal_Int32 columnIndex ) + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + + virtual REFERENCE< + com::sun::star::io::XInputStream > SAL_CALL + getBinaryStream( sal_Int32 columnIndex ) + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + + virtual REFERENCE< + com::sun::star::io::XInputStream > SAL_CALL + getCharacterStream( sal_Int32 columnIndex ) + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + + virtual com::sun::star::uno::Any SAL_CALL + getObject( sal_Int32 columnIndex, + const REFERENCE< + com::sun::star::container::XNameAccess >& typeMap ) + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + virtual REFERENCE< + com::sun::star::sdbc::XRef > SAL_CALL + getRef( sal_Int32 columnIndex ) + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + virtual REFERENCE< + com::sun::star::sdbc::XBlob > SAL_CALL + getBlob( sal_Int32 columnIndex ) + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + virtual REFERENCE< + com::sun::star::sdbc::XClob > SAL_CALL + getClob( sal_Int32 columnIndex ) + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + virtual REFERENCE< + com::sun::star::sdbc::XArray > SAL_CALL + getArray( sal_Int32 columnIndex ) + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + + // XCloseable + virtual void SAL_CALL + close() + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + + // XResultSetMetaDataSupplier + virtual REFERENCE< XRESULTSETMETADATA > SAL_CALL + getMetaData() + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + + + // XPropertySet + virtual REFERENCE< + com::sun::star::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo() + throw( RUNTIME_EXCEPTION ); + + virtual void SAL_CALL + setPropertyValue( const rtl::OUString& PropertyName, + const com::sun::star::uno::Any& Value ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::beans::PropertyVetoException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::lang::WrappedTargetException, + RUNTIME_EXCEPTION ); + + virtual com::sun::star::uno::Any SAL_CALL + getPropertyValue( const rtl::OUString& PropertyName ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::lang::WrappedTargetException, + RUNTIME_EXCEPTION ); + + virtual void SAL_CALL + addPropertyChangeListener( const rtl::OUString& PropertyName, + const REFERENCE< + com::sun::star::beans::XPropertyChangeListener >& Listener ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::lang::WrappedTargetException, + RUNTIME_EXCEPTION ); + + virtual void SAL_CALL + removePropertyChangeListener( const rtl::OUString& PropertyName, + const REFERENCE< + com::sun::star::beans::XPropertyChangeListener >& Listener ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::lang::WrappedTargetException, + RUNTIME_EXCEPTION ); + + virtual void SAL_CALL + addVetoableChangeListener( const rtl::OUString& PropertyName, + const REFERENCE< + com::sun::star::beans::XVetoableChangeListener >& Listener ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::lang::WrappedTargetException, + RUNTIME_EXCEPTION ); + + virtual void SAL_CALL + removeVetoableChangeListener( const rtl::OUString& PropertyName, + const REFERENCE< + com::sun::star::beans::XVetoableChangeListener >& aListener ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::lang::WrappedTargetException, + RUNTIME_EXCEPTION ); +}; + +#endif + diff --git a/ucb/source/sorter/srtrs.xml b/ucb/source/sorter/srtrs.xml new file mode 100644 index 000000000000..51626a1e6acc --- /dev/null +++ b/ucb/source/sorter/srtrs.xml @@ -0,0 +1,66 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE module-description PUBLIC "-//StarOffice//DTD ComponentDescription 1.0//EN" "module-description.dtd"> +<module-description xmlns:xlink="http://www.w3.org/1999/xlink"> + + <module-name> + srtrs + </module-name> + + <component-description> + <author> + Dirk Voelzke + </author> + <name> + com.sun.star.comp.ucb.SortedDynamicResultSetFactory + </name> + <description> + This component implements a factory for sorted Content Resultsets. + It can be used to sort resultsets obtained from UCB folder contents. + </description> + <loader-name> + com.sun.star.loader.SharedLibrary + </loader-name> + <language> + c++ + </language> + <status value="final"/> + <supported-service> + com.sun.star.ucb.SortedDynamicResultSetFactory + </supported-service> + + <service-dependency> + com.sun.star.ucb.CachedDynamicResultSetStubFactory + </service-dependency> + </component-description> + + <project-build-dependency> sal </project-build-dependency> + <project-build-dependency> cppu </project-build-dependency> + <project-build-dependency> cppuhelper </project-build-dependency> + + <runtime-module-dependency> sal3 </runtime-module-dependency> + <runtime-module-dependency> cppu3 </runtime-module-dependency> + <runtime-module-dependency> cppuhelper3$(COM) </runtime-module-dependency> + + <type> com.sun.star.beans.XPropertySet </type> + <type> com.sun.star.lang.XComponent </type> + <type> com.sun.star.lang.XMultiServiceFactory </type> + <type> com.sun.star.lang.XSingleServiceFactory </type> + <type> com.sun.star.lang.XServiceInfo </type> + <type> com.sun.star.lang.XTypeProvider </type> + <type> com.sun.star.registry.XRegistryKey </type> + <type> com.sun.star.sdbc.DataType </type> + <type> com.sun.star.sdbc.XCloseable </type> + <type> com.sun.star.sdbc.XResultSet </type> + <type> com.sun.star.sdbc.XResultSetMetaDataSupplier </type> + <type> com.sun.star.sdbc.XRow </type> + <type> com.sun.star.ucb.ContentResultSetCapability </type> + <type> com.sun.star.ucb.ListActionType </type> + <type> com.sun.star.ucb.NumberedSortingInfo </type> + <type> com.sun.star.ucb.WelcomeDynamicResultSetStruct </type> + <type> com.sun.star.ucb.XCachedDynamicResultSetStubFactory </type> + <type> com.sun.star.ucb.XContentAccess </type> + <type> com.sun.star.ucb.XDynamicResultSet </type> + <type> com.sun.star.ucb.XSortedDynamicResultSetFactory </type> + <type> com.sun.star.ucb.XSourceInitialization </type> + <type> com.sun.star.uno.XWeak </type> +</module-description> diff --git a/ucb/source/sorter/srtrs1.component b/ucb/source/sorter/srtrs1.component new file mode 100644 index 000000000000..c32705160c0f --- /dev/null +++ b/ucb/source/sorter/srtrs1.component @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* 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. +* +**********************************************************************--> + +<component loader="com.sun.star.loader.SharedLibrary" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.ucb.SortedDynamicResultSetFactory"> + <service name="com.sun.star.ucb.SortedDynamicResultSetFactory"/> + </implementation> +</component> diff --git a/ucb/source/ucp/expand/makefile.mk b/ucb/source/ucp/expand/makefile.mk new file mode 100644 index 000000000000..70e441171a44 --- /dev/null +++ b/ucb/source/ucp/expand/makefile.mk @@ -0,0 +1,69 @@ +#************************************************************************* +# +# 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 = ucb +UCPEXPAND_MAJOR = 1 +TARGET = ucpexpand$(UCPEXPAND_MAJOR).uno +ENABLE_EXCEPTIONS = TRUE +NO_BSYMBOLIC = TRUE + +.INCLUDE : settings.mk +DLLPRE = + +.IF "$(L10N_framework)"=="" + +SLOFILES= \ + $(SLO)$/ucpexpand.obj + +SHL1STDLIBS = \ + $(UCBHELPERLIB) \ + $(CPPUHELPERLIB) \ + $(CPPULIB) \ + $(SALLIB) + +SHL1VERSIONMAP = $(SOLARENV)/src/component.map +SHL1TARGET = $(TARGET) + +SHL1DEPN = +SHL1IMPLIB = i$(TARGET) +SHL1LIBS = $(SLB)$/$(TARGET).lib +SHL1DEF = $(MISC)$/$(SHL1TARGET).def + +DEF1NAME = $(SHL1TARGET) + +.ENDIF # L10N_framework + +.INCLUDE : target.mk + +ALLTAR : $(MISC)/ucpexpand1.component + +$(MISC)/ucpexpand1.component .ERRREMOVE : $(SOLARENV)/bin/createcomponent.xslt \ + ucpexpand1.component + $(XSLTPROC) --nonet --stringparam uri \ + '$(COMPONENTPREFIX_BASIS_NATIVE)$(SHL1TARGETN:f)' -o $@ \ + $(SOLARENV)/bin/createcomponent.xslt ucpexpand1.component diff --git a/ucb/source/ucp/expand/ucpexpand.cxx b/ucb/source/ucp/expand/ucpexpand.cxx new file mode 100644 index 000000000000..069aa894692b --- /dev/null +++ b/ucb/source/ucp/expand/ucpexpand.cxx @@ -0,0 +1,285 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +#include "rtl/uri.hxx" +#include "osl/mutex.hxx" +#include "cppuhelper/compbase2.hxx" +#include "cppuhelper/factory.hxx" +#include "cppuhelper/implementationentry.hxx" +#include "ucbhelper/content.hxx" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/lang/DisposedException.hpp" +#include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/lang/XMultiServiceFactory.hpp" +#include "com/sun/star/registry/XRegistryKey.hpp" +#include "com/sun/star/util/XMacroExpander.hpp" +#include "com/sun/star/ucb/XContentProvider.hpp" + +#define EXPAND_PROTOCOL "vnd.sun.star.expand" +#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) +#define ARLEN(x) sizeof (x) / sizeof *(x) + + +using namespace ::com::sun::star; +using ::rtl::OUString; + +namespace +{ + +struct MutexHolder +{ + mutable ::osl::Mutex m_mutex; +}; + +typedef ::cppu::WeakComponentImplHelper2< + lang::XServiceInfo, ucb::XContentProvider > t_impl_helper; + +//============================================================================== +class ExpandContentProviderImpl : protected MutexHolder, public t_impl_helper +{ + uno::Reference< util::XMacroExpander > m_xMacroExpander; + OUString expandUri( + uno::Reference< ucb::XContentIdentifier > const & xIdentifier ) const; + +protected: + inline void check() const; + virtual void SAL_CALL disposing(); + +public: + inline ExpandContentProviderImpl( + uno::Reference< uno::XComponentContext > const & xComponentContext ) + : t_impl_helper( m_mutex ), + m_xMacroExpander( + xComponentContext->getValueByName( + OUSTR("/singletons/com.sun.star.util.theMacroExpander") ), + uno::UNO_QUERY_THROW ) + {} + virtual ~ExpandContentProviderImpl() throw (); + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() + throw (uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( OUString const & serviceName ) + throw (uno::RuntimeException); + virtual uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() + throw (uno::RuntimeException); + + // XContentProvider + virtual uno::Reference< ucb::XContent > SAL_CALL queryContent( + uno::Reference< ucb::XContentIdentifier > const & xIdentifier ) + throw (ucb::IllegalIdentifierException, uno::RuntimeException); + virtual sal_Int32 SAL_CALL compareContentIds( + uno::Reference< ucb::XContentIdentifier > const & xId1, + uno::Reference< ucb::XContentIdentifier > const & xId2 ) + throw (uno::RuntimeException); +}; + +//______________________________________________________________________________ +inline void ExpandContentProviderImpl::check() const +{ + // xxx todo guard? +// MutexGuard guard( m_mutex ); + if (rBHelper.bInDispose || rBHelper.bDisposed) + { + throw lang::DisposedException( + OUSTR("expand content provider instance has " + "already been disposed!"), + static_cast< OWeakObject * >( + const_cast< ExpandContentProviderImpl * >(this) ) ); + } +} + +//______________________________________________________________________________ +ExpandContentProviderImpl::~ExpandContentProviderImpl() throw () +{ +} + +//______________________________________________________________________________ +void ExpandContentProviderImpl::disposing() +{ +} + +//============================================================================== +static uno::Reference< uno::XInterface > SAL_CALL create( + uno::Reference< uno::XComponentContext > const & xComponentContext ) + SAL_THROW( (uno::Exception) ) +{ + return static_cast< ::cppu::OWeakObject * >( + new ExpandContentProviderImpl( xComponentContext ) ); +} + +//============================================================================== +static OUString SAL_CALL implName() +{ + return OUSTR("com.sun.star.comp.ucb.ExpandContentProvider"); +} + +//============================================================================== +static uno::Sequence< OUString > SAL_CALL supportedServices() +{ + OUString names [] = { + OUSTR("com.sun.star.ucb.ExpandContentProvider"), + OUSTR("com.sun.star.ucb.ContentProvider") + }; + return uno::Sequence< OUString >( names, ARLEN(names) ); +} + +// XServiceInfo +//______________________________________________________________________________ +OUString ExpandContentProviderImpl::getImplementationName() + throw (uno::RuntimeException) +{ + check(); + return implName(); +} + +//______________________________________________________________________________ +uno::Sequence< OUString > ExpandContentProviderImpl::getSupportedServiceNames() + throw (uno::RuntimeException) +{ + check(); + return supportedServices(); +} + +//______________________________________________________________________________ +sal_Bool ExpandContentProviderImpl::supportsService( + OUString const & serviceName ) + throw (uno::RuntimeException) +{ +// check(); + uno::Sequence< OUString > supported_services( getSupportedServiceNames() ); + OUString const * ar = supported_services.getConstArray(); + for ( sal_Int32 pos = supported_services.getLength(); pos--; ) + { + if (ar[ pos ].equals( serviceName )) + return true; + } + return false; +} + +//______________________________________________________________________________ +OUString ExpandContentProviderImpl::expandUri( + uno::Reference< ucb::XContentIdentifier > const & xIdentifier ) const +{ + OUString uri( xIdentifier->getContentIdentifier() ); + if (uri.compareToAscii( + RTL_CONSTASCII_STRINGPARAM(EXPAND_PROTOCOL ":") ) != 0) + { + throw ucb::IllegalIdentifierException( + OUSTR("expected protocol " EXPAND_PROTOCOL "!"), + static_cast< OWeakObject * >( + const_cast< ExpandContentProviderImpl * >(this) ) ); + } + // cut protocol + OUString str( uri.copy( sizeof (EXPAND_PROTOCOL ":") -1 ) ); + // decode uric class chars + str = ::rtl::Uri::decode( + str, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8 ); + // expand macro string + return m_xMacroExpander->expandMacros( str ); +} + +// XContentProvider +//______________________________________________________________________________ +uno::Reference< ucb::XContent > ExpandContentProviderImpl::queryContent( + uno::Reference< ucb::XContentIdentifier > const & xIdentifier ) + throw (ucb::IllegalIdentifierException, uno::RuntimeException) +{ + check(); + OUString uri( expandUri( xIdentifier ) ); + + ::ucbhelper::Content ucb_content; + if (::ucbhelper::Content::create( + uri, uno::Reference< ucb::XCommandEnvironment >(), ucb_content )) + { + return ucb_content.get(); + } + else + { + return uno::Reference< ucb::XContent >(); + } +} + +//______________________________________________________________________________ +sal_Int32 ExpandContentProviderImpl::compareContentIds( + uno::Reference< ucb::XContentIdentifier > const & xId1, + uno::Reference< ucb::XContentIdentifier > const & xId2 ) + throw (uno::RuntimeException) +{ + check(); + try + { + OUString uri1( expandUri( xId1 ) ); + OUString uri2( expandUri( xId2 ) ); + return uri1.compareTo( uri2 ); + } + catch (ucb::IllegalIdentifierException & exc) + { + (void) exc; // unused + OSL_ENSURE( + 0, ::rtl::OUStringToOString( + exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() ); + return -1; + } +} + +static const ::cppu::ImplementationEntry s_entries [] = +{ + { + create, + implName, + supportedServices, + ::cppu::createSingleComponentFactory, + 0, 0 + }, + { 0, 0, 0, 0, 0, 0 } +}; + +} + +extern "C" +{ + +void SAL_CALL component_getImplementationEnvironment( + const sal_Char ** ppEnvTypeName, uno_Environment ** ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + +void * SAL_CALL component_getFactory( + const sal_Char * pImplName, + lang::XMultiServiceFactory * pServiceManager, + registry::XRegistryKey * pRegistryKey ) +{ + return ::cppu::component_getFactoryHelper( + pImplName, pServiceManager, pRegistryKey, s_entries ); +} + +} diff --git a/ucb/source/ucp/expand/ucpexpand1.component b/ucb/source/ucp/expand/ucpexpand1.component new file mode 100644 index 000000000000..c8a7e8e18c68 --- /dev/null +++ b/ucb/source/ucp/expand/ucpexpand1.component @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* 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. +* +**********************************************************************--> + +<component loader="com.sun.star.loader.SharedLibrary" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.ucb.ExpandContentProvider"> + <service name="com.sun.star.ucb.ExpandContentProvider"/> + </implementation> +</component> diff --git a/ucb/source/ucp/ext/makefile.mk b/ucb/source/ucp/ext/makefile.mk new file mode 100644 index 000000000000..e106b8e1ba31 --- /dev/null +++ b/ucb/source/ucp/ext/makefile.mk @@ -0,0 +1,73 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.4 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ = ..$/..$/.. +PRJNAME = ucb +TARGET = ucpext.uno +ENABLE_EXCEPTIONS = TRUE + +.INCLUDE : settings.mk +DLLPRE = + +SLOFILES= \ + $(SLO)$/ucpext_provider.obj \ + $(SLO)$/ucpext_content.obj \ + $(SLO)$/ucpext_services.obj \ + $(SLO)$/ucpext_resultset.obj \ + $(SLO)$/ucpext_datasupplier.obj + +SHL1STDLIBS = \ + $(UCBHELPERLIB) \ + $(COMPHELPERLIB) \ + $(CPPUHELPERLIB) \ + $(CPPULIB) \ + $(SALLIB) \ + $(SALHELPERLIB) + +SHL1VERSIONMAP = $(SOLARENV)/src/component.map +SHL1TARGET = $(TARGET) + +SHL1DEPN = +SHL1IMPLIB = i$(TARGET) +SHL1LIBS = $(SLB)$/$(TARGET).lib +SHL1DEF = $(MISC)$/$(SHL1TARGET).def + +DEF1NAME = $(SHL1TARGET) + +.INCLUDE : target.mk + +ALLTAR : $(MISC)/ucpext.component + +$(MISC)/ucpext.component .ERRREMOVE : $(SOLARENV)/bin/createcomponent.xslt \ + ucpext.component + $(XSLTPROC) --nonet --stringparam uri \ + '$(COMPONENTPREFIX_BASIS_NATIVE)$(SHL1TARGETN:f)' -o $@ \ + $(SOLARENV)/bin/createcomponent.xslt ucpext.component diff --git a/ucb/source/ucp/ext/ucpext.component b/ucb/source/ucp/ext/ucpext.component new file mode 100644 index 000000000000..2982529e539c --- /dev/null +++ b/ucb/source/ucp/ext/ucpext.component @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* 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. +* +**********************************************************************--> + +<component loader="com.sun.star.loader.SharedLibrary" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="org.openoffice.comp.ucp.ext.ContentProvider"> + <service name="com.sun.star.ucb.ExtensionContentProvider"/> + </implementation> +</component> diff --git a/ucb/source/ucp/ext/ucpext_content.cxx b/ucb/source/ucp/ext/ucpext_content.cxx new file mode 100644 index 000000000000..7b7ada742840 --- /dev/null +++ b/ucb/source/ucp/ext/ucpext_content.cxx @@ -0,0 +1,672 @@ +/************************************************************************* + * 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 "precompiled_ucb.hxx" + +#include "ucpext_content.hxx" + +#include "ucpext_content.hxx" +#include "ucpext_provider.hxx" +#include "ucpext_resultset.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/beans/XPropertyAccess.hpp> +#include <com/sun/star/lang/IllegalAccessException.hpp> +#include <com/sun/star/sdbc/XRow.hpp> +#include <com/sun/star/ucb/XCommandInfo.hpp> +#include <com/sun/star/ucb/XPersistentPropertySet.hpp> +#include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/io/XActiveDataSink.hpp> +#include <com/sun/star/ucb/OpenCommandArgument2.hpp> +#include <com/sun/star/ucb/OpenMode.hpp> +#include <com/sun/star/ucb/UnsupportedDataSinkException.hpp> +#include <com/sun/star/ucb/UnsupportedOpenModeException.hpp> +#include <com/sun/star/ucb/OpenCommandArgument2.hpp> +#include <com/sun/star/ucb/OpenMode.hpp> +#include <com/sun/star/ucb/XDynamicResultSet.hpp> +#include <com/sun/star/lang/IllegalAccessException.hpp> +#include <com/sun/star/deployment/XPackageInformationProvider.hpp> +/** === end UNO includes === **/ + +#include <ucbhelper/contentidentifier.hxx> +#include <ucbhelper/propertyvalueset.hxx> +#include <ucbhelper/cancelcommandexecution.hxx> +#include <ucbhelper/content.hxx> +#include <tools/diagnose_ex.h> +#include <comphelper/string.hxx> +#include <comphelper/componentcontext.hxx> +#include <rtl/ustrbuf.hxx> +#include <rtl/uri.hxx> + +#include <algorithm> + +//...................................................................................................................... +namespace ucb { namespace ucp { namespace ext +{ +//...................................................................................................................... + + /** === begin UNO using === **/ + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::XInterface; + using ::com::sun::star::uno::UNO_QUERY; + using ::com::sun::star::uno::UNO_QUERY_THROW; + using ::com::sun::star::uno::UNO_SET_THROW; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::uno::RuntimeException; + using ::com::sun::star::uno::Any; + using ::com::sun::star::uno::makeAny; + using ::com::sun::star::uno::Sequence; + using ::com::sun::star::uno::Type; + using ::com::sun::star::lang::XMultiServiceFactory; + using ::com::sun::star::ucb::XContentIdentifier; + using ::com::sun::star::ucb::IllegalIdentifierException; + using ::com::sun::star::ucb::XContent; + using ::com::sun::star::ucb::XCommandEnvironment; + using ::com::sun::star::ucb::Command; + using ::com::sun::star::ucb::CommandAbortedException; + using ::com::sun::star::beans::Property; + using ::com::sun::star::lang::IllegalArgumentException; + using ::com::sun::star::beans::PropertyValue; + using ::com::sun::star::ucb::OpenCommandArgument2; + using ::com::sun::star::ucb::XDynamicResultSet; + using ::com::sun::star::ucb::UnsupportedOpenModeException; + using ::com::sun::star::io::XOutputStream; + using ::com::sun::star::io::XActiveDataSink; + using ::com::sun::star::io::XInputStream; + using ::com::sun::star::ucb::UnsupportedDataSinkException; + using ::com::sun::star::ucb::UnsupportedCommandException; + using ::com::sun::star::sdbc::XRow; + using ::com::sun::star::beans::XPropertySet; + using ::com::sun::star::beans::PropertyChangeEvent; + using ::com::sun::star::lang::IllegalAccessException; + using ::com::sun::star::ucb::CommandInfo; + using ::com::sun::star::deployment::XPackageInformationProvider; + /** === end UNO using === **/ + namespace OpenMode = ::com::sun::star::ucb::OpenMode; + namespace PropertyAttribute = ::com::sun::star::beans::PropertyAttribute; + + //================================================================================================================== + //= helper + //================================================================================================================== + namespace + { + //-------------------------------------------------------------------------------------------------------------- + ::rtl::OUString lcl_compose( const ::rtl::OUString& i_rBaseURL, const ::rtl::OUString& i_rRelativeURL ) + { + ENSURE_OR_RETURN( i_rBaseURL.getLength(), "illegal base URL", i_rRelativeURL ); + + ::rtl::OUStringBuffer aComposer( i_rBaseURL ); + if ( i_rBaseURL.getStr()[ i_rBaseURL.getLength() - 1 ] != '/' ) + aComposer.append( sal_Unicode( '/' ) ); + aComposer.append( i_rRelativeURL ); + return aComposer.makeStringAndClear(); + } + + //-------------------------------------------------------------------------------------------------------------- + struct SelectPropertyName : public ::std::unary_function< Property, ::rtl::OUString > + { + const ::rtl::OUString& operator()( const Property& i_rProperty ) const + { + return i_rProperty.Name; + } + }; + } + + //================================================================================================================== + //= Content + //================================================================================================================== + //------------------------------------------------------------------------------------------------------------------ + Content::Content( const Reference< XMultiServiceFactory >& i_rORB, ::ucbhelper::ContentProviderImplHelper* i_pProvider, + const Reference< XContentIdentifier >& i_rIdentifier ) + :Content_Base( i_rORB, i_pProvider, i_rIdentifier ) + ,m_eExtContentType( E_UNKNOWN ) + ,m_aIsFolder() + ,m_aContentType() + ,m_sExtensionId() + ,m_sPathIntoExtension() + { + const ::rtl::OUString sURL( getIdentifier()->getContentIdentifier() ); + if ( denotesRootContent( sURL ) ) + { + m_eExtContentType = E_ROOT; + } + else + { + const ::rtl::OUString sRelativeURL( sURL.copy( ContentProvider::getRootURL().getLength() ) ); + const sal_Int32 nSepPos = sRelativeURL.indexOf( '/' ); + if ( ( nSepPos == -1 ) || ( nSepPos == sRelativeURL.getLength() - 1 ) ) + { + m_eExtContentType = E_EXTENSION_ROOT; + } + else + { + m_eExtContentType = E_EXTENSION_CONTENT; + } + } + + if ( m_eExtContentType != E_ROOT ) + { + const ::rtl::OUString sRootURL = ContentProvider::getRootURL(); + m_sExtensionId = sURL.copy( sRootURL.getLength() ); + + const sal_Int32 nNextSep = m_sExtensionId.indexOf( '/' ); + if ( nNextSep > -1 ) + { + m_sPathIntoExtension = m_sExtensionId.copy( nNextSep + 1 ); + m_sExtensionId = m_sExtensionId.copy( 0, nNextSep ); + } + m_sExtensionId = Content::decodeIdentifier( m_sExtensionId ); + } + } + + //------------------------------------------------------------------------------------------------------------------ + Content::~Content() + { + } + + //------------------------------------------------------------------------------------------------------------------ + ::rtl::OUString SAL_CALL Content::getImplementationName() throw( RuntimeException ) + { + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.comp.ucp.ext.Content" ) ); + } + + //------------------------------------------------------------------------------------------------------------------ + Sequence< ::rtl::OUString > SAL_CALL Content::getSupportedServiceNames() throw( RuntimeException ) + { + Sequence< ::rtl::OUString > aServiceNames(2); + aServiceNames[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ucb.Content" ) ); + aServiceNames[1] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ucb.ExtensionContent" ) ); + return aServiceNames; + } + + //------------------------------------------------------------------------------------------------------------------ + ::rtl::OUString SAL_CALL Content::getContentType() throw( RuntimeException ) + { + impl_determineContentType(); + return *m_aContentType; + } + + //------------------------------------------------------------------------------------------------------------------ + Any SAL_CALL Content::execute( const Command& aCommand, sal_Int32 /* CommandId */, const Reference< XCommandEnvironment >& i_rEvironment ) + throw( Exception, CommandAbortedException, RuntimeException ) + { + Any aRet; + + if ( aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "getPropertyValues" ) ) ) + { + Sequence< Property > Properties; + if ( !( aCommand.Argument >>= Properties ) ) + { + ::ucbhelper::cancelCommandExecution( makeAny( IllegalArgumentException( + ::rtl::OUString(), *this, -1 ) ), + i_rEvironment ); + // unreachable + } + + aRet <<= getPropertyValues( Properties, i_rEvironment ); + } + else if ( aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "setPropertyValues" ) ) ) + { + Sequence< PropertyValue > aProperties; + if ( !( aCommand.Argument >>= aProperties ) ) + { + ::ucbhelper::cancelCommandExecution( makeAny( IllegalArgumentException( + ::rtl::OUString(), *this, -1 ) ), + i_rEvironment ); + // unreachable + } + + if ( !aProperties.getLength() ) + { + ::ucbhelper::cancelCommandExecution( makeAny( IllegalArgumentException( + ::rtl::OUString(), *this, -1 ) ), + i_rEvironment ); + // unreachable + } + + aRet <<= setPropertyValues( aProperties, i_rEvironment ); + } + else if ( aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "getPropertySetInfo" ) ) ) + { + // implemented by base class. + aRet <<= getPropertySetInfo( i_rEvironment ); + } + else if ( aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "getCommandInfo" ) ) ) + { + // implemented by base class. + aRet <<= getCommandInfo( i_rEvironment ); + } + else if ( aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "open" ) ) ) + { + OpenCommandArgument2 aOpenCommand; + if ( !( aCommand.Argument >>= aOpenCommand ) ) + { + ::ucbhelper::cancelCommandExecution( makeAny( IllegalArgumentException( + ::rtl::OUString(), *this, -1 ) ), + i_rEvironment ); + // unreachable + } + + sal_Bool bOpenFolder = + ( ( aOpenCommand.Mode == OpenMode::ALL ) || + ( aOpenCommand.Mode == OpenMode::FOLDERS ) || + ( aOpenCommand.Mode == OpenMode::DOCUMENTS ) ); + + + if ( bOpenFolder && impl_isFolder() ) + { + Reference< XDynamicResultSet > xSet = new ResultSet( + m_xSMgr, this, aOpenCommand, i_rEvironment ); + aRet <<= xSet; + } + + if ( aOpenCommand.Sink.is() ) + { + const ::rtl::OUString sPhysicalContentURL( getPhysicalURL() ); + ::ucbhelper::Content aRequestedContent( sPhysicalContentURL, i_rEvironment ); + aRet = aRequestedContent.executeCommand( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "open" ) ), makeAny( aOpenCommand ) ); + } + } + + else + { + ::ucbhelper::cancelCommandExecution( makeAny( UnsupportedCommandException( + ::rtl::OUString(), *this ) ), + i_rEvironment ); + // unreachable + } + + return aRet; + } + + //------------------------------------------------------------------------------------------------------------------ + void SAL_CALL Content::abort( sal_Int32 ) throw( RuntimeException ) + { + } + + //------------------------------------------------------------------------------------------------------------------ + ::rtl::OUString Content::encodeIdentifier( const ::rtl::OUString& i_rIdentifier ) + { + return ::rtl::Uri::encode( i_rIdentifier, rtl_UriCharClassRegName, rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8 ); + } + + //------------------------------------------------------------------------------------------------------------------ + ::rtl::OUString Content::decodeIdentifier( const ::rtl::OUString& i_rIdentifier ) + { + return ::rtl::Uri::decode( i_rIdentifier, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8 ); + } + + //------------------------------------------------------------------------------------------------------------------ + bool Content::denotesRootContent( const ::rtl::OUString& i_rContentIdentifier ) + { + const ::rtl::OUString sRootURL( ContentProvider::getRootURL() ); + if ( i_rContentIdentifier == sRootURL ) + return true; + + // the root URL contains only two trailing /, but we also recognize 3 of them as denoting the root URL + if ( i_rContentIdentifier.match( sRootURL ) + && ( i_rContentIdentifier.getLength() == sRootURL.getLength() + 1 ) + && ( i_rContentIdentifier[ i_rContentIdentifier.getLength() - 1 ] == '/' ) + ) + return true; + + return false; + } + + //------------------------------------------------------------------------------------------------------------------ + ::rtl::OUString Content::getParentURL() + { + const ::rtl::OUString sRootURL( ContentProvider::getRootURL() ); + + switch ( m_eExtContentType ) + { + case E_ROOT: + // don't have a parent + return sRootURL; + + case E_EXTENSION_ROOT: + // our parent is the root itself + return sRootURL; + + case E_EXTENSION_CONTENT: + { + const ::rtl::OUString sURL = m_xIdentifier->getContentIdentifier(); + + // cut the root URL + ENSURE_OR_BREAK( sURL.match( sRootURL, 0 ), "illegal URL structure - no root" ); + ::rtl::OUString sRelativeURL( sURL.copy( sRootURL.getLength() ) ); + + // cut the extension ID + const ::rtl::OUString sSeparatedExtensionId( encodeIdentifier( m_sExtensionId ) + ::rtl::OUString( sal_Unicode( '/' ) ) ); + ENSURE_OR_BREAK( sRelativeURL.match( sSeparatedExtensionId ), "illegal URL structure - no extension ID" ); + sRelativeURL = sRelativeURL.copy( sSeparatedExtensionId.getLength() ); + + // cut the final slash (if any) + ENSURE_OR_BREAK( sRelativeURL.getLength(), "illegal URL structure - ExtensionContent should have a level below the extension ID" ); + if ( sRelativeURL.getStr()[ sRelativeURL.getLength() - 1 ] == '/' ) + sRelativeURL = sRelativeURL.copy( 0, sRelativeURL.getLength() - 1 ); + + // remove the last segment + const sal_Int32 nLastSep = sRelativeURL.lastIndexOf( '/' ); + sRelativeURL = sRelativeURL.copy( 0, nLastSep != -1 ? nLastSep : 0 ); + + ::rtl::OUStringBuffer aComposer; + aComposer.append( sRootURL ); + aComposer.append( sSeparatedExtensionId ); + aComposer.append( sRelativeURL ); + return aComposer.makeStringAndClear(); + } + + default: + OSL_ENSURE( false, "Content::getParentURL: unhandled case!" ); + break; + } + return ::rtl::OUString(); + } + + //------------------------------------------------------------------------------------------------------------------ + Reference< XRow > Content::getArtificialNodePropertyValues( const Reference< XMultiServiceFactory >& i_rORB, + const Sequence< Property >& i_rProperties, const ::rtl::OUString& i_rTitle ) + { + // note: empty sequence means "get values of all supported properties". + ::rtl::Reference< ::ucbhelper::PropertyValueSet > xRow = new ::ucbhelper::PropertyValueSet( i_rORB ); + + const sal_Int32 nCount = i_rProperties.getLength(); + if ( nCount ) + { + Reference< XPropertySet > xAdditionalPropSet; + + const Property* pProps = i_rProperties.getConstArray(); + for ( sal_Int32 n = 0; n < nCount; ++n ) + { + const Property& rProp = pProps[ n ]; + + // Process Core properties. + if ( rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) ) + { + xRow->appendString ( rProp, ContentProvider::getArtificialNodeContentType() ); + } + else if ( rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Title" ) ) ) + { + xRow->appendString ( rProp, i_rTitle ); + } + else if ( rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) ) + { + xRow->appendBoolean( rProp, sal_False ); + } + else if ( rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) ) + { + xRow->appendBoolean( rProp, sal_True ); + } + else + { + // append empty entry. + xRow->appendVoid( rProp ); + } + } + } + else + { + // Append all Core Properties. + xRow->appendString ( Property( ::rtl::OUString::createFromAscii( "ContentType" ), + -1, + getCppuType( static_cast< const ::rtl::OUString * >( 0 ) ), + PropertyAttribute::BOUND | PropertyAttribute::READONLY ), + ContentProvider::getArtificialNodeContentType() ); + xRow->appendString ( Property( ::rtl::OUString::createFromAscii( "Title" ), + -1, + getCppuType( static_cast< const ::rtl::OUString * >( 0 ) ), + PropertyAttribute::BOUND | PropertyAttribute::READONLY ), + i_rTitle ); + xRow->appendBoolean( Property( ::rtl::OUString::createFromAscii( "IsDocument" ), + -1, + getCppuBooleanType(), + PropertyAttribute::BOUND | PropertyAttribute::READONLY ), + sal_False ); + xRow->appendBoolean( Property( ::rtl::OUString::createFromAscii( "IsFolder" ), + -1, + getCppuBooleanType(), + PropertyAttribute::BOUND | PropertyAttribute::READONLY ), + sal_True ); + } + + return Reference< XRow >( xRow.get() ); + } + + //------------------------------------------------------------------------------------------------------------------ + ::rtl::OUString Content::getPhysicalURL() const + { + ENSURE_OR_RETURN( m_eExtContentType != E_ROOT, "illegal call", ::rtl::OUString() ); + + // create an ucb::XContent for the physical file within the deployed extension + const ::comphelper::ComponentContext aContext( m_xSMgr ); + const Reference< XPackageInformationProvider > xPackageInfo( + aContext.getSingleton( "com.sun.star.deployment.PackageInformationProvider" ), UNO_QUERY_THROW ); + const ::rtl::OUString sPackageLocation( xPackageInfo->getPackageLocation( m_sExtensionId ) ); + + if ( m_sPathIntoExtension.getLength() == 0 ) + return sPackageLocation; + return lcl_compose( sPackageLocation, m_sPathIntoExtension ); + } + + //------------------------------------------------------------------------------------------------------------------ + Reference< XRow > Content::getPropertyValues( const Sequence< Property >& i_rProperties, const Reference< XCommandEnvironment >& i_rEnv ) + { + ::osl::Guard< ::osl::Mutex > aGuard( m_aMutex ); + + switch ( m_eExtContentType ) + { + case E_ROOT: + return getArtificialNodePropertyValues( m_xSMgr, i_rProperties, ContentProvider::getRootURL() ); + case E_EXTENSION_ROOT: + return getArtificialNodePropertyValues( m_xSMgr, i_rProperties, m_sExtensionId ); + case E_EXTENSION_CONTENT: + { + const ::rtl::OUString sPhysicalContentURL( getPhysicalURL() ); + ::ucbhelper::Content aRequestedContent( sPhysicalContentURL, i_rEnv ); + + // translate the property request + Sequence< ::rtl::OUString > aPropertyNames( i_rProperties.getLength() ); + ::std::transform( + i_rProperties.getConstArray(), + i_rProperties.getConstArray() + i_rProperties.getLength(), + aPropertyNames.getArray(), + SelectPropertyName() + ); + const Sequence< Any > aPropertyValues = aRequestedContent.getPropertyValues( aPropertyNames ); + const ::rtl::Reference< ::ucbhelper::PropertyValueSet > xValueRow = new ::ucbhelper::PropertyValueSet( m_xSMgr ); + sal_Int32 i=0; + for ( const Any* value = aPropertyValues.getConstArray(); + value != aPropertyValues.getConstArray() + aPropertyValues.getLength(); + ++value, ++i + ) + { + xValueRow->appendObject( aPropertyNames[i], *value ); + } + return xValueRow.get(); + } + + default: + OSL_ENSURE( false, "Content::getPropertyValues: unhandled case!" ); + break; + } + + OSL_ENSURE( false, "Content::getPropertyValues: unreachable!" ); + return NULL; + } + + //------------------------------------------------------------------------------------------------------------------ + Sequence< Any > Content::setPropertyValues( const Sequence< PropertyValue >& i_rValues, const Reference< XCommandEnvironment >& /* xEnv */) + { + ::osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); + + Sequence< Any > aRet( i_rValues.getLength() ); + Sequence< PropertyChangeEvent > aChanges( i_rValues.getLength() ); + + PropertyChangeEvent aEvent; + aEvent.Source = static_cast< cppu::OWeakObject * >( this ); + aEvent.Further = sal_False; + aEvent.PropertyHandle = -1; + + const PropertyValue* pValues = i_rValues.getConstArray(); + const sal_Int32 nCount = i_rValues.getLength(); + + for ( sal_Int32 n = 0; n < nCount; ++n, ++pValues ) + { + // all our properties are read-only ... + aRet[ n ] <<= IllegalAccessException( ::rtl::OUString::createFromAscii( "property is read-only." ), *this ); + } + + return aRet; + } + + //------------------------------------------------------------------------------------------------------------------ + Sequence< CommandInfo > Content::getCommands( const Reference< XCommandEnvironment > & /*xEnv*/ ) + { + sal_uInt32 nCommandCount = 5; + static const CommandInfo aCommandInfoTable[] = + { + /////////////////////////////////////////////////////////////// + // Mandatory commands + /////////////////////////////////////////////////////////////// + CommandInfo( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getCommandInfo" ) ), + -1, + getCppuVoidType() + ), + CommandInfo( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getPropertySetInfo" ) ), + -1, + getCppuVoidType() + ), + CommandInfo( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getPropertyValues" ) ), + -1, + getCppuType( + static_cast< Sequence< Property > * >( 0 ) ) + ), + CommandInfo( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ), + -1, + getCppuType( + static_cast< Sequence< PropertyValue > * >( 0 ) ) + ) + /////////////////////////////////////////////////////////////// + // Optional standard commands + /////////////////////////////////////////////////////////////// + , CommandInfo( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "open" ) ), + -1, + getCppuType( static_cast< OpenCommandArgument2 * >( 0 ) ) + ) + }; + + return Sequence< CommandInfo >( aCommandInfoTable, nCommandCount ); + } + + //------------------------------------------------------------------------------------------------------------------ + Sequence< Property > Content::getProperties( const Reference< XCommandEnvironment > & /*xEnv*/ ) + { + static Property aProperties[] = + { + Property( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ContentType" ) ), + -1, + getCppuType( static_cast< const ::rtl::OUString * >( 0 ) ), + PropertyAttribute::BOUND | PropertyAttribute::READONLY + ), + Property( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsDocument" ) ), + -1, + getCppuBooleanType(), + PropertyAttribute::BOUND | PropertyAttribute::READONLY + ), + Property( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ), + -1, + getCppuBooleanType(), + PropertyAttribute::BOUND | PropertyAttribute::READONLY + ), + Property( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ), + -1, + getCppuType( static_cast< const ::rtl::OUString * >( 0 ) ), + PropertyAttribute::BOUND | PropertyAttribute::READONLY + ) + }; + return Sequence< Property >( aProperties, sizeof( aProperties ) / sizeof( aProperties[0] ) ); + } + + //------------------------------------------------------------------------------------------------------------------ + bool Content::impl_isFolder() + { + if ( !!m_aIsFolder ) + return *m_aIsFolder; + + bool bIsFolder = false; + try + { + Sequence< Property > aProps(1); + aProps[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ); + Reference< XRow > xRow( getPropertyValues( aProps, NULL ), UNO_SET_THROW ); + bIsFolder = xRow->getBoolean(1); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + m_aIsFolder.reset( bIsFolder ); + return *m_aIsFolder; + } + + //------------------------------------------------------------------------------------------------------------------ + void Content::impl_determineContentType() + { + if ( !!m_aContentType ) + return; + + m_aContentType.reset( ContentProvider::getArtificialNodeContentType() ); + if ( m_eExtContentType == E_EXTENSION_CONTENT ) + { + try + { + Sequence< Property > aProps(1); + aProps[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ContentType" ) ); + Reference< XRow > xRow( getPropertyValues( aProps, NULL ), UNO_SET_THROW ); + m_aContentType.reset( xRow->getString(1) ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + } + +//...................................................................................................................... +} } } // namespace ucp::ext +//...................................................................................................................... diff --git a/ucb/source/ucp/ext/ucpext_content.hxx b/ucb/source/ucp/ext/ucpext_content.hxx new file mode 100644 index 000000000000..36380d8a7d68 --- /dev/null +++ b/ucb/source/ucp/ext/ucpext_content.hxx @@ -0,0 +1,154 @@ +/************************************************************************* + * 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 UCB_UCPEXT_CONTENT_HXX +#define UCB_UCPEXT_CONTENT_HXX + +/** === begin UNO includes === **/ +#include <com/sun/star/sdbc/XRow.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +/** === end UNO includes === **/ + +#include <rtl/ref.hxx> +#include <ucbhelper/contenthelper.hxx> + +#include <list> +#include <boost/optional.hpp> + +//...................................................................................................................... +namespace ucb { namespace ucp { namespace ext +{ +//...................................................................................................................... + + //================================================================================================================== + //= ExtensionContentType + //================================================================================================================== + enum ExtensionContentType + { + E_ROOT, + E_EXTENSION_ROOT, + E_EXTENSION_CONTENT, + + E_UNKNOWN + }; + + //================================================================================================================== + //= ContentProvider + //================================================================================================================== + typedef ::ucbhelper::ContentImplHelper Content_Base; + class Content : public Content_Base + { + public: + Content( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + ::ucbhelper::ContentProviderImplHelper* pProvider, + const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContentIdentifier >& Identifier + ); + + static ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRow > + getArtificialNodePropertyValues( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rSMgr, + const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& rProperties, + const ::rtl::OUString& rTitle + ); + + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRow > + getPropertyValues( + const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& rProperties, + const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >& xEnv + ); + + static ::rtl::OUString + encodeIdentifier( const ::rtl::OUString& i_rIdentifier ); + static ::rtl::OUString + decodeIdentifier( const ::rtl::OUString& i_rIdentifier ); + + virtual ::rtl::OUString getParentURL(); + + ExtensionContentType getExtensionContentType() const { return m_eExtContentType; } + + /** retrieves the URL of the underlying physical content. Not to be called when getExtensionContentType() + returns E_ROOT. + */ + ::rtl::OUString getPhysicalURL() const; + + protected: + virtual ~Content(); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw (::com::sun::star::uno::RuntimeException); + + // XContent + virtual rtl::OUString SAL_CALL getContentType() throw( com::sun::star::uno::RuntimeException ); + + // XCommandProcessor + virtual com::sun::star::uno::Any SAL_CALL + execute( + const com::sun::star::ucb::Command& aCommand, + sal_Int32 CommandId, + const com::sun::star::uno::Reference< com::sun::star::ucb::XCommandEnvironment >& Environment + ) + throw ( ::com::sun::star::uno::Exception + , ::com::sun::star::ucb::CommandAbortedException + , ::com::sun::star::uno::RuntimeException + ); + + virtual void SAL_CALL + abort( + sal_Int32 CommandId + ) + throw ( ::com::sun::star::uno::RuntimeException + ); + + private: + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property > getProperties( const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >& i_rEnv ); + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::ucb::CommandInfo > getCommands( const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >& i_rEnv ); + + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > + setPropertyValues( + const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& rValues, + const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >& xEnv + ); + + static bool denotesRootContent( const ::rtl::OUString& i_rContentIdentifier ); + + bool impl_isFolder(); + void impl_determineContentType(); + + private: + ExtensionContentType m_eExtContentType; + ::boost::optional< bool > m_aIsFolder; + ::boost::optional< ::rtl::OUString > m_aContentType; + ::rtl::OUString m_sExtensionId; + ::rtl::OUString m_sPathIntoExtension; + }; + +//...................................................................................................................... +} } } // namespace ucb::ucp::ext +//...................................................................................................................... + +#endif // UCB_UCPEXT_CONTENT_HXX diff --git a/ucb/source/ucp/ext/ucpext_datasupplier.cxx b/ucb/source/ucp/ext/ucpext_datasupplier.cxx new file mode 100644 index 000000000000..a3a9cc6876ff --- /dev/null +++ b/ucb/source/ucp/ext/ucpext_datasupplier.cxx @@ -0,0 +1,375 @@ +/************************************************************************* + * 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 "precompiled_ucb.hxx" + +#include "ucpext_datasupplier.hxx" +#include "ucpext_content.hxx" +#include "ucpext_provider.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/deployment/XPackageInformationProvider.hpp> +/** === end UNO includes === **/ + +#include <ucbhelper/contentidentifier.hxx> +#include <comphelper/componentcontext.hxx> +#include <ucbhelper/providerhelper.hxx> +#include <ucbhelper/content.hxx> +#include <ucbhelper/propertyvalueset.hxx> +#include <tools/diagnose_ex.h> +#include <rtl/ustrbuf.hxx> + +#include <vector> +#include <boost/shared_ptr.hpp> + +//...................................................................................................................... +namespace ucb { namespace ucp { namespace ext +{ +//...................................................................................................................... + + /** === begin UNO using === **/ + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::XInterface; + using ::com::sun::star::uno::UNO_QUERY; + using ::com::sun::star::uno::UNO_QUERY_THROW; + using ::com::sun::star::uno::UNO_SET_THROW; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::uno::RuntimeException; + using ::com::sun::star::uno::Any; + using ::com::sun::star::uno::makeAny; + using ::com::sun::star::uno::Sequence; + using ::com::sun::star::uno::Type; + using ::com::sun::star::ucb::XContent; + using ::com::sun::star::ucb::XContentIdentifier; + using ::com::sun::star::sdbc::XRow; + using ::com::sun::star::lang::XMultiServiceFactory; + using ::com::sun::star::ucb::IllegalIdentifierException; + using ::com::sun::star::ucb::ResultSetException; + using ::com::sun::star::deployment::XPackageInformationProvider; + using ::com::sun::star::beans::Property; + using ::com::sun::star::sdbc::XResultSet; + using ::com::sun::star::sdbc::XRow; + using ::com::sun::star::ucb::XCommandEnvironment; + /** === end UNO using === **/ + //================================================================================================================== + //= ResultListEntry + //================================================================================================================== + struct ResultListEntry + { + ::rtl::OUString sId; + Reference< XContentIdentifier > xId; + ::rtl::Reference< Content > pContent; + Reference< XRow > xRow; + }; + + typedef ::std::vector< ResultListEntry > ResultList; + + //================================================================================================================== + //= DataSupplier_Impl + //================================================================================================================== + struct DataSupplier_Impl + { + ::osl::Mutex m_aMutex; + ResultList m_aResults; + ::rtl::Reference< Content > m_xContent; + Reference< XMultiServiceFactory > m_xSMgr; + sal_Int32 m_nOpenMode; + + DataSupplier_Impl( const Reference< XMultiServiceFactory >& i_rORB, const ::rtl::Reference< Content >& i_rContent, + const sal_Int32 i_nOpenMode ) + :m_xContent( i_rContent ) + ,m_xSMgr( i_rORB ) + ,m_nOpenMode( i_nOpenMode ) + { + } + ~DataSupplier_Impl(); + }; + + //------------------------------------------------------------------------------------------------------------------ + DataSupplier_Impl::~DataSupplier_Impl() + { + } + + //================================================================================================================== + //= helper + //================================================================================================================== + namespace + { + ::rtl::OUString lcl_compose( const ::rtl::OUString& i_rBaseURL, const ::rtl::OUString& i_rRelativeURL ) + { + ENSURE_OR_RETURN( i_rBaseURL.getLength(), "illegal base URL", i_rRelativeURL ); + + ::rtl::OUStringBuffer aComposer( i_rBaseURL ); + if ( i_rBaseURL.getStr()[ i_rBaseURL.getLength() - 1 ] != '/' ) + aComposer.append( sal_Unicode( '/' ) ); + aComposer.append( i_rRelativeURL ); + return aComposer.makeStringAndClear(); + } + } + + + //================================================================================================================== + //= DataSupplier + //================================================================================================================== + //------------------------------------------------------------------------------------------------------------------ + DataSupplier::DataSupplier( const Reference< XMultiServiceFactory >& i_rORB, + const ::rtl::Reference< Content >& i_rContent, + const sal_Int32 i_nOpenMode ) + :m_pImpl( new DataSupplier_Impl( i_rORB, i_rContent, i_nOpenMode ) ) + { + } + + //------------------------------------------------------------------------------------------------------------------ + void DataSupplier::fetchData() + { + try + { + const ::comphelper::ComponentContext aContext( m_pImpl->m_xSMgr ); + const Reference< XPackageInformationProvider > xPackageInfo( + aContext.getSingleton( "com.sun.star.deployment.PackageInformationProvider" ), UNO_QUERY_THROW ); + + const ::rtl::OUString sContentIdentifier( m_pImpl->m_xContent->getIdentifier()->getContentIdentifier() ); + + switch ( m_pImpl->m_xContent->getExtensionContentType() ) + { + case E_ROOT: + { + Sequence< Sequence< ::rtl::OUString > > aExtensionInfo( xPackageInfo->getExtensionList() ); + for ( const Sequence< ::rtl::OUString >* pExtInfo = aExtensionInfo.getConstArray(); + pExtInfo != aExtensionInfo.getConstArray() + aExtensionInfo.getLength(); + ++pExtInfo + ) + { + ENSURE_OR_CONTINUE( pExtInfo->getLength() > 0, "illegal extension info" ); + + const ::rtl::OUString& rLocalId = (*pExtInfo)[0]; + ResultListEntry aEntry; + aEntry.sId = ContentProvider::getRootURL() + Content::encodeIdentifier( rLocalId ) + ::rtl::OUString( sal_Unicode( '/' ) ); + m_pImpl->m_aResults.push_back( aEntry ); + } + } + break; + case E_EXTENSION_ROOT: + case E_EXTENSION_CONTENT: + { + const ::rtl::OUString sPackageLocation( m_pImpl->m_xContent->getPhysicalURL() ); + ::ucbhelper::Content aWrappedContent( sPackageLocation, getResultSet()->getEnvironment() ); + + // obtain the properties which our result set is set up for from the wrapped content + Sequence< ::rtl::OUString > aPropertyNames(1); + aPropertyNames[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ); + + const Reference< XResultSet > xFolderContent( aWrappedContent.createCursor( aPropertyNames ), UNO_SET_THROW ); + const Reference< XRow > xContentRow( xFolderContent, UNO_QUERY_THROW ); + while ( xFolderContent->next() ) + { + ResultListEntry aEntry; + aEntry.sId = lcl_compose( sContentIdentifier, xContentRow->getString( 1 ) ); + m_pImpl->m_aResults.push_back( aEntry ); + } + } + break; + default: + OSL_ENSURE( false, "DataSupplier::fetchData: unimplemented content type!" ); + break; + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + //------------------------------------------------------------------------------------------------------------------ + DataSupplier::~DataSupplier() + { + } + + //------------------------------------------------------------------------------------------------------------------ + ::rtl::OUString DataSupplier::queryContentIdentifierString( sal_uInt32 i_nIndex ) + { + ::osl::Guard< ::osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( i_nIndex < m_pImpl->m_aResults.size() ) + { + const ::rtl::OUString sId = m_pImpl->m_aResults[ i_nIndex ].sId; + if ( sId.getLength() ) + return sId; + } + + OSL_ENSURE( false, "DataSupplier::queryContentIdentifierString: illegal index, or illegal result entry id!" ); + return ::rtl::OUString(); + } + + //------------------------------------------------------------------------------------------------------------------ + Reference< XContentIdentifier > DataSupplier::queryContentIdentifier( sal_uInt32 i_nIndex ) + { + ::osl::Guard< ::osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( i_nIndex < m_pImpl->m_aResults.size() ) + { + Reference< XContentIdentifier > xId( m_pImpl->m_aResults[ i_nIndex ].xId ); + if ( xId.is() ) + return xId; + } + + ::rtl::OUString sId = queryContentIdentifierString( i_nIndex ); + if ( sId.getLength() ) + { + Reference< XContentIdentifier > xId = new ::ucbhelper::ContentIdentifier( sId ); + m_pImpl->m_aResults[ i_nIndex ].xId = xId; + return xId; + } + + return Reference< XContentIdentifier >(); + } + + //------------------------------------------------------------------------------------------------------------------ + Reference< XContent > DataSupplier::queryContent( sal_uInt32 i_nIndex ) + { + ::osl::Guard< ::osl::Mutex > aGuard( m_pImpl->m_aMutex ); + ENSURE_OR_RETURN( i_nIndex < m_pImpl->m_aResults.size(), "illegal index!", NULL ); + + + ::rtl::Reference< Content > pContent( m_pImpl->m_aResults[ i_nIndex ].pContent ); + if ( pContent.is() ) + return pContent.get(); + + Reference< XContentIdentifier > xId( queryContentIdentifier( i_nIndex ) ); + if ( xId.is() ) + { + try + { + Reference< XContent > xContent( m_pImpl->m_xContent->getProvider()->queryContent( xId ) ); + pContent.set( dynamic_cast< Content* >( xContent.get() ) ); + OSL_ENSURE( pContent.is() || !xContent.is(), "DataSupplier::queryContent: invalid content implementation!" ); + m_pImpl->m_aResults[ i_nIndex ].pContent = pContent; + return pContent.get(); + + } + catch ( const IllegalIdentifierException& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + return Reference< XContent >(); + } + + //------------------------------------------------------------------------------------------------------------------ + sal_Bool DataSupplier::getResult( sal_uInt32 i_nIndex ) + { + ::osl::ClearableGuard< ::osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( m_pImpl->m_aResults.size() > i_nIndex ) + // result already present. + return sal_True; + + return sal_False; + } + + //------------------------------------------------------------------------------------------------------------------ + sal_uInt32 DataSupplier::totalCount() + { + ::osl::ClearableGuard< ::osl::Mutex > aGuard( m_pImpl->m_aMutex ); + return m_pImpl->m_aResults.size(); + } + + //------------------------------------------------------------------------------------------------------------------ + sal_uInt32 DataSupplier::currentCount() + { + return m_pImpl->m_aResults.size(); + } + + //------------------------------------------------------------------------------------------------------------------ + sal_Bool DataSupplier::isCountFinal() + { + return sal_True; + } + + //------------------------------------------------------------------------------------------------------------------ + Reference< XRow > DataSupplier::queryPropertyValues( sal_uInt32 i_nIndex ) + { + ::osl::MutexGuard aGuard( m_pImpl->m_aMutex ); + ENSURE_OR_RETURN( i_nIndex < m_pImpl->m_aResults.size(), "DataSupplier::queryPropertyValues: illegal index!", NULL ); + + Reference< XRow > xRow = m_pImpl->m_aResults[ i_nIndex ].xRow; + if ( xRow.is() ) + return xRow; + + ENSURE_OR_RETURN( queryContent( i_nIndex ).is(), "could not retrieve the content", NULL ); + + switch ( m_pImpl->m_xContent->getExtensionContentType() ) + { + case E_ROOT: + { + const ::rtl::OUString& rId( m_pImpl->m_aResults[ i_nIndex ].sId ); + const ::rtl::OUString sRootURL( ContentProvider::getRootURL() ); + ::rtl::OUString sTitle = Content::decodeIdentifier( rId.copy( sRootURL.getLength() ) ); + if ( ( sTitle.getLength() > 0 ) && ( sTitle[ sTitle.getLength() - 1 ] == '/' ) ) + sTitle = sTitle.copy( 0, sTitle.getLength() - 1 ); + xRow = Content::getArtificialNodePropertyValues( m_pImpl->m_xSMgr, getResultSet()->getProperties(), sTitle ); + } + break; + + case E_EXTENSION_ROOT: + case E_EXTENSION_CONTENT: + { + xRow = m_pImpl->m_aResults[ i_nIndex ].pContent->getPropertyValues( + getResultSet()->getProperties(), getResultSet()->getEnvironment() ); + } + break; + default: + OSL_ENSURE( false, "DataSupplier::queryPropertyValues: unhandled case!" ); + break; + } + + m_pImpl->m_aResults[ i_nIndex ].xRow = xRow; + return xRow; + } + + //------------------------------------------------------------------------------------------------------------------ + void DataSupplier::releasePropertyValues( sal_uInt32 i_nIndex ) + { + ::osl::Guard< ::osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( i_nIndex < m_pImpl->m_aResults.size() ) + m_pImpl->m_aResults[ i_nIndex ].xRow.clear(); + } + + //------------------------------------------------------------------------------------------------------------------ + void DataSupplier::close() + { + } + + //------------------------------------------------------------------------------------------------------------------ + void DataSupplier::validate() throw( ResultSetException ) + { + } + +//...................................................................................................................... +} } } // namespace ucp::ext +//...................................................................................................................... diff --git a/ucb/source/ucp/ext/ucpext_datasupplier.hxx b/ucb/source/ucp/ext/ucpext_datasupplier.hxx new file mode 100644 index 000000000000..526491cd678b --- /dev/null +++ b/ucb/source/ucp/ext/ucpext_datasupplier.hxx @@ -0,0 +1,86 @@ +/************************************************************************* + * 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 UCB_UCPEXT_DATA_SUPPLIER_HXX +#define UCB_UCPEXT_DATA_SUPPLIER_HXX + +#include <rtl/ref.hxx> +#include <ucbhelper/resultset.hxx> + +#include <boost/scoped_ptr.hpp> + +//...................................................................................................................... +namespace ucb { namespace ucp { namespace ext +{ +//...................................................................................................................... + + struct DataSupplier_Impl; + class Content; + + //================================================================================================================== + //= DataSupplier + //================================================================================================================== + typedef ::ucbhelper::ResultSetDataSupplier DataSupplier_Base; + class DataSupplier : public ::ucbhelper::ResultSetDataSupplier + { + public: + DataSupplier( + const ::com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >& i_rORB, + const rtl::Reference< Content >& rContent, + const sal_Int32 nOpenMode + ); + + void fetchData(); + + protected: + virtual ~DataSupplier(); + + virtual rtl::OUString queryContentIdentifierString( sal_uInt32 nIndex ); + virtual com::sun::star::uno::Reference< com::sun::star::ucb::XContentIdentifier > queryContentIdentifier( sal_uInt32 nIndex ); + virtual com::sun::star::uno::Reference< com::sun::star::ucb::XContent > queryContent( sal_uInt32 nIndex ); + + virtual sal_Bool getResult( sal_uInt32 nIndex ); + + virtual sal_uInt32 totalCount(); + virtual sal_uInt32 currentCount(); + virtual sal_Bool isCountFinal(); + + virtual com::sun::star::uno::Reference< com::sun::star::sdbc::XRow > queryPropertyValues( sal_uInt32 nIndex ); + virtual void releasePropertyValues( sal_uInt32 nIndex ); + + virtual void close(); + + virtual void validate() throw( com::sun::star::ucb::ResultSetException ); + + private: + ::boost::scoped_ptr< DataSupplier_Impl > m_pImpl; + }; + +//...................................................................................................................... +} } } // namespace ucp::ext +//...................................................................................................................... + +#endif // UCB_UCPEXT_DATA_SUPPLIER_HXX diff --git a/ucb/source/ucp/ext/ucpext_provider.cxx b/ucb/source/ucp/ext/ucpext_provider.cxx new file mode 100644 index 000000000000..0fbad1d8cf17 --- /dev/null +++ b/ucb/source/ucp/ext/ucpext_provider.cxx @@ -0,0 +1,208 @@ +/************************************************************************* + * 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 "precompiled_ucb.hxx" + +#include "ucpext_provider.hxx" +#include "ucpext_content.hxx" + +/** === begin UNO includes === **/ +/** === end UNO includes === **/ + +#include <ucbhelper/contentidentifier.hxx> +#include <osl/diagnose.h> +#include <osl/mutex.hxx> +#include <comphelper/componentcontext.hxx> +#include <rtl/ustrbuf.hxx> + +//...................................................................................................................... +namespace ucb { namespace ucp { namespace ext +{ +//...................................................................................................................... + + /** === begin UNO using === **/ + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::XInterface; + using ::com::sun::star::uno::UNO_QUERY; + using ::com::sun::star::uno::UNO_QUERY_THROW; + using ::com::sun::star::uno::UNO_SET_THROW; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::uno::RuntimeException; + using ::com::sun::star::uno::Any; + using ::com::sun::star::uno::makeAny; + using ::com::sun::star::uno::Sequence; + using ::com::sun::star::uno::Type; + using ::com::sun::star::lang::XMultiServiceFactory; + using ::com::sun::star::ucb::XContentIdentifier; + using ::com::sun::star::ucb::IllegalIdentifierException; + using ::com::sun::star::ucb::XContent; + using ::com::sun::star::uno::XComponentContext; + /** === end UNO using === **/ + + //================================================================================================================== + //= ContentProvider + //================================================================================================================== + //------------------------------------------------------------------------------------------------------------------ + ContentProvider::ContentProvider( const Reference< XMultiServiceFactory >& i_rServiceManager ) + :ContentProvider_Base( i_rServiceManager ) + { + } + + //------------------------------------------------------------------------------------------------------------------ + ContentProvider::~ContentProvider() + { + } + + //------------------------------------------------------------------------------------------------------------------ + ::rtl::OUString SAL_CALL ContentProvider::getImplementationName_static() throw (RuntimeException) + { + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.comp.ucp.ext.ContentProvider" ) ); + } + + //------------------------------------------------------------------------------------------------------------------ + ::rtl::OUString SAL_CALL ContentProvider::getImplementationName() throw (RuntimeException) + { + return getImplementationName_static(); + } + + //------------------------------------------------------------------------------------------------------------------ + Sequence< ::rtl::OUString > SAL_CALL ContentProvider::getSupportedServiceNames_static( ) throw (RuntimeException) + { + Sequence< ::rtl::OUString > aServiceNames(2); + aServiceNames[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ucb.ContentProvider" ) ); + aServiceNames[1] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ucb.ExtensionContentProvider" ) ); + return aServiceNames; + } + + //------------------------------------------------------------------------------------------------------------------ + Sequence< ::rtl::OUString > SAL_CALL ContentProvider::getSupportedServiceNames( ) throw (RuntimeException) + { + return getSupportedServiceNames_static(); + } + + //------------------------------------------------------------------------------------------------------------------ + Reference< XInterface > ContentProvider::Create( const Reference< XComponentContext >& i_rContext ) + { + const ::comphelper::ComponentContext aContext( i_rContext ); + return *( new ContentProvider( aContext.getLegacyServiceFactory() ) ); + } + + //------------------------------------------------------------------------------------------------------------------ + ::rtl::OUString ContentProvider::getRootURL() + { + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.extension://" ) ); + } + + //------------------------------------------------------------------------------------------------------------------ + ::rtl::OUString ContentProvider::getArtificialNodeContentType() + { + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "application/vnd.sun.star.extension-content" ) ); + } + + //------------------------------------------------------------------------------------------------------------------ + namespace + { + void lcl_ensureAndTransfer( ::rtl::OUString& io_rIdentifierFragment, ::rtl::OUStringBuffer& o_rNormalization, const sal_Unicode i_nLeadingChar ) + { + if ( ( io_rIdentifierFragment.getLength() == 0 ) || ( io_rIdentifierFragment[0] != i_nLeadingChar ) ) + throw IllegalIdentifierException(); + io_rIdentifierFragment = io_rIdentifierFragment.copy( 1 ); + o_rNormalization.append( i_nLeadingChar ); + } + } + + //------------------------------------------------------------------------------------------------------------------ + Reference< XContent > SAL_CALL ContentProvider::queryContent( const Reference< XContentIdentifier >& i_rIdentifier ) + throw( IllegalIdentifierException, RuntimeException ) + { + // Check URL scheme... + const ::rtl::OUString sScheme( rtl::OUString::createFromAscii( "vnd.sun.star.extension" ) ); + if ( !i_rIdentifier->getContentProviderScheme().equalsIgnoreAsciiCase( sScheme ) ) + throw IllegalIdentifierException(); + + // normalize the identifier + const ::rtl::OUString sIdentifier( i_rIdentifier->getContentIdentifier() ); + + // the scheme needs to be lower-case + ::rtl::OUStringBuffer aComposer; + aComposer.append( sIdentifier.copy( 0, sScheme.getLength() ).toAsciiLowerCase() ); + + // one : is required after the scheme + ::rtl::OUString sRemaining( sIdentifier.copy( sScheme.getLength() ) ); + lcl_ensureAndTransfer( sRemaining, aComposer, ':' ); + + // and at least one / + lcl_ensureAndTransfer( sRemaining, aComposer, '/' ); + + // the normalized form requires one additional /, but we also accept identifiers which don't have it + if ( sRemaining.getLength() == 0 ) + { + // the root content is a special case, it requires /// + aComposer.appendAscii( "//" ); + } + else + { + if ( sRemaining[0] != '/' ) + { + aComposer.append( sal_Unicode( '/' ) ); + aComposer.append( sRemaining ); + } + else + { + lcl_ensureAndTransfer( sRemaining, aComposer, '/' ); + // by now, we moved "vnd.sun.star.extension://" from the URL to aComposer + if ( sRemaining.getLength() == 0 ) + { + // again, it's the root content, but one / is missing + aComposer.append( sal_Unicode( '/' ) ); + } + else + { + aComposer.append( sRemaining ); + } + } + } + const Reference< XContentIdentifier > xNormalizedIdentifier( new ::ucbhelper::ContentIdentifier( m_xSMgr, aComposer.makeStringAndClear() ) ); + + ::osl::MutexGuard aGuard( m_aMutex ); + + // check if a content with given id already exists... + Reference< XContent > xContent( queryExistingContent( xNormalizedIdentifier ).get() ); + if ( xContent.is() ) + return xContent; + + // create a new content + xContent = new Content( m_xSMgr, this, xNormalizedIdentifier ); + if ( !xContent->getIdentifier().is() ) + throw IllegalIdentifierException(); + + registerNewContent( xContent ); + return xContent; + } + +//...................................................................................................................... +} } } // namespace ucb::ucp::ext +//...................................................................................................................... diff --git a/ucb/source/ucp/ext/ucpext_provider.hxx b/ucb/source/ucp/ext/ucpext_provider.hxx new file mode 100644 index 000000000000..1f41fdd0f084 --- /dev/null +++ b/ucb/source/ucp/ext/ucpext_provider.hxx @@ -0,0 +1,68 @@ +/************************************************************************* + * 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 UCB_UCPEXT_CONTENT_PROVIDER_HXX +#define UCB_UCPEXT_CONTENT_PROVIDER_HXX + +#include <ucbhelper/providerhelper.hxx> + +//...................................................................................................................... +namespace ucb { namespace ucp { namespace ext +{ +//...................................................................................................................... + + //================================================================================================================== + //= ContentProvider + //================================================================================================================== + typedef ::ucbhelper::ContentProviderImplHelper ContentProvider_Base; + class ContentProvider : public ContentProvider_Base + { + public: + ContentProvider( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& i_rServiceManager ); + virtual ~ContentProvider(); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw (::com::sun::star::uno::RuntimeException); + + // XServiceInfo - static versions + static ::rtl::OUString SAL_CALL getImplementationName_static( ) throw (::com::sun::star::uno::RuntimeException); + static ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames_static() throw (::com::sun::star::uno::RuntimeException); + static ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL Create( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& i_rContext ); + + // XContentProvider + virtual ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContent > SAL_CALL queryContent( const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContentIdentifier >& Identifier ) throw (::com::sun::star::ucb::IllegalIdentifierException, ::com::sun::star::uno::RuntimeException); + + public: + static ::rtl::OUString getRootURL(); + static ::rtl::OUString getArtificialNodeContentType(); + }; + +//...................................................................................................................... +} } } // namespace ucb::ucp::ext +//...................................................................................................................... + +#endif // UCB_UCPEXT_CONTENT_PROVIDER_HXX diff --git a/ucb/source/ucp/ext/ucpext_resultset.cxx b/ucb/source/ucp/ext/ucpext_resultset.cxx new file mode 100644 index 000000000000..d8a2eb8e9914 --- /dev/null +++ b/ucb/source/ucp/ext/ucpext_resultset.cxx @@ -0,0 +1,99 @@ +/************************************************************************* + * 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 "precompiled_ucb.hxx" + +#include "ucpext_resultset.hxx" +#include "ucpext_content.hxx" +#include "ucpext_datasupplier.hxx" + +/** === begin UNO includes === **/ +/** === end UNO includes === **/ + +#include <ucbhelper/resultset.hxx> + +//...................................................................................................................... +namespace ucb { namespace ucp { namespace ext +{ +//...................................................................................................................... + + /** === begin UNO using === **/ + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::XInterface; + using ::com::sun::star::uno::UNO_QUERY; + using ::com::sun::star::uno::UNO_QUERY_THROW; + using ::com::sun::star::uno::UNO_SET_THROW; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::uno::RuntimeException; + using ::com::sun::star::uno::Any; + using ::com::sun::star::uno::makeAny; + using ::com::sun::star::uno::Sequence; + using ::com::sun::star::uno::Type; + using ::com::sun::star::lang::XMultiServiceFactory; + using ::com::sun::star::ucb::XContentIdentifier; + using ::com::sun::star::ucb::OpenCommandArgument2; + using ::com::sun::star::ucb::XCommandEnvironment; + /** === end UNO using === **/ + + //================================================================================================================== + //= ResultSet + //================================================================================================================== + //------------------------------------------------------------------------------------------------------------------ + ResultSet::ResultSet( const Reference< XMultiServiceFactory >& i_rORB, const ::rtl::Reference< Content >& i_rContent, + const OpenCommandArgument2& i_rCommand, const Reference< XCommandEnvironment >& i_rEnv ) + :ResultSetImplHelper( i_rORB, i_rCommand ) + ,m_xEnvironment( i_rEnv ) + ,m_xContent( i_rContent ) + { + } + + //------------------------------------------------------------------------------------------------------------------ + void ResultSet::initStatic() + { + ::rtl::Reference< DataSupplier > pDataSupplier( new DataSupplier( + m_xSMgr, + m_xContent, + m_aCommand.Mode + ) ); + m_xResultSet1 = new ::ucbhelper::ResultSet( + m_xSMgr, + m_aCommand.Properties, + pDataSupplier.get(), + m_xEnvironment + ); + pDataSupplier->fetchData(); + } + + //------------------------------------------------------------------------------------------------------------------ + void ResultSet::initDynamic() + { + initStatic(); + m_xResultSet2 = m_xResultSet1; + } + +//...................................................................................................................... +} } } // namespace ucp::ext +//...................................................................................................................... diff --git a/ucb/source/ucp/ext/ucpext_resultset.hxx b/ucb/source/ucp/ext/ucpext_resultset.hxx new file mode 100644 index 000000000000..2924197a0fdc --- /dev/null +++ b/ucb/source/ucp/ext/ucpext_resultset.hxx @@ -0,0 +1,66 @@ +/************************************************************************* + * 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 UCB_UCPEXT_RESULT_SET_HXX +#define UCB_UCPEXT_RESULT_SET_HXX + +#include <rtl/ref.hxx> +#include <ucbhelper/resultsethelper.hxx> + +//...................................................................................................................... +namespace ucb { namespace ucp { namespace ext +{ +//...................................................................................................................... + + class Content; + + //================================================================================================================== + //= ResultSet + //================================================================================================================== + class ResultSet : public ::ucbhelper::ResultSetImplHelper + { + public: + ResultSet( + const com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >& i_rORB, + const rtl::Reference< Content >& i_rContent, + const com::sun::star::ucb::OpenCommandArgument2& i_rCommand, + const com::sun::star::uno::Reference< com::sun::star::ucb::XCommandEnvironment >& i_rEnv + ); + + private: + ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment > m_xEnvironment; + ::rtl::Reference< Content > m_xContent; + + private: + virtual void initStatic(); + virtual void initDynamic(); + }; + +//...................................................................................................................... +} } } // namespace ucp::ext +//...................................................................................................................... + +#endif // UCB_UCPEXT_RESULT_SET_HXX diff --git a/ucb/source/ucp/ext/ucpext_services.cxx b/ucb/source/ucp/ext/ucpext_services.cxx new file mode 100644 index 000000000000..ce525c2da665 --- /dev/null +++ b/ucb/source/ucp/ext/ucpext_services.cxx @@ -0,0 +1,87 @@ +/************************************************************************* + * 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 "precompiled_ucb.hxx" + +#include "ucpext_provider.hxx" + +/** === begin UNO includes === **/ +/** === end UNO includes === **/ + +#include <cppuhelper/implementationentry.hxx> + +//...................................................................................................................... +namespace ucb { namespace ucp { namespace ext +{ +//...................................................................................................................... + + /** === begin UNO using === **/ + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::XInterface; + using ::com::sun::star::uno::UNO_QUERY; + using ::com::sun::star::uno::UNO_QUERY_THROW; + using ::com::sun::star::uno::UNO_SET_THROW; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::uno::RuntimeException; + using ::com::sun::star::uno::Any; + using ::com::sun::star::uno::makeAny; + using ::com::sun::star::uno::Sequence; + using ::com::sun::star::uno::Type; + using ::com::sun::star::lang::XSingleComponentFactory; + /** === end UNO using === **/ + + //================================================================================================================== + //= descriptors for the services implemented in this component + //================================================================================================================== + static struct ::cppu::ImplementationEntry s_aServiceEntries[] = + { + { + ContentProvider::Create, + ContentProvider::getImplementationName_static, + ContentProvider::getSupportedServiceNames_static, + ::cppu::createOneInstanceComponentFactory, NULL, 0 + }, + { 0, 0, 0, 0, 0, 0 } + }; + +//...................................................................................................................... +} } } // namespace ucb::ucp::ext +//...................................................................................................................... + +extern "C" +{ + //------------------------------------------------------------------------------------------------------------------ + void SAL_CALL component_getImplementationEnvironment( const sal_Char ** ppEnvTypeName, uno_Environment ** ) + { + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; + } + + //------------------------------------------------------------------------------------------------------------------ + void * SAL_CALL component_getFactory( const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey ) + { + return ::cppu::component_getFactoryHelper( pImplName, pServiceManager, pRegistryKey , ::ucb::ucp::ext::s_aServiceEntries ); + } +} diff --git a/ucb/source/ucp/file/bc.cxx b/ucb/source/ucp/file/bc.cxx new file mode 100644 index 000000000000..b78e5d6e4890 --- /dev/null +++ b/ucb/source/ucp/file/bc.cxx @@ -0,0 +1,1409 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" +#include <rtl/uri.hxx> +#include <rtl/ustrbuf.hxx> +#include <osl/file.hxx> + +#include "osl/diagnose.h" +#include <com/sun/star/ucb/OpenMode.hpp> +#ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBBUTE_HPP_ +#include <com/sun/star/beans/PropertyAttribute.hpp> +#endif +#include <com/sun/star/ucb/XProgressHandler.hpp> +#include <com/sun/star/task/XInteractionHandler.hpp> +#include <com/sun/star/io/XActiveDataStreamer.hpp> +#include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/ucb/NumberedSortingInfo.hpp> +#include <com/sun/star/io/XActiveDataSink.hpp> +#include <com/sun/star/beans/PropertyChangeEvent.hpp> +#include <com/sun/star/beans/PropertySetInfoChange.hpp> +#include <com/sun/star/ucb/ContentAction.hpp> +#include <com/sun/star/ucb/NameClash.hpp> +#include "filglob.hxx" +#include "filid.hxx" +#include "filrow.hxx" +#include "bc.hxx" +#include "prov.hxx" +#ifndef _FILERROR_HXX_ +#include "filerror.hxx" +#endif +#include "filinsreq.hxx" + + +using namespace fileaccess; +using namespace com::sun::star; +using namespace com::sun::star::uno; +using namespace com::sun::star::ucb; + +// PropertyListeners + + +typedef cppu::OMultiTypeInterfaceContainerHelperVar< rtl::OUString,hashOUString,equalOUString > +PropertyListeners_impl; + +class fileaccess::PropertyListeners + : public PropertyListeners_impl +{ +public: + PropertyListeners( ::osl::Mutex& aMutex ) + : PropertyListeners_impl( aMutex ) + { + } +}; + + +/****************************************************************************************/ +/* */ +/* BaseContent */ +/* */ +/****************************************************************************************/ + +//////////////////////////////////////////////////////////////////////////////// +// Private Constructor for just inserted Contents + +BaseContent::BaseContent( shell* pMyShell, + const rtl::OUString& parentName, + sal_Bool bFolder ) + : m_pMyShell( pMyShell ), + m_xContentIdentifier( 0 ), + m_aUncPath( parentName ), + m_bFolder( bFolder ), + m_nState( JustInserted ), + m_pDisposeEventListeners( 0 ), + m_pContentEventListeners( 0 ), + m_pPropertySetInfoChangeListeners( 0 ), + m_pPropertyListener( 0 ) +{ + m_pMyShell->m_pProvider->acquire(); + // No registering, since we have no name +} + + +//////////////////////////////////////////////////////////////////////////////// +// Constructor for full featured Contents + +BaseContent::BaseContent( shell* pMyShell, + const Reference< XContentIdentifier >& xContentIdentifier, + const rtl::OUString& aUncPath ) + : m_pMyShell( pMyShell ), + m_xContentIdentifier( xContentIdentifier ), + m_aUncPath( aUncPath ), + m_bFolder( false ), + m_nState( FullFeatured ), + m_pDisposeEventListeners( 0 ), + m_pContentEventListeners( 0 ), + m_pPropertySetInfoChangeListeners( 0 ), + m_pPropertyListener( 0 ) +{ + m_pMyShell->m_pProvider->acquire(); + m_pMyShell->registerNotifier( m_aUncPath,this ); + m_pMyShell->insertDefaultProperties( m_aUncPath ); +} + + +BaseContent::~BaseContent( ) +{ + if( ( m_nState & FullFeatured ) || ( m_nState & Deleted ) ) + { + m_pMyShell->deregisterNotifier( m_aUncPath,this ); + } + m_pMyShell->m_pProvider->release(); + + delete m_pDisposeEventListeners; + delete m_pContentEventListeners; + delete m_pPropertyListener; + delete m_pPropertySetInfoChangeListeners; +} + + +////////////////////////////////////////////////////////////////////////// +// XInterface +////////////////////////////////////////////////////////////////////////// + +void SAL_CALL +BaseContent::acquire( void ) + throw() +{ + OWeakObject::acquire(); +} + + +void SAL_CALL +BaseContent::release( void ) + throw() +{ + OWeakObject::release(); +} + + +Any SAL_CALL +BaseContent::queryInterface( const Type& rType ) + throw( RuntimeException ) +{ + Any aRet = cppu::queryInterface( rType, + SAL_STATIC_CAST( lang::XComponent*, this ), + SAL_STATIC_CAST( lang::XTypeProvider*, this ), + SAL_STATIC_CAST( lang::XServiceInfo*, this ), + SAL_STATIC_CAST( XCommandProcessor*, this ), + SAL_STATIC_CAST( container::XChild*, this ), + SAL_STATIC_CAST( beans::XPropertiesChangeNotifier*, this ), + SAL_STATIC_CAST( beans::XPropertyContainer*, this ), + SAL_STATIC_CAST( XContentCreator*,this ), + SAL_STATIC_CAST( beans::XPropertySetInfoChangeNotifier*, this ), + SAL_STATIC_CAST( XContent*,this) ); + return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ); +} + + + + +////////////////////////////////////////////////////////////////////////////////////////// +// XComponent +//////////////////////////////////////////////////////////////////////////////////////// + +void SAL_CALL +BaseContent::addEventListener( const Reference< lang::XEventListener >& Listener ) + throw( RuntimeException ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + if ( ! m_pDisposeEventListeners ) + m_pDisposeEventListeners = + new cppu::OInterfaceContainerHelper( m_aEventListenerMutex ); + + m_pDisposeEventListeners->addInterface( Listener ); +} + + +void SAL_CALL +BaseContent::removeEventListener( const Reference< lang::XEventListener >& Listener ) + throw( RuntimeException ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + if ( m_pDisposeEventListeners ) + m_pDisposeEventListeners->removeInterface( Listener ); +} + + +void SAL_CALL +BaseContent::dispose() + throw( RuntimeException ) +{ + lang::EventObject aEvt; + cppu::OInterfaceContainerHelper* pDisposeEventListeners; + cppu::OInterfaceContainerHelper* pContentEventListeners; + cppu::OInterfaceContainerHelper* pPropertySetInfoChangeListeners; + PropertyListeners* pPropertyListener; + + { + osl::MutexGuard aGuard( m_aMutex ); + aEvt.Source = static_cast< XContent* >( this ); + + + pDisposeEventListeners = + m_pDisposeEventListeners, m_pDisposeEventListeners = 0; + + pContentEventListeners = + m_pContentEventListeners, m_pContentEventListeners = 0; + + pPropertySetInfoChangeListeners = + m_pPropertySetInfoChangeListeners, + m_pPropertySetInfoChangeListeners = 0; + + pPropertyListener = + m_pPropertyListener, m_pPropertyListener = 0; + } + + if ( pDisposeEventListeners && pDisposeEventListeners->getLength() ) + pDisposeEventListeners->disposeAndClear( aEvt ); + + if ( pContentEventListeners && pContentEventListeners->getLength() ) + pContentEventListeners->disposeAndClear( aEvt ); + + if( pPropertyListener ) + pPropertyListener->disposeAndClear( aEvt ); + + if( pPropertySetInfoChangeListeners ) + pPropertySetInfoChangeListeners->disposeAndClear( aEvt ); + + delete pDisposeEventListeners; + delete pContentEventListeners; + delete pPropertyListener; + delete pPropertySetInfoChangeListeners; +} + + + +////////////////////////////////////////////////////////////////////////////////////////// +// XServiceInfo +////////////////////////////////////////////////////////////////////////////////////////// + +rtl::OUString SAL_CALL +BaseContent::getImplementationName() + throw( RuntimeException) +{ + return rtl::OUString::createFromAscii( "com.sun.star.comp.ucb.FileContent" ); +} + + + +sal_Bool SAL_CALL +BaseContent::supportsService( const rtl::OUString& ServiceName ) + throw( RuntimeException) +{ + if( ServiceName.compareToAscii( "com.sun.star.ucb.FileContent" ) == 0 ) + return true; + else + return false; +} + + + +Sequence< rtl::OUString > SAL_CALL +BaseContent::getSupportedServiceNames() + throw( RuntimeException ) +{ + Sequence< rtl::OUString > ret( 1 ); + ret[0] = rtl::OUString::createFromAscii( "com.sun.star.ucb.FileContent" ); + return ret; +} + + + +////////////////////////////////////////////////////////////////////////////////////////// +// XTypeProvider +////////////////////////////////////////////////////////////////////////////////////////// + +XTYPEPROVIDER_IMPL_10( BaseContent, + lang::XComponent, + lang::XTypeProvider, + lang::XServiceInfo, + XCommandProcessor, + XContentCreator, + XContent, + container::XChild, + beans::XPropertiesChangeNotifier, + beans::XPropertyContainer, + beans::XPropertySetInfoChangeNotifier ) + + +////////////////////////////////////////////////////////////////////////////////////////// +// XCommandProcessor +////////////////////////////////////////////////////////////////////////////////////////// + +sal_Int32 SAL_CALL +BaseContent::createCommandIdentifier( void ) + throw( RuntimeException ) +{ + return m_pMyShell->getCommandId(); +} + + +void SAL_CALL +BaseContent::abort( sal_Int32 CommandId ) + throw( RuntimeException ) +{ + m_pMyShell->abort( CommandId ); +} + + +Any SAL_CALL +BaseContent::execute( const Command& aCommand, + sal_Int32 CommandId, + const Reference< XCommandEnvironment >& Environment ) + throw( Exception, + CommandAbortedException, + RuntimeException ) +{ + if( ! CommandId ) + // A Command with commandid zero cannot be aborted + CommandId = createCommandIdentifier(); + + m_pMyShell->startTask( CommandId, + Environment ); + + Any aAny; + + if( ! aCommand.Name.compareToAscii( "getPropertySetInfo" ) ) // No exceptions + { + aAny <<= getPropertySetInfo( CommandId ); + } + else if( ! aCommand.Name.compareToAscii( "getCommandInfo" ) ) // no exceptions + { + aAny <<= getCommandInfo(); + } + else if( ! aCommand.Name.compareToAscii( "setPropertyValues" ) ) + { + Sequence< beans::PropertyValue > sPropertyValues; + + if( ! ( aCommand.Argument >>= sPropertyValues ) ) + m_pMyShell->installError( CommandId, + TASKHANDLING_WRONG_SETPROPERTYVALUES_ARGUMENT ); + else + aAny <<= setPropertyValues( CommandId,sPropertyValues ); // calls endTask by itself + } + else if( ! aCommand.Name.compareToAscii( "getPropertyValues" ) ) + { + Sequence< beans::Property > ListOfRequestedProperties; + + if( ! ( aCommand.Argument >>= ListOfRequestedProperties ) ) + m_pMyShell->installError( CommandId, + TASKHANDLING_WRONG_GETPROPERTYVALUES_ARGUMENT ); + else + aAny <<= getPropertyValues( CommandId, + ListOfRequestedProperties ); + } + else if( ! aCommand.Name.compareToAscii( "open" ) ) + { + OpenCommandArgument2 aOpenArgument; + if( ! ( aCommand.Argument >>= aOpenArgument ) ) + m_pMyShell->installError( CommandId, + TASKHANDLING_WRONG_OPEN_ARGUMENT ); + else + { + Reference< XDynamicResultSet > result = open( CommandId,aOpenArgument ); + if( result.is() ) + aAny <<= result; + } + } + else if( ! aCommand.Name.compareToAscii( "delete" ) ) + { + if( ! aCommand.Argument.has< sal_Bool >() ) + m_pMyShell->installError( CommandId, + TASKHANDLING_WRONG_DELETE_ARGUMENT ); + else + deleteContent( CommandId ); + } + else if( ! aCommand.Name.compareToAscii( "transfer" ) ) + { + TransferInfo aTransferInfo; + if( ! ( aCommand.Argument >>= aTransferInfo ) ) + m_pMyShell->installError( CommandId, + TASKHANDLING_WRONG_TRANSFER_ARGUMENT ); + else + transfer( CommandId, aTransferInfo ); + } + else if( ! aCommand.Name.compareToAscii( "insert" ) ) + { + InsertCommandArgument aInsertArgument; + if( ! ( aCommand.Argument >>= aInsertArgument ) ) + m_pMyShell->installError( CommandId, + TASKHANDLING_WRONG_INSERT_ARGUMENT ); + else + insert( CommandId,aInsertArgument ); + } + else if( ! aCommand.Name.compareToAscii( "getCasePreservingURL" ) ) + { + Sequence< beans::Property > seq(1); + seq[0] = beans::Property( + rtl::OUString::createFromAscii("CasePreservingURL"), + -1, + getCppuType( static_cast< sal_Bool* >(0) ), + 0 ); + Reference< sdbc::XRow > xRow = getPropertyValues( CommandId,seq ); + rtl::OUString CasePreservingURL = xRow->getString(1); + if(!xRow->wasNull()) + aAny <<= CasePreservingURL; + } + else if( ! aCommand.Name.compareToAscii( "createNewContent" ) ) + { + ucb::ContentInfo aArg; + if ( !( aCommand.Argument >>= aArg ) ) + m_pMyShell->installError( CommandId, + TASKHANDLING_WRONG_CREATENEWCONTENT_ARGUMENT ); + else + aAny <<= createNewContent( aArg ); + } + else + m_pMyShell->installError( CommandId, + TASKHANDLER_UNSUPPORTED_COMMAND ); + + + // This is the only function allowed to throw an exception + endTask( CommandId ); + + return aAny; +} + + + +void SAL_CALL +BaseContent::addPropertiesChangeListener( + const Sequence< rtl::OUString >& PropertyNames, + const Reference< beans::XPropertiesChangeListener >& Listener ) + throw( RuntimeException ) +{ + if( ! Listener.is() ) + return; + + osl::MutexGuard aGuard( m_aMutex ); + + if( ! m_pPropertyListener ) + m_pPropertyListener = new PropertyListeners( m_aEventListenerMutex ); + + + if( PropertyNames.getLength() == 0 ) + m_pPropertyListener->addInterface( rtl::OUString(),Listener ); + else + { + Reference< beans::XPropertySetInfo > xProp = m_pMyShell->info_p( m_aUncPath ); + for( sal_Int32 i = 0; i < PropertyNames.getLength(); ++i ) + if( xProp->hasPropertyByName( PropertyNames[i] ) ) + m_pPropertyListener->addInterface( PropertyNames[i],Listener ); + } +} + + +void SAL_CALL +BaseContent::removePropertiesChangeListener( const Sequence< rtl::OUString >& PropertyNames, + const Reference< beans::XPropertiesChangeListener >& Listener ) + throw( RuntimeException ) +{ + if( ! Listener.is() ) + return; + + osl::MutexGuard aGuard( m_aMutex ); + + if( ! m_pPropertyListener ) + return; + + for( sal_Int32 i = 0; i < PropertyNames.getLength(); ++i ) + m_pPropertyListener->removeInterface( PropertyNames[i],Listener ); + + m_pPropertyListener->removeInterface( rtl::OUString(), Listener ); +} + + +///////////////////////////////////////////////////////////////////////////////////////// +// XContent +///////////////////////////////////////////////////////////////////////////////////////// + +Reference< ucb::XContentIdentifier > SAL_CALL +BaseContent::getIdentifier() + throw( RuntimeException ) +{ + return m_xContentIdentifier; +} + + +rtl::OUString SAL_CALL +BaseContent::getContentType() + throw( RuntimeException ) +{ + if( !( m_nState & Deleted ) ) + { + if( m_nState & JustInserted ) + { + if ( m_bFolder ) + return m_pMyShell->FolderContentType; + else + return m_pMyShell->FileContentType; + } + else + { + try + { + // Who am I ? + Sequence< beans::Property > seq(1); + seq[0] = beans::Property( rtl::OUString::createFromAscii("IsDocument"), + -1, + getCppuType( static_cast< sal_Bool* >(0) ), + 0 ); + Reference< sdbc::XRow > xRow = getPropertyValues( -1,seq ); + sal_Bool IsDocument = xRow->getBoolean( 1 ); + + if ( !xRow->wasNull() ) + { + if ( IsDocument ) + return m_pMyShell->FileContentType; + else + return m_pMyShell->FolderContentType; + } + else + { + OSL_ENSURE( false, + "BaseContent::getContentType - Property value was null!" ); + } + } + catch ( sdbc::SQLException const & ) + { + OSL_ENSURE( false, + "BaseContent::getContentType - Caught SQLException!" ); + } + } + } + + return rtl::OUString(); +} + + + +void SAL_CALL +BaseContent::addContentEventListener( + const Reference< XContentEventListener >& Listener ) + throw( RuntimeException ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + if ( ! m_pContentEventListeners ) + m_pContentEventListeners = + new cppu::OInterfaceContainerHelper( m_aEventListenerMutex ); + + + m_pContentEventListeners->addInterface( Listener ); +} + + +void SAL_CALL +BaseContent::removeContentEventListener( + const Reference< XContentEventListener >& Listener ) + throw( RuntimeException ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + if ( m_pContentEventListeners ) + m_pContentEventListeners->removeInterface( Listener ); +} + + + +//////////////////////////////////////////////////////////////////////////////// +// XPropertyContainer +//////////////////////////////////////////////////////////////////////////////// + + +void SAL_CALL +BaseContent::addProperty( + const rtl::OUString& Name, + sal_Int16 Attributes, + const Any& DefaultValue ) + throw( beans::PropertyExistException, + beans::IllegalTypeException, + lang::IllegalArgumentException, + RuntimeException) +{ + if( ( m_nState & JustInserted ) || ( m_nState & Deleted ) || Name == rtl::OUString() ) + { + throw lang::IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), 0 ); + } + + m_pMyShell->associate( m_aUncPath,Name,DefaultValue,Attributes ); +} + + +void SAL_CALL +BaseContent::removeProperty( + const rtl::OUString& Name ) + throw( beans::UnknownPropertyException, + beans::NotRemoveableException, + RuntimeException) +{ + + if( m_nState & Deleted ) + throw beans::UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); + + m_pMyShell->deassociate( m_aUncPath, Name ); +} + +//////////////////////////////////////////////////////////////////////////////// +// XContentCreator +//////////////////////////////////////////////////////////////////////////////// + +Sequence< ContentInfo > SAL_CALL +BaseContent::queryCreatableContentsInfo( + void ) + throw( RuntimeException ) +{ + return m_pMyShell->queryCreatableContentsInfo(); +} + + +Reference< XContent > SAL_CALL +BaseContent::createNewContent( + const ContentInfo& Info ) + throw( RuntimeException ) +{ + // Check type. + if ( !Info.Type.getLength() ) + return Reference< XContent >(); + + sal_Bool bFolder + = ( Info.Type.compareTo( m_pMyShell->FolderContentType ) == 0 ); + if ( !bFolder ) + { + if ( Info.Type.compareTo( m_pMyShell->FileContentType ) != 0 ) + { + // Neither folder nor file to create! + return Reference< XContent >(); + } + } + + // Who am I ? + sal_Bool IsDocument = false; + + try + { + Sequence< beans::Property > seq(1); + seq[0] = beans::Property( rtl::OUString::createFromAscii("IsDocument"), + -1, + getCppuType( static_cast< sal_Bool* >(0) ), + 0 ); + Reference< sdbc::XRow > xRow = getPropertyValues( -1,seq ); + IsDocument = xRow->getBoolean( 1 ); + + if ( xRow->wasNull() ) + { + IsDocument = false; +// OSL_ENSURE( false, +// "BaseContent::createNewContent - Property value was null!" ); +// return Reference< XContent >(); + } + } + catch ( sdbc::SQLException const & ) + { + OSL_ENSURE( false, + "BaseContent::createNewContent - Caught SQLException!" ); + return Reference< XContent >(); + } + + rtl::OUString dstUncPath; + + if( IsDocument ) + { + // KSO: Why is a document a XContentCreator? This is quite unusual. + dstUncPath = getParentName( m_aUncPath ); + } + else + dstUncPath = m_aUncPath; + + BaseContent* p = new BaseContent( m_pMyShell, dstUncPath, bFolder ); + return Reference< XContent >( p ); +} + + +//////////////////////////////////////////////////////////////////////////////// +// XPropertySetInfoChangeNotifier +//////////////////////////////////////////////////////////////////////////////// + + +void SAL_CALL +BaseContent::addPropertySetInfoChangeListener( + const Reference< beans::XPropertySetInfoChangeListener >& Listener ) + throw( RuntimeException ) +{ + osl::MutexGuard aGuard( m_aMutex ); + if( ! m_pPropertySetInfoChangeListeners ) + m_pPropertySetInfoChangeListeners = new cppu::OInterfaceContainerHelper( m_aEventListenerMutex ); + + m_pPropertySetInfoChangeListeners->addInterface( Listener ); +} + + +void SAL_CALL +BaseContent::removePropertySetInfoChangeListener( + const Reference< beans::XPropertySetInfoChangeListener >& Listener ) + throw( RuntimeException ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + if( m_pPropertySetInfoChangeListeners ) + m_pPropertySetInfoChangeListeners->removeInterface( Listener ); +} + + +//////////////////////////////////////////////////////////////////////////////// +// XChild +//////////////////////////////////////////////////////////////////////////////// + +Reference< XInterface > SAL_CALL +BaseContent::getParent( + void ) + throw( RuntimeException ) +{ + rtl::OUString ParentUnq = getParentName( m_aUncPath ); + rtl::OUString ParentUrl; + + + sal_Bool err = m_pMyShell->getUrlFromUnq( ParentUnq, ParentUrl ); + if( err ) + return Reference< XInterface >( 0 ); + + FileContentIdentifier* p = new FileContentIdentifier( m_pMyShell,ParentUnq ); + Reference< XContentIdentifier > Identifier( p ); + + try + { + Reference< XContent > content = m_pMyShell->m_pProvider->queryContent( Identifier ); + return Reference<XInterface>(content,UNO_QUERY); + } + catch( IllegalIdentifierException ) + { + return Reference< XInterface >(); + } +} + + +void SAL_CALL +BaseContent::setParent( + const Reference< XInterface >& ) + throw( lang::NoSupportException, + RuntimeException) +{ + throw lang::NoSupportException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); +} + + +////////////////////////////////////////////////////////////////////////////////////////// +// Private Methods +////////////////////////////////////////////////////////////////////////////////////////// + + +Reference< XCommandInfo > SAL_CALL +BaseContent::getCommandInfo() + throw( RuntimeException ) +{ + if( m_nState & Deleted ) + return Reference< XCommandInfo >(); + + return m_pMyShell->info_c(); +} + + +Reference< beans::XPropertySetInfo > SAL_CALL +BaseContent::getPropertySetInfo( + sal_Int32 ) + throw( RuntimeException ) +{ + if( m_nState & Deleted ) + return Reference< beans::XPropertySetInfo >(); + + return m_pMyShell->info_p( m_aUncPath ); +} + + + + +Reference< sdbc::XRow > SAL_CALL +BaseContent::getPropertyValues( + sal_Int32 nMyCommandIdentifier, + const Sequence< beans::Property >& PropertySet ) + throw( RuntimeException ) +{ + sal_Int32 nProps = PropertySet.getLength(); + if ( !nProps ) + return Reference< sdbc::XRow >(); + + if( m_nState & Deleted ) + { + Sequence< Any > aValues( nProps ); + return Reference< sdbc::XRow >( new XRow_impl( m_pMyShell, aValues ) ); + } + + if( m_nState & JustInserted ) + { + Sequence< Any > aValues( nProps ); + Any* pValues = aValues.getArray(); + + const beans::Property* pProps = PropertySet.getConstArray(); + + for ( sal_Int32 n = 0; n < nProps; ++n ) + { + const beans::Property& rProp = pProps[ n ]; + Any& rValue = pValues[ n ]; + + if( rProp.Name.compareToAscii( "ContentType" ) == 0 ) + { + rValue <<= m_bFolder ? m_pMyShell->FolderContentType + : m_pMyShell->FileContentType; + } + else if( rProp.Name.compareToAscii( "IsFolder" ) == 0 ) + { + rValue <<= m_bFolder; + } + else if( rProp.Name.compareToAscii( "IsDocument" ) == 0 ) + { + rValue <<= sal_Bool( !m_bFolder ); + } + } + + return Reference< sdbc::XRow >( + new XRow_impl( m_pMyShell, aValues ) ); + } + + return m_pMyShell->getv( nMyCommandIdentifier, + m_aUncPath, + PropertySet ); +} + + +Sequence< Any > SAL_CALL +BaseContent::setPropertyValues( + sal_Int32 nMyCommandIdentifier, + const Sequence< beans::PropertyValue >& Values ) + throw() +{ + if( m_nState & Deleted ) + { // To do + return Sequence< Any >( Values.getLength() ); + } + + const rtl::OUString Title = rtl::OUString::createFromAscii( "Title" ); + + // Special handling for files which have to be inserted + if( m_nState & JustInserted ) + { + for( sal_Int32 i = 0; i < Values.getLength(); ++i ) + { + if( Values[i].Name == Title ) + { + rtl::OUString NewTitle; + if( Values[i].Value >>= NewTitle ) + { + if ( m_nState & NameForInsertionSet ) + { + // User wants to set another Title before "insert". + // m_aUncPath contains previous own URI. + + sal_Int32 nLastSlash = m_aUncPath.lastIndexOf( '/' ); + bool bTrailingSlash = false; + if ( nLastSlash == m_aUncPath.getLength() - 1 ) + { + bTrailingSlash = true; + nLastSlash + = m_aUncPath.lastIndexOf( '/', nLastSlash ); + } + + OSL_ENSURE( nLastSlash != -1, + "BaseContent::setPropertyValues: " + "Invalid URL!" ); + + rtl::OUStringBuffer aBuf( + m_aUncPath.copy( 0, nLastSlash + 1 ) ); + + if ( NewTitle.getLength() > 0 ) + { + aBuf.append( NewTitle ); + if ( bTrailingSlash ) + aBuf.append( sal_Unicode( '/' ) ); + } + else + { + m_nState &= ~NameForInsertionSet; + } + + m_aUncPath = aBuf.makeStringAndClear(); + } + else + { + if ( NewTitle.getLength() > 0 ) + { + // Initial Title before "insert". + // m_aUncPath contains parent's URI. + + if( m_aUncPath.lastIndexOf( sal_Unicode('/') ) != m_aUncPath.getLength() - 1 ) + m_aUncPath += rtl::OUString::createFromAscii("/"); + + m_aUncPath += rtl::Uri::encode( NewTitle, + rtl_UriCharClassPchar, + rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8 ); + m_nState |= NameForInsertionSet; + } + } + } + } + } + + return Sequence< Any >( Values.getLength() ); + } + else + { + Sequence< Any > ret = m_pMyShell->setv( m_aUncPath, // Does not handle Title + Values ); + + // Special handling Title: Setting Title is equivalent to a renaming of the underlying file + for( sal_Int32 i = 0; i < Values.getLength(); ++i ) + { + if( Values[i].Name != Title ) + continue; // handled by setv + + rtl::OUString NewTitle; + if( !( Values[i].Value >>= NewTitle ) ) + { + ret[i] <<= beans::IllegalTypeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); + break; + } + else if( ! NewTitle.getLength() ) + { + ret[i] <<= lang::IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), 0 ); + break; + } + + + rtl::OUString aDstName = getParentName( m_aUncPath ); + if( aDstName.lastIndexOf( sal_Unicode('/') ) != aDstName.getLength() - 1 ) + aDstName += rtl::OUString::createFromAscii("/"); + + aDstName += rtl::Uri::encode( NewTitle, + rtl_UriCharClassPchar, + rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8 ); + + m_pMyShell->move( nMyCommandIdentifier, // move notifies the childs also; + m_aUncPath, + aDstName, + NameClash::KEEP ); + + try + { + endTask( nMyCommandIdentifier ); + } + catch( const Exception& e ) + { + ret[i] <<= e; + } + + // NameChanges come back trough a ContentEvent + break; // only handling Title + } // end for + + return ret; + } +} + + + +Reference< XDynamicResultSet > SAL_CALL +BaseContent::open( + sal_Int32 nMyCommandIdentifier, + const OpenCommandArgument2& aCommandArgument ) + throw() +{ + Reference< XDynamicResultSet > retValue( 0 ); + + if( ( m_nState & Deleted ) ) + { + m_pMyShell->installError( nMyCommandIdentifier, + TASKHANDLING_DELETED_STATE_IN_OPEN_COMMAND ); + } + else if( m_nState & JustInserted ) + { + m_pMyShell->installError( nMyCommandIdentifier, + TASKHANDLING_INSERTED_STATE_IN_OPEN_COMMAND ); + } + else + { + if( aCommandArgument.Mode == OpenMode::DOCUMENT || + aCommandArgument.Mode == OpenMode::DOCUMENT_SHARE_DENY_NONE ) + + { + Reference< io::XOutputStream > outputStream( aCommandArgument.Sink,UNO_QUERY ); + if( outputStream.is() ) + { + m_pMyShell->page( nMyCommandIdentifier, + m_aUncPath, + outputStream ); + } + + sal_Bool bLock = ( aCommandArgument.Mode != OpenMode::DOCUMENT_SHARE_DENY_NONE ); + + Reference< io::XActiveDataSink > activeDataSink( aCommandArgument.Sink,UNO_QUERY ); + if( activeDataSink.is() ) + { + activeDataSink->setInputStream( m_pMyShell->open( nMyCommandIdentifier, + m_aUncPath, + bLock ) ); + } + + Reference< io::XActiveDataStreamer > activeDataStreamer( aCommandArgument.Sink,UNO_QUERY ); + if( activeDataStreamer.is() ) + { + activeDataStreamer->setStream( m_pMyShell->open_rw( nMyCommandIdentifier, + m_aUncPath, + bLock ) ); + } + } + else if ( aCommandArgument.Mode == OpenMode::ALL || + aCommandArgument.Mode == OpenMode::FOLDERS || + aCommandArgument.Mode == OpenMode::DOCUMENTS ) + { + retValue = m_pMyShell->ls( nMyCommandIdentifier, + m_aUncPath, + aCommandArgument.Mode, + aCommandArgument.Properties, + aCommandArgument.SortingInfo ); + } +// else if( aCommandArgument.Mode == +// OpenMode::DOCUMENT_SHARE_DENY_NONE || +// aCommandArgument.Mode == +// OpenMode::DOCUMENT_SHARE_DENY_WRITE ) +// m_pMyShell->installError( nMyCommandIdentifier, +// TASKHANDLING_UNSUPPORTED_OPEN_MODE, +// aCommandArgument.Mode); + else + m_pMyShell->installError( nMyCommandIdentifier, + TASKHANDLING_UNSUPPORTED_OPEN_MODE, + aCommandArgument.Mode); + } + + return retValue; +} + + + +void SAL_CALL +BaseContent::deleteContent( sal_Int32 nMyCommandIdentifier ) + throw() +{ + if( m_nState & Deleted ) + return; + + if( m_pMyShell->remove( nMyCommandIdentifier,m_aUncPath ) ) + { + osl::MutexGuard aGuard( m_aMutex ); + m_nState |= Deleted; + } +} + + + +void SAL_CALL +BaseContent::transfer( sal_Int32 nMyCommandIdentifier, + const TransferInfo& aTransferInfo ) + throw() +{ + if( m_nState & Deleted ) + return; + + if( aTransferInfo.SourceURL.compareToAscii( "file:",5 ) != 0 ) + { + m_pMyShell->installError( nMyCommandIdentifier, + TASKHANDLING_TRANSFER_INVALIDSCHEME ); + return; + } + + rtl::OUString srcUnc; + if( m_pMyShell->getUnqFromUrl( aTransferInfo.SourceURL,srcUnc ) ) + { + m_pMyShell->installError( nMyCommandIdentifier, + TASKHANDLING_TRANSFER_INVALIDURL ); + return; + } + + rtl::OUString srcUncPath = srcUnc; + + // Determine the new title ! + rtl::OUString NewTitle; + if( aTransferInfo.NewTitle.getLength() ) + NewTitle = rtl::Uri::encode( aTransferInfo.NewTitle, + rtl_UriCharClassPchar, + rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8 ); + else + NewTitle = srcUncPath.copy( 1 + srcUncPath.lastIndexOf( sal_Unicode('/') ) ); + + // Is destination a document or a folder ? + Sequence< beans::Property > seq(1); + seq[0] = beans::Property( rtl::OUString::createFromAscii("IsDocument"), + -1, + getCppuType( static_cast< sal_Bool* >(0) ), + 0 ); + Reference< sdbc::XRow > xRow = getPropertyValues( nMyCommandIdentifier,seq ); + sal_Bool IsDocument = xRow->getBoolean( 1 ); + if( xRow->wasNull() ) + { // Destination file type could not be determined + m_pMyShell->installError( nMyCommandIdentifier, + TASKHANDLING_TRANSFER_DESTFILETYPE ); + return; + } + + rtl::OUString dstUncPath; + if( IsDocument ) + { // as sibling + sal_Int32 lastSlash = m_aUncPath.lastIndexOf( sal_Unicode('/') ); + dstUncPath = m_aUncPath.copy(0,lastSlash ); + } + else + // as child + dstUncPath = m_aUncPath; + + dstUncPath += ( rtl::OUString::createFromAscii( "/" ) + NewTitle ); + + sal_Int32 NameClash = aTransferInfo.NameClash; + + if( aTransferInfo.MoveData ) + m_pMyShell->move( nMyCommandIdentifier,srcUncPath,dstUncPath,NameClash ); + else + m_pMyShell->copy( nMyCommandIdentifier,srcUncPath,dstUncPath,NameClash ); +} + + + + +void SAL_CALL BaseContent::insert( sal_Int32 nMyCommandIdentifier, + const InsertCommandArgument& aInsertArgument ) + throw() +{ + if( m_nState & FullFeatured ) + { + m_pMyShell->write( nMyCommandIdentifier, + m_aUncPath, + aInsertArgument.ReplaceExisting, + aInsertArgument.Data ); + return; + } + + if( ! ( m_nState & JustInserted ) ) + { + m_pMyShell->installError( nMyCommandIdentifier, + TASKHANDLING_NOFRESHINSERT_IN_INSERT_COMMAND ); + return; + } + + // Inserts the content, which has the flag m_bIsFresh + + if( ! m_nState & NameForInsertionSet ) + { + m_pMyShell->installError( nMyCommandIdentifier, + TASKHANDLING_NONAMESET_INSERT_COMMAND ); + return; + } + + // Inserting a document or a file? + sal_Bool bDocument = false; + + Sequence< beans::Property > seq(1); + seq[0] = beans::Property( rtl::OUString::createFromAscii("IsDocument"), + -1, + getCppuType( static_cast< sal_Bool* >(0) ), + 0 ); + + Reference< sdbc::XRow > xRow = getPropertyValues( -1,seq ); + + bool contentTypeSet = true; // is set to false, if contentType not set + try + { + bDocument = xRow->getBoolean( 1 ); + if( xRow->wasNull() ) + contentTypeSet = false; + + } + catch ( sdbc::SQLException const & ) + { + OSL_ENSURE( false, + "BaseContent::insert - Caught SQLException!" ); + contentTypeSet = false; + } + + if( ! contentTypeSet ) + { + m_pMyShell->installError( nMyCommandIdentifier, + TASKHANDLING_NOCONTENTTYPE_INSERT_COMMAND ); + return; + } + + + sal_Bool success = false; + if( bDocument ) + success = m_pMyShell->mkfil( nMyCommandIdentifier, + m_aUncPath, + aInsertArgument.ReplaceExisting, + aInsertArgument.Data ); + else + { + while( ! success ) + { + success = m_pMyShell->mkdir( nMyCommandIdentifier, + m_aUncPath, + aInsertArgument.ReplaceExisting ); + if( success ) + break; + + XInteractionRequestImpl *aRequestImpl = + new XInteractionRequestImpl( + rtl::Uri::decode( + getTitle(m_aUncPath), + rtl_UriDecodeWithCharset, + RTL_TEXTENCODING_UTF8), + (cppu::OWeakObject*)this, + m_pMyShell,nMyCommandIdentifier); + uno::Reference< task::XInteractionRequest > aReq( aRequestImpl ); + + m_pMyShell->handleTask( nMyCommandIdentifier,aReq ); + if( aRequestImpl->aborted() || + !aRequestImpl->newName().getLength() ) + // means aborting + break; + + // determine new uncpath + m_pMyShell->clearError( nMyCommandIdentifier ); + m_aUncPath = getParentName( m_aUncPath ); + if( m_aUncPath.lastIndexOf( sal_Unicode('/') ) != m_aUncPath.getLength() - 1 ) + m_aUncPath += rtl::OUString::createFromAscii("/"); + + m_aUncPath += rtl::Uri::encode( aRequestImpl->newName(), + rtl_UriCharClassPchar, + rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8 ); + } + } + + if ( ! success ) + return; + + FileContentIdentifier* p = new FileContentIdentifier( m_pMyShell,m_aUncPath ); + m_xContentIdentifier = Reference< XContentIdentifier >( p ); + + m_pMyShell->registerNotifier( m_aUncPath,this ); + m_pMyShell->insertDefaultProperties( m_aUncPath ); + + osl::MutexGuard aGuard( m_aMutex ); + m_nState = FullFeatured; +} + + + +void SAL_CALL BaseContent::endTask( sal_Int32 CommandId ) +{ + // This is the only function allowed to throw an exception + m_pMyShell->endTask( CommandId,m_aUncPath,this ); +} + + + +ContentEventNotifier* +BaseContent::cDEL( void ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + m_nState |= Deleted; + + ContentEventNotifier* p; + if( m_pContentEventListeners ) + p = new ContentEventNotifier( m_pMyShell, + this, + m_xContentIdentifier, + m_pContentEventListeners->getElements() ); + else + p = 0; + + return p; +} + + +ContentEventNotifier* +BaseContent::cEXC( const rtl::OUString aNewName ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + Reference< XContentIdentifier > xOldRef = m_xContentIdentifier; + m_aUncPath = aNewName; + FileContentIdentifier* pp = new FileContentIdentifier( m_pMyShell,aNewName ); + m_xContentIdentifier = Reference< XContentIdentifier >( pp ); + + ContentEventNotifier* p = 0; + if( m_pContentEventListeners ) + p = new ContentEventNotifier( m_pMyShell, + this, + m_xContentIdentifier, + xOldRef, + m_pContentEventListeners->getElements() ); + + return p; +} + + +ContentEventNotifier* +BaseContent::cCEL( void ) +{ + osl::MutexGuard aGuard( m_aMutex ); + ContentEventNotifier* p = 0; + if( m_pContentEventListeners ) + p = new ContentEventNotifier( m_pMyShell, + this, + m_xContentIdentifier, + m_pContentEventListeners->getElements() ); + + return p; +} + +PropertySetInfoChangeNotifier* +BaseContent::cPSL( void ) +{ + osl::MutexGuard aGuard( m_aMutex ); + PropertySetInfoChangeNotifier* p = 0; + if( m_pPropertySetInfoChangeListeners ) + p = new PropertySetInfoChangeNotifier( m_pMyShell, + this, + m_xContentIdentifier, + m_pPropertySetInfoChangeListeners->getElements() ); + + return p; +} + + + +PropertyChangeNotifier* +BaseContent::cPCL( void ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + Sequence< rtl::OUString > seqNames; + + if( m_pPropertyListener ) + seqNames = m_pPropertyListener->getContainedTypes(); + + PropertyChangeNotifier* p = 0; + + sal_Int32 length = seqNames.getLength(); + + if( length ) + { + ListenerMap* listener = new ListenerMap(); + for( sal_Int32 i = 0; i < length; ++i ) + { + (*listener)[seqNames[i]] = m_pPropertyListener->getContainer( seqNames[i] )->getElements(); + } + + p = new PropertyChangeNotifier( m_pMyShell, + this, + m_xContentIdentifier, + listener ); + } + + return p; +} + + +rtl::OUString BaseContent::getKey( void ) +{ + return m_aUncPath; +} diff --git a/ucb/source/ucp/file/bc.hxx b/ucb/source/ucp/file/bc.hxx new file mode 100644 index 000000000000..2163758bfffc --- /dev/null +++ b/ucb/source/ucp/file/bc.hxx @@ -0,0 +1,353 @@ +/************************************************************************* + * + * 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 _BC_HXX_ +#define _BC_HXX_ + +#include "osl/mutex.hxx" +#include "rtl/ustring.hxx" +#include <cppuhelper/weak.hxx> +#include <ucbhelper/macros.hxx> +#include <cppuhelper/interfacecontainer.h> +#include <com/sun/star/uno/XInterface.hpp> +#include <com/sun/star/lang/XTypeProvider.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/ucb/XCommandProcessor.hpp> +#include <com/sun/star/beans/XPropertiesChangeNotifier.hpp> +#include <com/sun/star/ucb/XContent.hpp> +#include <com/sun/star/ucb/XContentProvider.hpp> +#ifndef _COM_SUN_STAR_UCB_XRESULTSET_HPP_ +#include <com/sun/star/ucb/XDynamicResultSet.hpp> +#endif +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/sdbc/XRow.hpp> +#include <com/sun/star/beans/PropertyChangeEvent.hpp> +#include <com/sun/star/beans/Property.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/ucb/XCommandInfo.hpp> +#include <com/sun/star/ucb/InsertCommandArgument.hpp> +#include <com/sun/star/beans/XPropertySetInfo.hpp> +#include <com/sun/star/beans/XPropertyContainer.hpp> +#include <com/sun/star/beans/XPropertySetInfoChangeNotifier.hpp> +#include <com/sun/star/beans/XPropertySetInfoChangeListener.hpp> +#include <com/sun/star/container/XChild.hpp> +#include <com/sun/star/ucb/XContentCreator.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/ucb/OpenCommandArgument2.hpp> +#include <com/sun/star/ucb/InteractiveBadTransferURLException.hpp> +#ifndef _COM_SUN_STAR_UCB_SHELL_HXX_ +#include "shell.hxx" +#endif + + +namespace fileaccess { + + class PropertyListeners; + class shell; + class FileProvider; + + class BaseContent: + public cppu::OWeakObject, + public com::sun::star::lang::XComponent, + public com::sun::star::lang::XServiceInfo, + public com::sun::star::lang::XTypeProvider, + public com::sun::star::ucb::XCommandProcessor, + public com::sun::star::beans::XPropertiesChangeNotifier, + public com::sun::star::beans::XPropertyContainer, + public com::sun::star::beans::XPropertySetInfoChangeNotifier, + public com::sun::star::ucb::XContentCreator, + public com::sun::star::container::XChild, + public com::sun::star::ucb::XContent, + public fileaccess::Notifier // implementation class + { + private: + + // A special creator for inserted contents; Creates an ugly object + BaseContent( shell* pMyShell, + const rtl::OUString& parentName, + sal_Bool bFolder ); + + public: + BaseContent( + shell* pMyShell, + const com::sun::star::uno::Reference< com::sun::star::ucb::XContentIdentifier >& xContentIdentifier, + const rtl::OUString& aUnqPath ); + + virtual ~BaseContent(); + + // XInterface + virtual com::sun::star::uno::Any SAL_CALL + queryInterface( + const com::sun::star::uno::Type& aType ) + throw( com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + acquire( + void ) + throw(); + + virtual void SAL_CALL + release( + void ) + throw(); + + + // XComponent + virtual void SAL_CALL + dispose( + void ) + throw( com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL + addEventListener( + const com::sun::star::uno::Reference< com::sun::star::lang::XEventListener >& xListener ) + throw( com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL + removeEventListener( const com::sun::star::uno::Reference< com::sun::star::lang::XEventListener >& aListener ) + throw( com::sun::star::uno::RuntimeException ); + + + // XTypeProvider + + XTYPEPROVIDER_DECL() + + + // XServiceInfo + virtual rtl::OUString SAL_CALL + getImplementationName() + throw( com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL + supportsService( const rtl::OUString& ServiceName ) + throw( com::sun::star::uno::RuntimeException); + + virtual com::sun::star::uno::Sequence< rtl::OUString > SAL_CALL + getSupportedServiceNames() + throw( com::sun::star::uno::RuntimeException ); + + + // XCommandProcessor + virtual sal_Int32 SAL_CALL + createCommandIdentifier( + void ) + throw( com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::uno::Any SAL_CALL + execute( + const com::sun::star::ucb::Command& aCommand, + sal_Int32 CommandId, + const com::sun::star::uno::Reference< com::sun::star::ucb::XCommandEnvironment >& Environment ) + throw( com::sun::star::uno::Exception, + com::sun::star::ucb::CommandAbortedException, + com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL + abort( + sal_Int32 CommandId ) + throw( com::sun::star::uno::RuntimeException ); + + + // XContent + virtual com::sun::star::uno::Reference< com::sun::star::ucb::XContentIdentifier > SAL_CALL + getIdentifier( + void ) + throw( com::sun::star::uno::RuntimeException ); + + virtual rtl::OUString SAL_CALL + getContentType( + void ) + throw( com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL + addContentEventListener( + const com::sun::star::uno::Reference< com::sun::star::ucb::XContentEventListener >& Listener ) + throw( com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL + removeContentEventListener( + const com::sun::star::uno::Reference< com::sun::star::ucb::XContentEventListener >& Listener ) + throw( com::sun::star::uno::RuntimeException ); + + // XPropertiesChangeNotifier + + virtual void SAL_CALL + addPropertiesChangeListener( + const com::sun::star::uno::Sequence< rtl::OUString >& PropertyNames, + const com::sun::star::uno::Reference< + com::sun::star::beans::XPropertiesChangeListener >& Listener ) + throw( com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL + removePropertiesChangeListener( const com::sun::star::uno::Sequence< rtl::OUString >& PropertyNames, + const com::sun::star::uno::Reference< + com::sun::star::beans::XPropertiesChangeListener >& Listener ) + throw( com::sun::star::uno::RuntimeException ); + + // XPropertyContainer + + virtual void SAL_CALL + addProperty( + const rtl::OUString& Name, + sal_Int16 Attributes, + const com::sun::star::uno::Any& DefaultValue ) + throw( com::sun::star::beans::PropertyExistException, + com::sun::star::beans::IllegalTypeException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + removeProperty( + const rtl::OUString& Name ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::beans::NotRemoveableException, + com::sun::star::uno::RuntimeException ); + + // XPropertySetInfoChangeNotifier + + virtual void SAL_CALL + addPropertySetInfoChangeListener( + const com::sun::star::uno::Reference< + com::sun::star::beans::XPropertySetInfoChangeListener >& Listener ) + throw( com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL + removePropertySetInfoChangeListener( + const com::sun::star::uno::Reference< + com::sun::star::beans::XPropertySetInfoChangeListener >& Listener ) + throw( com::sun::star::uno::RuntimeException ); + + + // XContentCreator + + virtual com::sun::star::uno::Sequence< com::sun::star::ucb::ContentInfo > SAL_CALL + queryCreatableContentsInfo( + void ) + throw( com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::uno::Reference< com::sun::star::ucb::XContent > SAL_CALL + createNewContent( + const com::sun::star::ucb::ContentInfo& Info ) + throw( com::sun::star::uno::RuntimeException ); + + + // XChild + virtual com::sun::star::uno::Reference< com::sun::star::uno::XInterface > SAL_CALL + getParent( + void ) throw( com::sun::star::uno::RuntimeException ); + + // Not supported + virtual void SAL_CALL + setParent( const com::sun::star::uno::Reference< com::sun::star::uno::XInterface >& Parent ) + throw( com::sun::star::lang::NoSupportException, + com::sun::star::uno::RuntimeException); + + + // Notifier + + ContentEventNotifier* cDEL( void ); + ContentEventNotifier* cEXC( const rtl::OUString aNewName ); + ContentEventNotifier* cCEL( void ); + PropertySetInfoChangeNotifier* cPSL( void ); + PropertyChangeNotifier* cPCL( void ); + rtl::OUString getKey( void ); + + private: + // Data members + shell* m_pMyShell; + com::sun::star::uno::Reference< com::sun::star::ucb::XContentIdentifier > m_xContentIdentifier; + rtl::OUString m_aUncPath; + + enum state { NameForInsertionSet = 1, + JustInserted = 2, + Deleted = 4, + FullFeatured = 8, + Connected = 16 }; + sal_Bool m_bFolder; + sal_uInt16 m_nState; + + osl::Mutex m_aMutex; + + osl::Mutex m_aEventListenerMutex; + cppu::OInterfaceContainerHelper* m_pDisposeEventListeners; + cppu::OInterfaceContainerHelper* m_pContentEventListeners; + cppu::OInterfaceContainerHelper* m_pPropertySetInfoChangeListeners; + PropertyListeners* m_pPropertyListener; + + + // Private Methods + com::sun::star::uno::Reference< com::sun::star::ucb::XCommandInfo > SAL_CALL + getCommandInfo() + throw( com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::uno::Reference< com::sun::star::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo( + sal_Int32 nMyCommandIdentifier ) + throw( com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::uno::Reference< com::sun::star::sdbc::XRow > SAL_CALL + getPropertyValues( + sal_Int32 nMyCommandIdentifier, + const com::sun::star::uno::Sequence< com::sun::star::beans::Property >& PropertySet ) + throw( com::sun::star::uno::RuntimeException ); + + com::sun::star::uno::Sequence< com::sun::star::uno::Any > SAL_CALL + setPropertyValues( + sal_Int32 nMyCommandIdentifier, + const com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >& Values ) + throw( ); + + com::sun::star::uno::Reference< com::sun::star::ucb::XDynamicResultSet > SAL_CALL + open( + sal_Int32 nMyCommandIdentifier, + const com::sun::star::ucb::OpenCommandArgument2& aCommandArgument ) + throw(); + + void SAL_CALL + deleteContent( sal_Int32 nMyCommandIdentifier ) + throw(); + + + void SAL_CALL + transfer( sal_Int32 nMyCommandIdentifier, + const com::sun::star::ucb::TransferInfo& aTransferInfo ) + throw(); + + void SAL_CALL + insert( sal_Int32 nMyCommandIdentifier, + const com::sun::star::ucb::InsertCommandArgument& aInsertArgument ) + throw(); + + void SAL_CALL endTask( sal_Int32 CommandId ); + + friend class ContentEventNotifier; + }; + +} // end namespace fileaccess + +#endif + diff --git a/ucb/source/ucp/file/exports2.dxp b/ucb/source/ucp/file/exports2.dxp new file mode 100644 index 000000000000..4804c8d0ae57 --- /dev/null +++ b/ucb/source/ucp/file/exports2.dxp @@ -0,0 +1,8 @@ +component_getImplementationEnvironment +component_getFactory + +_ZTIN3com3sun4star3ucb31InteractiveAugmentedIOExceptionE +_ZTIN3com3sun4star3ucb22InteractiveIOExceptionE +_ZTIN3com3sun4star4task28ClassifiedInteractionRequestE +_ZTIN3com3sun4star3ucb18NameClashExceptionE +_ZTIN3com3sun4star3ucb27UnsupportedCommandExceptionE diff --git a/ucb/source/ucp/file/filcmd.cxx b/ucb/source/ucp/file/filcmd.cxx new file mode 100644 index 000000000000..776482957c1e --- /dev/null +++ b/ucb/source/ucp/file/filcmd.cxx @@ -0,0 +1,141 @@ + /************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" +#include "filcmd.hxx" +#include "shell.hxx" +#include "prov.hxx" + + +using namespace fileaccess; +using namespace com::sun::star; +using namespace com::sun::star::ucb; + + +XCommandInfo_impl::XCommandInfo_impl( shell* pMyShell ) + : m_pMyShell( pMyShell ), + m_xProvider( pMyShell->m_pProvider ) +{ +} + +XCommandInfo_impl::~XCommandInfo_impl() +{ +} + + + +void SAL_CALL +XCommandInfo_impl::acquire( + void ) + throw() +{ + OWeakObject::acquire(); +} + + +void SAL_CALL +XCommandInfo_impl::release( + void ) + throw() +{ + OWeakObject::release(); +} + + +uno::Any SAL_CALL +XCommandInfo_impl::queryInterface( + const uno::Type& rType ) + throw( uno::RuntimeException ) +{ + uno::Any aRet = cppu::queryInterface( rType, + SAL_STATIC_CAST( XCommandInfo*,this) ); + return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ); +} + + +uno::Sequence< CommandInfo > SAL_CALL +XCommandInfo_impl::getCommands( + void ) + throw( uno::RuntimeException ) +{ + return m_pMyShell->m_sCommandInfo; +} + + +CommandInfo SAL_CALL +XCommandInfo_impl::getCommandInfoByName( + const rtl::OUString& aName ) + throw( UnsupportedCommandException, + uno::RuntimeException) +{ + for( sal_Int32 i = 0; i < m_pMyShell->m_sCommandInfo.getLength(); i++ ) + if( m_pMyShell->m_sCommandInfo[i].Name == aName ) + return m_pMyShell->m_sCommandInfo[i]; + + throw UnsupportedCommandException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); +} + + +CommandInfo SAL_CALL +XCommandInfo_impl::getCommandInfoByHandle( + sal_Int32 Handle ) + throw( UnsupportedCommandException, + uno::RuntimeException ) +{ + for( sal_Int32 i = 0; i < m_pMyShell->m_sCommandInfo.getLength(); ++i ) + if( m_pMyShell->m_sCommandInfo[i].Handle == Handle ) + return m_pMyShell->m_sCommandInfo[i]; + + throw UnsupportedCommandException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); +} + + +sal_Bool SAL_CALL +XCommandInfo_impl::hasCommandByName( + const rtl::OUString& aName ) + throw( uno::RuntimeException ) +{ + for( sal_Int32 i = 0; i < m_pMyShell->m_sCommandInfo.getLength(); ++i ) + if( m_pMyShell->m_sCommandInfo[i].Name == aName ) + return true; + + return false; +} + + +sal_Bool SAL_CALL +XCommandInfo_impl::hasCommandByHandle( + sal_Int32 Handle ) + throw( uno::RuntimeException ) +{ + for( sal_Int32 i = 0; i < m_pMyShell->m_sCommandInfo.getLength(); ++i ) + if( m_pMyShell->m_sCommandInfo[i].Handle == Handle ) + return true; + + return false; +} diff --git a/ucb/source/ucp/file/filcmd.hxx b/ucb/source/ucp/file/filcmd.hxx new file mode 100644 index 000000000000..6a6725bfcb17 --- /dev/null +++ b/ucb/source/ucp/file/filcmd.hxx @@ -0,0 +1,108 @@ + /************************************************************************* + * + * 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 _FILCMD_HXX_ +#define _FILCMD_HXX_ + +#include <rtl/ustring.hxx> +#include <cppuhelper/weak.hxx> +#include <com/sun/star/uno/XInterface.hpp> +#include <com/sun/star/ucb/XCommandInfo.hpp> +#include <com/sun/star/ucb/XContentProvider.hpp> + + +namespace fileaccess { + + + // forward + class shell; + + + class XCommandInfo_impl + : public cppu::OWeakObject, + public com::sun::star::ucb::XCommandInfo + { + public: + + XCommandInfo_impl( shell* pMyShell ); + + virtual ~XCommandInfo_impl(); + + // XInterface + virtual com::sun::star::uno::Any SAL_CALL + queryInterface( + const com::sun::star::uno::Type& aType ) + throw( com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + acquire( + void ) + throw(); + + virtual void SAL_CALL + release( + void ) + throw(); + + // XCommandInfo + + virtual com::sun::star::uno::Sequence< com::sun::star::ucb::CommandInfo > SAL_CALL + getCommands( + void ) + throw( com::sun::star::uno::RuntimeException); + + virtual com::sun::star::ucb::CommandInfo SAL_CALL + getCommandInfoByName( + const rtl::OUString& Name ) + throw( com::sun::star::ucb::UnsupportedCommandException, + com::sun::star::uno::RuntimeException); + + virtual com::sun::star::ucb::CommandInfo SAL_CALL + getCommandInfoByHandle( + sal_Int32 Handle ) + throw( com::sun::star::ucb::UnsupportedCommandException, + com::sun::star::uno::RuntimeException ); + + virtual sal_Bool SAL_CALL + hasCommandByName( + const rtl::OUString& Name ) + throw( com::sun::star::uno::RuntimeException ); + + virtual sal_Bool SAL_CALL + hasCommandByHandle( + sal_Int32 Handle ) + throw( com::sun::star::uno::RuntimeException ); + + + private: + + shell* m_pMyShell; + com::sun::star::uno::Reference< com::sun::star::ucb::XContentProvider > m_xProvider; + }; + +} + +#endif diff --git a/ucb/source/ucp/file/filerror.hxx b/ucb/source/ucp/file/filerror.hxx new file mode 100644 index 000000000000..35b0d8ae5ce8 --- /dev/null +++ b/ucb/source/ucp/file/filerror.hxx @@ -0,0 +1,118 @@ + /************************************************************************* + * + * 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 _FILERROR_HXX_ + +namespace fileaccess { + +// Error codes used to deliver the resulting exceptions +#define LOWEST_FREE_ERROR 72 + +#define TASKHANDLER_NO_ERROR 0 +#define TASKHANDLER_UNSUPPORTED_COMMAND 1 +#define TASKHANDLING_WRONG_SETPROPERTYVALUES_ARGUMENT 2 +#define TASKHANDLING_WRONG_GETPROPERTYVALUES_ARGUMENT 3 +#define TASKHANDLING_WRONG_OPEN_ARGUMENT 4 +#define TASKHANDLING_WRONG_DELETE_ARGUMENT 5 +#define TASKHANDLING_WRONG_TRANSFER_ARGUMENT 6 +#define TASKHANDLING_WRONG_INSERT_ARGUMENT 7 +#define TASKHANDLING_WRONG_CREATENEWCONTENT_ARGUMENT 8 +#define TASKHANDLING_UNSUPPORTED_OPEN_MODE 9 + +#define TASKHANDLING_DELETED_STATE_IN_OPEN_COMMAND 10 +#define TASKHANDLING_INSERTED_STATE_IN_OPEN_COMMAND 11 + +#define TASKHANDLING_OPEN_FILE_FOR_PAGING 12 +#define TASKHANDLING_NOTCONNECTED_FOR_PAGING 13 +#define TASKHANDLING_BUFFERSIZEEXCEEDED_FOR_PAGING 14 +#define TASKHANDLING_IOEXCEPTION_FOR_PAGING 15 +#define TASKHANDLING_READING_FILE_FOR_PAGING 16 + +#define TASKHANDLING_OPEN_FOR_INPUTSTREAM 17 +#define TASKHANDLING_OPEN_FOR_STREAM 18 +#define TASKHANDLING_OPEN_FOR_DIRECTORYLISTING 19 + +#define TASKHANDLING_NOFRESHINSERT_IN_INSERT_COMMAND 22 +#define TASKHANDLING_NONAMESET_INSERT_COMMAND 23 +#define TASKHANDLING_NOCONTENTTYPE_INSERT_COMMAND 24 + +#define TASKHANDLING_ANYOTHER_WRITE 25 // not used +#define TASKHANDLING_NO_OPEN_FILE_FOR_OVERWRITE 26 +#define TASKHANDLING_NO_OPEN_FILE_FOR_WRITE 27 +#define TASKHANDLING_NOTCONNECTED_FOR_WRITE 28 +#define TASKHANDLING_BUFFERSIZEEXCEEDED_FOR_WRITE 29 +#define TASKHANDLING_IOEXCEPTION_FOR_WRITE 30 +#define TASKHANDLING_FILEIOERROR_FOR_WRITE 31 +#define TASKHANDLING_FILEIOERROR_FOR_NO_SPACE 71 +#define TASKHANDLING_FILESIZE_FOR_WRITE 32 +#define TASKHANDLING_INPUTSTREAM_FOR_WRITE 33 +#define TASKHANDLING_NOREPLACE_FOR_WRITE 34 +#define TASKHANDLING_ENSUREDIR_FOR_WRITE 35 + +#define TASKHANDLING_FOLDER_EXISTS_MKDIR 69 +#define TASKHANDLING_INVALID_NAME_MKDIR 70 +#define TASKHANDLING_CREATEDIRECTORY_MKDIR 36 + +#define TASKHANDLING_NOSUCHFILEORDIR_FOR_REMOVE 38 +#define TASKHANDLING_VALIDFILESTATUS_FOR_REMOVE 39 +#define TASKHANDLING_OPENDIRECTORY_FOR_REMOVE 40 +#define TASKHANDLING_DELETEFILE_FOR_REMOVE 41 +#define TASKHANDLING_DELETEDIRECTORY_FOR_REMOVE 42 +#define TASKHANDLING_FILETYPE_FOR_REMOVE 43 +#define TASKHANDLING_VALIDFILESTATUSWHILE_FOR_REMOVE 44 +#define TASKHANDLING_DIRECTORYEXHAUSTED_FOR_REMOVE 45 + +#define TASKHANDLING_TRANSFER_ACCESSINGROOT 46 +#define TASKHANDLING_TRANSFER_INVALIDSCHEME 47 +#define TASKHANDLING_TRANSFER_INVALIDURL 48 +#define TASKHANDLING_TRANSFER_DESTFILETYPE 50 +#define TASKHANDLING_TRANSFER_BY_MOVE_SOURCE 51 +#define TASKHANDLING_TRANSFER_BY_MOVE_SOURCESTAT 52 +#define TASKHANDLING_KEEPERROR_FOR_MOVE 53 +#define TASKHANDLING_NAMECLASH_FOR_MOVE 54 +#define TASKHANDLING_NAMECLASHMOVE_FOR_MOVE 55 +#define TASKHANDLING_NAMECLASHSUPPORT_FOR_MOVE 56 +#define TASKHANDLING_OVERWRITE_FOR_MOVE 57 +#define TASKHANDLING_RENAME_FOR_MOVE 58 +#define TASKHANDLING_RENAMEMOVE_FOR_MOVE 59 + +#define TASKHANDLING_TRANSFER_BY_COPY_SOURCE 60 +#define TASKHANDLING_TRANSFER_BY_COPY_SOURCESTAT 61 +#define TASKHANDLING_KEEPERROR_FOR_COPY 62 +#define TASKHANDLING_OVERWRITE_FOR_COPY 63 +#define TASKHANDLING_RENAME_FOR_COPY 64 +#define TASKHANDLING_RENAMEMOVE_FOR_COPY 65 +#define TASKHANDLING_NAMECLASH_FOR_COPY 66 +#define TASKHANDLING_NAMECLASHMOVE_FOR_COPY 67 +#define TASKHANDLING_NAMECLASHSUPPORT_FOR_COPY 68 + +} + +#endif + + + + diff --git a/ucb/source/ucp/file/filglob.cxx b/ucb/source/ucp/file/filglob.cxx new file mode 100644 index 000000000000..e947c68da1ba --- /dev/null +++ b/ucb/source/ucp/file/filglob.cxx @@ -0,0 +1,954 @@ + /************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" +#include <stdio.h> +#include "filglob.hxx" +#ifndef _FILERROR_HXX_ +#include "filerror.hxx" +#endif +#include "shell.hxx" +#include "bc.hxx" +#include <osl/file.hxx> +#ifndef INCLUDED_STL_VECTOR +#include <vector> +#define INCLUDED_STL_VECTOR +#endif +#include <ucbhelper/cancelcommandexecution.hxx> +#include <com/sun/star/ucb/CommandAbortedException.hpp> +#include <com/sun/star/ucb/UnsupportedCommandException.hpp> +#include <com/sun/star/ucb/UnsupportedOpenModeException.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <com/sun/star/ucb/IOErrorCode.hpp> +#include <com/sun/star/ucb/MissingPropertiesException.hpp> +#include <com/sun/star/ucb/MissingInputStreamException.hpp> +#include <com/sun/star/ucb/NameClashException.hpp> +#include <com/sun/star/ucb/InteractiveBadTransferURLException.hpp> +#include <com/sun/star/ucb/UnsupportedNameClashException.hpp> +#include "com/sun/star/beans/PropertyState.hpp" +#include "com/sun/star/beans/PropertyValue.hpp" +#include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp> +#include "com/sun/star/uno/Any.hxx" +#include "com/sun/star/uno/Sequence.hxx" +#include "osl/diagnose.h" +#include "rtl/ustrbuf.hxx" +#include <rtl/uri.hxx> +#include <rtl/ustring.hxx> +#include "sal/types.h" + +using namespace ucbhelper; +using namespace osl; +using namespace ::com::sun::star; +using namespace com::sun::star::task; +using namespace com::sun::star::beans; +using namespace com::sun::star::lang; +using namespace com::sun::star::uno; +using namespace com::sun::star::ucb; + +namespace { + + Sequence< Any > generateErrorArguments( + rtl::OUString const & rPhysicalUrl) + { + rtl::OUString aResourceName; + rtl::OUString aResourceType; + sal_Bool bRemovable; + bool bResourceName = false; + bool bResourceType = false; + bool bRemoveProperty = false; + + if (osl::FileBase::getSystemPathFromFileURL( + rPhysicalUrl, + aResourceName) + == osl::FileBase::E_None) + bResourceName = true; + + // The resource types "folder" (i.e., directory) and + // "volume" seem to be + // the most interesting when producing meaningful error messages: + osl::DirectoryItem aItem; + if (osl::DirectoryItem::get(rPhysicalUrl, aItem) == + osl::FileBase::E_None) + { + osl::FileStatus aStatus( FileStatusMask_Type ); + if (aItem.getFileStatus(aStatus) == osl::FileBase::E_None) + switch (aStatus.getFileType()) + { + case osl::FileStatus::Directory: + aResourceType + = rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("folder")); + bResourceType = true; + break; + + case osl::FileStatus::Volume: + { + aResourceType + = rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("volume")); + bResourceType = true; + osl::VolumeInfo aVolumeInfo( + VolumeInfoMask_Attributes ); + if( osl::Directory::getVolumeInfo( + rPhysicalUrl,aVolumeInfo ) == + osl::FileBase::E_None ) + { + bRemovable = aVolumeInfo.getRemoveableFlag(); + bRemoveProperty = true; + } + } + break; + case osl::FileStatus::Regular: + case osl::FileStatus::Fifo: + case osl::FileStatus::Socket: + case osl::FileStatus::Link: + case osl::FileStatus::Special: + case osl::FileStatus::Unknown: + // do nothing for now + break; + } + } + + Sequence< Any > aArguments( 1 + + (bResourceName ? 1 : 0) + + (bResourceType ? 1 : 0) + + (bRemoveProperty ? 1 : 0) ); + sal_Int32 i = 0; + aArguments[i++] + <<= PropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Uri")), + -1, + makeAny(rPhysicalUrl), + PropertyState_DIRECT_VALUE); + if (bResourceName) + aArguments[i++] + <<= PropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "ResourceName")), + -1, + makeAny(aResourceName), + PropertyState_DIRECT_VALUE); + if (bResourceType) + aArguments[i++] + <<= PropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "ResourceType")), + -1, + makeAny(aResourceType), + PropertyState_DIRECT_VALUE); + if (bRemoveProperty) + aArguments[i++] + <<= PropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Removable")), + -1, + makeAny(bRemovable), + PropertyState_DIRECT_VALUE); + + return aArguments; + } +} + + + +namespace fileaccess { + + + sal_Bool isChild( const rtl::OUString& srcUnqPath, + const rtl::OUString& dstUnqPath ) + { + static sal_Unicode slash = '/'; + // Simple lexical comparison + sal_Int32 srcL = srcUnqPath.getLength(); + sal_Int32 dstL = dstUnqPath.getLength(); + + return ( + ( srcUnqPath == dstUnqPath ) + || + ( ( dstL > srcL ) + && + ( srcUnqPath.compareTo( dstUnqPath, srcL ) == 0 ) + && + ( dstUnqPath[ srcL ] == slash ) ) + ); + } + + + rtl::OUString newName( + const rtl::OUString& aNewPrefix, + const rtl::OUString& aOldPrefix, + const rtl::OUString& old_Name ) + { + sal_Int32 srcL = aOldPrefix.getLength(); + + rtl::OUString new_Name = old_Name.copy( srcL ); + new_Name = ( aNewPrefix + new_Name ); + return new_Name; + } + + + rtl::OUString getTitle( const rtl::OUString& aPath ) + { + sal_Unicode slash = '/'; + sal_Int32 lastIndex = aPath.lastIndexOf( slash ); + return aPath.copy( lastIndex + 1 ); + } + + + rtl::OUString getParentName( const rtl::OUString& aFileName ) + { + sal_Int32 lastIndex = aFileName.lastIndexOf( sal_Unicode('/') ); + rtl::OUString aParent = aFileName.copy( 0,lastIndex ); + + if( aParent[ aParent.getLength()-1] == sal_Unicode(':') && aParent.getLength() == 6 ) + aParent += rtl::OUString::createFromAscii( "/" ); + + if( 0 == aParent.compareToAscii( "file://" ) ) + aParent = rtl::OUString::createFromAscii( "file:///" ); + + return aParent; + } + + + osl::FileBase::RC osl_File_copy( const rtl::OUString& strPath, + const rtl::OUString& strDestPath, + sal_Bool test ) + { + if( test ) + { + osl::DirectoryItem aItem; + if( osl::DirectoryItem::get( strDestPath,aItem ) != osl::FileBase:: E_NOENT ) + return osl::FileBase::E_EXIST; + } + + return osl::File::copy( strPath,strDestPath ); + } + + + osl::FileBase::RC osl_File_move( const rtl::OUString& strPath, + const rtl::OUString& strDestPath, + sal_Bool test ) + { + if( test ) + { + osl::DirectoryItem aItem; + if( osl::DirectoryItem::get( strDestPath,aItem ) != osl::FileBase:: E_NOENT ) + return osl::FileBase::E_EXIST; + } + + return osl::File::move( strPath,strDestPath ); + } + + void throw_handler( + sal_Int32 errorCode, + sal_Int32 minorCode, + const Reference< XCommandEnvironment >& xEnv, + const rtl::OUString& aUncPath, + BaseContent* pContent, + bool isHandled ) + { + Reference<XCommandProcessor> xComProc(pContent); + Any aAny; + IOErrorCode ioErrorCode; + + if( errorCode == TASKHANDLER_UNSUPPORTED_COMMAND ) + { + aAny <<= UnsupportedCommandException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); + cancelCommandExecution( aAny,xEnv ); + } + else if( errorCode == TASKHANDLING_WRONG_SETPROPERTYVALUES_ARGUMENT || + errorCode == TASKHANDLING_WRONG_GETPROPERTYVALUES_ARGUMENT || + errorCode == TASKHANDLING_WRONG_OPEN_ARGUMENT || + errorCode == TASKHANDLING_WRONG_DELETE_ARGUMENT || + errorCode == TASKHANDLING_WRONG_TRANSFER_ARGUMENT || + errorCode == TASKHANDLING_WRONG_INSERT_ARGUMENT || + errorCode == TASKHANDLING_WRONG_CREATENEWCONTENT_ARGUMENT ) + { + IllegalArgumentException excep; + excep.ArgumentPosition = 0; + aAny <<= excep; + cancelCommandExecution( + aAny,xEnv); + } + else if( errorCode == TASKHANDLING_UNSUPPORTED_OPEN_MODE ) + { + UnsupportedOpenModeException excep; + excep.Mode = sal::static_int_cast< sal_Int16 >(minorCode); + aAny <<= excep; + cancelCommandExecution( aAny,xEnv ); + } + else if(errorCode == TASKHANDLING_DELETED_STATE_IN_OPEN_COMMAND || + errorCode == TASKHANDLING_INSERTED_STATE_IN_OPEN_COMMAND || + errorCode == TASKHANDLING_NOFRESHINSERT_IN_INSERT_COMMAND ) + { + // What to do here? + } + else if( + // error in opening file + errorCode == TASKHANDLING_NO_OPEN_FILE_FOR_OVERWRITE || + // error in opening file + errorCode == TASKHANDLING_NO_OPEN_FILE_FOR_WRITE || + // error in opening file + errorCode == TASKHANDLING_OPEN_FOR_STREAM || + // error in opening file + errorCode == TASKHANDLING_OPEN_FOR_INPUTSTREAM || + // error in opening file + errorCode == TASKHANDLING_OPEN_FILE_FOR_PAGING ) + { + switch( minorCode ) + { + case FileBase::E_NAMETOOLONG: + // pathname was too long + ioErrorCode = IOErrorCode_NAME_TOO_LONG; + break; + case FileBase::E_NXIO: + // No such device or address + case FileBase::E_NODEV: + // No such device + ioErrorCode = IOErrorCode_INVALID_DEVICE; + break; + case FileBase::E_NOENT: + // No such file or directory + ioErrorCode = IOErrorCode_NOT_EXISTING; + break; + case FileBase::E_ROFS: + // #i4735# handle ROFS transparently as ACCESS_DENIED + case FileBase::E_ACCES: + // permission denied<P> + ioErrorCode = IOErrorCode_ACCESS_DENIED; + break; + case FileBase::E_ISDIR: + // Is a directory<p> + ioErrorCode = IOErrorCode_NO_FILE; + break; + case FileBase::E_NOTREADY: + ioErrorCode = IOErrorCode_DEVICE_NOT_READY; + break; + case FileBase::E_MFILE: + // too many open files used by the process + case FileBase::E_NFILE: + // too many open files in the system + ioErrorCode = IOErrorCode_OUT_OF_FILE_HANDLES; + break; + case FileBase::E_INVAL: + // the format of the parameters was not valid + ioErrorCode = IOErrorCode_INVALID_PARAMETER; + break; + case FileBase::E_NOMEM: + // not enough memory for allocating structures + ioErrorCode = IOErrorCode_OUT_OF_MEMORY; + break; + case FileBase::E_BUSY: + // Text file busy + ioErrorCode = IOErrorCode_LOCKING_VIOLATION; + break; + case FileBase::E_AGAIN: + // Operation would block + ioErrorCode = IOErrorCode_LOCKING_VIOLATION; + break; + case FileBase::E_NOLCK: // No record locks available + ioErrorCode = IOErrorCode_LOCKING_VIOLATION; + break; + + case FileBase::E_FAULT: // Bad address + case FileBase::E_LOOP: // Too many symbolic links encountered + case FileBase::E_NOSPC: // No space left on device + case FileBase::E_INTR: // function call was interrupted + case FileBase::E_IO: // I/O error + case FileBase::E_MULTIHOP: // Multihop attempted + case FileBase::E_NOLINK: // Link has been severed + default: + ioErrorCode = IOErrorCode_GENERAL; + break; + } + + cancelCommandExecution( + ioErrorCode, + generateErrorArguments(aUncPath), + xEnv, + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "an error occured during file opening")), + xComProc); + } + else if( errorCode == TASKHANDLING_OPEN_FOR_DIRECTORYLISTING || + errorCode == TASKHANDLING_OPENDIRECTORY_FOR_REMOVE ) + { + switch( minorCode ) + { + case FileBase::E_INVAL: + // the format of the parameters was not valid + ioErrorCode = IOErrorCode_INVALID_PARAMETER; + break; + case FileBase::E_NOENT: + // the specified path doesn't exist + ioErrorCode = IOErrorCode_NOT_EXISTING; + break; + case FileBase::E_NOTDIR: + // the specified path is not an directory + ioErrorCode = IOErrorCode_NO_DIRECTORY; + break; + case FileBase::E_NOMEM: + // not enough memory for allocating structures + ioErrorCode = IOErrorCode_OUT_OF_MEMORY; + break; + case FileBase::E_ROFS: + // #i4735# handle ROFS transparently as ACCESS_DENIED + case FileBase::E_ACCES: // permission denied + ioErrorCode = IOErrorCode_ACCESS_DENIED; + break; + case FileBase::E_NOTREADY: + ioErrorCode = IOErrorCode_DEVICE_NOT_READY; + break; + case FileBase::E_MFILE: + // too many open files used by the process + case FileBase::E_NFILE: + // too many open files in the system + ioErrorCode = IOErrorCode_OUT_OF_FILE_HANDLES; + break; + case FileBase::E_NAMETOOLONG: + // File name too long + ioErrorCode = IOErrorCode_NAME_TOO_LONG; + break; + case FileBase::E_LOOP: + // Too many symbolic links encountered<p> + default: + ioErrorCode = IOErrorCode_GENERAL; + break; + } + + cancelCommandExecution( + ioErrorCode, + generateErrorArguments(aUncPath), + xEnv, + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "an error occured during opening a directory")), + xComProc); + } + else if( errorCode == TASKHANDLING_NOTCONNECTED_FOR_WRITE || + errorCode == TASKHANDLING_BUFFERSIZEEXCEEDED_FOR_WRITE || + errorCode == TASKHANDLING_IOEXCEPTION_FOR_WRITE || + errorCode == TASKHANDLING_NOTCONNECTED_FOR_PAGING || + errorCode == TASKHANDLING_BUFFERSIZEEXCEEDED_FOR_PAGING || + errorCode == TASKHANDLING_IOEXCEPTION_FOR_PAGING ) + { + ioErrorCode = IOErrorCode_UNKNOWN; + cancelCommandExecution( + ioErrorCode, + generateErrorArguments(aUncPath), + xEnv, + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "an error occured writing or reading from a file")), + xComProc ); + } + else if( errorCode == TASKHANDLING_FILEIOERROR_FOR_NO_SPACE ) + { + ioErrorCode = IOErrorCode_OUT_OF_DISK_SPACE; + cancelCommandExecution( + ioErrorCode, + generateErrorArguments(aUncPath), + xEnv, + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "device full")), + xComProc); + } + else if( errorCode == TASKHANDLING_FILEIOERROR_FOR_WRITE || + errorCode == TASKHANDLING_READING_FILE_FOR_PAGING ) + { + switch( minorCode ) + { + case FileBase::E_INVAL: + // the format of the parameters was not valid + ioErrorCode = IOErrorCode_INVALID_PARAMETER; + break; + case FileBase::E_FBIG: + // File too large + ioErrorCode = IOErrorCode_CANT_WRITE; + break; + case FileBase::E_NOSPC: + // No space left on device + ioErrorCode = IOErrorCode_OUT_OF_DISK_SPACE; + break; + case FileBase::E_NXIO: + // No such device or address + ioErrorCode = IOErrorCode_INVALID_DEVICE; + break; + case FileBase::E_NOLINK: + // Link has been severed + case FileBase::E_ISDIR: + // Is a directory + ioErrorCode = IOErrorCode_NO_FILE; + break; + case FileBase::E_AGAIN: + // Operation would block + ioErrorCode = IOErrorCode_LOCKING_VIOLATION; + break; + case FileBase::E_TIMEDOUT: + ioErrorCode = IOErrorCode_DEVICE_NOT_READY; + break; + case FileBase::E_NOLCK: // No record locks available + ioErrorCode = IOErrorCode_LOCKING_VIOLATION; + break; + case FileBase::E_IO: // I/O error + case FileBase::E_BADF: // Bad file + case FileBase::E_FAULT: // Bad address + case FileBase::E_INTR: // function call was interrupted + default: + ioErrorCode = IOErrorCode_GENERAL; + break; + } + cancelCommandExecution( + ioErrorCode, + generateErrorArguments(aUncPath), + xEnv, + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "an error occured during opening a file")), + xComProc); + } + else if( errorCode == TASKHANDLING_NONAMESET_INSERT_COMMAND || + errorCode == TASKHANDLING_NOCONTENTTYPE_INSERT_COMMAND ) + { + Sequence< ::rtl::OUString > aSeq( 1 ); + aSeq[0] = + ( errorCode == TASKHANDLING_NONAMESET_INSERT_COMMAND ) ? + rtl::OUString::createFromAscii( "Title" ) : + rtl::OUString::createFromAscii( "ContentType" ); + + aAny <<= MissingPropertiesException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "a property is missing necessary" + "to create a content")), + xComProc, + aSeq); + cancelCommandExecution(aAny,xEnv); + } + else if( errorCode == TASKHANDLING_FILESIZE_FOR_WRITE ) + { + switch( minorCode ) + { + case FileBase::E_INVAL: + // the format of the parameters was not valid + case FileBase::E_OVERFLOW: + // The resulting file offset would be a value which cannot + // be represented correctly for regular files + ioErrorCode = IOErrorCode_INVALID_PARAMETER; + break; + default: + ioErrorCode = IOErrorCode_GENERAL; + break; + } + cancelCommandExecution( + ioErrorCode, + generateErrorArguments(aUncPath), + xEnv, + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "there were problems with the filesize")), + xComProc); + } + else if(errorCode == TASKHANDLING_INPUTSTREAM_FOR_WRITE) + { + Reference<XInterface> xContext(xComProc,UNO_QUERY); + aAny <<= + MissingInputStreamException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "the inputstream is missing necessary" + "to create a content")), + xContext); + cancelCommandExecution(aAny,xEnv); + } + else if( errorCode == TASKHANDLING_NOREPLACE_FOR_WRITE ) + // Overwrite = false and file exists + { + NameClashException excep; + excep.Name = getTitle(aUncPath); + excep.Classification = InteractionClassification_ERROR; + Reference<XInterface> xContext(xComProc,UNO_QUERY); + excep.Context = xContext; + excep.Message = rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "file exists and overwrite forbidden")); + aAny <<= excep; + cancelCommandExecution( aAny,xEnv ); + } + else if( errorCode == TASKHANDLING_INVALID_NAME_MKDIR ) + { + InteractiveAugmentedIOException excep; + excep.Code = IOErrorCode_INVALID_CHARACTER; + PropertyValue prop; + prop.Name = rtl::OUString::createFromAscii("ResourceName"); + prop.Handle = -1; + rtl::OUString m_aClashingName( + rtl::Uri::decode( + getTitle(aUncPath), + rtl_UriDecodeWithCharset, + RTL_TEXTENCODING_UTF8)); + prop.Value <<= m_aClashingName; + Sequence<Any> seq(1); + seq[0] <<= prop; + excep.Arguments = seq; + excep.Classification = InteractionClassification_ERROR; + Reference<XInterface> xContext(xComProc,UNO_QUERY); + excep.Context = xContext; + excep.Message = rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "the name contained invalid characters")); + if(isHandled) + throw excep; + else { + aAny <<= excep; + cancelCommandExecution( aAny,xEnv ); + } +// ioErrorCode = IOErrorCode_INVALID_CHARACTER; +// cancelCommandExecution( +// ioErrorCode, +// generateErrorArguments(aUncPath), +// xEnv, +// rtl::OUString( +// RTL_CONSTASCII_USTRINGPARAM( +// "the name contained invalid characters")), +// xComProc ); + } + else if( errorCode == TASKHANDLING_FOLDER_EXISTS_MKDIR ) + { + NameClashException excep; + excep.Name = getTitle(aUncPath); + excep.Classification = InteractionClassification_ERROR; + Reference<XInterface> xContext(xComProc,UNO_QUERY); + excep.Context = xContext; + excep.Message = rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "folder exists and overwrite forbidden")); + if(isHandled) + throw excep; + else { + aAny <<= excep; + cancelCommandExecution( aAny,xEnv ); + } +// ioErrorCode = IOErrorCode_ALREADY_EXISTING; +// cancelCommandExecution( +// ioErrorCode, +// generateErrorArguments(aUncPath), +// xEnv, +// rtl::OUString( +// RTL_CONSTASCII_USTRINGPARAM( +// "the folder exists")), +// xComProc ); + } + else if( errorCode == TASKHANDLING_ENSUREDIR_FOR_WRITE || + errorCode == TASKHANDLING_CREATEDIRECTORY_MKDIR ) + { + switch( minorCode ) + { + case FileBase::E_ACCES: + ioErrorCode = IOErrorCode_ACCESS_DENIED; + break; + case FileBase::E_ROFS: + ioErrorCode = IOErrorCode_WRITE_PROTECTED; + break; + case FileBase::E_NAMETOOLONG: + ioErrorCode = IOErrorCode_NAME_TOO_LONG; + break; + default: + ioErrorCode = IOErrorCode_NOT_EXISTING_PATH; + break; + } + cancelCommandExecution( + ioErrorCode, + generateErrorArguments(getParentName(aUncPath)), + //TODO! ok to supply physical URL to getParentName()? + xEnv, + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "a folder could not be created")), + xComProc ); + } + else if( errorCode == TASKHANDLING_VALIDFILESTATUSWHILE_FOR_REMOVE || + errorCode == TASKHANDLING_VALIDFILESTATUS_FOR_REMOVE || + errorCode == TASKHANDLING_NOSUCHFILEORDIR_FOR_REMOVE ) + { + switch( minorCode ) + { + case FileBase::E_INVAL: // the format of the parameters was not valid + ioErrorCode = IOErrorCode_INVALID_PARAMETER; + break; + case FileBase::E_NOMEM: // not enough memory for allocating structures + ioErrorCode = IOErrorCode_OUT_OF_MEMORY; + break; + case FileBase::E_ROFS: // #i4735# handle ROFS transparently as ACCESS_DENIED + case FileBase::E_ACCES: // permission denied + ioErrorCode = IOErrorCode_ACCESS_DENIED; + break; + case FileBase::E_MFILE: // too many open files used by the process + case FileBase::E_NFILE: // too many open files in the system + ioErrorCode = IOErrorCode_OUT_OF_FILE_HANDLES; + break; + case FileBase::E_NOLINK: // Link has been severed + case FileBase::E_NOENT: // No such file or directory + ioErrorCode = IOErrorCode_NOT_EXISTING; + break; + case FileBase::E_NAMETOOLONG: // File name too long + ioErrorCode = IOErrorCode_NAME_TOO_LONG; + break; + case FileBase::E_NOTDIR: // A component of the path prefix of path is not a directory + ioErrorCode = IOErrorCode_NOT_EXISTING_PATH; + break; + case FileBase::E_LOOP: // Too many symbolic links encountered + case FileBase::E_IO: // I/O error + case FileBase::E_MULTIHOP: // Multihop attempted + case FileBase::E_FAULT: // Bad address + case FileBase::E_INTR: // function call was interrupted + case FileBase::E_NOSYS: // Function not implemented + case FileBase::E_NOSPC: // No space left on device + case FileBase::E_NXIO: // No such device or address + case FileBase::E_OVERFLOW: // Value too large for defined data type + case FileBase::E_BADF: // Invalid oslDirectoryItem parameter + default: + ioErrorCode = IOErrorCode_GENERAL; + break; + } + cancelCommandExecution( + ioErrorCode, + generateErrorArguments(aUncPath), + xEnv, + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "a file status object could not be filled")), + xComProc ); + } + else if( errorCode == TASKHANDLING_DELETEFILE_FOR_REMOVE || + errorCode == TASKHANDLING_DELETEDIRECTORY_FOR_REMOVE ) + { + switch( minorCode ) + { + case FileBase::E_INVAL: // the format of the parameters was not valid + ioErrorCode = IOErrorCode_INVALID_PARAMETER; + break; + case FileBase::E_NOMEM: // not enough memory for allocating structures + ioErrorCode = IOErrorCode_OUT_OF_MEMORY; + break; + case FileBase::E_ACCES: // Permission denied + ioErrorCode = IOErrorCode_ACCESS_DENIED; + break; + case FileBase::E_PERM: // Operation not permitted + ioErrorCode = IOErrorCode_NOT_SUPPORTED; + break; + case FileBase::E_NAMETOOLONG: // File name too long + ioErrorCode = IOErrorCode_NAME_TOO_LONG; + break; + case FileBase::E_NOLINK: // Link has been severed + case FileBase::E_NOENT: // No such file or directory + ioErrorCode = IOErrorCode_NOT_EXISTING; + break; + case FileBase::E_ISDIR: // Is a directory + case FileBase::E_ROFS: // Read-only file system + ioErrorCode = IOErrorCode_NOT_SUPPORTED; + break; + case FileBase::E_BUSY: // Device or resource busy + ioErrorCode = IOErrorCode_LOCKING_VIOLATION; + break; + case FileBase::E_FAULT: // Bad address + case FileBase::E_LOOP: // Too many symbolic links encountered + case FileBase::E_IO: // I/O error + case FileBase::E_INTR: // function call was interrupted + case FileBase::E_MULTIHOP: // Multihop attempted + default: + ioErrorCode = IOErrorCode_GENERAL; + break; + } + cancelCommandExecution( + ioErrorCode, + generateErrorArguments(aUncPath), + xEnv, + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "a file or directory could not be deleted")), + xComProc ); + } + else if( errorCode == TASKHANDLING_TRANSFER_BY_COPY_SOURCE || + errorCode == TASKHANDLING_TRANSFER_BY_COPY_SOURCESTAT || + errorCode == TASKHANDLING_TRANSFER_BY_MOVE_SOURCE || + errorCode == TASKHANDLING_TRANSFER_BY_MOVE_SOURCESTAT || + errorCode == TASKHANDLING_TRANSFER_DESTFILETYPE || + errorCode == TASKHANDLING_FILETYPE_FOR_REMOVE || + errorCode == TASKHANDLING_DIRECTORYEXHAUSTED_FOR_REMOVE || + errorCode == TASKHANDLING_TRANSFER_INVALIDURL ) + { + rtl::OUString aMsg; + switch( minorCode ) + { + case FileBase::E_NOENT: // No such file or directory + if ( errorCode == TASKHANDLING_TRANSFER_BY_COPY_SOURCE || + errorCode == TASKHANDLING_TRANSFER_BY_COPY_SOURCESTAT || + errorCode == TASKHANDLING_TRANSFER_BY_MOVE_SOURCE || + errorCode == TASKHANDLING_TRANSFER_BY_MOVE_SOURCESTAT ) + { + ioErrorCode = IOErrorCode_NOT_EXISTING; + aMsg = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "source file/folder does not exist")); + break; + } + else + { + ioErrorCode = IOErrorCode_GENERAL; + aMsg = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "a general error during transfer command")); + break; + } + default: + ioErrorCode = IOErrorCode_GENERAL; + aMsg = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "a general error during transfer command")); + break; + } + cancelCommandExecution( + ioErrorCode, + generateErrorArguments(aUncPath), + xEnv, + aMsg, + xComProc ); + } + else if( errorCode == TASKHANDLING_TRANSFER_ACCESSINGROOT ) + { + ioErrorCode = IOErrorCode_WRITE_PROTECTED; + cancelCommandExecution( + ioErrorCode, + generateErrorArguments(aUncPath), + xEnv, + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "accessing the root during transfer")), + xComProc ); + } + else if( errorCode == TASKHANDLING_TRANSFER_INVALIDSCHEME ) + { + Reference<XInterface> xContext(xComProc,UNO_QUERY); + + aAny <<= + InteractiveBadTransferURLException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "bad tranfer url")), + xContext); + cancelCommandExecution( aAny,xEnv ); + } + else if( errorCode == TASKHANDLING_OVERWRITE_FOR_MOVE || + errorCode == TASKHANDLING_OVERWRITE_FOR_COPY || + errorCode == TASKHANDLING_NAMECLASHMOVE_FOR_MOVE || + errorCode == TASKHANDLING_NAMECLASHMOVE_FOR_COPY || + errorCode == TASKHANDLING_KEEPERROR_FOR_MOVE || + errorCode == TASKHANDLING_KEEPERROR_FOR_COPY || + errorCode == TASKHANDLING_RENAME_FOR_MOVE || + errorCode == TASKHANDLING_RENAME_FOR_COPY || + errorCode == TASKHANDLING_RENAMEMOVE_FOR_MOVE || + errorCode == TASKHANDLING_RENAMEMOVE_FOR_COPY ) + { + rtl::OUString aMsg(RTL_CONSTASCII_USTRINGPARAM( + "general error during transfer")); + + switch( minorCode ) + { + case FileBase::E_EXIST: + ioErrorCode = IOErrorCode_ALREADY_EXISTING; + break; + case FileBase::E_INVAL: // the format of the parameters was not valid + ioErrorCode = IOErrorCode_INVALID_PARAMETER; + break; + case FileBase::E_NOMEM: // not enough memory for allocating structures + ioErrorCode = IOErrorCode_OUT_OF_MEMORY; + break; + case FileBase::E_ACCES: // Permission denied + ioErrorCode = IOErrorCode_ACCESS_DENIED; + break; + case FileBase::E_PERM: // Operation not permitted + ioErrorCode = IOErrorCode_NOT_SUPPORTED; + break; + case FileBase::E_NAMETOOLONG: // File name too long + ioErrorCode = IOErrorCode_NAME_TOO_LONG; + break; + case FileBase::E_NOENT: // No such file or directory + ioErrorCode = IOErrorCode_NOT_EXISTING; + aMsg = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "file/folder does not exist")); + break; + case FileBase::E_ROFS: // Read-only file system<p> + ioErrorCode = IOErrorCode_NOT_EXISTING; + break; + default: + ioErrorCode = IOErrorCode_GENERAL; + break; + } + cancelCommandExecution( + ioErrorCode, + generateErrorArguments(aUncPath), + xEnv, + aMsg, + xComProc ); + } + else if( errorCode == TASKHANDLING_NAMECLASH_FOR_COPY || + errorCode == TASKHANDLING_NAMECLASH_FOR_MOVE ) + { + NameClashException excep; + excep.Name = getTitle(aUncPath); + excep.Classification = InteractionClassification_ERROR; + Reference<XInterface> xContext(xComProc,UNO_QUERY); + excep.Context = xContext; + excep.Message = rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "name clash during copy or move")); + aAny <<= excep; + + cancelCommandExecution(aAny,xEnv); + } + else if( errorCode == TASKHANDLING_NAMECLASHSUPPORT_FOR_MOVE || + errorCode == TASKHANDLING_NAMECLASHSUPPORT_FOR_COPY ) + { + Reference<XInterface> xContext( + xComProc,UNO_QUERY); + UnsupportedNameClashException excep; + excep.NameClash = minorCode; + excep.Context = xContext; + excep.Message = rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "name clash value not supported during copy or move")); + + aAny <<= excep; + cancelCommandExecution(aAny,xEnv); + } + else + { + // case TASKHANDLER_NO_ERROR: + return; + } + } + + +} // end namespace fileaccess diff --git a/ucb/source/ucp/file/filglob.hxx b/ucb/source/ucp/file/filglob.hxx new file mode 100644 index 000000000000..015128e6588b --- /dev/null +++ b/ucb/source/ucp/file/filglob.hxx @@ -0,0 +1,119 @@ +/************************************************************************* + * + * 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 _FILGLOB_HXX_ +#define _FILGLOB_HXX_ + +#include <rtl/ustring.hxx> +#include <osl/file.hxx> +#include <com/sun/star/ucb/XCommandEnvironment.hpp> + + +namespace fileaccess { + + class BaseContent; + + struct equalOUString + { + bool operator()( const rtl::OUString& rKey1, const rtl::OUString& rKey2 ) const + { + return !!( rKey1 == rKey2 ); + } + }; + + + struct hashOUString + { + size_t operator()( const rtl::OUString& rName ) const + { + return rName.hashCode(); + } + }; + + + /******************************************************************************/ + /* */ + /* Helper functions */ + /* */ + /******************************************************************************/ + + + // Returns true if dstUnqPath is a child from srcUnqPath or both are equal + + extern sal_Bool isChild( const rtl::OUString& srcUnqPath, + const rtl::OUString& dstUnqPath ); + + + // Changes the prefix in name + extern rtl::OUString newName( const rtl::OUString& aNewPrefix, + const rtl::OUString& aOldPrefix, + const rtl::OUString& old_Name ); + + // returns the last part of the given url as title + extern rtl::OUString getTitle( const rtl::OUString& aPath ); + + // returns the url without last part as parentname + // In case aFileName is root ( file:/// ) root is returned + + extern rtl::OUString getParentName( const rtl::OUString& aFileName ); + + /** + * special copy: + * On test = true, the implementation determines whether the + * destination exists and returns the appropriate errorcode E_EXIST. + * osl::File::copy copies unchecked. + */ + + extern osl::FileBase::RC osl_File_copy( const rtl::OUString& strPath, + const rtl::OUString& strDestPath, + sal_Bool test = false ); + + /** + * special move: + * On test = true, the implementation determines whether the + * destination exists and returns the appropriate errorcode E_EXIST. + * osl::File::move moves unchecked + */ + + extern osl::FileBase::RC osl_File_move( const rtl::OUString& strPath, + const rtl::OUString& strDestPath, + sal_Bool test = false ); + + // This function implements the global exception handler of the file_ucp; + // It never returns; + + extern void throw_handler( sal_Int32 errorCode, + sal_Int32 minorCode, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment >& xEnv, + const rtl::OUString& aUncPath, + BaseContent* pContent, + bool isHandled = false); + // the physical URL of the object + +} // end namespace fileaccess + +#endif diff --git a/ucb/source/ucp/file/filid.cxx b/ucb/source/ucp/file/filid.cxx new file mode 100644 index 000000000000..8ccd8980fb9b --- /dev/null +++ b/ucb/source/ucp/file/filid.cxx @@ -0,0 +1,148 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" +#include "filid.hxx" +#include "shell.hxx" + +using namespace fileaccess; +using namespace com::sun::star; +using namespace com::sun::star::ucb; + + +FileContentIdentifier::FileContentIdentifier( + shell* pMyShell, + const rtl::OUString& aUnqPath, + sal_Bool IsNormalized ) + : m_pMyShell( pMyShell ), + m_bNormalized( IsNormalized ) +{ + if( IsNormalized ) + { + m_pMyShell->getUrlFromUnq( aUnqPath,m_aContentId ); + m_aNormalizedId = aUnqPath; + m_pMyShell->getScheme( m_aProviderScheme ); + } + else + { + m_pMyShell->getUnqFromUrl( aUnqPath,m_aNormalizedId ); + m_aContentId = aUnqPath; + m_pMyShell->getScheme( m_aProviderScheme ); + } +} + +FileContentIdentifier::~FileContentIdentifier() +{ +} + + +void SAL_CALL +FileContentIdentifier::acquire( + void ) + throw() +{ + OWeakObject::acquire(); +} + + +void SAL_CALL +FileContentIdentifier::release( + void ) + throw() +{ + OWeakObject::release(); +} + + +uno::Any SAL_CALL +FileContentIdentifier::queryInterface( + const uno::Type& rType ) + throw( uno::RuntimeException ) +{ + uno::Any aRet = cppu::queryInterface( rType, + SAL_STATIC_CAST( lang::XTypeProvider*, this), + SAL_STATIC_CAST( XContentIdentifier*, this) ); + return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ); +} + + +uno::Sequence< sal_Int8 > SAL_CALL +FileContentIdentifier::getImplementationId() + throw( uno::RuntimeException ) +{ + static cppu::OImplementationId* pId = NULL; + if ( !pId ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + if ( !pId ) + { + static cppu::OImplementationId id( sal_False ); + pId = &id; + } + } + return (*pId).getImplementationId(); +} + + +uno::Sequence< uno::Type > SAL_CALL +FileContentIdentifier::getTypes( + void ) + throw( uno::RuntimeException ) +{ + static cppu::OTypeCollection* pCollection = NULL; + if ( !pCollection ) { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + if ( !pCollection ) + { + static cppu::OTypeCollection collection( + getCppuType( static_cast< uno::Reference< lang::XTypeProvider >* >( 0 ) ), + getCppuType( static_cast< uno::Reference< XContentIdentifier >* >( 0 ) ) ); + pCollection = &collection; + } + } + return (*pCollection).getTypes(); +} + + +rtl::OUString +SAL_CALL +FileContentIdentifier::getContentIdentifier( + void ) + throw( uno::RuntimeException ) +{ + return m_aContentId; +} + + +rtl::OUString SAL_CALL +FileContentIdentifier::getContentProviderScheme( + void ) + throw( uno::RuntimeException ) +{ + return m_aProviderScheme; +} diff --git a/ucb/source/ucp/file/filid.hxx b/ucb/source/ucp/file/filid.hxx new file mode 100644 index 000000000000..36c774353120 --- /dev/null +++ b/ucb/source/ucp/file/filid.hxx @@ -0,0 +1,102 @@ +/************************************************************************* + * + * 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 _FILID_HXX_ +#define _FILID_HXX_ + +#include <rtl/ustring.hxx> +#include <cppuhelper/weak.hxx> +#include <com/sun/star/lang/XTypeProvider.hpp> +#include <com/sun/star/ucb/XContentIdentifier.hpp> + +namespace fileaccess { + + class shell; + + class FileContentIdentifier : + public cppu::OWeakObject, + public com::sun::star::lang::XTypeProvider, + public com::sun::star::ucb::XContentIdentifier + { + + // This implementation has to be reworked + public: + FileContentIdentifier( shell* pMyShell, + const rtl::OUString& aUnqPath, + sal_Bool IsNormalized = true ); + + virtual ~FileContentIdentifier(); + + // XInterface + virtual com::sun::star::uno::Any SAL_CALL + queryInterface( + const com::sun::star::uno::Type& aType ) + throw( com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL + acquire( + void ) + throw(); + + virtual void SAL_CALL + release( + void ) + throw(); + + // XTypeProvider + virtual com::sun::star::uno::Sequence< com::sun::star::uno::Type > SAL_CALL + getTypes( + void ) + throw( com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL + getImplementationId( + void ) + throw( com::sun::star::uno::RuntimeException ); + + // XContentIdentifier + virtual rtl::OUString SAL_CALL + getContentIdentifier( + void ) + throw( com::sun::star::uno::RuntimeException ); + + virtual rtl::OUString SAL_CALL + getContentProviderScheme( + void ) + throw( com::sun::star::uno::RuntimeException ); + + private: + shell* m_pMyShell; + rtl::OUString m_aContentId; // The URL string + rtl::OUString m_aNormalizedId; // The somehow normalized string + rtl::OUString m_aProviderScheme; + sal_Bool m_bNormalized; + }; + +} // end namespace fileaccess + + +#endif diff --git a/ucb/source/ucp/file/filinl.hxx b/ucb/source/ucp/file/filinl.hxx new file mode 100644 index 000000000000..d28af751403b --- /dev/null +++ b/ucb/source/ucp/file/filinl.hxx @@ -0,0 +1,76 @@ +/************************************************************************* + * + * 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 _FILINL_HXX_ +#define _FILINL_HXX_ + +inline const sal_Bool& SAL_CALL shell::MyProperty::IsNative() const +{ + return isNative; +} +inline const sal_Int32& SAL_CALL shell::MyProperty::getHandle() const +{ + return Handle; +} +inline const com::sun::star::uno::Type& SAL_CALL shell::MyProperty::getType() const +{ + return Typ; +} +inline const com::sun::star::uno::Any& SAL_CALL shell::MyProperty::getValue() const +{ + return Value; +} +inline const com::sun::star::beans::PropertyState& SAL_CALL shell::MyProperty::getState() const +{ + return State; +} +inline const sal_Int16& SAL_CALL shell::MyProperty::getAttributes() const +{ + return Attributes; +} +inline void SAL_CALL shell::MyProperty::setHandle( const sal_Int32& __Handle ) const +{ + (( MyProperty* )this )->Handle = __Handle; +} +inline void SAL_CALL shell::MyProperty::setType( const com::sun::star::uno::Type& __Typ ) const +{ + (( MyProperty* )this )->Typ = __Typ; +} +inline void SAL_CALL shell::MyProperty::setValue( const com::sun::star::uno::Any& __Value ) const +{ + (( MyProperty* )this )->Value = __Value; +} +inline void SAL_CALL shell::MyProperty::setState( const com::sun::star::beans::PropertyState& __State ) const +{ + (( MyProperty* )this )->State = __State; +} +inline void SAL_CALL shell::MyProperty::setAttributes( const sal_Int16& __Attributes ) const +{ + (( MyProperty* )this )->Attributes = __Attributes; +} + + +#endif diff --git a/ucb/source/ucp/file/filinpstr.cxx b/ucb/source/ucp/file/filinpstr.cxx new file mode 100644 index 000000000000..a66a0daf5def --- /dev/null +++ b/ucb/source/ucp/file/filinpstr.cxx @@ -0,0 +1,262 @@ + /************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" +#include "filinpstr.hxx" +#ifndef _FILERROR_HXX_ +#include "filerror.hxx" +#endif +#include "shell.hxx" +#include "prov.hxx" + + +using namespace fileaccess; +using namespace com::sun::star; +using namespace com::sun::star::ucb; + + + +XInputStream_impl::XInputStream_impl( shell* pMyShell,const rtl::OUString& aUncPath, sal_Bool bLock ) + : m_pMyShell( pMyShell ), + m_xProvider( pMyShell->m_pProvider ), + m_bLock( bLock ), + m_aFile( aUncPath ), + m_nErrorCode( TASKHANDLER_NO_ERROR ), + m_nMinorErrorCode( TASKHANDLER_NO_ERROR ) +{ + sal_uInt32 nFlags = OpenFlag_Read; + if ( !bLock ) + nFlags |= OpenFlag_NoLock; + + osl::FileBase::RC err = m_aFile.open( nFlags ); + if( err != osl::FileBase::E_None ) + { + m_nIsOpen = false; + m_aFile.close(); + + m_nErrorCode = TASKHANDLING_OPEN_FOR_INPUTSTREAM; + m_nMinorErrorCode = err; + } + else + m_nIsOpen = true; +} + + +XInputStream_impl::~XInputStream_impl() +{ + try + { + closeInput(); + } + catch (io::IOException const &) + { + OSL_ENSURE(false, "unexpected situation"); + } + catch (uno::RuntimeException const &) + { + OSL_ENSURE(false, "unexpected situation"); + } +} + + +sal_Int32 SAL_CALL XInputStream_impl::CtorSuccess() +{ + return m_nErrorCode; +}; + + + +sal_Int32 SAL_CALL XInputStream_impl::getMinorError() +{ + return m_nMinorErrorCode; +} + + +////////////////////////////////////////////////////////////////////////////////////////// +// XTypeProvider +////////////////////////////////////////////////////////////////////////////////////////// + + +XTYPEPROVIDER_IMPL_3( XInputStream_impl, + lang::XTypeProvider, + io::XSeekable, + io::XInputStream ) + + + +uno::Any SAL_CALL +XInputStream_impl::queryInterface( + const uno::Type& rType ) + throw( uno::RuntimeException) +{ + uno::Any aRet = cppu::queryInterface( rType, + SAL_STATIC_CAST( io::XInputStream*,this ), + SAL_STATIC_CAST( lang::XTypeProvider*,this ), + SAL_STATIC_CAST( io::XSeekable*,this ) ); + return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ); +} + + +void SAL_CALL +XInputStream_impl::acquire( + void ) + throw() +{ + OWeakObject::acquire(); +} + + +void SAL_CALL +XInputStream_impl::release( + void ) + throw() +{ + OWeakObject::release(); +} + + + +sal_Int32 SAL_CALL +XInputStream_impl::readBytes( + uno::Sequence< sal_Int8 >& aData, + sal_Int32 nBytesToRead ) + throw( io::NotConnectedException, + io::BufferSizeExceededException, + io::IOException, + uno::RuntimeException) +{ + if( ! m_nIsOpen ) throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); + + aData.realloc(nBytesToRead); + //TODO! translate memory exhaustion (if it were detectable...) into + // io::BufferSizeExceededException + + sal_uInt64 nrc(0); + if(m_aFile.read( aData.getArray(),sal_uInt64(nBytesToRead),nrc ) + != osl::FileBase::E_None) + throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); + + // Shrink aData in case we read less than nBytesToRead (XInputStream + // documentation does not tell whether this is required, and I do not know + // if any code relies on this, so be conservative---SB): + if (sal::static_int_cast<sal_Int32>(nrc) != nBytesToRead) + aData.realloc(sal_Int32(nrc)); + return ( sal_Int32 ) nrc; +} + +sal_Int32 SAL_CALL +XInputStream_impl::readSomeBytes( + uno::Sequence< sal_Int8 >& aData, + sal_Int32 nMaxBytesToRead ) + throw( io::NotConnectedException, + io::BufferSizeExceededException, + io::IOException, + uno::RuntimeException) +{ + return readBytes( aData,nMaxBytesToRead ); +} + + +void SAL_CALL +XInputStream_impl::skipBytes( + sal_Int32 nBytesToSkip ) + throw( io::NotConnectedException, + io::BufferSizeExceededException, + io::IOException, + uno::RuntimeException) +{ + m_aFile.setPos( osl_Pos_Current, sal_uInt64( nBytesToSkip ) ); +} + + +sal_Int32 SAL_CALL +XInputStream_impl::available( + void ) + throw( io::NotConnectedException, + io::IOException, + uno::RuntimeException) +{ + return 0; +} + + +void SAL_CALL +XInputStream_impl::closeInput( + void ) + throw( io::NotConnectedException, + io::IOException, + uno::RuntimeException ) +{ + if( m_nIsOpen ) + { + osl::FileBase::RC err = m_aFile.close(); + if( err != osl::FileBase::E_None ) + throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); + m_nIsOpen = false; + } +} + + +void SAL_CALL +XInputStream_impl::seek( + sal_Int64 location ) + throw( lang::IllegalArgumentException, + io::IOException, + uno::RuntimeException ) +{ + if( location < 0 ) + throw lang::IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), 0 ); + if( osl::FileBase::E_None != m_aFile.setPos( Pos_Absolut, sal_uInt64( location ) ) ) + throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); +} + + +sal_Int64 SAL_CALL +XInputStream_impl::getPosition( + void ) + throw( io::IOException, + uno::RuntimeException ) +{ + sal_uInt64 uPos; + if( osl::FileBase::E_None != m_aFile.getPos( uPos ) ) + throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); + return sal_Int64( uPos ); +} + +sal_Int64 SAL_CALL +XInputStream_impl::getLength( + void ) + throw( io::IOException, + uno::RuntimeException ) +{ + sal_uInt64 uEndPos; + if ( m_aFile.getSize(uEndPos) != osl::FileBase::E_None ) + throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); + else + return sal_Int64( uEndPos ); +} diff --git a/ucb/source/ucp/file/filinpstr.hxx b/ucb/source/ucp/file/filinpstr.hxx new file mode 100644 index 000000000000..cb0668c10c82 --- /dev/null +++ b/ucb/source/ucp/file/filinpstr.hxx @@ -0,0 +1,164 @@ + /************************************************************************* + * + * 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 _FILINPSTR_HXX_ +#define _FILINPSTR_HXX_ + +#include <rtl/ustring.hxx> +#include <cppuhelper/weak.hxx> +#include <ucbhelper/macros.hxx> +#include <com/sun/star/uno/XInterface.hpp> +#include <com/sun/star/lang/XTypeProvider.hpp> +#include <com/sun/star/io/XSeekable.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/ucb/XContentProvider.hpp> + +#include "filrec.hxx" + +namespace fileaccess { + + // forward declaration + + class shell; + + + class XInputStream_impl + : public cppu::OWeakObject, + public com::sun::star::lang::XTypeProvider, + public com::sun::star::io::XInputStream, + public com::sun::star::io::XSeekable + { + public: + + XInputStream_impl( shell* pMyShell,const rtl::OUString& aUncPath, sal_Bool bLock ); + + virtual ~XInputStream_impl(); + + /** + * Returns an error code as given by filerror.hxx + */ + + sal_Int32 SAL_CALL CtorSuccess(); + sal_Int32 SAL_CALL getMinorError(); + + + // XTypeProvider + + XTYPEPROVIDER_DECL() + + virtual com::sun::star::uno::Any SAL_CALL + queryInterface( + const com::sun::star::uno::Type& rType ) + throw( com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + acquire( + void ) + throw(); + + virtual void SAL_CALL + release( + void ) + throw(); + + virtual sal_Int32 SAL_CALL + readBytes( + com::sun::star::uno::Sequence< sal_Int8 >& aData, + sal_Int32 nBytesToRead ) + throw( com::sun::star::io::NotConnectedException, + com::sun::star::io::BufferSizeExceededException, + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException); + + virtual sal_Int32 SAL_CALL + readSomeBytes( + com::sun::star::uno::Sequence< sal_Int8 >& aData, + sal_Int32 nMaxBytesToRead ) + throw( com::sun::star::io::NotConnectedException, + com::sun::star::io::BufferSizeExceededException, + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + skipBytes( + sal_Int32 nBytesToSkip ) + throw( com::sun::star::io::NotConnectedException, + com::sun::star::io::BufferSizeExceededException, + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException ); + + virtual sal_Int32 SAL_CALL + available( + void ) + throw( com::sun::star::io::NotConnectedException, + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL + closeInput( + void ) + throw( com::sun::star::io::NotConnectedException, + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL + seek( + sal_Int64 location ) + throw( com::sun::star::lang::IllegalArgumentException, + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException ); + + virtual sal_Int64 SAL_CALL + getPosition( + void ) + throw( com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException ); + + virtual sal_Int64 SAL_CALL + getLength( + void ) + throw( com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException ); + + private: + + shell* m_pMyShell; + com::sun::star::uno::Reference< + com::sun::star::ucb::XContentProvider > m_xProvider; + sal_Bool m_nIsOpen; + + sal_Bool m_bLock; + + ReconnectingFile m_aFile; + + sal_Int32 m_nErrorCode; + sal_Int32 m_nMinorErrorCode; + }; + + +} // end namespace XInputStream_impl + +#endif diff --git a/ucb/source/ucp/file/filinsreq.cxx b/ucb/source/ucp/file/filinsreq.cxx new file mode 100644 index 000000000000..586c9a6f3c85 --- /dev/null +++ b/ucb/source/ucp/file/filinsreq.cxx @@ -0,0 +1,224 @@ + /************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" +#include "filinsreq.hxx" +#include "shell.hxx" +#include "filglob.hxx" +#include <com/sun/star/ucb/IOErrorCode.hpp> +#include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp> +#include <com/sun/star/ucb/NameClashException.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> + + + +using namespace cppu; +using namespace com::sun::star; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::task; +using namespace com::sun::star::ucb; +using namespace com::sun::star::beans; +using namespace fileaccess; + + + +void SAL_CALL +XInteractionSupplyNameImpl::acquire( void ) + throw() +{ + OWeakObject::acquire(); +} + + + +void SAL_CALL +XInteractionSupplyNameImpl::release( void ) + throw() +{ + OWeakObject::release(); +} + + + +Any SAL_CALL +XInteractionSupplyNameImpl::queryInterface( const Type& rType ) + throw( RuntimeException ) +{ + Any aRet = cppu::queryInterface( rType, + SAL_STATIC_CAST( lang::XTypeProvider*, this ), + SAL_STATIC_CAST( XInteractionSupplyName*,this) ); + return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ); +} + + +////////////////////////////////////////////////////////////////////////////////////////// +// XTypeProvider +////////////////////////////////////////////////////////////////////////////////////////// + +XTYPEPROVIDER_IMPL_2( XInteractionSupplyNameImpl, + XTypeProvider, + XInteractionSupplyName ) + + + +void SAL_CALL +XInteractionAbortImpl::acquire( void ) + throw() +{ + OWeakObject::acquire(); +} + + + +void SAL_CALL +XInteractionAbortImpl::release( void ) + throw() +{ + OWeakObject::release(); +} + + + +Any SAL_CALL +XInteractionAbortImpl::queryInterface( const Type& rType ) + throw( RuntimeException ) +{ + Any aRet = cppu::queryInterface( rType, + SAL_STATIC_CAST( lang::XTypeProvider*, this ), + SAL_STATIC_CAST( XInteractionAbort*,this) ); + return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ); +} + + +////////////////////////////////////////////////////////////////////////////////////////// +// XTypeProvider +////////////////////////////////////////////////////////////////////////////////////////// + +XTYPEPROVIDER_IMPL_2( XInteractionAbortImpl, + XTypeProvider, + XInteractionAbort ) + + + +XInteractionRequestImpl::XInteractionRequestImpl( + const rtl::OUString& aClashingName, + const Reference<XInterface>& xOrigin, + shell *pShell,sal_Int32 CommandId) + : p1( new XInteractionSupplyNameImpl ), + p2( new XInteractionAbortImpl ), + m_nErrorCode(0), + m_nMinorError(0), + m_aSeq( 2 ), + m_aClashingName(aClashingName), + m_xOrigin(xOrigin) +{ + if( pShell ) + pShell->retrieveError(CommandId,m_nErrorCode,m_nMinorError); + m_aSeq[0] = Reference<XInteractionContinuation>(p1); + m_aSeq[1] = Reference<XInteractionContinuation>(p2); +} + + +void SAL_CALL +XInteractionRequestImpl::acquire( void ) + throw() +{ + OWeakObject::acquire(); +} + + + +void SAL_CALL +XInteractionRequestImpl::release( void ) + throw() +{ + OWeakObject::release(); +} + + + +Any SAL_CALL +XInteractionRequestImpl::queryInterface( const Type& rType ) + throw( RuntimeException ) +{ + Any aRet = + cppu::queryInterface( + rType, + SAL_STATIC_CAST( lang::XTypeProvider*, this ), + SAL_STATIC_CAST( XInteractionRequest*,this) ); + return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ); +} + + +////////////////////////////////////////////////////////////////////////////////////////// +// XTypeProvider +////////////////////////////////////////////////////////////////////////////////////////// + +XTYPEPROVIDER_IMPL_2( XInteractionRequestImpl, + XTypeProvider, + XInteractionRequest ) + + +Any SAL_CALL +XInteractionRequestImpl::getRequest() + throw(RuntimeException) +{ + Any aAny; + if(m_nErrorCode == TASKHANDLING_FOLDER_EXISTS_MKDIR) + { + NameClashException excep; + excep.Name = m_aClashingName; + excep.Classification = InteractionClassification_ERROR; + excep.Context = m_xOrigin; + excep.Message = rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "folder exists and overwritte forbidden")); + aAny <<= excep; + } + else if(m_nErrorCode == TASKHANDLING_INVALID_NAME_MKDIR) + { + InteractiveAugmentedIOException excep; + excep.Code = IOErrorCode_INVALID_CHARACTER; + PropertyValue prop; + prop.Name = rtl::OUString::createFromAscii("ResourceName"); + prop.Handle = -1; + prop.Value <<= m_aClashingName; + Sequence<Any> seq(1); + seq[0] <<= prop; + excep.Arguments = seq; + excep.Classification = InteractionClassification_ERROR; + excep.Context = m_xOrigin; + excep.Message = rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "the name contained invalid characters")); + aAny <<= excep; + + } + return aAny; +} diff --git a/ucb/source/ucp/file/filinsreq.hxx b/ucb/source/ucp/file/filinsreq.hxx new file mode 100644 index 000000000000..bb78bd4c2973 --- /dev/null +++ b/ucb/source/ucp/file/filinsreq.hxx @@ -0,0 +1,240 @@ +/************************************************************************* + * + * 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 _FILINSREQ_HXX_ +#define _FILINSREQ_HXX_ + +#include <cppuhelper/weak.hxx> +#include <ucbhelper/macros.hxx> +#include <rtl/ustring.hxx> +#include <com/sun/star/uno/XInterface.hpp> +#include <com/sun/star/lang/XTypeProvider.hpp> +#include <com/sun/star/task/XInteractionAbort.hpp> +#include <com/sun/star/ucb/XInteractionSupplyName.hpp> +#include <com/sun/star/task/XInteractionRequest.hpp> + + +namespace fileaccess { + + + class shell; + + + class XInteractionSupplyNameImpl + : public cppu::OWeakObject, + public com::sun::star::lang::XTypeProvider, + public com::sun::star::ucb::XInteractionSupplyName + { + public: + + XInteractionSupplyNameImpl() + : m_bSelected(false) + { + } + + virtual com::sun::star::uno::Any SAL_CALL + queryInterface( + const com::sun::star::uno::Type& rType ) + throw( com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + acquire( + void ) + throw(); + + virtual void SAL_CALL + release( + void ) + throw(); + + + // XTypeProvider + + XTYPEPROVIDER_DECL() + + + virtual void SAL_CALL select() + throw (::com::sun::star::uno::RuntimeException) + { + m_bSelected = true; + } + + void SAL_CALL setName(const ::rtl::OUString& Name) + throw(::com::sun::star::uno::RuntimeException) + { + m_aNewName = Name; + } + + rtl::OUString getName() const + { + return m_aNewName; + } + + bool isSelected() const + { + return m_bSelected; + } + + private: + + bool m_bSelected; + rtl::OUString m_aNewName; + }; + + + + class XInteractionAbortImpl + : public cppu::OWeakObject, + public com::sun::star::lang::XTypeProvider, + public com::sun::star::task::XInteractionAbort + { + public: + + XInteractionAbortImpl() + : m_bSelected(false) + { + } + + virtual com::sun::star::uno::Any SAL_CALL + queryInterface( + const com::sun::star::uno::Type& rType ) + throw( com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + acquire( + void ) + throw(); + + virtual void SAL_CALL + release( + void ) + throw(); + + + // XTypeProvider + + XTYPEPROVIDER_DECL() + + + virtual void SAL_CALL select() + throw (::com::sun::star::uno::RuntimeException) + { + m_bSelected = true; + } + + + bool isSelected() const + { + return m_bSelected; + } + + private: + + bool m_bSelected; + }; + + + + class XInteractionRequestImpl + : public cppu::OWeakObject, + public com::sun::star::lang::XTypeProvider, + public com::sun::star::task::XInteractionRequest + { + public: + + XInteractionRequestImpl( + const rtl::OUString& aClashingName, + const com::sun::star::uno::Reference< + com::sun::star::uno::XInterface>& xOrigin, + shell* pShell, + sal_Int32 CommandId); + + virtual com::sun::star::uno::Any SAL_CALL + queryInterface( + const com::sun::star::uno::Type& rType ) + throw( com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + acquire( + void ) + throw(); + + virtual void SAL_CALL + release( + void ) + throw(); + + + // XTypeProvider + + XTYPEPROVIDER_DECL() + + ::com::sun::star::uno::Any SAL_CALL getRequest( ) + throw (::com::sun::star::uno::RuntimeException); + + com::sun::star::uno::Sequence< + com::sun::star::uno::Reference< + com::sun::star::task::XInteractionContinuation > > SAL_CALL + getContinuations( ) + throw (::com::sun::star::uno::RuntimeException) + { + return m_aSeq; + } + + bool aborted() const + { + return p2->isSelected(); + } + + rtl::OUString newName() const + { + if( p1->isSelected() ) + return p1->getName(); + else + return rtl::OUString(); + } + + private: + + XInteractionSupplyNameImpl* p1; + XInteractionAbortImpl* p2; + sal_Int32 m_nErrorCode,m_nMinorError; + + com::sun::star::uno::Sequence< + com::sun::star::uno::Reference< + com::sun::star::task::XInteractionContinuation > > m_aSeq; + + rtl::OUString m_aClashingName; + com::sun::star::uno::Reference< + com::sun::star::uno::XInterface> m_xOrigin; + }; + +} + + +#endif diff --git a/ucb/source/ucp/file/filnot.cxx b/ucb/source/ucp/file/filnot.cxx new file mode 100644 index 000000000000..0d2d5b4cb9b1 --- /dev/null +++ b/ucb/source/ucp/file/filnot.cxx @@ -0,0 +1,269 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" +#include <com/sun/star/ucb/XContent.hpp> +#include <com/sun/star/ucb/ContentAction.hpp> +#include <com/sun/star/beans/PropertySetInfoChange.hpp> +#include "filnot.hxx" +#include "filid.hxx" +#include "bc.hxx" +#include "prov.hxx" + + + +using namespace fileaccess; +using namespace com::sun::star; +using namespace com::sun::star::ucb; + + +ContentEventNotifier::ContentEventNotifier( shell* pMyShell, + const uno::Reference< XContent >& xCreatorContent, + const uno::Reference< XContentIdentifier >& xCreatorId, + const uno::Sequence< uno::Reference< uno::XInterface > >& sListeners ) + : m_pMyShell( pMyShell ), + m_xCreatorContent( xCreatorContent ), + m_xCreatorId( xCreatorId ), + m_sListeners( sListeners ) +{ +} + + +ContentEventNotifier::ContentEventNotifier( shell* pMyShell, + const uno::Reference< XContent >& xCreatorContent, + const uno::Reference< XContentIdentifier >& xCreatorId, + const uno::Reference< XContentIdentifier >& xOldId, + const uno::Sequence< uno::Reference< uno::XInterface > >& sListeners ) + : m_pMyShell( pMyShell ), + m_xCreatorContent( xCreatorContent ), + m_xCreatorId( xCreatorId ), + m_xOldId( xOldId ), + m_sListeners( sListeners ) +{ +} + + + +void ContentEventNotifier::notifyChildInserted( const rtl::OUString& aChildName ) +{ + FileContentIdentifier* p = new FileContentIdentifier( m_pMyShell,aChildName ); + uno::Reference< XContentIdentifier > xChildId( p ); + + uno::Reference< XContent > xChildContent = m_pMyShell->m_pProvider->queryContent( xChildId ); + + ContentEvent aEvt( m_xCreatorContent, + ContentAction::INSERTED, + xChildContent, + m_xCreatorId ); + + for( sal_Int32 i = 0; i < m_sListeners.getLength(); ++i ) + { + uno::Reference< XContentEventListener > ref( m_sListeners[i],uno::UNO_QUERY ); + if( ref.is() ) + ref->contentEvent( aEvt ); + } +} + +void ContentEventNotifier::notifyDeleted( void ) +{ + + ContentEvent aEvt( m_xCreatorContent, + ContentAction::DELETED, + m_xCreatorContent, + m_xCreatorId ); + + + for( sal_Int32 i = 0; i < m_sListeners.getLength(); ++i ) + { + uno::Reference< XContentEventListener > ref( m_sListeners[i],uno::UNO_QUERY ); + if( ref.is() ) + ref->contentEvent( aEvt ); + } +} + + + +void ContentEventNotifier::notifyRemoved( const rtl::OUString& aChildName ) +{ + FileContentIdentifier* p = new FileContentIdentifier( m_pMyShell,aChildName ); + uno::Reference< XContentIdentifier > xChildId( p ); + + BaseContent* pp = new BaseContent( m_pMyShell,xChildId,aChildName ); + { + osl::MutexGuard aGuard( pp->m_aMutex ); + pp->m_nState |= BaseContent::Deleted; + } + + uno::Reference< XContent > xDeletedContent( pp ); + + + ContentEvent aEvt( m_xCreatorContent, + ContentAction::REMOVED, + xDeletedContent, + m_xCreatorId ); + + for( sal_Int32 i = 0; i < m_sListeners.getLength(); ++i ) + { + uno::Reference< XContentEventListener > ref( m_sListeners[i],uno::UNO_QUERY ); + if( ref.is() ) + ref->contentEvent( aEvt ); + } +} + +void ContentEventNotifier::notifyExchanged() +{ + ContentEvent aEvt( m_xCreatorContent, + ContentAction::EXCHANGED, + m_xCreatorContent, + m_xOldId ); + + for( sal_Int32 i = 0; i < m_sListeners.getLength(); ++i ) + { + uno::Reference< XContentEventListener > ref( m_sListeners[i],uno::UNO_QUERY ); + if( ref.is() ) + ref->contentEvent( aEvt ); + } +} + +/*********************************************************************************/ +/* */ +/* PropertySetInfoChangeNotifier */ +/* */ +/*********************************************************************************/ + + +PropertySetInfoChangeNotifier::PropertySetInfoChangeNotifier( + shell* pMyShell, + const uno::Reference< XContent >& xCreatorContent, + const uno::Reference< XContentIdentifier >& xCreatorId, + const uno::Sequence< uno::Reference< uno::XInterface > >& sListeners ) + : m_pMyShell( pMyShell ), + m_xCreatorContent( xCreatorContent ), + m_xCreatorId( xCreatorId ), + m_sListeners( sListeners ) +{ + +} + + +void SAL_CALL +PropertySetInfoChangeNotifier::notifyPropertyAdded( const rtl::OUString & aPropertyName ) +{ + beans::PropertySetInfoChangeEvent aEvt( m_xCreatorContent, + aPropertyName, + -1, + beans::PropertySetInfoChange::PROPERTY_INSERTED ); + + for( sal_Int32 i = 0; i < m_sListeners.getLength(); ++i ) + { + uno::Reference< beans::XPropertySetInfoChangeListener > ref( m_sListeners[i],uno::UNO_QUERY ); + if( ref.is() ) + ref->propertySetInfoChange( aEvt ); + } +} + + +void SAL_CALL +PropertySetInfoChangeNotifier::notifyPropertyRemoved( const rtl::OUString & aPropertyName ) +{ + beans::PropertySetInfoChangeEvent aEvt( m_xCreatorContent, + aPropertyName, + -1, + beans::PropertySetInfoChange::PROPERTY_REMOVED ); + + for( sal_Int32 i = 0; i < m_sListeners.getLength(); ++i ) + { + uno::Reference< beans::XPropertySetInfoChangeListener > ref( m_sListeners[i],uno::UNO_QUERY ); + if( ref.is() ) + ref->propertySetInfoChange( aEvt ); + } +} + + +/*********************************************************************************/ +/* */ +/* PropertySetInfoChangeNotifier */ +/* */ +/*********************************************************************************/ + + +PropertyChangeNotifier::PropertyChangeNotifier( + shell* pMyShell, + const com::sun::star::uno::Reference< XContent >& xCreatorContent, + const com::sun::star::uno::Reference< com::sun::star::ucb::XContentIdentifier >& xCreatorId, + ListenerMap* pListeners ) + : m_pMyShell( pMyShell ), + m_xCreatorContent( xCreatorContent ), + m_xCreatorId( xCreatorId ), + m_pListeners( pListeners ) +{ +} + + +PropertyChangeNotifier::~PropertyChangeNotifier() +{ + delete m_pListeners; +} + + +void PropertyChangeNotifier::notifyPropertyChanged( + uno::Sequence< beans::PropertyChangeEvent > Changes ) +{ + sal_Int32 j; + + for( j = 0; j < Changes.getLength(); ++j ) + Changes[j].Source = m_xCreatorContent; + + // notify listeners for all Events + + uno::Sequence< uno::Reference< uno::XInterface > > seqList = (*m_pListeners)[ rtl::OUString() ]; + for( j = 0; j < seqList.getLength(); ++j ) + { + uno::Reference< beans::XPropertiesChangeListener > aListener( seqList[j],uno::UNO_QUERY ); + if( aListener.is() ) + { + aListener->propertiesChange( Changes ); + } + } + + uno::Sequence< beans::PropertyChangeEvent > seq(1); + for( j = 0; j < Changes.getLength(); ++j ) + { + seq[0] = Changes[j]; + seqList = (*m_pListeners)[ seq[0].PropertyName ]; + + for( sal_Int32 i = 0; i < seqList.getLength(); ++i ) + { + uno::Reference< beans::XPropertiesChangeListener > aListener( seqList[j],uno::UNO_QUERY ); + if( aListener.is() ) + { + aListener->propertiesChange( seq ); + } + } + } +} diff --git a/ucb/source/ucp/file/filnot.hxx b/ucb/source/ucp/file/filnot.hxx new file mode 100644 index 000000000000..24f982372328 --- /dev/null +++ b/ucb/source/ucp/file/filnot.hxx @@ -0,0 +1,137 @@ +/************************************************************************* + * + * 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 _FILNOT_HXX_ +#define _FILNOT_HXX_ + +#include <hash_map> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/uno/XInterface.hpp> +#include <com/sun/star/beans/PropertyChangeEvent.hpp> +#include <com/sun/star/ucb/XContentIdentifier.hpp> +#include "filglob.hxx" + + +namespace fileaccess { + + class shell; + class BaseContent; + + class ContentEventNotifier + { + private: + shell* m_pMyShell; + com::sun::star::uno::Reference< com::sun::star::ucb::XContent > m_xCreatorContent; + com::sun::star::uno::Reference< com::sun::star::ucb::XContentIdentifier > m_xCreatorId; + com::sun::star::uno::Reference< com::sun::star::ucb::XContentIdentifier > m_xOldId; + com::sun::star::uno::Sequence< com::sun::star::uno::Reference< com::sun::star::uno::XInterface > > m_sListeners; + public: + + ContentEventNotifier( + shell* pMyShell, + const com::sun::star::uno::Reference< com::sun::star::ucb::XContent >& xCreatorContent, + const com::sun::star::uno::Reference< com::sun::star::ucb::XContentIdentifier >& xCreatorId, + const com::sun::star::uno::Sequence< + com::sun::star::uno::Reference< com::sun::star::uno::XInterface > >& sListeners ); + + ContentEventNotifier( + shell* pMyShell, + const com::sun::star::uno::Reference< com::sun::star::ucb::XContent >& xCreatorContent, + const com::sun::star::uno::Reference< com::sun::star::ucb::XContentIdentifier >& xCreatorId, + const com::sun::star::uno::Reference< com::sun::star::ucb::XContentIdentifier >& xOldId, + const com::sun::star::uno::Sequence< + com::sun::star::uno::Reference< com::sun::star::uno::XInterface > >& sListeners ); + + void notifyChildInserted( const rtl::OUString& aChildName ); + void notifyDeleted( void ); + void notifyRemoved( const rtl::OUString& aChildName ); + void notifyExchanged( ); + }; + + + class PropertySetInfoChangeNotifier + { + private: + shell* m_pMyShell; + com::sun::star::uno::Reference< com::sun::star::ucb::XContent > m_xCreatorContent; + com::sun::star::uno::Reference< com::sun::star::ucb::XContentIdentifier > m_xCreatorId; + com::sun::star::uno::Sequence< com::sun::star::uno::Reference< com::sun::star::uno::XInterface > > m_sListeners; + public: + PropertySetInfoChangeNotifier( + shell* pMyShell, + const com::sun::star::uno::Reference< com::sun::star::ucb::XContent >& xCreatorContent, + const com::sun::star::uno::Reference< com::sun::star::ucb::XContentIdentifier >& xCreatorId, + const com::sun::star::uno::Sequence< + com::sun::star::uno::Reference< com::sun::star::uno::XInterface > >& sListeners ); + + void SAL_CALL notifyPropertyAdded( const rtl::OUString & aPropertyName ); + void SAL_CALL notifyPropertyRemoved( const rtl::OUString & aPropertyName ); + }; + + + typedef std::hash_map< rtl::OUString, + com::sun::star::uno::Sequence< com::sun::star::uno::Reference< com::sun::star::uno::XInterface > >, + hashOUString, + equalOUString > ListenerMap; + + class PropertyChangeNotifier + { + private: + shell* m_pMyShell; + com::sun::star::uno::Reference< com::sun::star::ucb::XContent > m_xCreatorContent; + com::sun::star::uno::Reference< com::sun::star::ucb::XContentIdentifier > m_xCreatorId; + ListenerMap* m_pListeners; + public: + PropertyChangeNotifier( + shell* pMyShell, + const com::sun::star::uno::Reference< com::sun::star::ucb::XContent >& xCreatorContent, + const com::sun::star::uno::Reference< com::sun::star::ucb::XContentIdentifier >& xCreatorId, + ListenerMap* pListeners ); + + ~PropertyChangeNotifier(); + + void notifyPropertyChanged( + com::sun::star::uno::Sequence< com::sun::star::beans::PropertyChangeEvent > seqChanged ); + }; + + + class Notifier + { + public: + // Side effect of this function is the change of the name + virtual ContentEventNotifier* cEXC( const rtl::OUString aNewName ) = 0; + // Side effect is the change of the state of the object to "deleted". + virtual ContentEventNotifier* cDEL( void ) = 0; + virtual ContentEventNotifier* cCEL( void ) = 0; + virtual PropertySetInfoChangeNotifier* cPSL( void ) = 0; + virtual PropertyChangeNotifier* cPCL( void ) = 0; + virtual rtl::OUString getKey( void ) = 0; + }; + + +} // end namespace fileaccess + +#endif diff --git a/ucb/source/ucp/file/filprp.cxx b/ucb/source/ucp/file/filprp.cxx new file mode 100644 index 000000000000..86c494cbd710 --- /dev/null +++ b/ucb/source/ucp/file/filprp.cxx @@ -0,0 +1,151 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" +#include "shell.hxx" +#include "prov.hxx" +#include "filprp.hxx" + +using namespace fileaccess; +using namespace com::sun::star; +using namespace com::sun::star::uno; +using namespace com::sun::star::ucb; + + +#include "filinl.hxx" + + +XPropertySetInfo_impl::XPropertySetInfo_impl( shell* pMyShell,const rtl::OUString& aUnqPath ) + : m_pMyShell( pMyShell ), + m_xProvider( pMyShell->m_pProvider ), + m_count( 0 ), + m_seq( 0 ) +{ + m_pMyShell->m_pProvider->acquire(); + + shell::ContentMap::iterator it = m_pMyShell->m_aContent.find( aUnqPath ); + + shell::PropertySet& properties = *(it->second.properties); + shell::PropertySet::iterator it1 = properties.begin(); + + m_seq.realloc( properties.size() ); + + while( it1 != properties.end() ) + { + m_seq[ m_count++ ] = beans::Property( it1->getPropertyName(), + it1->getHandle(), + it1->getType(), + it1->getAttributes() ); + ++it1; + } +} + + +XPropertySetInfo_impl::XPropertySetInfo_impl( shell* pMyShell,const Sequence< beans::Property >& seq ) + : m_pMyShell( pMyShell ), + m_count( seq.getLength() ), + m_seq( seq ) +{ + m_pMyShell->m_pProvider->acquire(); +} + + +XPropertySetInfo_impl::~XPropertySetInfo_impl() +{ + m_pMyShell->m_pProvider->release(); +} + + +void SAL_CALL +XPropertySetInfo_impl::acquire( + void ) + throw() +{ + OWeakObject::acquire(); +} + + +void SAL_CALL +XPropertySetInfo_impl::release( + void ) + throw() +{ + OWeakObject::release(); +} + + + +XTYPEPROVIDER_IMPL_2( XPropertySetInfo_impl, + lang::XTypeProvider, + beans::XPropertySetInfo ) + + +Any SAL_CALL +XPropertySetInfo_impl::queryInterface( + const Type& rType ) + throw( RuntimeException ) +{ + Any aRet = cppu::queryInterface( rType, + SAL_STATIC_CAST( lang::XTypeProvider*,this), + SAL_STATIC_CAST( beans::XPropertySetInfo*,this) ); + return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ); +} + + +beans::Property SAL_CALL +XPropertySetInfo_impl::getPropertyByName( + const rtl::OUString& aName ) + throw( beans::UnknownPropertyException, + RuntimeException) +{ + for( sal_Int32 i = 0; i < m_seq.getLength(); ++i ) + if( m_seq[i].Name == aName ) return m_seq[i]; + + throw beans::UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); +} + + + +Sequence< beans::Property > SAL_CALL +XPropertySetInfo_impl::getProperties( + void ) + throw( RuntimeException ) +{ + return m_seq; +} + + +sal_Bool SAL_CALL +XPropertySetInfo_impl::hasPropertyByName( + const rtl::OUString& aName ) + throw( RuntimeException ) +{ + for( sal_Int32 i = 0; i < m_seq.getLength(); ++i ) + if( m_seq[i].Name == aName ) return true; + return false; +} diff --git a/ucb/source/ucp/file/filprp.hxx b/ucb/source/ucp/file/filprp.hxx new file mode 100644 index 000000000000..24d1bf324339 --- /dev/null +++ b/ucb/source/ucp/file/filprp.hxx @@ -0,0 +1,97 @@ +/************************************************************************* + * + * 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 _FILPRP_HXX_ +#define _FILPRP_HXX_ + +#include <ucbhelper/macros.hxx> +#include <cppuhelper/weak.hxx> +#include <com/sun/star/beans/XPropertySetInfo.hpp> +#include <com/sun/star/ucb/XContentProvider.hpp> +#include <com/sun/star/lang/XTypeProvider.hpp> + + +namespace fileaccess { + + class shell; + + class XPropertySetInfo_impl + : public cppu::OWeakObject, + public com::sun::star::lang::XTypeProvider, + public com::sun::star::beans::XPropertySetInfo + { + public: + XPropertySetInfo_impl( shell* pMyShell,const rtl::OUString& aUnqPath ); + XPropertySetInfo_impl( shell* pMyShell,const com::sun::star::uno::Sequence< com::sun::star::beans::Property >& seq ); + + virtual ~XPropertySetInfo_impl(); + + // XInterface + virtual com::sun::star::uno::Any SAL_CALL + queryInterface( + const com::sun::star::uno::Type& aType ) + throw( com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + acquire( + void ) + throw(); + + virtual void SAL_CALL + release( + void ) + throw(); + + + // XTypeProvider + + XTYPEPROVIDER_DECL() + + virtual com::sun::star::uno::Sequence< com::sun::star::beans::Property > SAL_CALL + getProperties( + void ) + throw( com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::beans::Property SAL_CALL + getPropertyByName( + const rtl::OUString& aName ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL + hasPropertyByName( const rtl::OUString& Name ) + throw( com::sun::star::uno::RuntimeException ); + + private: + shell* m_pMyShell; + com::sun::star::uno::Reference< com::sun::star::ucb::XContentProvider > m_xProvider; + sal_Int32 m_count; + com::sun::star::uno::Sequence< com::sun::star::beans::Property > m_seq; + }; +} + +#endif + diff --git a/ucb/source/ucp/file/filrec.cxx b/ucb/source/ucp/file/filrec.cxx new file mode 100644 index 000000000000..c0e9b02ddb70 --- /dev/null +++ b/ucb/source/ucp/file/filrec.cxx @@ -0,0 +1,201 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +#include "filrec.hxx" + +namespace fileaccess { + +void ReconnectingFile::disconnect() +{ + m_aFile.close(); + m_bDisconnect = sal_True; +} + +sal_Bool ReconnectingFile::reconnect() +{ + sal_Bool bResult = sal_False; + if ( m_bFlagsSet ) + { + disconnect(); + if ( m_aFile.open( m_nFlags ) == ::osl::FileBase::E_None + || m_aFile.open( OpenFlag_Read ) == ::osl::FileBase::E_None ) + { + m_bDisconnect = sal_False; + bResult = sal_True; + } + } + + return bResult; +} + +::osl::FileBase::RC ReconnectingFile::open( sal_uInt32 uFlags ) +{ + ::osl::FileBase::RC nResult = m_aFile.open( uFlags ); + if ( nResult == ::osl::FileBase::E_None ) + { + if ( uFlags & OpenFlag_Create ) + m_nFlags = (uFlags & ( ~OpenFlag_Create )) | OpenFlag_Write; + else + m_nFlags = uFlags; + + m_bFlagsSet = sal_True; + } + + return nResult; +} + +::osl::FileBase::RC ReconnectingFile::close() +{ + m_nFlags = 0; + m_bFlagsSet = sal_False; + m_bDisconnect = sal_False; + + return m_aFile.close(); +} + +::osl::FileBase::RC ReconnectingFile::setPos( sal_uInt32 uHow, sal_Int64 uPos ) +{ + ::osl::FileBase::RC nRes = ::osl::FileBase::E_NETWORK; + + if ( uHow == Pos_Absolut && uPos > 0 ) + { + if ( m_bDisconnect ) + { + if ( reconnect() ) + nRes = m_aFile.setPos( uHow, uPos ); + } + else + { + // E_INVAL error code means in this case that + // the file handler is invalid + nRes = m_aFile.setPos( uHow, uPos ); + if ( ( nRes == ::osl::FileBase::E_NETWORK + || nRes == ::osl::FileBase::E_INVAL ) + && reconnect() ) + nRes = m_aFile.setPos( uHow, uPos ); + } + } + else + { + if ( !m_bDisconnect ) + nRes = m_aFile.setPos( uHow, uPos ); + } + + return nRes; +} + +::osl::FileBase::RC ReconnectingFile::getPos( sal_uInt64& uPos ) +{ + if ( m_bDisconnect ) + return ::osl::FileBase::E_NETWORK; + + return m_aFile.getPos( uPos ); +} + +::osl::FileBase::RC ReconnectingFile::setSize( sal_uInt64 uSize ) +{ + ::osl::FileBase::RC nRes = ::osl::FileBase::E_NETWORK; + + if ( uSize == 0 ) + { + if ( m_bDisconnect ) + { + if ( reconnect() ) + nRes = m_aFile.setSize( uSize ); + } + else + { + // E_INVAL error code means in this case that + // the file handler is invalid + nRes = m_aFile.setSize( uSize ); + if ( ( nRes == ::osl::FileBase::E_NETWORK + || nRes == ::osl::FileBase::E_INVAL ) + && reconnect() ) + nRes = m_aFile.setSize( uSize ); + } + } + else + { + if ( !m_bDisconnect ) + nRes = m_aFile.setSize( uSize ); + } + + return nRes; +} + +::osl::FileBase::RC ReconnectingFile::getSize( sal_uInt64 &rSize ) +{ + ::osl::FileBase::RC nRes = ::osl::FileBase::E_NETWORK; + + if ( !m_bDisconnect ) + nRes = m_aFile.getSize( rSize ); + + // E_INVAL error code means in this case that + // the file handler is invalid + if ( ( nRes == ::osl::FileBase::E_NETWORK + || nRes == ::osl::FileBase::E_INVAL ) + && reconnect() ) + { + nRes = m_aFile.getSize( rSize ); + + // the repairing should be disconnected, since the position might be wrong + // but the result should be retrieved + disconnect(); + } + + return nRes; +} + +::osl::FileBase::RC ReconnectingFile::read( void *pBuffer, sal_uInt64 uBytesRequested, sal_uInt64& rBytesRead ) +{ + if ( m_bDisconnect ) + return ::osl::FileBase::E_NETWORK; + + return m_aFile.read( pBuffer, uBytesRequested, rBytesRead ); +} + +::osl::FileBase::RC ReconnectingFile::write(const void *pBuffer, sal_uInt64 uBytesToWrite, sal_uInt64& rBytesWritten) +{ + if ( m_bDisconnect ) + return ::osl::FileBase::E_NETWORK; + + return m_aFile.write( pBuffer, uBytesToWrite, rBytesWritten ); +} + +::osl::FileBase::RC ReconnectingFile::sync() const +{ + if ( m_bDisconnect ) + return ::osl::FileBase::E_NETWORK; + + return m_aFile.sync(); +} + +} // namespace fileaccess + diff --git a/ucb/source/ucp/file/filrec.hxx b/ucb/source/ucp/file/filrec.hxx new file mode 100644 index 000000000000..90168da2c9a5 --- /dev/null +++ b/ucb/source/ucp/file/filrec.hxx @@ -0,0 +1,86 @@ +/************************************************************************* + * + * 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 _FILREC_HXX_ +#define _FILREC_HXX_ + +#include <osl/file.hxx> + +namespace fileaccess { + +class ReconnectingFile +{ + ::osl::File m_aFile; + + sal_uInt32 m_nFlags; + sal_Bool m_bFlagsSet; + + sal_Bool m_bDisconnect; + + ReconnectingFile( ReconnectingFile& ); + + ReconnectingFile& operator=( ReconnectingFile& ); + +public: + + ReconnectingFile( const ::rtl::OUString& aFileURL ) + : m_aFile( aFileURL ) + , m_nFlags( 0 ) + , m_bFlagsSet( sal_False ) + , m_bDisconnect( sal_False ) + {} + + ~ReconnectingFile() + { + close(); + } + + void disconnect(); + sal_Bool reconnect(); + + ::osl::FileBase::RC open( sal_uInt32 uFlags ); + + ::osl::FileBase::RC close(); + + ::osl::FileBase::RC setPos( sal_uInt32 uHow, sal_Int64 uPos ); + + ::osl::FileBase::RC getPos( sal_uInt64& uPos ); + + ::osl::FileBase::RC setSize( sal_uInt64 uSize ); + + ::osl::FileBase::RC getSize( sal_uInt64 &rSize ); + + ::osl::FileBase::RC read( void *pBuffer, sal_uInt64 uBytesRequested, sal_uInt64& rBytesRead ); + + ::osl::FileBase::RC write(const void *pBuffer, sal_uInt64 uBytesToWrite, sal_uInt64& rBytesWritten); + + ::osl::FileBase::RC sync() const; +}; + +} // namespace fileaccess +#endif // _FILREC_HXX_ + diff --git a/ucb/source/ucp/file/filrow.cxx b/ucb/source/ucp/file/filrow.cxx new file mode 100644 index 000000000000..5b135358cf31 --- /dev/null +++ b/ucb/source/ucp/file/filrow.cxx @@ -0,0 +1,429 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" +#include "filrow.hxx" +#include "shell.hxx" +#include "prov.hxx" + +using namespace fileaccess; +using namespace com::sun::star; +using namespace com::sun::star::uno; +//using namespace com::sun::star::ucb; + + +// Funktion for TypeConverting + + +template< class _type_ > +sal_Bool convert( shell* pShell, + uno::Reference< script::XTypeConverter >& xConverter, + uno::Any& rValue, + _type_& aReturn ) +{ + // Try first without converting + sal_Bool no_success = ! ( rValue >>= aReturn ); + + if ( no_success ) + { + if( ! xConverter.is() ) + { + xConverter = uno::Reference< script::XTypeConverter >( + pShell->m_xMultiServiceFactory->createInstance( + rtl::OUString::createFromAscii( "com.sun.star.script.Converter" ) ),uno::UNO_QUERY ); + +/* DBG_ASSERT( m_xTypeConverter.is(), + "PropertyValueSet::getTypeConverter() - " + "Service 'com.sun.star.script.Converter' n/a!" );*/ + } + + try + { + if( rValue.hasValue() ) + { + uno::Any aConvertedValue + = xConverter->convertTo( rValue,getCppuType( static_cast< const _type_* >(0) ) ); + no_success = ! ( aConvertedValue >>= aReturn ); + } + else + no_success = sal_True; + } + catch ( lang::IllegalArgumentException ) + { + no_success = sal_True; + } + catch ( script::CannotConvertException ) + { + no_success = sal_True; + } + } + return no_success; +} + + +XRow_impl::XRow_impl( shell* pMyShell,const uno::Sequence< uno::Any >& seq ) + : m_aValueMap( seq ), + m_pMyShell( pMyShell ), + m_xProvider( pMyShell->m_pProvider ), + m_xTypeConverter( 0 ) +{ +} + +XRow_impl::~XRow_impl() +{ +} + + +void SAL_CALL +XRow_impl::acquire( + void ) + throw() +{ + OWeakObject::acquire(); +} + +void SAL_CALL +XRow_impl::release( + void ) + throw() +{ + OWeakObject::release(); +} + + +uno::Any SAL_CALL +XRow_impl::queryInterface( + const uno::Type& rType ) + throw( uno::RuntimeException ) +{ + uno::Any aRet = cppu::queryInterface( rType, + SAL_STATIC_CAST( lang::XTypeProvider*,this), + SAL_STATIC_CAST( sdbc::XRow*,this) ); + return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ); +} + + +XTYPEPROVIDER_IMPL_2( XRow_impl, + lang::XTypeProvider, + sdbc::XRow ) + + +sal_Bool SAL_CALL +XRow_impl::wasNull( + void ) + throw( sdbc::SQLException, + uno::RuntimeException) +{ + return m_nWasNull; +} + + +rtl::OUString SAL_CALL +XRow_impl::getString( + sal_Int32 columnIndex ) + throw( sdbc::SQLException, + uno::RuntimeException) +{ + if( columnIndex < 1 || columnIndex > m_aValueMap.getLength() ) + throw sdbc::SQLException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), ::rtl::OUString(), 0, uno::Any() ); + rtl::OUString Value; + osl::MutexGuard aGuard( m_aMutex ); + m_nWasNull = ::convert<rtl::OUString>( m_pMyShell,m_xTypeConverter,m_aValueMap[ --columnIndex ],Value ); + return Value; +} + +sal_Bool SAL_CALL +XRow_impl::getBoolean( + sal_Int32 columnIndex ) + throw( sdbc::SQLException, + uno::RuntimeException) +{ + if( columnIndex < 1 || columnIndex > m_aValueMap.getLength() ) + throw sdbc::SQLException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), ::rtl::OUString(), 0, uno::Any() ); + sal_Bool Value( false ); + osl::MutexGuard aGuard( m_aMutex ); + m_nWasNull = ::convert<sal_Bool>( m_pMyShell,m_xTypeConverter,m_aValueMap[ --columnIndex ],Value ); + return Value; +} + + +sal_Int8 SAL_CALL +XRow_impl::getByte( + sal_Int32 columnIndex ) + throw( sdbc::SQLException, + uno::RuntimeException) +{ + if( columnIndex < 1 || columnIndex > m_aValueMap.getLength() ) + throw sdbc::SQLException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), ::rtl::OUString(), 0, uno::Any() ); + sal_Int8 Value( 0 ); + osl::MutexGuard aGuard( m_aMutex ); + m_nWasNull = ::convert<sal_Int8>( m_pMyShell,m_xTypeConverter,m_aValueMap[ --columnIndex ],Value ); + return Value; +} + +sal_Int16 SAL_CALL +XRow_impl::getShort( + sal_Int32 columnIndex ) + throw( sdbc::SQLException, + uno::RuntimeException) +{ + if( columnIndex < 1 || columnIndex > m_aValueMap.getLength() ) + throw sdbc::SQLException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), ::rtl::OUString(), 0, uno::Any() ); + sal_Int16 Value( 0 ); + osl::MutexGuard aGuard( m_aMutex ); + m_nWasNull = ::convert<sal_Int16>( m_pMyShell,m_xTypeConverter,m_aValueMap[ --columnIndex ],Value ); + return Value; +} + + +sal_Int32 SAL_CALL +XRow_impl::getInt( + sal_Int32 columnIndex ) + throw( sdbc::SQLException, + uno::RuntimeException) +{ + if( columnIndex < 1 || columnIndex > m_aValueMap.getLength() ) + throw sdbc::SQLException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), ::rtl::OUString(), 0, uno::Any() ); + sal_Int32 Value( 0 ); + osl::MutexGuard aGuard( m_aMutex ); + m_nWasNull = ::convert<sal_Int32>( m_pMyShell,m_xTypeConverter,m_aValueMap[ --columnIndex ],Value ); + return Value; +} + +sal_Int64 SAL_CALL +XRow_impl::getLong( + sal_Int32 columnIndex ) + throw( sdbc::SQLException, + uno::RuntimeException) +{ + if( columnIndex < 1 || columnIndex > m_aValueMap.getLength() ) + throw sdbc::SQLException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), ::rtl::OUString(), 0, uno::Any() ); + sal_Int64 Value( 0 ); + osl::MutexGuard aGuard( m_aMutex ); + m_nWasNull = ::convert<sal_Int64>( m_pMyShell,m_xTypeConverter,m_aValueMap[ --columnIndex ],Value ); + return Value; +} + +float SAL_CALL +XRow_impl::getFloat( + sal_Int32 columnIndex ) + throw( sdbc::SQLException, + uno::RuntimeException) +{ + if( columnIndex < 1 || columnIndex > m_aValueMap.getLength() ) + throw sdbc::SQLException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), ::rtl::OUString(), 0, uno::Any() ); + float Value( 0 ); + osl::MutexGuard aGuard( m_aMutex ); + m_nWasNull = ::convert<float>( m_pMyShell,m_xTypeConverter,m_aValueMap[ --columnIndex ],Value ); + return Value; +} + +double SAL_CALL +XRow_impl::getDouble( + sal_Int32 columnIndex ) + throw( sdbc::SQLException, + uno::RuntimeException) +{ + if( columnIndex < 1 || columnIndex > m_aValueMap.getLength() ) + throw sdbc::SQLException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), ::rtl::OUString(), 0, uno::Any() ); + double Value( 0 ); + osl::MutexGuard aGuard( m_aMutex ); + m_nWasNull = ::convert<double>( m_pMyShell,m_xTypeConverter,m_aValueMap[ --columnIndex ],Value ); + return Value; +} + +uno::Sequence< sal_Int8 > SAL_CALL +XRow_impl::getBytes( + sal_Int32 columnIndex ) + throw( sdbc::SQLException, + uno::RuntimeException) +{ + if( columnIndex < 1 || columnIndex > m_aValueMap.getLength() ) + throw sdbc::SQLException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), ::rtl::OUString(), 0, uno::Any() ); + uno::Sequence< sal_Int8 > Value(0); + osl::MutexGuard aGuard( m_aMutex ); + m_nWasNull = ::convert<uno::Sequence< sal_Int8 > >( m_pMyShell,m_xTypeConverter,m_aValueMap[ --columnIndex ],Value ); + return Value; +} + +util::Date SAL_CALL +XRow_impl::getDate( + sal_Int32 columnIndex ) + throw( sdbc::SQLException, + uno::RuntimeException) +{ + if( columnIndex < 1 || columnIndex > m_aValueMap.getLength() ) + throw sdbc::SQLException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), ::rtl::OUString(), 0, uno::Any() ); + util::Date Value; + osl::MutexGuard aGuard( m_aMutex ); + m_nWasNull = ::convert<util::Date>( m_pMyShell,m_xTypeConverter,m_aValueMap[ --columnIndex ],Value ); + return Value; +} + +util::Time SAL_CALL +XRow_impl::getTime( + sal_Int32 columnIndex ) + throw( sdbc::SQLException, + uno::RuntimeException) +{ + if( columnIndex < 1 || columnIndex > m_aValueMap.getLength() ) + throw sdbc::SQLException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), ::rtl::OUString(), 0, uno::Any() ); + util::Time Value; + osl::MutexGuard aGuard( m_aMutex ); + m_nWasNull = ::convert<util::Time>( m_pMyShell,m_xTypeConverter,m_aValueMap[ --columnIndex ],Value ); + return Value; +} + +util::DateTime SAL_CALL +XRow_impl::getTimestamp( + sal_Int32 columnIndex ) + throw( sdbc::SQLException, + uno::RuntimeException) +{ + if( columnIndex < 1 || columnIndex > m_aValueMap.getLength() ) + throw sdbc::SQLException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), ::rtl::OUString(), 0, uno::Any() ); + util::DateTime Value; + osl::MutexGuard aGuard( m_aMutex ); + m_nWasNull = ::convert<util::DateTime>( m_pMyShell,m_xTypeConverter,m_aValueMap[ --columnIndex ],Value ); + return Value; +} + + +uno::Reference< io::XInputStream > SAL_CALL +XRow_impl::getBinaryStream( + sal_Int32 columnIndex ) + throw( sdbc::SQLException, + uno::RuntimeException) +{ + if( columnIndex < 1 || columnIndex > m_aValueMap.getLength() ) + throw sdbc::SQLException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), ::rtl::OUString(), 0, uno::Any() ); + uno::Reference< io::XInputStream > Value; + osl::MutexGuard aGuard( m_aMutex ); + m_nWasNull = ::convert<uno::Reference< io::XInputStream > >( m_pMyShell,m_xTypeConverter,m_aValueMap[ --columnIndex ],Value ); + return Value; +} + + +uno::Reference< io::XInputStream > SAL_CALL +XRow_impl::getCharacterStream( + sal_Int32 columnIndex ) + throw( sdbc::SQLException, + uno::RuntimeException) +{ + if( columnIndex < 1 || columnIndex > m_aValueMap.getLength() ) + throw sdbc::SQLException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), ::rtl::OUString(), 0, uno::Any() ); + uno::Reference< io::XInputStream > Value; + osl::MutexGuard aGuard( m_aMutex ); + m_nWasNull = ::convert< uno::Reference< io::XInputStream> >( m_pMyShell,m_xTypeConverter,m_aValueMap[ --columnIndex ],Value ); + return Value; +} + + +uno::Any SAL_CALL +XRow_impl::getObject( + sal_Int32 columnIndex, + const uno::Reference< container::XNameAccess >& ) + throw( sdbc::SQLException, + uno::RuntimeException) +{ + if( columnIndex < 1 || columnIndex > m_aValueMap.getLength() ) + throw sdbc::SQLException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), ::rtl::OUString(), 0, uno::Any() ); + uno::Any Value; + osl::MutexGuard aGuard( m_aMutex ); + m_nWasNull = ::convert<uno::Any>( m_pMyShell,m_xTypeConverter,m_aValueMap[ --columnIndex ],Value ); + return Value; +} + +uno::Reference< sdbc::XRef > SAL_CALL +XRow_impl::getRef( + sal_Int32 columnIndex ) + throw( sdbc::SQLException, + uno::RuntimeException) +{ + if( columnIndex < 1 || columnIndex > m_aValueMap.getLength() ) + throw sdbc::SQLException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), ::rtl::OUString(), 0, uno::Any() ); + uno::Reference< sdbc::XRef > Value; + osl::MutexGuard aGuard( m_aMutex ); + m_nWasNull = ::convert<uno::Reference< sdbc::XRef> >( m_pMyShell, + m_xTypeConverter, + m_aValueMap[ --columnIndex ], + Value ); + return Value; +} + +uno::Reference< sdbc::XBlob > SAL_CALL +XRow_impl::getBlob( + sal_Int32 columnIndex ) + throw( sdbc::SQLException, + uno::RuntimeException) +{ + if( columnIndex < 1 || columnIndex > m_aValueMap.getLength() ) + throw sdbc::SQLException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), ::rtl::OUString(), 0, uno::Any() ); + uno::Reference< sdbc::XBlob > Value; + osl::MutexGuard aGuard( m_aMutex ); + m_nWasNull = ::convert<uno::Reference< sdbc::XBlob> >( m_pMyShell, + m_xTypeConverter, + m_aValueMap[ --columnIndex ], + Value ); + return Value; +} + +uno::Reference< sdbc::XClob > SAL_CALL +XRow_impl::getClob( + sal_Int32 columnIndex ) + throw( sdbc::SQLException, + uno::RuntimeException) +{ + if( columnIndex < 1 || columnIndex > m_aValueMap.getLength() ) + throw sdbc::SQLException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), ::rtl::OUString(), 0, uno::Any() ); + uno::Reference< sdbc::XClob > Value; + osl::MutexGuard aGuard( m_aMutex ); + m_nWasNull = ::convert<uno::Reference< sdbc::XClob> >( m_pMyShell, + m_xTypeConverter, + m_aValueMap[ --columnIndex ], + Value ); + return Value; +} + + +uno::Reference< sdbc::XArray > SAL_CALL +XRow_impl::getArray( + sal_Int32 columnIndex ) + throw( sdbc::SQLException, + uno::RuntimeException) +{ + if( columnIndex < 1 || columnIndex > m_aValueMap.getLength() ) + throw sdbc::SQLException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), ::rtl::OUString(), 0, uno::Any() ); + uno::Reference< sdbc::XArray > Value; + osl::MutexGuard aGuard( m_aMutex ); + m_nWasNull = ::convert<uno::Reference< sdbc::XArray> >( m_pMyShell, + m_xTypeConverter, + m_aValueMap[ --columnIndex ], + Value ); + return Value; +} diff --git a/ucb/source/ucp/file/filrow.hxx b/ucb/source/ucp/file/filrow.hxx new file mode 100644 index 000000000000..bc8954da3510 --- /dev/null +++ b/ucb/source/ucp/file/filrow.hxx @@ -0,0 +1,204 @@ +/************************************************************************* + * + * 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 _FILROW_HXX_ +#define _FILROW_HXX_ + +#include <ucbhelper/macros.hxx> + +#include "osl/mutex.hxx" +#include <cppuhelper/weak.hxx> +#include <com/sun/star/sdbc/XRow.hpp> +#include <com/sun/star/script/XTypeConverter.hpp> +#include <com/sun/star/lang/XTypeProvider.hpp> +#include <com/sun/star/ucb/XContentProvider.hpp> + +namespace fileaccess { + + class shell; + + class XRow_impl: + public cppu::OWeakObject, + public com::sun::star::lang::XTypeProvider, + public com::sun::star::sdbc::XRow + { + public: + XRow_impl( shell* pShell,const com::sun::star::uno::Sequence< com::sun::star::uno::Any >& __m_aValueMap ); + ~XRow_impl(); + + virtual com::sun::star::uno::Any SAL_CALL + queryInterface( + const com::sun::star::uno::Type& aType ) + throw( com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + acquire( + void ) + throw(); + + virtual void SAL_CALL + release( + void ) + throw(); + + // XTypeProvider + + XTYPEPROVIDER_DECL() + + virtual sal_Bool SAL_CALL + wasNull( + void ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + virtual rtl::OUString SAL_CALL + getString( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL + getBoolean( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + virtual sal_Int8 SAL_CALL + getByte( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + virtual sal_Int16 SAL_CALL + getShort( + sal_Int32 columnIndex ) + throw( + com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + virtual sal_Int32 SAL_CALL + getInt( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + virtual sal_Int64 SAL_CALL + getLong( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + virtual float SAL_CALL + getFloat( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + virtual double SAL_CALL + getDouble( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + virtual com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL + getBytes( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + virtual com::sun::star::util::Date SAL_CALL + getDate( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + virtual com::sun::star::util::Time SAL_CALL + getTime( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + virtual com::sun::star::util::DateTime SAL_CALL + getTimestamp( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + virtual com::sun::star::uno::Reference< com::sun::star::io::XInputStream > SAL_CALL + getBinaryStream( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + virtual com::sun::star::uno::Reference< com::sun::star::io::XInputStream > SAL_CALL + getCharacterStream( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + virtual com::sun::star::uno::Any SAL_CALL + getObject( + sal_Int32 columnIndex, + const com::sun::star::uno::Reference< com::sun::star::container::XNameAccess >& typeMap ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + virtual com::sun::star::uno::Reference< com::sun::star::sdbc::XRef > SAL_CALL + getRef( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + virtual com::sun::star::uno::Reference< com::sun::star::sdbc::XBlob > SAL_CALL + getBlob( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + virtual com::sun::star::uno::Reference< com::sun::star::sdbc::XClob > SAL_CALL + getClob( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + virtual com::sun::star::uno::Reference< com::sun::star::sdbc::XArray > SAL_CALL + getArray( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + private: + osl::Mutex m_aMutex; + com::sun::star::uno::Sequence< com::sun::star::uno::Any > m_aValueMap; + sal_Bool m_nWasNull; + shell* m_pMyShell; + com::sun::star::uno::Reference< com::sun::star::ucb::XContentProvider > m_xProvider; + com::sun::star::uno::Reference< com::sun::star::script::XTypeConverter > m_xTypeConverter; + }; + +} // end namespace fileaccess + +#endif diff --git a/ucb/source/ucp/file/filrset.cxx b/ucb/source/ucp/file/filrset.cxx new file mode 100644 index 000000000000..5dcdd8445556 --- /dev/null +++ b/ucb/source/ucp/file/filrset.cxx @@ -0,0 +1,936 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" +#include <com/sun/star/ucb/WelcomeDynamicResultSetStruct.hpp> +#include "filid.hxx" +#include "shell.hxx" +#include "filprp.hxx" +#include "filrset.hxx" +#include <com/sun/star/ucb/OpenMode.hpp> +#include "prov.hxx" +#include <com/sun/star/uno/Reference.h> + +#ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBBUTE_HPP_ +#include <com/sun/star/beans/PropertyAttribute.hpp> +#endif +#include <com/sun/star/ucb/ListActionType.hpp> +#include <com/sun/star/ucb/XSourceInitialization.hpp> +#include <com/sun/star/ucb/XCachedDynamicResultSetStubFactory.hpp> +#include <ucbhelper/resultsetmetadata.hxx> + +using namespace fileaccess; +using namespace com::sun::star; + +XResultSet_impl::XResultSet_impl( + shell* pMyShell, + const rtl::OUString& aUnqPath, + sal_Int32 OpenMode, + const uno::Sequence< beans::Property >& seq, + const uno::Sequence< ucb::NumberedSortingInfo >& seqSort ) + : m_pMyShell( pMyShell ), + m_xProvider( pMyShell->m_pProvider ), + m_nRow( -1 ), + m_nOpenMode( OpenMode ), + m_bRowCountFinal( false ), + m_aBaseDirectory( aUnqPath ), + m_aFolder( aUnqPath ), + m_sProperty( seq ), + m_sSortingInfo( seqSort ), + m_pDisposeEventListeners( 0 ), + m_pRowCountListeners( 0 ), + m_pIsFinalListeners( 0 ), + m_bStatic( false ), + m_nErrorCode( TASKHANDLER_NO_ERROR ), + m_nMinorErrorCode( TASKHANDLER_NO_ERROR ) +{ + osl::FileBase::RC err = m_aFolder.open(); + if( err != osl::FileBase::E_None ) + { + m_nIsOpen = false; + m_aFolder.close(); + + m_nErrorCode = TASKHANDLING_OPEN_FOR_DIRECTORYLISTING; + m_nMinorErrorCode = err; + } + else + m_nIsOpen = true; + + m_pMyShell->registerNotifier( m_aBaseDirectory,this ); +} + + +XResultSet_impl::~XResultSet_impl() +{ + m_pMyShell->deregisterNotifier( m_aBaseDirectory,this ); + + if( m_nIsOpen ) + m_aFolder.close(); + + delete m_pDisposeEventListeners; + delete m_pRowCountListeners; + delete m_pIsFinalListeners; +} + + + +sal_Int32 SAL_CALL XResultSet_impl::CtorSuccess() +{ + return m_nErrorCode; +} + + + +sal_Int32 SAL_CALL XResultSet_impl::getMinorError() +{ + return m_nMinorErrorCode; +} + + +void SAL_CALL +XResultSet_impl::acquire( + void ) + throw() +{ + OWeakObject::acquire(); +} + + +void SAL_CALL +XResultSet_impl::release( + void ) + throw() +{ + OWeakObject::release(); +} + + + +uno::Any SAL_CALL +XResultSet_impl::queryInterface( + const uno::Type& rType ) + throw( uno::RuntimeException ) +{ + uno::Any aRet = cppu::queryInterface( + rType, + SAL_STATIC_CAST( lang::XComponent*, this), + SAL_STATIC_CAST( lang::XTypeProvider*, this), + SAL_STATIC_CAST( lang::XEventListener*, this), + SAL_STATIC_CAST( sdbc::XRow*, this), + SAL_STATIC_CAST( sdbc::XResultSet*, this), + SAL_STATIC_CAST( sdbc::XCloseable*, this), + SAL_STATIC_CAST( sdbc::XResultSetMetaDataSupplier*, this), + SAL_STATIC_CAST( beans::XPropertySet*, this ), + SAL_STATIC_CAST( ucb::XContentAccess*, this), + SAL_STATIC_CAST( ucb::XDynamicResultSet*,this) ); + return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ); +} + + +void SAL_CALL +XResultSet_impl::disposing( const lang::EventObject& ) + throw( uno::RuntimeException ) +{ + // To do, but what +} + + +XTYPEPROVIDER_IMPL_10( XResultSet_impl, + lang::XTypeProvider, + lang::XTypeProvider, + lang::XEventListener, + sdbc::XRow, + sdbc::XResultSet, + XDynamicResultSet, + sdbc::XCloseable, + sdbc::XResultSetMetaDataSupplier, + beans::XPropertySet, + ucb::XContentAccess ) + + +void SAL_CALL +XResultSet_impl::addEventListener( + const uno::Reference< lang::XEventListener >& Listener ) + throw( uno::RuntimeException ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + if ( ! m_pDisposeEventListeners ) + m_pDisposeEventListeners = + new cppu::OInterfaceContainerHelper( m_aEventListenerMutex ); + + m_pDisposeEventListeners->addInterface( Listener ); +} + + +void SAL_CALL +XResultSet_impl::removeEventListener( + const uno::Reference< lang::XEventListener >& Listener ) + throw( uno::RuntimeException ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + if ( m_pDisposeEventListeners ) + m_pDisposeEventListeners->removeInterface( Listener ); +} + + + +void SAL_CALL +XResultSet_impl::dispose() + throw( uno::RuntimeException ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + lang::EventObject aEvt; + aEvt.Source = static_cast< lang::XComponent * >( this ); + + if ( m_pDisposeEventListeners && m_pDisposeEventListeners->getLength() ) + { + m_pDisposeEventListeners->disposeAndClear( aEvt ); + } + if( m_pRowCountListeners && m_pRowCountListeners->getLength() ) + { + m_pRowCountListeners->disposeAndClear( aEvt ); + } + if( m_pIsFinalListeners && m_pIsFinalListeners->getLength() ) + { + m_pIsFinalListeners->disposeAndClear( aEvt ); + } +} + + + +void XResultSet_impl::rowCountChanged() +{ + sal_Int32 aOldValue,aNewValue; + uno::Sequence< uno::Reference< uno::XInterface > > seq; + { + osl::MutexGuard aGuard( m_aMutex ); + if( m_pRowCountListeners ) + seq = m_pRowCountListeners->getElements(); + aNewValue = m_aItems.size(); + aOldValue = aNewValue-1; + } + beans::PropertyChangeEvent aEv; + aEv.PropertyName = rtl::OUString::createFromAscii( "RowCount" ); + aEv.Further = false; + aEv.PropertyHandle = -1; + aEv.OldValue <<= aOldValue; + aEv.NewValue <<= aNewValue; + for( sal_Int32 i = 0; i < seq.getLength(); ++i ) + { + uno::Reference< beans::XPropertyChangeListener > listener( + seq[i], uno::UNO_QUERY ); + if( listener.is() ) + listener->propertyChange( aEv ); + } +} + + +void XResultSet_impl::isFinalChanged() +{ + uno::Sequence< uno::Reference< XInterface > > seq; + { + osl::MutexGuard aGuard( m_aMutex ); + if( m_pIsFinalListeners ) + seq = m_pIsFinalListeners->getElements(); + m_bRowCountFinal = true; + } + beans::PropertyChangeEvent aEv; + aEv.PropertyName = rtl::OUString::createFromAscii( "IsRowCountFinal" ); + aEv.Further = false; + aEv.PropertyHandle = -1; + sal_Bool fval = false; + sal_Bool tval = true; + aEv.OldValue <<= fval; + aEv.NewValue <<= tval; + for( sal_Int32 i = 0; i < seq.getLength(); ++i ) + { + uno::Reference< beans::XPropertyChangeListener > listener( + seq[i], uno::UNO_QUERY ); + if( listener.is() ) + listener->propertyChange( aEv ); + } +} + + +sal_Bool SAL_CALL +XResultSet_impl::OneMore( + void ) + throw( sdbc::SQLException, + uno::RuntimeException ) +{ + if( ! m_nIsOpen ) + return false; + + osl::FileBase::RC err; + sal_Bool IsRegular; + rtl::OUString aUnqPath; + osl::DirectoryItem m_aDirIte; + uno::Reference< sdbc::XRow > aRow; + + while( true ) + { + err = m_aFolder.getNextItem( m_aDirIte ); + + if( err == osl::FileBase::E_NOENT || err == osl::FileBase::E_INVAL ) + { + m_aFolder.close(); + isFinalChanged(); + return ( m_nIsOpen = false ); + } + else if( err == osl::FileBase::E_None ) + { + aRow = m_pMyShell->getv( + this, m_sProperty, m_aDirIte, aUnqPath, IsRegular ); + + if( m_nOpenMode == ucb::OpenMode::DOCUMENTS && IsRegular ) + { + osl::MutexGuard aGuard( m_aMutex ); + m_aItems.push_back( aRow ); + m_aIdents.push_back( + uno::Reference< ucb::XContentIdentifier >() ); + m_aUnqPath.push_back( aUnqPath ); + rowCountChanged(); + return true; + + } + else if( m_nOpenMode == ucb::OpenMode::DOCUMENTS && ! IsRegular ) + { + continue; + } + else if( m_nOpenMode == ucb::OpenMode::FOLDERS && ! IsRegular ) + { + osl::MutexGuard aGuard( m_aMutex ); + m_aItems.push_back( aRow ); + m_aIdents.push_back( + uno::Reference< ucb::XContentIdentifier >() ); + m_aUnqPath.push_back( aUnqPath ); + rowCountChanged(); + return true; + } + else if( m_nOpenMode == ucb::OpenMode::FOLDERS && IsRegular ) + { + continue; + } + else + { + osl::MutexGuard aGuard( m_aMutex ); + m_aItems.push_back( aRow ); + m_aIdents.push_back( + uno::Reference< ucb::XContentIdentifier >() ); + m_aUnqPath.push_back( aUnqPath ); + rowCountChanged(); + return true; + } + } + else // error fetching anything + { + throw sdbc::SQLException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), ::rtl::OUString(), 0, uno::Any() ); + } + } +} + + + + + +sal_Bool SAL_CALL +XResultSet_impl::next( + void ) + throw( sdbc::SQLException, + uno::RuntimeException ) +{ + sal_Bool test; + if( ++m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()) ) test = true; + else + test = OneMore(); + return test; +} + + +sal_Bool SAL_CALL +XResultSet_impl::isBeforeFirst( + void ) + throw( sdbc::SQLException, + uno::RuntimeException ) +{ + return m_nRow == -1; +} + + +sal_Bool SAL_CALL +XResultSet_impl::isAfterLast( + void ) + throw( sdbc::SQLException, + uno::RuntimeException ) +{ + return m_nRow >= sal::static_int_cast<sal_Int32>(m_aItems.size()); // Cannot happen, if m_aFolder.isOpen() +} + + +sal_Bool SAL_CALL +XResultSet_impl::isFirst( + void ) + throw( sdbc::SQLException, + uno::RuntimeException ) +{ + return m_nRow == 0; +} + + +sal_Bool SAL_CALL +XResultSet_impl::isLast( + void ) + throw( sdbc::SQLException, + uno::RuntimeException) +{ + if( m_nRow == sal::static_int_cast<sal_Int32>(m_aItems.size()) - 1 ) + return ! OneMore(); + else + return false; +} + + +void SAL_CALL +XResultSet_impl::beforeFirst( + void ) + throw( sdbc::SQLException, + uno::RuntimeException) +{ + m_nRow = -1; +} + + +void SAL_CALL +XResultSet_impl::afterLast( + void ) + throw( sdbc::SQLException, + uno::RuntimeException ) +{ + m_nRow = sal::static_int_cast<sal_Int32>(m_aItems.size()); + while( OneMore() ) + ++m_nRow; +} + + +sal_Bool SAL_CALL +XResultSet_impl::first( + void ) + throw( sdbc::SQLException, + uno::RuntimeException) +{ + m_nRow = -1; + return next(); +} + + +sal_Bool SAL_CALL +XResultSet_impl::last( + void ) + throw( sdbc::SQLException, + uno::RuntimeException ) +{ + m_nRow = sal::static_int_cast<sal_Int32>(m_aItems.size()) - 1; + while( OneMore() ) + ++m_nRow; + return true; +} + + +sal_Int32 SAL_CALL +XResultSet_impl::getRow( + void ) + throw( sdbc::SQLException, + uno::RuntimeException) +{ + // Test, whether behind last row + if( -1 == m_nRow || m_nRow >= sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + return 0; + else + return m_nRow+1; +} + + + +sal_Bool SAL_CALL XResultSet_impl::absolute( sal_Int32 row ) + throw( sdbc::SQLException, uno::RuntimeException) +{ + if( row >= 0 ) + { + m_nRow = row - 1; + if( row >= sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + while( row-- && OneMore() ) + ; + } + else + { + last(); + m_nRow += ( row + 1 ); + if( m_nRow < -1 ) + m_nRow = -1; + } + + return 0<= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()); +} + + + + +sal_Bool SAL_CALL +XResultSet_impl::relative( + sal_Int32 row ) + throw( sdbc::SQLException, + uno::RuntimeException) +{ + if( isAfterLast() || isBeforeFirst() ) + throw sdbc::SQLException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), ::rtl::OUString(), 0, uno::Any() ); + if( row > 0 ) + while( row-- ) next(); + else if( row < 0 ) + while( row++ && m_nRow > - 1 ) previous(); + + return 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()); +} + + + +sal_Bool SAL_CALL +XResultSet_impl::previous( + void ) + throw( sdbc::SQLException, + uno::RuntimeException) +{ + if( m_nRow > sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + m_nRow = sal::static_int_cast<sal_Int32>(m_aItems.size()); // Correct Handling of afterLast + if( 0 <= m_nRow ) -- m_nRow; + + return 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()); +} + + +void SAL_CALL +XResultSet_impl::refreshRow( + void ) + throw( sdbc::SQLException, + uno::RuntimeException) +{ + // get the row from the filesystem + return; +} + + +sal_Bool SAL_CALL +XResultSet_impl::rowUpdated( + void ) + throw( sdbc::SQLException, + uno::RuntimeException ) +{ + return false; +} + +sal_Bool SAL_CALL +XResultSet_impl::rowInserted( + void ) + throw( sdbc::SQLException, + uno::RuntimeException ) +{ + return false; +} + +sal_Bool SAL_CALL +XResultSet_impl::rowDeleted( + void ) + throw( sdbc::SQLException, + uno::RuntimeException ) +{ + return false; +} + + +uno::Reference< uno::XInterface > SAL_CALL +XResultSet_impl::getStatement( + void ) + throw( sdbc::SQLException, + uno::RuntimeException ) +{ + return uno::Reference< uno::XInterface >(); +} + + +// XCloseable + +void SAL_CALL +XResultSet_impl::close( + void ) + throw( sdbc::SQLException, + uno::RuntimeException) +{ + if( m_nIsOpen ) + { + m_aFolder.close(); + isFinalChanged(); + osl::MutexGuard aGuard( m_aMutex ); + m_nIsOpen = false; + } +} + + + +rtl::OUString SAL_CALL +XResultSet_impl::queryContentIdentifierString( + void ) + throw( uno::RuntimeException ) +{ + uno::Reference< ucb::XContentIdentifier > xContentId + = queryContentIdentifier(); + + if( xContentId.is() ) + return xContentId->getContentIdentifier(); + else + return rtl::OUString(); +} + + +uno::Reference< ucb::XContentIdentifier > SAL_CALL +XResultSet_impl::queryContentIdentifier( + void ) + throw( uno::RuntimeException ) +{ + if( 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + { + if( ! m_aIdents[m_nRow].is() ) + { + FileContentIdentifier* p + = new FileContentIdentifier( m_pMyShell, + m_aUnqPath[ m_nRow ] ); + m_aIdents[m_nRow] = uno::Reference< ucb::XContentIdentifier >(p); + } + return m_aIdents[m_nRow]; + } + return uno::Reference< ucb::XContentIdentifier >(); +} + + +uno::Reference< ucb::XContent > SAL_CALL +XResultSet_impl::queryContent( + void ) + throw( uno::RuntimeException ) +{ + if( 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + return m_pMyShell->m_pProvider->queryContent( queryContentIdentifier() ); + else + return uno::Reference< ucb::XContent >(); +} + + +// XDynamicResultSet + + +// virtual +uno::Reference< sdbc::XResultSet > SAL_CALL +XResultSet_impl::getStaticResultSet() + throw( ucb::ListenerAlreadySetException, + uno::RuntimeException ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + if ( m_xListener.is() ) + throw ucb::ListenerAlreadySetException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); + + return uno::Reference< sdbc::XResultSet >( this ); +} + +//========================================================================= +// virtual +void SAL_CALL +XResultSet_impl::setListener( + const uno::Reference< ucb::XDynamicResultSetListener >& Listener ) + throw( ucb::ListenerAlreadySetException, + uno::RuntimeException ) +{ + osl::ClearableMutexGuard aGuard( m_aMutex ); + + if ( m_xListener.is() ) + throw ucb::ListenerAlreadySetException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); + + m_xListener = Listener; + + ////////////////////////////////////////////////////////////////////// + // Create "welcome event" and send it to listener. + ////////////////////////////////////////////////////////////////////// + + // Note: We only have the implementation for a static result set at the + // moment (src590). The dynamic result sets passed to the listener + // are a fake. This implementation will never call "notify" at the + // listener to propagate any changes!!! + + uno::Any aInfo; + aInfo <<= ucb::WelcomeDynamicResultSetStruct( this, /* "old" */ + this /* "new" */ ); + + uno::Sequence< ucb::ListAction > aActions( 1 ); + aActions.getArray()[ 0 ] = ucb::ListAction( 0, // Position; not used + 0, // Count; not used + ucb::ListActionType::WELCOME, + aInfo ); + aGuard.clear(); + + Listener->notify( + ucb::ListEvent( + static_cast< cppu::OWeakObject * >( this ), aActions ) ); +} + +//========================================================================= +// virtual +void SAL_CALL +XResultSet_impl::connectToCache( + const uno::Reference< ucb::XDynamicResultSet > & xCache ) + throw( ucb::ListenerAlreadySetException, + ucb::AlreadyInitializedException, + ucb::ServiceNotFoundException, + uno::RuntimeException ) +{ + uno::Reference< lang::XMultiServiceFactory > mxSMgr + = m_pMyShell->m_xMultiServiceFactory; + + if( m_xListener.is() ) + throw ucb::ListenerAlreadySetException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); + if( m_bStatic ) + throw ucb::ListenerAlreadySetException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); + + uno::Reference< ucb::XSourceInitialization > xTarget( + xCache, uno::UNO_QUERY ); + if( xTarget.is() && mxSMgr.is() ) + { + uno::Reference< ucb::XCachedDynamicResultSetStubFactory > xStubFactory; + try + { + xStubFactory + = uno::Reference< ucb::XCachedDynamicResultSetStubFactory >( + mxSMgr->createInstance( + rtl::OUString::createFromAscii( + "com.sun.star.ucb.CachedDynamicResultSetStubFactory" ) ), + uno::UNO_QUERY ); + } + catch ( uno::Exception const & ) + { + } + + if( xStubFactory.is() ) + { + xStubFactory->connectToCache( + this, xCache,m_sSortingInfo, NULL ); + return; + } + } + throw ucb::ServiceNotFoundException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); +} + +//========================================================================= +// virtual +sal_Int16 SAL_CALL +XResultSet_impl::getCapabilities() + throw( uno::RuntimeException ) +{ + // Never set ucb::ContentResultSetCapability::SORTED + // - Underlying content cannot provide sorted data... + return 0; +} + +// XResultSetMetaDataSupplier +uno::Reference< sdbc::XResultSetMetaData > SAL_CALL +XResultSet_impl::getMetaData( + void ) + throw( sdbc::SQLException, + uno::RuntimeException ) +{ + for ( sal_Int32 n = 0; n < m_sProperty.getLength(); ++n ) + { + if ( m_sProperty.getConstArray()[ n ].Name.compareToAscii( "Title" ) + == 0 ) + { + // @@@ #82177# - Determine correct value! + sal_Bool bCaseSensitiveChildren = sal_False; + + std::vector< ::ucbhelper::ResultSetColumnData > + aColumnData( m_sProperty.getLength() ); + aColumnData[ n ].isCaseSensitive = bCaseSensitiveChildren; + + ::ucbhelper::ResultSetMetaData* p = + new ::ucbhelper::ResultSetMetaData( + m_pMyShell->m_xMultiServiceFactory, + m_sProperty, + aColumnData ); + return uno::Reference< sdbc::XResultSetMetaData >( p ); + } + } + + ::ucbhelper::ResultSetMetaData* p = + new ::ucbhelper::ResultSetMetaData( + m_pMyShell->m_xMultiServiceFactory, m_sProperty ); + return uno::Reference< sdbc::XResultSetMetaData >( p ); +} + + + +// XPropertySet +uno::Reference< beans::XPropertySetInfo > SAL_CALL +XResultSet_impl::getPropertySetInfo() + throw( uno::RuntimeException) +{ + + uno::Sequence< beans::Property > seq(2); + seq[0].Name = rtl::OUString::createFromAscii( "RowCount" ); + seq[0].Handle = -1; + seq[0].Type = getCppuType( static_cast< sal_Int32* >(0) ); + seq[0].Attributes = beans::PropertyAttribute::READONLY; + + seq[0].Name = rtl::OUString::createFromAscii( "IsRowCountFinal" ); + seq[0].Handle = -1; + seq[0].Type = getCppuType( static_cast< sal_Bool* >(0) ); + seq[0].Attributes = beans::PropertyAttribute::READONLY; + + XPropertySetInfo_impl* p = new XPropertySetInfo_impl( m_pMyShell, + seq ); + return uno::Reference< beans::XPropertySetInfo > ( p ); +} + + + +void SAL_CALL XResultSet_impl::setPropertyValue( + const rtl::OUString& aPropertyName, const uno::Any& ) + throw( beans::UnknownPropertyException, + beans::PropertyVetoException, + lang::IllegalArgumentException, + lang::WrappedTargetException, + uno::RuntimeException) +{ + if( aPropertyName == rtl::OUString::createFromAscii( "IsRowCountFinal" ) || + aPropertyName == rtl::OUString::createFromAscii( "RowCount" ) ) + return; + throw beans::UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); +} + + +uno::Any SAL_CALL XResultSet_impl::getPropertyValue( + const rtl::OUString& PropertyName ) + throw( beans::UnknownPropertyException, + lang::WrappedTargetException, + uno::RuntimeException) +{ + if( PropertyName == rtl::OUString::createFromAscii( "IsRowCountFinal" ) ) + { + uno::Any aAny; + aAny <<= m_bRowCountFinal; + return aAny; + } + else if ( PropertyName == rtl::OUString::createFromAscii( "RowCount" ) ) + { + uno::Any aAny; + sal_Int32 count = sal::static_int_cast<sal_Int32>(m_aItems.size()); + aAny <<= count; + return aAny; + } + else + throw beans::UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); +} + + +void SAL_CALL XResultSet_impl::addPropertyChangeListener( + const rtl::OUString& aPropertyName, + const uno::Reference< beans::XPropertyChangeListener >& xListener ) + throw( beans::UnknownPropertyException, + lang::WrappedTargetException, + uno::RuntimeException) +{ + if( aPropertyName == rtl::OUString::createFromAscii( "IsRowCountFinal" ) ) + { + osl::MutexGuard aGuard( m_aMutex ); + if ( ! m_pIsFinalListeners ) + m_pIsFinalListeners = + new cppu::OInterfaceContainerHelper( m_aEventListenerMutex ); + + m_pIsFinalListeners->addInterface( xListener ); + } + else if ( aPropertyName == rtl::OUString::createFromAscii( "RowCount" ) ) + { + osl::MutexGuard aGuard( m_aMutex ); + if ( ! m_pRowCountListeners ) + m_pRowCountListeners = + new cppu::OInterfaceContainerHelper( m_aEventListenerMutex ); + m_pRowCountListeners->addInterface( xListener ); + } + else + throw beans::UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); +} + + +void SAL_CALL XResultSet_impl::removePropertyChangeListener( + const rtl::OUString& aPropertyName, + const uno::Reference< beans::XPropertyChangeListener >& aListener ) + throw( beans::UnknownPropertyException, + lang::WrappedTargetException, + uno::RuntimeException) +{ + if( aPropertyName == rtl::OUString::createFromAscii( "IsRowCountFinal" ) && + m_pIsFinalListeners ) + { + osl::MutexGuard aGuard( m_aMutex ); + m_pIsFinalListeners->removeInterface( aListener ); + } + else if ( aPropertyName == rtl::OUString::createFromAscii( "RowCount" ) && + m_pRowCountListeners ) + { + osl::MutexGuard aGuard( m_aMutex ); + + m_pRowCountListeners->removeInterface( aListener ); + } + else + throw beans::UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); +} + +void SAL_CALL XResultSet_impl::addVetoableChangeListener( + const rtl::OUString&, + const uno::Reference< beans::XVetoableChangeListener >& ) + throw( beans::UnknownPropertyException, + lang::WrappedTargetException, + uno::RuntimeException) +{ +} + + +void SAL_CALL XResultSet_impl::removeVetoableChangeListener( + const rtl::OUString&, + const uno::Reference< beans::XVetoableChangeListener >& ) + throw( beans::UnknownPropertyException, + lang::WrappedTargetException, + uno::RuntimeException) +{ +} diff --git a/ucb/source/ucp/file/filrset.hxx b/ucb/source/ucp/file/filrset.hxx new file mode 100644 index 000000000000..977eddec8ccd --- /dev/null +++ b/ucb/source/ucp/file/filrset.hxx @@ -0,0 +1,683 @@ +/************************************************************************* + * + * 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 _FILRSET_HXX_ +#define _FILRSET_HXX_ + +#ifndef __SGI_STL_VECTOR +#include <vector> +#endif +#include <ucbhelper/macros.hxx> +#include <osl/file.hxx> + +#include "osl/mutex.hxx" +#include <cppuhelper/weak.hxx> +#include <cppuhelper/interfacecontainer.hxx> +#include <com/sun/star/lang/XTypeProvider.hpp> +#include <com/sun/star/ucb/XContentAccess.hpp> +#include <com/sun/star/sdbc/XCloseable.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#ifndef _COM_SUN_STAR_UCB_XDYNAMICRESULTSET_HPP__ +#include <com/sun/star/ucb/XDynamicResultSet.hpp> +#endif +#include <com/sun/star/ucb/XDynamicResultSetListener.hpp> +#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp> +#include <com/sun/star/ucb/NumberedSortingInfo.hpp> +#include <com/sun/star/ucb/XContentProvider.hpp> +#include <com/sun/star/ucb/XContentIdentifier.hpp> +#include <com/sun/star/beans/Property.hpp> +#include "filrow.hxx" +#include "filnot.hxx" + + + +namespace fileaccess { + + class Notifier; + + class XResultSet_impl + : public cppu::OWeakObject, + public com::sun::star::lang::XTypeProvider, + public com::sun::star::lang::XEventListener, + public com::sun::star::sdbc::XRow, + public com::sun::star::sdbc::XResultSet, + public com::sun::star::ucb::XDynamicResultSet, + public com::sun::star::sdbc::XCloseable, + public com::sun::star::sdbc::XResultSetMetaDataSupplier, + public com::sun::star::beans::XPropertySet, + public com::sun::star::ucb::XContentAccess, + public Notifier + { + public: + + XResultSet_impl( shell* pMyShell, + const rtl::OUString& aUnqPath, + sal_Int32 OpenMode, + const com::sun::star::uno::Sequence< com::sun::star::beans::Property >& seq, + const com::sun::star::uno::Sequence< com::sun::star::ucb::NumberedSortingInfo >& seqSort ); + + virtual ~XResultSet_impl(); + + virtual ContentEventNotifier* cDEL( void ) + { + return 0; + } + + virtual ContentEventNotifier* cEXC( const rtl::OUString ) + { + return 0; + } + + virtual ContentEventNotifier* cCEL( void ) + { + return 0; + } + + virtual PropertySetInfoChangeNotifier* cPSL( void ) + { + return 0; + } + + virtual PropertyChangeNotifier* cPCL( void ) + { + return 0; + } + + virtual rtl::OUString getKey( void ) + { + return m_aBaseDirectory; + } + + sal_Int32 SAL_CALL CtorSuccess(); + sal_Int32 SAL_CALL getMinorError(); + + // XInterface + virtual com::sun::star::uno::Any SAL_CALL + queryInterface( + const com::sun::star::uno::Type& aType ) + throw( com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + acquire( + void ) + throw(); + + virtual void SAL_CALL + release( + void ) + throw(); + + + // XTypeProvider + + XTYPEPROVIDER_DECL() + + + // XEventListener + virtual void SAL_CALL + disposing( + const com::sun::star::lang::EventObject& Source ) + throw( com::sun::star::uno::RuntimeException ); + + // XComponent + virtual void SAL_CALL + dispose( + void ) + throw( com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL + addEventListener( + const com::sun::star::uno::Reference< com::sun::star::lang::XEventListener >& xListener ) + throw( com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL + removeEventListener( const com::sun::star::uno::Reference< com::sun::star::lang::XEventListener >& aListener ) + throw( com::sun::star::uno::RuntimeException ); + + + // XRow + virtual sal_Bool SAL_CALL + wasNull( + void ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ) + { + if( 0<= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + m_nWasNull = m_aItems[m_nRow]->wasNull(); + else + m_nWasNull = true; + return m_nWasNull; + } + + virtual rtl::OUString SAL_CALL + getString( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException) + { + if( 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + return m_aItems[m_nRow]->getString( columnIndex ); + else + return rtl::OUString(); + } + + virtual sal_Bool SAL_CALL + getBoolean( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException) + { + if( 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + return m_aItems[m_nRow]->getBoolean( columnIndex ); + else + return false; + } + + virtual sal_Int8 SAL_CALL + getByte( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException) + { + if( 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + return m_aItems[m_nRow]->getByte( columnIndex ); + else + return sal_Int8( 0 ); + } + + virtual sal_Int16 SAL_CALL + getShort( + sal_Int32 columnIndex ) + throw( + com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException) + { + if( 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + return m_aItems[m_nRow]->getShort( columnIndex ); + else + return sal_Int16( 0 ); + } + + virtual sal_Int32 SAL_CALL + getInt( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ) + { + if( 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + return m_aItems[m_nRow]->getInt( columnIndex ); + else + return sal_Int32( 0 ); + } + + virtual sal_Int64 SAL_CALL + getLong( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException) + { + if( 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + return m_aItems[m_nRow]->getLong( columnIndex ); + else + return sal_Int64( 0 ); + } + + virtual float SAL_CALL + getFloat( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ) + { + if( 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + return m_aItems[m_nRow]->getFloat( columnIndex ); + else + return float( 0 ); + } + + virtual double SAL_CALL + getDouble( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ) + { + if( 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + return m_aItems[m_nRow]->getDouble( columnIndex ); + else + return double( 0 ); + } + + virtual com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL + getBytes( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ) + { + if( 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + return m_aItems[m_nRow]->getBytes( columnIndex ); + else + return com::sun::star::uno::Sequence< sal_Int8 >(); + } + + virtual com::sun::star::util::Date SAL_CALL + getDate( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException) + { + if( 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + return m_aItems[m_nRow]->getDate( columnIndex ); + else + return com::sun::star::util::Date(); + } + + virtual com::sun::star::util::Time SAL_CALL + getTime( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException) + { + if( 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + return m_aItems[m_nRow]->getTime( columnIndex ); + else + return com::sun::star::util::Time(); + } + + virtual com::sun::star::util::DateTime SAL_CALL + getTimestamp( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException) + { + if( 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + return m_aItems[m_nRow]->getTimestamp( columnIndex ); + else + return com::sun::star::util::DateTime(); + } + + virtual com::sun::star::uno::Reference< com::sun::star::io::XInputStream > SAL_CALL + getBinaryStream( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException) + { + if( 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + return m_aItems[m_nRow]->getBinaryStream( columnIndex ); + else + return com::sun::star::uno::Reference< com::sun::star::io::XInputStream >(); + } + + virtual com::sun::star::uno::Reference< com::sun::star::io::XInputStream > SAL_CALL + getCharacterStream( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException) + { + if( 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + return m_aItems[m_nRow]->getCharacterStream( columnIndex ); + else + return com::sun::star::uno::Reference< com::sun::star::io::XInputStream >(); + } + + virtual com::sun::star::uno::Any SAL_CALL + getObject( + sal_Int32 columnIndex, + const com::sun::star::uno::Reference< com::sun::star::container::XNameAccess >& typeMap ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException) + { + if( 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + return m_aItems[m_nRow]->getObject( columnIndex,typeMap ); + else + return com::sun::star::uno::Any(); + } + + virtual com::sun::star::uno::Reference< com::sun::star::sdbc::XRef > SAL_CALL + getRef( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException) + { + if( 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + return m_aItems[m_nRow]->getRef( columnIndex ); + else + return com::sun::star::uno::Reference< com::sun::star::sdbc::XRef >(); + } + + virtual com::sun::star::uno::Reference< com::sun::star::sdbc::XBlob > SAL_CALL + getBlob( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException) + { + if( 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + return m_aItems[m_nRow]->getBlob( columnIndex ); + else + return com::sun::star::uno::Reference< com::sun::star::sdbc::XBlob >(); + } + + virtual com::sun::star::uno::Reference< com::sun::star::sdbc::XClob > SAL_CALL + getClob( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException) + { + if( 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + return m_aItems[m_nRow]->getClob( columnIndex ); + else + return com::sun::star::uno::Reference< com::sun::star::sdbc::XClob >(); + } + + virtual com::sun::star::uno::Reference< com::sun::star::sdbc::XArray > SAL_CALL + getArray( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException) + { + if( 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + return m_aItems[m_nRow]->getArray( columnIndex ); + else + return com::sun::star::uno::Reference< com::sun::star::sdbc::XArray >(); + } + + + // XResultSet + + virtual sal_Bool SAL_CALL + next( + void ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL + isBeforeFirst( + void ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL + isAfterLast( + void ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL + isFirst( + void ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL + isLast( + void ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + beforeFirst( + void ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + afterLast( + void ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL + first( + void ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL + last( + void ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + virtual sal_Int32 SAL_CALL + getRow( + void ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL + absolute( + sal_Int32 row ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL + relative( + sal_Int32 rows ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL + previous( + void ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + refreshRow( + void ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL + rowUpdated( + void ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL + rowInserted( + void ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL + rowDeleted( + void ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + + virtual com::sun::star::uno::Reference< com::sun::star::uno::XInterface > SAL_CALL + getStatement( + void ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + + // XDynamicResultSet + + virtual com::sun::star::uno::Reference< com::sun::star::sdbc::XResultSet > SAL_CALL + getStaticResultSet( + void ) + throw( com::sun::star::ucb::ListenerAlreadySetException, + com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL + setListener( + const com::sun::star::uno::Reference< + com::sun::star::ucb::XDynamicResultSetListener >& Listener ) + throw( com::sun::star::ucb::ListenerAlreadySetException, + com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL + connectToCache( const com::sun::star::uno::Reference< com::sun::star::ucb::XDynamicResultSet > & xCache ) + throw( com::sun::star::ucb::ListenerAlreadySetException, + com::sun::star::ucb::AlreadyInitializedException, + com::sun::star::ucb::ServiceNotFoundException, + com::sun::star::uno::RuntimeException ); + + virtual sal_Int16 SAL_CALL + getCapabilities() + throw( com::sun::star::uno::RuntimeException ); + + + // XCloseable + + virtual void SAL_CALL + close( + void ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + // XContentAccess + + virtual rtl::OUString SAL_CALL + queryContentIdentifierString( + void ) + throw( com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::uno::Reference< com::sun::star::ucb::XContentIdentifier > SAL_CALL + queryContentIdentifier( + void ) + throw( com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::uno::Reference< com::sun::star::ucb::XContent > SAL_CALL + queryContent( + void ) + throw( com::sun::star::uno::RuntimeException ); + + // XResultSetMetaDataSupplier + virtual com::sun::star::uno::Reference< com::sun::star::sdbc::XResultSetMetaData > SAL_CALL + getMetaData( + void ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + + // XPropertySet + virtual com::sun::star::uno::Reference< com::sun::star::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo() + throw( com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL setPropertyValue( + const rtl::OUString& aPropertyName, + const com::sun::star::uno::Any& aValue ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::beans::PropertyVetoException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException); + + virtual com::sun::star::uno::Any SAL_CALL + getPropertyValue( + const rtl::OUString& PropertyName ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + addPropertyChangeListener( + const rtl::OUString& aPropertyName, + const com::sun::star::uno::Reference< com::sun::star::beans::XPropertyChangeListener >& xListener ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + removePropertyChangeListener( + const rtl::OUString& aPropertyName, + const com::sun::star::uno::Reference< com::sun::star::beans::XPropertyChangeListener >& aListener ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + addVetoableChangeListener( + const rtl::OUString& PropertyName, + const com::sun::star::uno::Reference< com::sun::star::beans::XVetoableChangeListener >& aListener ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL removeVetoableChangeListener( + const rtl::OUString& PropertyName, + const com::sun::star::uno::Reference< com::sun::star::beans::XVetoableChangeListener >& aListener ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException); + + private: + + // Members + // const uno::Reference< lang::XMultiServiceFactory > m_xMSF; + // const uno::Reference< ucb::XContentProvider > m_xProvider; + + shell* m_pMyShell; + com::sun::star::uno::Reference< com::sun::star::ucb::XContentProvider > m_xProvider; + sal_Bool m_nIsOpen; + sal_Int32 m_nRow; + sal_Bool m_nWasNull; + sal_Int32 m_nOpenMode; + sal_Bool m_bRowCountFinal; + + typedef std::vector< com::sun::star::uno::Reference< com::sun::star::ucb::XContentIdentifier > > IdentSet; + typedef std::vector< com::sun::star::uno::Reference< com::sun::star::sdbc::XRow > > ItemSet; + typedef std::vector< rtl::OUString > UnqPathSet; + + IdentSet m_aIdents; + ItemSet m_aItems; + UnqPathSet m_aUnqPath; + const rtl::OUString m_aBaseDirectory; + + osl::Directory m_aFolder; + com::sun::star::uno::Sequence< com::sun::star::beans::Property > m_sProperty; + com::sun::star::uno::Sequence< com::sun::star::ucb::NumberedSortingInfo > m_sSortingInfo; + + osl::Mutex m_aMutex; + osl::Mutex m_aEventListenerMutex; + cppu::OInterfaceContainerHelper* m_pDisposeEventListeners; + + cppu::OInterfaceContainerHelper* m_pRowCountListeners; + cppu::OInterfaceContainerHelper* m_pIsFinalListeners; + + com::sun::star::uno::Reference< com::sun::star::ucb::XDynamicResultSetListener > m_xListener; + sal_Bool m_bStatic; + + sal_Int32 m_nErrorCode; + sal_Int32 m_nMinorErrorCode; + + // Methods + sal_Bool SAL_CALL OneMore( void ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ); + + void rowCountChanged(); + void isFinalChanged(); + }; + + +} // end namespace fileaccess + + +#endif diff --git a/ucb/source/ucp/file/filstr.cxx b/ucb/source/ucp/file/filstr.cxx new file mode 100644 index 000000000000..2e45e22b790b --- /dev/null +++ b/ucb/source/ucp/file/filstr.cxx @@ -0,0 +1,404 @@ + /************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" +#include "com/sun/star/io/IOException.hpp" +#include "com/sun/star/uno/RuntimeException.hpp" +#include "osl/diagnose.h" +#include "filstr.hxx" +#include "shell.hxx" +#include "prov.hxx" + + +using namespace fileaccess; +using namespace com::sun::star; +using namespace com::sun::star::ucb; + + + +/******************************************************************************/ +/* */ +/* XStream_impl implementation */ +/* */ +/******************************************************************************/ + + +uno::Any SAL_CALL +XStream_impl::queryInterface( + const uno::Type& rType ) + throw( uno::RuntimeException) +{ + uno::Any aRet = cppu::queryInterface( rType, + SAL_STATIC_CAST( lang::XTypeProvider*,this ), + SAL_STATIC_CAST( io::XStream*,this ), + SAL_STATIC_CAST( io::XInputStream*,this ), + SAL_STATIC_CAST( io::XOutputStream*,this ), + SAL_STATIC_CAST( io::XSeekable*,this ), + SAL_STATIC_CAST( io::XTruncate*,this ), + SAL_STATIC_CAST( io::XAsyncOutputMonitor*,this ) ); + return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ); +} + + +void SAL_CALL +XStream_impl::acquire( + void ) + throw() +{ + OWeakObject::acquire(); +} + + +void SAL_CALL +XStream_impl::release( + void ) + throw() +{ + OWeakObject::release(); +} + + +////////////////////////////////////////////////////////////////////////////////////////// +// XTypeProvider +////////////////////////////////////////////////////////////////////////////////////////// + + +XTYPEPROVIDER_IMPL_7( XStream_impl, + lang::XTypeProvider, + io::XStream, + io::XSeekable, + io::XInputStream, + io::XOutputStream, + io::XTruncate, + io::XAsyncOutputMonitor ) + + + +XStream_impl::XStream_impl( shell* pMyShell,const rtl::OUString& aUncPath, sal_Bool bLock ) + : m_bInputStreamCalled( false ), + m_bOutputStreamCalled( false ), + m_pMyShell( pMyShell ), + m_xProvider( m_pMyShell->m_pProvider ), + m_bLock( bLock ), + m_aFile( aUncPath ), + m_nErrorCode( TASKHANDLER_NO_ERROR ), + m_nMinorErrorCode( TASKHANDLER_NO_ERROR ) +{ + sal_uInt32 nFlags = ( OpenFlag_Read | OpenFlag_Write ); + if ( !bLock ) + nFlags |= OpenFlag_NoLock; + + osl::FileBase::RC err = m_aFile.open( nFlags ); + if( err != osl::FileBase::E_None ) + { + m_nIsOpen = false; + m_aFile.close(); + + m_nErrorCode = TASKHANDLING_OPEN_FOR_STREAM; + m_nMinorErrorCode = err; + } + else + m_nIsOpen = true; +} + + +XStream_impl::~XStream_impl() +{ + try + { + closeStream(); + } + catch (io::IOException const &) + { + OSL_ENSURE(false, "unexpected situation"); + } + catch (uno::RuntimeException const &) + { + OSL_ENSURE(false, "unexpected situation"); + } +} + + +sal_Int32 SAL_CALL XStream_impl::CtorSuccess() +{ + return m_nErrorCode; +} + + + +sal_Int32 SAL_CALL XStream_impl::getMinorError() +{ + return m_nMinorErrorCode; +} + + + +uno::Reference< io::XInputStream > SAL_CALL +XStream_impl::getInputStream( ) + throw( uno::RuntimeException) +{ + { + osl::MutexGuard aGuard( m_aMutex ); + m_bInputStreamCalled = true; + } + return uno::Reference< io::XInputStream >( this ); +} + + +uno::Reference< io::XOutputStream > SAL_CALL +XStream_impl::getOutputStream( ) + throw( uno::RuntimeException ) +{ + { + osl::MutexGuard aGuard( m_aMutex ); + m_bOutputStreamCalled = true; + } + return uno::Reference< io::XOutputStream >( this ); +} + + +void SAL_CALL XStream_impl::truncate(void) + throw( io::IOException, uno::RuntimeException ) +{ + if (osl::FileBase::E_None != m_aFile.setSize(0)) + throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); + + if (osl::FileBase::E_None != m_aFile.setPos(Pos_Absolut,sal_uInt64(0))) + throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); +} + + + +//=========================================================================== +// XStream_impl private non interface methods +//=========================================================================== + +sal_Int32 SAL_CALL +XStream_impl::readBytes( + uno::Sequence< sal_Int8 >& aData, + sal_Int32 nBytesToRead ) + throw( io::NotConnectedException, + io::BufferSizeExceededException, + io::IOException, + uno::RuntimeException) +{ + if( ! m_nIsOpen ) + throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); + + sal_Int8 * buffer; + try + { + buffer = new sal_Int8[nBytesToRead]; + } + catch( std::bad_alloc ) + { + if( m_nIsOpen ) m_aFile.close(); + throw io::BufferSizeExceededException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); + } + + sal_uInt64 nrc(0); + if(m_aFile.read( (void* )buffer,sal_uInt64(nBytesToRead),nrc ) + != osl::FileBase::E_None) + { + delete[] buffer; + throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); + } + aData = uno::Sequence< sal_Int8 > ( buffer, (sal_uInt32)nrc ); + delete[] buffer; + return ( sal_Int32 ) nrc; +} + + +sal_Int32 SAL_CALL +XStream_impl::readSomeBytes( + uno::Sequence< sal_Int8 >& aData, + sal_Int32 nMaxBytesToRead ) + throw( io::NotConnectedException, + io::BufferSizeExceededException, + io::IOException, + uno::RuntimeException) +{ + return readBytes( aData,nMaxBytesToRead ); +} + + +void SAL_CALL +XStream_impl::skipBytes( + sal_Int32 nBytesToSkip ) + throw( io::NotConnectedException, + io::BufferSizeExceededException, + io::IOException, + uno::RuntimeException ) +{ + m_aFile.setPos( osl_Pos_Current, sal_uInt64( nBytesToSkip ) ); +} + + +sal_Int32 SAL_CALL +XStream_impl::available( + void ) + throw( io::NotConnectedException, + io::IOException, + uno::RuntimeException) +{ + return 0; +} + + +void SAL_CALL +XStream_impl::writeBytes( const uno::Sequence< sal_Int8 >& aData ) + throw( io::NotConnectedException, + io::BufferSizeExceededException, + io::IOException, + uno::RuntimeException) +{ + sal_uInt32 length = aData.getLength(); + if(length) + { + sal_uInt64 nWrittenBytes(0); + const sal_Int8* p = aData.getConstArray(); + if(osl::FileBase::E_None != m_aFile.write(((void*)(p)),sal_uInt64(length),nWrittenBytes) || + nWrittenBytes != length ) + throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); + } +} + + +void SAL_CALL +XStream_impl::closeStream( + void ) + throw( io::NotConnectedException, + io::IOException, + uno::RuntimeException ) +{ + if( m_nIsOpen ) + { + osl::FileBase::RC err = m_aFile.close(); + + if( err != osl::FileBase::E_None ) { + io::IOException ex; + ex.Message = rtl::OUString::createFromAscii( + "could not close file"); + throw ex; + } + + m_nIsOpen = false; + } +} + +void SAL_CALL +XStream_impl::closeInput( + void ) + throw( io::NotConnectedException, + io::IOException, + uno::RuntimeException ) +{ + osl::MutexGuard aGuard( m_aMutex ); + m_bInputStreamCalled = false; + + if( ! m_bOutputStreamCalled ) + closeStream(); +} + + +void SAL_CALL +XStream_impl::closeOutput( + void ) + throw( io::NotConnectedException, + io::IOException, + uno::RuntimeException ) +{ + osl::MutexGuard aGuard( m_aMutex ); + m_bOutputStreamCalled = false; + + if( ! m_bInputStreamCalled ) + closeStream(); +} + + +void SAL_CALL +XStream_impl::seek( + sal_Int64 location ) + throw( lang::IllegalArgumentException, + io::IOException, + uno::RuntimeException ) +{ + if( location < 0 ) + throw lang::IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), 0 ); + if( osl::FileBase::E_None != m_aFile.setPos( Pos_Absolut, sal_uInt64( location ) ) ) + throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); +} + + +sal_Int64 SAL_CALL +XStream_impl::getPosition( + void ) + throw( io::IOException, + uno::RuntimeException ) +{ + sal_uInt64 uPos; + if( osl::FileBase::E_None != m_aFile.getPos( uPos ) ) + throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); + return sal_Int64( uPos ); +} + +sal_Int64 SAL_CALL +XStream_impl::getLength( + void ) + throw( io::IOException, + uno::RuntimeException ) +{ + sal_uInt64 uEndPos; + if ( m_aFile.getSize(uEndPos) != osl::FileBase::E_None ) + throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); + else + return sal_Int64( uEndPos ); +} + +void SAL_CALL +XStream_impl::flush() + throw( io::NotConnectedException, + io::BufferSizeExceededException, + io::IOException, + uno::RuntimeException ) +{} + +void XStream_impl::waitForCompletion() + throw (io::IOException, uno::RuntimeException) +{ + // At least on UNIX, to reliably learn about any errors encountered by + // asynchronous NFS write operations, without closing the file directly + // afterwards, there appears to be no cheaper way than to call fsync: + if (m_nIsOpen && m_aFile.sync() != osl::FileBase::E_None) { + throw io::IOException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "could not synchronize file to disc")), + static_cast< OWeakObject * >(this)); + } +} diff --git a/ucb/source/ucp/file/filstr.hxx b/ucb/source/ucp/file/filstr.hxx new file mode 100644 index 000000000000..b5ffae2a5ea2 --- /dev/null +++ b/ucb/source/ucp/file/filstr.hxx @@ -0,0 +1,246 @@ + /************************************************************************* + * + * 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 _FILSTR_HXX_ +#define _FILSTR_HXX_ + +#include <osl/mutex.hxx> +#include <rtl/ustring.hxx> +#include <cppuhelper/weak.hxx> +#include <ucbhelper/macros.hxx> +#include <com/sun/star/uno/XInterface.hpp> +#include <com/sun/star/lang/XTypeProvider.hpp> +#include <com/sun/star/io/XSeekable.hpp> +#include <com/sun/star/io/XTruncate.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/io/XStream.hpp> +#include "com/sun/star/io/XAsyncOutputMonitor.hpp" +#include <com/sun/star/ucb/XContentProvider.hpp> + +#include "filrec.hxx" + +namespace fileaccess { + + // forward: + class shell; + class XInputStreamForStream; + class XOutputStreamForStream; + + class XStream_impl + : public cppu::OWeakObject, + public com::sun::star::lang::XTypeProvider, + public com::sun::star::io::XStream, + public com::sun::star::io::XSeekable, + public com::sun::star::io::XInputStream, + public com::sun::star::io::XOutputStream, + public com::sun::star::io::XTruncate, + public com::sun::star::io::XAsyncOutputMonitor + { + friend class XInputStreamForStream; + friend class XOutputStreamForStream; + + public: + + XStream_impl( shell* pMyShell,const rtl::OUString& aUncPath, sal_Bool bLock ); + + /** + * Returns an error code as given by filerror.hxx + */ + + sal_Int32 SAL_CALL CtorSuccess(); + sal_Int32 SAL_CALL getMinorError(); + + virtual ~XStream_impl(); + + + // OWeakObject + + virtual com::sun::star::uno::Any SAL_CALL + queryInterface( + const com::sun::star::uno::Type& rType ) + throw( com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + acquire( + void ) + throw(); + + virtual void SAL_CALL + release( + void ) + throw(); + + + // XTypeProvider + + XTYPEPROVIDER_DECL() + + + // XStream + + virtual com::sun::star::uno::Reference< com::sun::star::io::XInputStream > SAL_CALL + getInputStream( ) + throw( com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::uno::Reference< com::sun::star::io::XOutputStream > SAL_CALL + getOutputStream( ) + throw( com::sun::star::uno::RuntimeException ); + + + // XTruncate + + virtual void SAL_CALL truncate( void ) + throw( com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException ); + + + // XInputStream + + sal_Int32 SAL_CALL + readBytes( + com::sun::star::uno::Sequence< sal_Int8 >& aData, + sal_Int32 nBytesToRead ) + throw( com::sun::star::io::NotConnectedException, + com::sun::star::io::BufferSizeExceededException, + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException); + + sal_Int32 SAL_CALL + readSomeBytes( + com::sun::star::uno::Sequence< sal_Int8 >& aData, + sal_Int32 nMaxBytesToRead ) + throw( com::sun::star::io::NotConnectedException, + com::sun::star::io::BufferSizeExceededException, + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException); + + + void SAL_CALL + skipBytes( + sal_Int32 nBytesToSkip ) + throw( com::sun::star::io::NotConnectedException, + com::sun::star::io::BufferSizeExceededException, + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException ); + + sal_Int32 SAL_CALL + available( + void ) + throw( com::sun::star::io::NotConnectedException, + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException ); + + void SAL_CALL + closeInput( + void ) + throw( com::sun::star::io::NotConnectedException, + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException ); + + // XSeekable + + void SAL_CALL + seek( + sal_Int64 location ) + throw( com::sun::star::lang::IllegalArgumentException, + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException ); + + sal_Int64 SAL_CALL + getPosition( + void ) + throw( com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException ); + + sal_Int64 SAL_CALL + getLength( + void ) + throw( com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException ); + + + // XOutputStream + + void SAL_CALL + writeBytes( const com::sun::star::uno::Sequence< sal_Int8 >& aData ) + throw( com::sun::star::io::NotConnectedException, + com::sun::star::io::BufferSizeExceededException, + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException); + + + + void SAL_CALL + flush() + throw( com::sun::star::io::NotConnectedException, + com::sun::star::io::BufferSizeExceededException, + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException); + + + void SAL_CALL + closeOutput( + void ) + throw( com::sun::star::io::NotConnectedException, + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL waitForCompletion() + throw ( + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException); + + private: + + osl::Mutex m_aMutex; + bool m_bInputStreamCalled,m_bOutputStreamCalled; + + shell* m_pMyShell; + com::sun::star::uno::Reference< com::sun::star::ucb::XContentProvider > m_xProvider; + sal_Bool m_nIsOpen; + + sal_Bool m_bLock; + + ReconnectingFile m_aFile; + + sal_Int32 m_nErrorCode; + sal_Int32 m_nMinorErrorCode; + + // Implementation methods + + void SAL_CALL + closeStream( + void ) + throw( com::sun::star::io::NotConnectedException, + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException ); + + }; + +} // end namespace XStream_impl + +#endif diff --git a/ucb/source/ucp/file/filtask.cxx b/ucb/source/ucp/file/filtask.cxx new file mode 100644 index 000000000000..a1350bb4cfaf --- /dev/null +++ b/ucb/source/ucp/file/filtask.cxx @@ -0,0 +1,184 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" +#include "filtask.hxx" +#include "filglob.hxx" + +/******************************************************************************/ +/* */ +/* TaskHandling */ +/* */ +/******************************************************************************/ + + +using namespace fileaccess; +using namespace com::sun::star; +using namespace com::sun::star::uno; +using namespace com::sun::star::ucb; + + + +TaskManager::TaskManager() + : m_nCommandId( 0 ) +{ +} + + + +TaskManager::~TaskManager() +{ +} + + + +void SAL_CALL +TaskManager::startTask( + sal_Int32 CommandId, + const uno::Reference< XCommandEnvironment >& xCommandEnv ) + throw( DuplicateCommandIdentifierException ) +{ + osl::MutexGuard aGuard( m_aMutex ); + TaskMap::iterator it = m_aTaskMap.find( CommandId ); + if( it != m_aTaskMap.end() ) + { + throw DuplicateCommandIdentifierException( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), + uno::Reference< uno::XInterface >() ); + } + m_aTaskMap[ CommandId ] = TaskHandling( xCommandEnv ); +} + + + +void SAL_CALL +TaskManager::endTask( sal_Int32 CommandId, + const rtl::OUString& aUncPath, + BaseContent* pContent) +{ + osl::MutexGuard aGuard( m_aMutex ); + TaskMap::iterator it = m_aTaskMap.find( CommandId ); + if( it == m_aTaskMap.end() ) + return; + + sal_Int32 ErrorCode = it->second.getInstalledError(); + sal_Int32 MinorCode = it->second.getMinorErrorCode(); + bool isHandled = it->second.isHandled(); + + Reference< XCommandEnvironment > xComEnv + = it->second.getCommandEnvironment(); + + m_aTaskMap.erase( it ); + + if( ErrorCode != TASKHANDLER_NO_ERROR ) + throw_handler( + ErrorCode, + MinorCode, + xComEnv, + aUncPath, + pContent, + isHandled); +} + + + +void SAL_CALL +TaskManager::abort( sal_Int32 CommandId ) +{ + if( CommandId ) + { + osl::MutexGuard aGuard( m_aMutex ); + TaskMap::iterator it = m_aTaskMap.find( CommandId ); + if( it == m_aTaskMap.end() ) + return; + else + it->second.abort(); + } +} + + +void SAL_CALL TaskManager::clearError( sal_Int32 CommandId ) +{ + osl::MutexGuard aGuard( m_aMutex ); + TaskMap::iterator it = m_aTaskMap.find( CommandId ); + if( it != m_aTaskMap.end() ) + it->second.clearError(); +} + + +void SAL_CALL TaskManager::retrieveError( sal_Int32 CommandId, + sal_Int32 &ErrorCode, + sal_Int32 &minorCode) +{ + osl::MutexGuard aGuard( m_aMutex ); + TaskMap::iterator it = m_aTaskMap.find( CommandId ); + if( it != m_aTaskMap.end() ) + { + ErrorCode = it->second.getInstalledError(); + minorCode = it->second. getMinorErrorCode(); + } +} + + + +void SAL_CALL TaskManager::installError( sal_Int32 CommandId, + sal_Int32 ErrorCode, + sal_Int32 MinorCode ) +{ + osl::MutexGuard aGuard( m_aMutex ); + TaskMap::iterator it = m_aTaskMap.find( CommandId ); + if( it != m_aTaskMap.end() ) + it->second.installError( ErrorCode,MinorCode ); +} + + + +sal_Int32 SAL_CALL +TaskManager::getCommandId( void ) +{ + osl::MutexGuard aGuard( m_aMutex ); + return ++m_nCommandId; +} + + + +void SAL_CALL TaskManager::handleTask( + sal_Int32 CommandId, + const uno::Reference< task::XInteractionRequest >& request ) +{ + osl::MutexGuard aGuard( m_aMutex ); + TaskMap::iterator it = m_aTaskMap.find( CommandId ); + uno::Reference< task::XInteractionHandler > xInt; + if( it != m_aTaskMap.end() ) + { + xInt = it->second.getInteractionHandler(); + if( xInt.is() ) + xInt->handle( request ); + it->second.setHandled(); + } +} diff --git a/ucb/source/ucp/file/filtask.hxx b/ucb/source/ucp/file/filtask.hxx new file mode 100644 index 000000000000..6ce4f35b4240 --- /dev/null +++ b/ucb/source/ucp/file/filtask.hxx @@ -0,0 +1,225 @@ +/************************************************************************* + * + * 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 _FILTASK_HXX_ +#define _FILTASK_HXX_ +#endif + +#include <hash_map> +#include <rtl/ustring.hxx> + +#include "osl/mutex.hxx" +#include <com/sun/star/ucb/DuplicateCommandIdentifierException.hpp> +#include <com/sun/star/ucb/XCommandEnvironment.hpp> +#include <com/sun/star/ucb/XProgressHandler.hpp> +#include <com/sun/star/task/XInteractionHandler.hpp> +#include <com/sun/star/task/XInteractionRequest.hpp> +#include "filerror.hxx" + + +namespace fileaccess +{ + class BaseContent; + + /* + * This implementation is inherited by class fileaccess::shell. + * The relevant methods in this class all have as first argument the CommandId, + * so if necessary, every method has access to its relevant XInteractionHandler and + * XProgressHandler. + */ + + + class TaskManager + { + protected: + + class TaskHandling + { + private: + + bool m_bAbort,m_bHandled; + sal_Int32 m_nErrorCode,m_nMinorCode; + com::sun::star::uno::Reference< com::sun::star::task::XInteractionHandler > m_xInteractionHandler; + com::sun::star::uno::Reference< com::sun::star::ucb::XProgressHandler > m_xProgressHandler; + com::sun::star::uno::Reference< com::sun::star::ucb::XCommandEnvironment > m_xCommandEnvironment; + + + public: + + TaskHandling( + const com::sun::star::uno::Reference< com::sun::star::ucb::XCommandEnvironment >& xCommandEnv + = com::sun::star::uno::Reference< com::sun::star::ucb::XCommandEnvironment >( 0 ) ) + : m_bAbort( false ), + m_bHandled( false ), + m_nErrorCode( TASKHANDLER_NO_ERROR ), + m_nMinorCode( TASKHANDLER_NO_ERROR ), + m_xInteractionHandler( 0 ), + m_xProgressHandler( 0 ), + m_xCommandEnvironment( xCommandEnv ) + { + } + + void SAL_CALL abort() + { + m_bAbort = true; + } + + void setHandled() + { + m_bHandled = true; + } + + bool isHandled() + { + return true; + } + + void clearError() + { + m_nErrorCode = TASKHANDLER_NO_ERROR; + m_nMinorCode = TASKHANDLER_NO_ERROR; + } + + void SAL_CALL installError( sal_Int32 nErrorCode, + sal_Int32 nMinorCode = TASKHANDLER_NO_ERROR ) + { + m_nErrorCode = nErrorCode; + m_nMinorCode = nMinorCode; + } + + sal_Int32 SAL_CALL getInstalledError() + { + return m_nErrorCode; + } + + sal_Int32 SAL_CALL getMinorErrorCode() + { + return m_nMinorCode; + } + + com::sun::star::uno::Reference< com::sun::star::ucb::XProgressHandler > SAL_CALL + getProgressHandler() + { + if( ! m_xProgressHandler.is() && m_xCommandEnvironment.is() ) + m_xProgressHandler = m_xCommandEnvironment->getProgressHandler(); + + return m_xProgressHandler; + } + + com::sun::star::uno::Reference< com::sun::star::task::XInteractionHandler > SAL_CALL + getInteractionHandler() + { + if( ! m_xInteractionHandler.is() && m_xCommandEnvironment.is() ) + m_xInteractionHandler = m_xCommandEnvironment->getInteractionHandler(); + + return m_xInteractionHandler; + } + + com::sun::star::uno::Reference< com::sun::star::ucb::XCommandEnvironment > SAL_CALL + getCommandEnvironment() + { + return m_xCommandEnvironment; + } + + }; // end class TaskHandling + + + typedef std::hash_map< sal_Int32,TaskHandling,std::hash< sal_Int32 > > TaskMap; + + + private: + + osl::Mutex m_aMutex; + sal_Int32 m_nCommandId; + TaskMap m_aTaskMap; + + + public: + + TaskManager(); + virtual ~TaskManager(); + + void SAL_CALL startTask( + sal_Int32 CommandId, + const com::sun::star::uno::Reference< com::sun::star::ucb::XCommandEnvironment >& xCommandEnv ) + throw( com::sun::star::ucb::DuplicateCommandIdentifierException ); + + sal_Int32 SAL_CALL getCommandId( void ); + void SAL_CALL abort( sal_Int32 CommandId ); + + + /** + * The error code may be one of the error codes defined in + * filerror.hxx. + * The minor code refines the information given in ErrorCode. + */ + + void SAL_CALL clearError(); + + void SAL_CALL installError( sal_Int32 CommandId, + sal_Int32 ErrorCode, + sal_Int32 minorCode = TASKHANDLER_NO_ERROR ); + + +// void SAL_CALL installError( sal_Int32 CommandId, +// sal_Int32 ErrorCode, +// rtl::OUString message ); + +// void SAL_CALL installError( sal_Int32 CommandId, +// sal_Int32 ErrorCode, +// rtl::OUString message ); + + void SAL_CALL retrieveError( sal_Int32 CommandId, + sal_Int32 &ErrorCode, + sal_Int32 &minorCode); + + /** + * Deinstalls the task and evaluates a possibly set error code. + * "endTask" throws in case an error code is set the corresponding exception. + */ + + void SAL_CALL endTask( sal_Int32 CommandId, + // the physical URL of the object + const rtl::OUString& aUnqPath, + BaseContent* pContent); + + + /** + * Handles an interactionrequest + */ + + void SAL_CALL handleTask( sal_Int32 CommandId, + const com::sun::star::uno::Reference< com::sun::star::task::XInteractionRequest >& request ); + + /** + * Clears any error which are set on the commandid + */ + + void SAL_CALL clearError( sal_Int32 ); + + }; + +} // end namespace TaskHandling diff --git a/ucb/source/ucp/file/makefile.mk b/ucb/source/ucp/file/makefile.mk new file mode 100644 index 000000000000..3d97cb23873c --- /dev/null +++ b/ucb/source/ucp/file/makefile.mk @@ -0,0 +1,88 @@ +#************************************************************************* +# +# 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=ucb +TARGET=ucpfile +ENABLE_EXCEPTIONS=TRUE +NO_BSYMBOLIC=TRUE + +# Version +UCPFILE_MAJOR=1 + +.INCLUDE: settings.mk +.IF "$(L10N_framework)"=="" + +SLOFILES=\ + $(SLO)$/prov.obj \ + $(SLO)$/bc.obj \ + $(SLO)$/shell.obj \ + $(SLO)$/filtask.obj \ + $(SLO)$/filrow.obj \ + $(SLO)$/filrset.obj \ + $(SLO)$/filid.obj \ + $(SLO)$/filnot.obj \ + $(SLO)$/filprp.obj \ + $(SLO)$/filinpstr.obj \ + $(SLO)$/filstr.obj \ + $(SLO)$/filcmd.obj \ + $(SLO)$/filglob.obj \ + $(SLO)$/filinsreq.obj \ + $(SLO)$/filrec.obj + +LIB1TARGET=$(SLB)$/_$(TARGET).lib +LIB1OBJFILES=$(SLOFILES) + +SHL1TARGET=$(TARGET)$(UCPFILE_MAJOR) +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +SHL1LIBS=$(LIB1TARGET) +SHL1IMPLIB=i$(TARGET) +SHL1STDLIBS=\ + $(CPPUHELPERLIB) \ + $(CPPULIB) \ + $(SALLIB) \ + $(UCBHELPERLIB) + +SHL1VERSIONMAP=$(SOLARENV)/src/component.map + +.IF "$(GUI)" == "OS2" +DEF1EXPORTFILE=exports2.dxp +.ENDIF + +DEF1NAME=$(SHL1TARGET) +.ENDIF # L10N_framework + +.INCLUDE: target.mk + + +ALLTAR : $(MISC)/ucpfile1.component + +$(MISC)/ucpfile1.component .ERRREMOVE : $(SOLARENV)/bin/createcomponent.xslt \ + ucpfile1.component + $(XSLTPROC) --nonet --stringparam uri \ + '$(COMPONENTPREFIX_BASIS_NATIVE)$(SHL1TARGETN:f)' -o $@ \ + $(SOLARENV)/bin/createcomponent.xslt ucpfile1.component diff --git a/ucb/source/ucp/file/prov.cxx b/ucb/source/ucp/file/prov.cxx new file mode 100644 index 000000000000..2b9c09a7d0fa --- /dev/null +++ b/ucb/source/ucp/file/prov.cxx @@ -0,0 +1,684 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" +#include <osl/security.hxx> +#include <osl/file.hxx> +#include <osl/socket.h> +#include <cppuhelper/factory.hxx> +#ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBBUTE_HPP_ +#include <com/sun/star/beans/PropertyAttribute.hpp> +#endif +#include <com/sun/star/ucb/FileSystemNotation.hpp> +#include <com/sun/star/beans/PropertyState.hpp> +#include "filglob.hxx" +#include "filid.hxx" +#include "shell.hxx" +#include "bc.hxx" +#include "prov.hxx" + + +using namespace fileaccess; +using namespace com::sun::star; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::beans; +using namespace com::sun::star::ucb; +using namespace com::sun::star::container; + +//========================================================================= +extern "C" void SAL_CALL component_getImplementationEnvironment( + const sal_Char ** ppEnvTypeName, uno_Environment ** ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + +//========================================================================= +extern "C" void * SAL_CALL component_getFactory( + const sal_Char * pImplName, void * pServiceManager, void * ) +{ + void * pRet = 0; + + Reference< XMultiServiceFactory > xSMgr( + reinterpret_cast< XMultiServiceFactory * >( pServiceManager ) ); + Reference< XSingleServiceFactory > xFactory; + + ////////////////////////////////////////////////////////////////////// + // File Content Provider. + ////////////////////////////////////////////////////////////////////// + + if ( fileaccess::shell::getImplementationName_static(). + compareToAscii( pImplName ) == 0 ) + { + xFactory = FileProvider::createServiceFactory( xSMgr ); + } + + ////////////////////////////////////////////////////////////////////// + + if ( xFactory.is() ) + { + xFactory->acquire(); + pRet = xFactory.get(); + } + + return pRet; +} + +/****************************************************************************/ +/* */ +/* */ +/* FileProvider */ +/* */ +/* */ +/****************************************************************************/ + + + +FileProvider::FileProvider( const Reference< XMultiServiceFactory >& xMultiServiceFactory ) + : m_xMultiServiceFactory( xMultiServiceFactory ), + m_pMyShell( 0 ) +{ +} + + +FileProvider::~FileProvider() +{ + if( m_pMyShell ) + delete m_pMyShell; +} + + +////////////////////////////////////////////////////////////////////////// +// XInterface +////////////////////////////////////////////////////////////////////////// + +void SAL_CALL +FileProvider::acquire( + void ) + throw() +{ + OWeakObject::acquire(); +} + + +void SAL_CALL +FileProvider::release( + void ) + throw() +{ + OWeakObject::release(); +} + + +Any SAL_CALL +FileProvider::queryInterface( + const Type& rType ) + throw( RuntimeException ) +{ + Any aRet = cppu::queryInterface( + rType, + SAL_STATIC_CAST( XContentProvider*, this ), + SAL_STATIC_CAST( XInitialization*, this ), + SAL_STATIC_CAST( XContentIdentifierFactory*, this ), + SAL_STATIC_CAST( XServiceInfo*, this ), + SAL_STATIC_CAST( XTypeProvider*, this ), + SAL_STATIC_CAST( XFileIdentifierConverter*,this ), + SAL_STATIC_CAST( XPropertySet*, this ) ); + return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ); +} + +/////////////////////////////////////////////////////////////////////////////// +// XInitialization + +void SAL_CALL FileProvider::init() +{ + if( ! m_pMyShell ) + m_pMyShell = new shell( m_xMultiServiceFactory, this, sal_True ); +} + + +void SAL_CALL +FileProvider::initialize( + const Sequence< Any >& aArguments ) + throw (Exception, RuntimeException) +{ + if( ! m_pMyShell ) { + rtl::OUString config; + if( aArguments.getLength() > 0 && + (aArguments[0] >>= config) && + config.compareToAscii("NoConfig") == 0 ) + m_pMyShell = new shell( m_xMultiServiceFactory, this, sal_False ); + else + m_pMyShell = new shell( m_xMultiServiceFactory, this, sal_True ); + } +} + + +//////////////////////////////////////////////////////////////////////////////// +// +// XTypeProvider methods. + + +XTYPEPROVIDER_IMPL_7( FileProvider, + XTypeProvider, + XServiceInfo, + XInitialization, + XContentIdentifierFactory, + XPropertySet, + XFileIdentifierConverter, + XContentProvider ) + + +//////////////////////////////////////////////////////////////////////////////// +// XServiceInfo methods. + +rtl::OUString SAL_CALL +FileProvider::getImplementationName() + throw( RuntimeException ) +{ + return fileaccess::shell::getImplementationName_static(); +} + + +sal_Bool SAL_CALL +FileProvider::supportsService( + const rtl::OUString& ServiceName ) + throw( RuntimeException ) +{ + return ServiceName == rtl::OUString::createFromAscii( "com.sun.star.ucb.FileContentProvider" ); +} + + +Sequence< rtl::OUString > SAL_CALL +FileProvider::getSupportedServiceNames( + void ) + throw( RuntimeException ) +{ + return fileaccess::shell::getSupportedServiceNames_static(); +} + + + +Reference< XSingleServiceFactory > SAL_CALL +FileProvider::createServiceFactory( + const Reference< XMultiServiceFactory >& rxServiceMgr ) +{ + /** + * Create a single service factory.<BR> + * Note: The function pointer ComponentInstantiation points to a function throws Exception. + * + * @param rServiceManager the service manager used by the implementation. + * @param rImplementationName the implementation name. An empty string is possible. + * @param ComponentInstantiation the function pointer to create an object. + * @param rServiceNames the service supported by the implementation. + * @return a factory that support the interfaces XServiceProvider, XServiceInfo + * XSingleServiceFactory and XComponent. + * + * @see createOneInstanceFactory + */ + /* + * Reference< ::com::sun::star::XSingleServiceFactory > createSingleFactory + * ( + * const ::com::sun::star::Reference< ::com::sun::star::XMultiServiceFactory > & rServiceManager, + * const ::rtl::OUString & rImplementationName, + * ComponentInstantiation pCreateFunction, + + * const ::com::sun::star::Sequence< ::rtl::OUString > & rServiceNames + * ); + */ + + return Reference< XSingleServiceFactory > ( cppu::createSingleFactory( + rxServiceMgr, + fileaccess::shell::getImplementationName_static(), + FileProvider::CreateInstance, + fileaccess::shell::getSupportedServiceNames_static() ) ); +} + +Reference< XInterface > SAL_CALL +FileProvider::CreateInstance( + const Reference< XMultiServiceFactory >& xMultiServiceFactory ) +{ + XServiceInfo* xP = (XServiceInfo*) new FileProvider( xMultiServiceFactory ); + return Reference< XInterface >::query( xP ); +} + + + +//////////////////////////////////////////////////////////////////////////////// +// XContent +//////////////////////////////////////////////////////////////////////////////// + + +Reference< XContent > SAL_CALL +FileProvider::queryContent( + const Reference< XContentIdentifier >& xIdentifier ) + throw( IllegalIdentifierException, + RuntimeException) +{ + init(); + rtl::OUString aUnc; + sal_Bool err = m_pMyShell->getUnqFromUrl( xIdentifier->getContentIdentifier(), + aUnc ); + + if( err ) + throw IllegalIdentifierException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); + + return Reference< XContent >( new BaseContent( m_pMyShell,xIdentifier,aUnc ) ); +} + + + +sal_Int32 SAL_CALL +FileProvider::compareContentIds( + const Reference< XContentIdentifier >& Id1, + const Reference< XContentIdentifier >& Id2 ) + throw( RuntimeException ) +{ + init(); + rtl::OUString aUrl1 = Id1->getContentIdentifier(); + rtl::OUString aUrl2 = Id2->getContentIdentifier(); + + sal_Int32 iComp = aUrl1.compareTo( aUrl2 ); + + if ( 0 != iComp ) + { + rtl::OUString aPath1, aPath2; + + m_pMyShell->getUnqFromUrl( aUrl1, aPath1 ); + m_pMyShell->getUnqFromUrl( aUrl2, aPath2 ); + + osl::FileBase::RC error; + osl::DirectoryItem aItem1, aItem2; + + error = osl::DirectoryItem::get( aPath1, aItem1 ); + if ( error == osl::FileBase::E_None ) + error = osl::DirectoryItem::get( aPath2, aItem2 ); + + if ( error != osl::FileBase::E_None ) + return iComp; + + osl::FileStatus aStatus1( FileStatusMask_FileURL ); + osl::FileStatus aStatus2( FileStatusMask_FileURL ); + error = aItem1.getFileStatus( aStatus1 ); + if ( error == osl::FileBase::E_None ) + error = aItem2.getFileStatus( aStatus2 ); + + if ( error == osl::FileBase::E_None ) + { + iComp = aStatus1.getFileURL().compareTo( aStatus2.getFileURL() ); + +// Quick hack for Windows to threat all file systems as case insensitive +#ifdef WNT + if ( 0 != iComp ) + { + error = osl::FileBase::getSystemPathFromFileURL( aStatus1.getFileURL(), aPath1 ); + if ( error == osl::FileBase::E_None ) + error = osl::FileBase::getSystemPathFromFileURL( aStatus2.getFileURL(), aPath2 ); + + if ( error == osl::FileBase::E_None ) + iComp = rtl_ustr_compareIgnoreAsciiCase( aPath1.getStr(), aPath2.getStr() ); + } +#endif + } + } + + return iComp; +} + + + +Reference< XContentIdentifier > SAL_CALL +FileProvider::createContentIdentifier( + const rtl::OUString& ContentId ) + throw( RuntimeException ) +{ + init(); + FileContentIdentifier* p = new FileContentIdentifier( m_pMyShell,ContentId,false ); + return Reference< XContentIdentifier >( p ); +} + + + +//XPropertySetInfoImpl + +class XPropertySetInfoImpl2 + : public cppu::OWeakObject, + public XPropertySetInfo +{ +public: + XPropertySetInfoImpl2(); + ~XPropertySetInfoImpl2(); + + // XInterface + virtual Any SAL_CALL + queryInterface( + const Type& aType ) + throw( RuntimeException); + + virtual void SAL_CALL + acquire( + void ) + throw(); + + virtual void SAL_CALL + release( + void ) + throw(); + + + virtual Sequence< Property > SAL_CALL + getProperties( + void ) + throw( RuntimeException ); + + virtual Property SAL_CALL + getPropertyByName( + const rtl::OUString& aName ) + throw( UnknownPropertyException, + RuntimeException); + + virtual sal_Bool SAL_CALL + hasPropertyByName( const rtl::OUString& Name ) + throw( RuntimeException ); + + +private: + Sequence< Property > m_seq; +}; + + +XPropertySetInfoImpl2::XPropertySetInfoImpl2() + : m_seq( 3 ) +{ + m_seq[0] = Property( rtl::OUString::createFromAscii( "HostName" ), + -1, + getCppuType( static_cast< rtl::OUString* >( 0 ) ), + PropertyAttribute::READONLY ); + + m_seq[1] = Property( rtl::OUString::createFromAscii( "HomeDirectory" ), + -1, + getCppuType( static_cast< rtl::OUString* >( 0 ) ), + PropertyAttribute::READONLY ); + + m_seq[2] = Property( rtl::OUString::createFromAscii( "FileSystemNotation" ), + -1, + getCppuType( static_cast< sal_Int32* >( 0 ) ), + PropertyAttribute::READONLY ); +} + + +XPropertySetInfoImpl2::~XPropertySetInfoImpl2() +{ + // nothing +} + + +void SAL_CALL +XPropertySetInfoImpl2::acquire( + void ) + throw() +{ + OWeakObject::acquire(); +} + + +void SAL_CALL +XPropertySetInfoImpl2::release( + void ) + throw() +{ + OWeakObject::release(); +} + + +Any SAL_CALL +XPropertySetInfoImpl2::queryInterface( + const Type& rType ) + throw( RuntimeException ) +{ + Any aRet = cppu::queryInterface( rType, + SAL_STATIC_CAST( XPropertySetInfo*,this) ); + return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ); +} + + +Property SAL_CALL +XPropertySetInfoImpl2::getPropertyByName( + const rtl::OUString& aName ) + throw( UnknownPropertyException, + RuntimeException) +{ + for( sal_Int32 i = 0; i < m_seq.getLength(); ++i ) + if( m_seq[i].Name == aName ) + return m_seq[i]; + + throw UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); +} + + + +Sequence< Property > SAL_CALL +XPropertySetInfoImpl2::getProperties( + void ) + throw( RuntimeException ) +{ + return m_seq; +} + + +sal_Bool SAL_CALL +XPropertySetInfoImpl2::hasPropertyByName( + const rtl::OUString& aName ) + throw( RuntimeException ) +{ + for( sal_Int32 i = 0; i < m_seq.getLength(); ++i ) + if( m_seq[i].Name == aName ) + return true; + return false; +} + + + + + +void SAL_CALL FileProvider::initProperties( void ) +{ + osl::MutexGuard aGuard( m_aMutex ); + if( ! m_xPropertySetInfo.is() ) + { + osl_getLocalHostname( &m_HostName.pData ); + +#if defined ( UNX ) + m_FileSystemNotation = FileSystemNotation::UNIX_NOTATION; +#elif defined( WNT ) || defined( OS2 ) + m_FileSystemNotation = FileSystemNotation::DOS_NOTATION; +#else + m_FileSystemNotation = FileSystemNotation::UNKNOWN_NOTATION; +#endif + osl::Security aSecurity; + aSecurity.getHomeDir( m_HomeDirectory ); + + // static const sal_Int32 UNKNOWN_NOTATION = (sal_Int32)0; + // static const sal_Int32 UNIX_NOTATION = (sal_Int32)1; + // static const sal_Int32 DOS_NOTATION = (sal_Int32)2; + // static const sal_Int32 MAC_NOTATION = (sal_Int32)3; + + XPropertySetInfoImpl2* p = new XPropertySetInfoImpl2(); + m_xPropertySetInfo = Reference< XPropertySetInfo >( p ); + } +} + + +// XPropertySet + +Reference< XPropertySetInfo > SAL_CALL +FileProvider::getPropertySetInfo( ) + throw( RuntimeException ) +{ + initProperties(); + return m_xPropertySetInfo; +} + + +void SAL_CALL +FileProvider::setPropertyValue( const rtl::OUString& aPropertyName, + const Any& ) + throw( UnknownPropertyException, + PropertyVetoException, + IllegalArgumentException, + WrappedTargetException, + RuntimeException ) +{ + if( aPropertyName.compareToAscii( "FileSystemNotation" ) == 0 || + aPropertyName.compareToAscii( "HomeDirectory" ) == 0 || + aPropertyName.compareToAscii( "HostName" ) == 0 ) + return; + else + throw UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); +} + + + +Any SAL_CALL +FileProvider::getPropertyValue( + const rtl::OUString& aPropertyName ) + throw( UnknownPropertyException, + WrappedTargetException, + RuntimeException ) +{ + initProperties(); + if( aPropertyName.compareToAscii( "FileSystemNotation" ) == 0 ) + { + Any aAny; + aAny <<= m_FileSystemNotation; + return aAny; + } + else if( aPropertyName.compareToAscii( "HomeDirectory" ) == 0 ) + { + Any aAny; + aAny <<= m_HomeDirectory; + return aAny; + } + else if( aPropertyName.compareToAscii( "HostName" ) == 0 ) + { + Any aAny; + aAny <<= m_HostName; + return aAny; + } + else + throw UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); +} + + +void SAL_CALL +FileProvider::addPropertyChangeListener( + const rtl::OUString&, + const Reference< XPropertyChangeListener >& ) + throw( UnknownPropertyException, + WrappedTargetException, + RuntimeException) +{ + return; +} + + +void SAL_CALL +FileProvider::removePropertyChangeListener( + const rtl::OUString&, + const Reference< XPropertyChangeListener >& ) + throw( UnknownPropertyException, + WrappedTargetException, + RuntimeException ) +{ + return; +} + +void SAL_CALL +FileProvider::addVetoableChangeListener( + const rtl::OUString&, + const Reference< XVetoableChangeListener >& ) + throw( UnknownPropertyException, + WrappedTargetException, + RuntimeException ) +{ + return; +} + + +void SAL_CALL +FileProvider::removeVetoableChangeListener( + const rtl::OUString&, + const Reference< XVetoableChangeListener >& ) + throw( UnknownPropertyException, + WrappedTargetException, + RuntimeException) +{ + return; +} + + + +// XFileIdentifierConverter + +sal_Int32 SAL_CALL +FileProvider::getFileProviderLocality( const rtl::OUString& BaseURL ) + throw( RuntimeException ) +{ + // If the base URL is a 'file' URL, return 10 (very 'local'), otherwise + // return -1 (missmatch). What is missing is a fast comparison to ASCII, + // ignoring case: + return BaseURL.getLength() >= 5 + && (BaseURL[0] == 'F' || BaseURL[0] == 'f') + && (BaseURL[1] == 'I' || BaseURL[1] == 'i') + && (BaseURL[2] == 'L' || BaseURL[2] == 'l') + && (BaseURL[3] == 'E' || BaseURL[3] == 'e') + && BaseURL[4] == ':' ? + 10 : -1; +} + +rtl::OUString SAL_CALL FileProvider::getFileURLFromSystemPath( const rtl::OUString&, + const rtl::OUString& SystemPath ) + throw( RuntimeException ) +{ + rtl::OUString aNormalizedPath; + if ( osl::FileBase::getFileURLFromSystemPath( SystemPath,aNormalizedPath ) != osl::FileBase::E_None ) + return rtl::OUString(); + + return aNormalizedPath; +} + +rtl::OUString SAL_CALL FileProvider::getSystemPathFromFileURL( const rtl::OUString& URL ) + throw( RuntimeException ) +{ + rtl::OUString aSystemPath; + if (osl::FileBase::getSystemPathFromFileURL( URL,aSystemPath ) != osl::FileBase::E_None ) + return rtl::OUString(); + + return aSystemPath; +} + diff --git a/ucb/source/ucp/file/prov.hxx b/ucb/source/ucp/file/prov.hxx new file mode 100644 index 000000000000..52f0ba35f3cb --- /dev/null +++ b/ucb/source/ucp/file/prov.hxx @@ -0,0 +1,238 @@ +/************************************************************************* + * + * 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 _PROV_HXX_ +#define _PROV_HXX_ + +#include <cppuhelper/weak.hxx> + +#include "osl/mutex.hxx" +#include <ucbhelper/macros.hxx> +#include <com/sun/star/uno/XInterface.hpp> +#include <com/sun/star/lang/XTypeProvider.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/XServiceInfo.hpp> +#include <com/sun/star/ucb/XContentProvider.hpp> +#include <com/sun/star/ucb/XContentIdentifierFactory.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/ucb/XFileIdentifierConverter.hpp> +#include <com/sun/star/container/XHierarchicalNameAccess.hpp> + +// FileProvider + + + +namespace fileaccess { + + // Forward declaration + + class BaseContent; + class shell; + + class FileProvider: + public cppu::OWeakObject, + public com::sun::star::lang::XServiceInfo, + public com::sun::star::lang::XInitialization, + public com::sun::star::lang::XTypeProvider, + public com::sun::star::ucb::XContentProvider, + public com::sun::star::ucb::XContentIdentifierFactory, + public com::sun::star::beans::XPropertySet, + public com::sun::star::ucb::XFileIdentifierConverter + { + friend class BaseContent; + public: + + FileProvider( const com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >& xMSF ); + ~FileProvider(); + + // XInterface + virtual com::sun::star::uno::Any SAL_CALL + queryInterface( + const com::sun::star::uno::Type& aType ) + throw( com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + acquire( + void ) + throw(); + + virtual void SAL_CALL + release( + void ) + throw(); + + // XServiceInfo + virtual rtl::OUString SAL_CALL + getImplementationName( + void ) + throw( com::sun::star::uno::RuntimeException ); + + virtual sal_Bool SAL_CALL + supportsService( + const rtl::OUString& ServiceName ) + throw(com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL + getSupportedServiceNames( + void ) + throw( com::sun::star::uno::RuntimeException ); + + + static com::sun::star::uno::Reference< com::sun::star::lang::XSingleServiceFactory > SAL_CALL + createServiceFactory( + const com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >& rxServiceMgr ); + + static com::sun::star::uno::Reference< com::sun::star::uno::XInterface > SAL_CALL + CreateInstance( + const com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >& xMultiServiceFactory ); + + // XTypeProvider + + XTYPEPROVIDER_DECL() + + // XInitialization + virtual void SAL_CALL + initialize( + const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) + throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + + + // XContentProvider + virtual com::sun::star::uno::Reference< com::sun::star::ucb::XContent > SAL_CALL + queryContent( + const com::sun::star::uno::Reference< com::sun::star::ucb::XContentIdentifier >& Identifier ) + throw( com::sun::star::ucb::IllegalIdentifierException, + com::sun::star::uno::RuntimeException ); + + // XContentIdentifierFactory + + virtual com::sun::star::uno::Reference< com::sun::star::ucb::XContentIdentifier > SAL_CALL + createContentIdentifier( + const rtl::OUString& ContentId ) + throw( com::sun::star::uno::RuntimeException ); + + + virtual sal_Int32 SAL_CALL + compareContentIds( + const com::sun::star::uno::Reference< com::sun::star::ucb::XContentIdentifier >& Id1, + const com::sun::star::uno::Reference< com::sun::star::ucb::XContentIdentifier >& Id2 ) + throw( com::sun::star::uno::RuntimeException ); + + // XProperySet + + virtual com::sun::star::uno::Reference< com::sun::star::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo( ) + throw( com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL + setPropertyValue( + const rtl::OUString& aPropertyName, + const com::sun::star::uno::Any& aValue ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::beans::PropertyVetoException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::uno::Any SAL_CALL + getPropertyValue( + const rtl::OUString& PropertyName ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL + addPropertyChangeListener( + const rtl::OUString& aPropertyName, + const com::sun::star::uno::Reference< com::sun::star::beans::XPropertyChangeListener >& xListener ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + removePropertyChangeListener( + const rtl::OUString& aPropertyName, + const com::sun::star::uno::Reference< com::sun::star::beans::XPropertyChangeListener >& aListener ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL + addVetoableChangeListener( + const rtl::OUString& PropertyName, + const com::sun::star::uno::Reference< com::sun::star::beans::XVetoableChangeListener >& aListener ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL + removeVetoableChangeListener( + const rtl::OUString& PropertyName, + const com::sun::star::uno::Reference< com::sun::star::beans::XVetoableChangeListener >& aListener ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException); + + + // XFileIdentifierConverter + + virtual sal_Int32 SAL_CALL + getFileProviderLocality( const rtl::OUString& BaseURL ) + throw( com::sun::star::uno::RuntimeException ); + + virtual rtl::OUString SAL_CALL getFileURLFromSystemPath( const rtl::OUString& BaseURL, + const rtl::OUString& SystemPath ) + throw( com::sun::star::uno::RuntimeException ); + + virtual rtl::OUString SAL_CALL getSystemPathFromFileURL( const rtl::OUString& URL ) + throw( com::sun::star::uno::RuntimeException ); + + + private: + // methods + void SAL_CALL init(); + + // Members + com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory > m_xMultiServiceFactory; + + void SAL_CALL initProperties( void ); + osl::Mutex m_aMutex; + rtl::OUString m_HostName; + rtl::OUString m_HomeDirectory; + sal_Int32 m_FileSystemNotation; + + com::sun::star::uno::Reference< com::sun::star::beans::XPropertySetInfo > m_xPropertySetInfo; + + shell* m_pMyShell; + }; + +} // end namespace fileaccess + +#endif + diff --git a/ucb/source/ucp/file/shell.cxx b/ucb/source/ucp/file/shell.cxx new file mode 100644 index 000000000000..f324c93b878f --- /dev/null +++ b/ucb/source/ucp/file/shell.cxx @@ -0,0 +1,3074 @@ + /************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" +#ifndef INCLUDED_STL_STACK +#include <stack> +#define INCLUDED_STL_STACK +#endif + +#include "osl/diagnose.h" +#include <rtl/uri.hxx> +#include <rtl/ustrbuf.hxx> +#include <osl/time.h> +#include <osl/file.hxx> +#include <com/sun/star/lang/IllegalAccessException.hpp> +#include <com/sun/star/beans/IllegalTypeException.hpp> +#include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp> +#include <com/sun/star/ucb/InsertCommandArgument.hpp> +#include <com/sun/star/ucb/NameClash.hpp> +#include <com/sun/star/ucb/XContentIdentifier.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/ucb/XContentAccess.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/io/XSeekable.hpp> +#include <com/sun/star/io/XTruncate.hpp> +#include <com/sun/star/ucb/OpenCommandArgument.hpp> +#include <com/sun/star/ucb/XPropertySetRegistryFactory.hpp> +#include <com/sun/star/ucb/TransferInfo.hpp> +#include <com/sun/star/ucb/ContentInfoAttribute.hpp> +#include <com/sun/star/beans/PropertyChangeEvent.hpp> +#include <com/sun/star/beans/XPropertiesChangeListener.hpp> +#include <rtl/string.hxx> +#include "filerror.hxx" +#include "filglob.hxx" +#include "filcmd.hxx" +#include "filinpstr.hxx" +#include "filstr.hxx" +#include "filrset.hxx" +#include "filrow.hxx" +#include "filprp.hxx" +#include "filid.hxx" +#include "shell.hxx" +#include "prov.hxx" +#include "bc.hxx" + + +using namespace fileaccess; +using namespace com::sun::star; +using namespace com::sun::star::ucb; + + +shell::UnqPathData::UnqPathData() + : properties( 0 ), + notifier( 0 ), + xS( 0 ), + xC( 0 ), + xA( 0 ) +{ + // empty +} + + +shell::UnqPathData::UnqPathData( const UnqPathData& a ) + : properties( a.properties ), + notifier( a.notifier ), + xS( a.xS ), + xC( a.xC ), + xA( a.xA ) +{ +} + + +shell::UnqPathData& shell::UnqPathData::operator=( UnqPathData& a ) +{ + properties = a.properties; + notifier = a.notifier; + xS = a.xS; + xC = a.xC; + xA = a.xA; + a.properties = 0; + a.notifier = 0; + a.xS = 0; + a.xC = 0; + a.xA = 0; + return *this; +} + +shell::UnqPathData::~UnqPathData() +{ + if( properties ) + delete properties; + if( notifier ) + delete notifier; +} + + + +//////////////////////////////////////////////////////////////////////////////////////// + + + + + +shell::MyProperty::MyProperty( const rtl::OUString& __PropertyName ) + : PropertyName( __PropertyName ) +{ + // empty +} + + +shell::MyProperty::MyProperty( const sal_Bool& __isNative, + const rtl::OUString& __PropertyName, + const sal_Int32& __Handle, + const com::sun::star::uno::Type& __Typ, + const com::sun::star::uno::Any& __Value, + const com::sun::star::beans::PropertyState& __State, + const sal_Int16& __Attributes ) + : PropertyName( __PropertyName ), + Handle( __Handle ), + isNative( __isNative ), + Typ( __Typ ), + Value( __Value ), + State( __State ), + Attributes( __Attributes ) +{ + // empty +} + +shell::MyProperty::~MyProperty() +{ + // empty for now +} + + +#include "filinl.hxx" + + +shell::shell( const uno::Reference< lang::XMultiServiceFactory >& xMultiServiceFactory, + FileProvider* pProvider, sal_Bool bWithConfig ) + : TaskManager(), + m_bWithConfig( bWithConfig ), + m_pProvider( pProvider ), + m_xMultiServiceFactory( xMultiServiceFactory ), + Title( rtl::OUString::createFromAscii( "Title" ) ), + CasePreservingURL( + rtl::OUString::createFromAscii( "CasePreservingURL" ) ), + IsDocument( rtl::OUString::createFromAscii( "IsDocument" ) ), + IsFolder( rtl::OUString::createFromAscii( "IsFolder" ) ), + DateModified( rtl::OUString::createFromAscii( "DateModified" ) ), + Size( rtl::OUString::createFromAscii( "Size" ) ), + IsVolume( rtl::OUString::createFromAscii( "IsVolume" ) ), + IsRemoveable( rtl::OUString::createFromAscii( "IsRemoveable" ) ), + IsRemote( rtl::OUString::createFromAscii( "IsRemote" ) ), + IsCompactDisc( rtl::OUString::createFromAscii( "IsCompactDisc" ) ), + IsFloppy( rtl::OUString::createFromAscii( "IsFloppy" ) ), + IsHidden( rtl::OUString::createFromAscii( "IsHidden" ) ), + ContentType( rtl::OUString::createFromAscii( "ContentType" ) ), + IsReadOnly( rtl::OUString::createFromAscii( "IsReadOnly" ) ), + CreatableContentsInfo( rtl::OUString::createFromAscii( "CreatableContentsInfo" ) ), + FolderContentType( rtl::OUString::createFromAscii( "application/vnd.sun.staroffice.fsys-folder" ) ), + FileContentType( rtl::OUString::createFromAscii( "application/vnd.sun.staroffice.fsys-file" ) ), + m_sCommandInfo( 9 ) +{ + // Title + m_aDefaultProperties.insert( MyProperty( true, + Title, + -1 , + getCppuType( static_cast< rtl::OUString* >( 0 ) ), + uno::Any(), + beans::PropertyState_DEFAULT_VALUE, + beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::BOUND ) ); + + // CasePreservingURL + m_aDefaultProperties.insert( + MyProperty( true, + CasePreservingURL, + -1 , + getCppuType( static_cast< rtl::OUString* >( 0 ) ), + uno::Any(), + beans::PropertyState_DEFAULT_VALUE, + beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ) ); + + + // IsFolder + m_aDefaultProperties.insert( MyProperty( true, + IsFolder, + -1 , + getCppuType( static_cast< sal_Bool* >( 0 ) ), + uno::Any(), + beans::PropertyState_DEFAULT_VALUE, + beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ) ); + + + // IsDocument + m_aDefaultProperties.insert( MyProperty( true, + IsDocument, + -1 , + getCppuType( static_cast< sal_Bool* >( 0 ) ), + uno::Any(), + beans::PropertyState_DEFAULT_VALUE, + beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ) ); + + // Removable + m_aDefaultProperties.insert( MyProperty( true, + IsVolume, + -1 , + getCppuType( static_cast< sal_Bool* >( 0 ) ), + uno::Any(), + beans::PropertyState_DEFAULT_VALUE, + beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ) ); + + + // Removable + m_aDefaultProperties.insert( MyProperty( true, + IsRemoveable, + -1 , + getCppuType( static_cast< sal_Bool* >( 0 ) ), + uno::Any(), + beans::PropertyState_DEFAULT_VALUE, + beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ) ); + + // Remote + m_aDefaultProperties.insert( MyProperty( true, + IsRemote, + -1 , + getCppuType( static_cast< sal_Bool* >( 0 ) ), + uno::Any(), + beans::PropertyState_DEFAULT_VALUE, + beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ) ); + + // CompactDisc + m_aDefaultProperties.insert( MyProperty( true, + IsCompactDisc, + -1 , + getCppuType( static_cast< sal_Bool* >( 0 ) ), + uno::Any(), + beans::PropertyState_DEFAULT_VALUE, + beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ) ); + + // Floppy + m_aDefaultProperties.insert( MyProperty( true, + IsFloppy, + -1 , + getCppuType( static_cast< sal_Bool* >( 0 ) ), + uno::Any(), + beans::PropertyState_DEFAULT_VALUE, + beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ) ); + + // Hidden + m_aDefaultProperties.insert( + MyProperty( + true, + IsHidden, + -1 , + getCppuType( static_cast< sal_Bool* >( 0 ) ), + uno::Any(), + beans::PropertyState_DEFAULT_VALUE, + beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::BOUND +#if defined( WNT ) || defined( OS2 ) + )); +#else + | beans::PropertyAttribute::READONLY)); // under unix/linux only readable +#endif + + + // ContentType + uno::Any aAny; + aAny <<= rtl::OUString(); + m_aDefaultProperties.insert( MyProperty( false, + ContentType, + -1 , + getCppuType( static_cast< rtl::OUString* >( 0 ) ), + aAny, + beans::PropertyState_DEFAULT_VALUE, + beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ) ); + + + // DateModified + m_aDefaultProperties.insert( MyProperty( true, + DateModified, + -1 , + getCppuType( static_cast< util::DateTime* >( 0 ) ), + uno::Any(), + beans::PropertyState_DEFAULT_VALUE, + beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::BOUND ) ); + + // Size + m_aDefaultProperties.insert( MyProperty( true, + Size, + -1, + getCppuType( static_cast< sal_Int64* >( 0 ) ), + uno::Any(), + beans::PropertyState_DEFAULT_VALUE, + beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::BOUND ) ); + + // IsReadOnly + m_aDefaultProperties.insert( MyProperty( true, + IsReadOnly, + -1 , + getCppuType( static_cast< sal_Bool* >( 0 ) ), + uno::Any(), + beans::PropertyState_DEFAULT_VALUE, + beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::BOUND ) ); + + + // CreatableContentsInfo + m_aDefaultProperties.insert( MyProperty( true, + CreatableContentsInfo, + -1 , + getCppuType( static_cast< const uno::Sequence< ucb::ContentInfo > * >( 0 ) ), + uno::Any(), + beans::PropertyState_DEFAULT_VALUE, + beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ) ); + + // Commands + m_sCommandInfo[0].Name = rtl::OUString::createFromAscii( "getCommandInfo" ); + m_sCommandInfo[0].Handle = -1; + m_sCommandInfo[0].ArgType = getCppuVoidType(); + + m_sCommandInfo[1].Name = rtl::OUString::createFromAscii( "getPropertySetInfo" ); + m_sCommandInfo[1].Handle = -1; + m_sCommandInfo[1].ArgType = getCppuVoidType(); + + m_sCommandInfo[2].Name = rtl::OUString::createFromAscii( "getPropertyValues" ); + m_sCommandInfo[2].Handle = -1; + m_sCommandInfo[2].ArgType = getCppuType( static_cast< uno::Sequence< beans::Property >* >( 0 ) ); + + m_sCommandInfo[3].Name = rtl::OUString::createFromAscii( "setPropertyValues" ); + m_sCommandInfo[3].Handle = -1; + m_sCommandInfo[3].ArgType = getCppuType( static_cast< uno::Sequence< beans::PropertyValue >* >( 0 ) ); + + m_sCommandInfo[4].Name = rtl::OUString::createFromAscii( "open" ); + m_sCommandInfo[4].Handle = -1; + m_sCommandInfo[4].ArgType = getCppuType( static_cast< OpenCommandArgument* >( 0 ) ); + + m_sCommandInfo[5].Name = rtl::OUString::createFromAscii( "transfer" ); + m_sCommandInfo[5].Handle = -1; + m_sCommandInfo[5].ArgType = getCppuType( static_cast< TransferInfo* >( 0 ) ); + + m_sCommandInfo[6].Name = rtl::OUString::createFromAscii( "delete" ); + m_sCommandInfo[6].Handle = -1; + m_sCommandInfo[6].ArgType = getCppuType( static_cast< sal_Bool* >( 0 ) ); + + m_sCommandInfo[7].Name = rtl::OUString::createFromAscii( "insert" ); + m_sCommandInfo[7].Handle = -1; + m_sCommandInfo[7].ArgType = getCppuType( static_cast< InsertCommandArgument* > ( 0 ) ); + + m_sCommandInfo[7].Name = rtl::OUString::createFromAscii( "createNewContent" ); + m_sCommandInfo[7].Handle = -1; + m_sCommandInfo[7].ArgType = getCppuType( static_cast< ucb::ContentInfo * > ( 0 ) ); + + if(m_bWithConfig) + { + rtl::OUString Store = rtl::OUString::createFromAscii( "com.sun.star.ucb.Store" ); + uno::Reference< XPropertySetRegistryFactory > xRegFac( + m_xMultiServiceFactory->createInstance( Store ), + uno::UNO_QUERY ); + if ( xRegFac.is() ) + { + // Open/create a registry + m_xFileRegistry = xRegFac->createPropertySetRegistry( rtl::OUString() ); + } + } +} + + +shell::~shell() +{ +} + + +/*********************************************************************************/ +/* */ +/* de/registerNotifier-Implementation */ +/* */ +/*********************************************************************************/ + +// +// This two methods register and deregister a change listener for the content belonging +// to URL aUnqPath +// + +void SAL_CALL +shell::registerNotifier( const rtl::OUString& aUnqPath, Notifier* pNotifier ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + ContentMap::iterator it = + m_aContent.insert( ContentMap::value_type( aUnqPath,UnqPathData() ) ).first; + + if( ! it->second.notifier ) + it->second.notifier = new NotifierList(); + + std::list< Notifier* >& nlist = *( it->second.notifier ); + + std::list<Notifier*>::iterator it1 = nlist.begin(); + while( it1 != nlist.end() ) // Every "Notifier" only once + { + if( *it1 == pNotifier ) return; + ++it1; + } + nlist.push_back( pNotifier ); +} + + + +void SAL_CALL +shell::deregisterNotifier( const rtl::OUString& aUnqPath,Notifier* pNotifier ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + ContentMap::iterator it = m_aContent.find( aUnqPath ); + if( it == m_aContent.end() ) + return; + + it->second.notifier->remove( pNotifier ); + + if( ! it->second.notifier->size() ) + m_aContent.erase( it ); +} + + + +/*********************************************************************************/ +/* */ +/* de/associate-Implementation */ +/* */ +/*********************************************************************************/ +// +// Used to associate and deassociate a new property with +// the content belonging to URL UnqPath. +// The default value and the the attributes are input +// + +void SAL_CALL +shell::associate( const rtl::OUString& aUnqPath, + const rtl::OUString& PropertyName, + const uno::Any& DefaultValue, + const sal_Int16 Attributes ) + throw( beans::PropertyExistException, + beans::IllegalTypeException, + uno::RuntimeException ) +{ + MyProperty newProperty( false, + PropertyName, + -1, + DefaultValue.getValueType(), + DefaultValue, + beans::PropertyState_DEFAULT_VALUE, + Attributes ); + + shell::PropertySet::iterator it1 = m_aDefaultProperties.find( newProperty ); + if( it1 != m_aDefaultProperties.end() ) + throw beans::PropertyExistException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); + + { + osl::MutexGuard aGuard( m_aMutex ); + + ContentMap::iterator it = m_aContent.insert( ContentMap::value_type( aUnqPath,UnqPathData() ) ).first; + + // Load the XPersistentPropertySetInfo and create it, if it does not exist + load( it,true ); + + PropertySet& properties = *(it->second.properties); + it1 = properties.find( newProperty ); + if( it1 != properties.end() ) + throw beans::PropertyExistException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); + + // Property does not exist + properties.insert( newProperty ); + it->second.xC->addProperty( PropertyName,Attributes,DefaultValue ); + } + notifyPropertyAdded( getPropertySetListeners( aUnqPath ), PropertyName ); +} + + + + +void SAL_CALL +shell::deassociate( const rtl::OUString& aUnqPath, + const rtl::OUString& PropertyName ) + throw( beans::UnknownPropertyException, + beans::NotRemoveableException, + uno::RuntimeException ) +{ + MyProperty oldProperty( PropertyName ); + + shell::PropertySet::iterator it1 = m_aDefaultProperties.find( oldProperty ); + if( it1 != m_aDefaultProperties.end() ) + throw beans::NotRemoveableException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); + + osl::MutexGuard aGuard( m_aMutex ); + + ContentMap::iterator it = m_aContent.insert( ContentMap::value_type( aUnqPath,UnqPathData() ) ).first; + + load( it,false ); + + PropertySet& properties = *(it->second.properties); + + it1 = properties.find( oldProperty ); + if( it1 == properties.end() ) + throw beans::UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); + + properties.erase( it1 ); + + if( it->second.xC.is() ) + it->second.xC->removeProperty( PropertyName ); + + if( properties.size() == 9 ) + { + MyProperty ContentTProperty( ContentType ); + + if( properties.find( ContentTProperty )->getState() == beans::PropertyState_DEFAULT_VALUE ) + { + it->second.xS = 0; + it->second.xC = 0; + it->second.xA = 0; + if(m_xFileRegistry.is()) + m_xFileRegistry->removePropertySet( aUnqPath ); + } + } + notifyPropertyRemoved( getPropertySetListeners( aUnqPath ), PropertyName ); +} + + + + +/*********************************************************************************/ +/* */ +/* page-Implementation */ +/* */ +/*********************************************************************************/ +// +// Given an xOutputStream, this method writes the content of the file belonging to +// URL aUnqPath into the XOutputStream +// + + +void SAL_CALL shell::page( sal_Int32 CommandId, + const rtl::OUString& aUnqPath, + const uno::Reference< io::XOutputStream >& xOutputStream ) + throw() +{ + uno::Reference< XContentProvider > xProvider( m_pProvider ); + osl::File aFile( aUnqPath ); + osl::FileBase::RC err = aFile.open( OpenFlag_Read ); + + if( err != osl::FileBase::E_None ) + { + aFile.close(); + installError( CommandId, + TASKHANDLING_OPEN_FILE_FOR_PAGING, + err ); + return; + } + + const sal_uInt64 bfz = 4*1024; + sal_Int8 BFF[bfz]; + sal_uInt64 nrc; // Retrieved number of Bytes; + + do + { + err = aFile.read( (void*) BFF,bfz,nrc ); + if( err == osl::FileBase::E_None ) + { + uno::Sequence< sal_Int8 > seq( BFF, (sal_uInt32)nrc ); + try + { + xOutputStream->writeBytes( seq ); + } + catch( io::NotConnectedException ) + { + installError( CommandId, + TASKHANDLING_NOTCONNECTED_FOR_PAGING ); + break; + } + catch( io::BufferSizeExceededException ) + { + installError( CommandId, + TASKHANDLING_BUFFERSIZEEXCEEDED_FOR_PAGING ); + break; + } + catch( io::IOException ) + { + installError( CommandId, + TASKHANDLING_IOEXCEPTION_FOR_PAGING ); + break; + } + } + else + { + installError( CommandId, + TASKHANDLING_READING_FILE_FOR_PAGING, + err ); + break; + } + } while( nrc == bfz ); + + + aFile.close(); + + + try + { + xOutputStream->closeOutput(); + } + catch( io::NotConnectedException ) + { + } + catch( io::BufferSizeExceededException ) + { + } + catch( io::IOException ) + { + } +} + + +/*********************************************************************************/ +/* */ +/* open-Implementation */ +/* */ +/*********************************************************************************/ +// +// Given a file URL aUnqPath, this methods returns a XInputStream which reads from the open file. +// + + +uno::Reference< io::XInputStream > SAL_CALL +shell::open( sal_Int32 CommandId, + const rtl::OUString& aUnqPath, + sal_Bool bLock ) + throw() +{ + XInputStream_impl* xInputStream = new XInputStream_impl( this, aUnqPath, bLock ); // from filinpstr.hxx + + sal_Int32 ErrorCode = xInputStream->CtorSuccess(); + + if( ErrorCode != TASKHANDLER_NO_ERROR ) + { + installError( CommandId, + ErrorCode, + xInputStream->getMinorError() ); + + delete xInputStream; + xInputStream = 0; + } + + return uno::Reference< io::XInputStream >( xInputStream ); +} + + + + +/*********************************************************************************/ +/* */ +/* open for read/write access-Implementation */ +/* */ +/*********************************************************************************/ +// +// Given a file URL aUnqPath, this methods returns a XStream which can be used +// to read and write from/to the file. +// + + +uno::Reference< io::XStream > SAL_CALL +shell::open_rw( sal_Int32 CommandId, + const rtl::OUString& aUnqPath, + sal_Bool bLock ) + throw() +{ + XStream_impl* xStream = new XStream_impl( this, aUnqPath, bLock ); // from filstr.hxx + + sal_Int32 ErrorCode = xStream->CtorSuccess(); + + if( ErrorCode != TASKHANDLER_NO_ERROR ) + { + installError( CommandId, + ErrorCode, + xStream->getMinorError() ); + + delete xStream; + xStream = 0; + } + return uno::Reference< io::XStream >( xStream ); +} + + + +/*********************************************************************************/ +/* */ +/* ls-Implementation */ +/* */ +/*********************************************************************************/ +// +// This method returns the result set containing the the children of the directory belonging +// to file URL aUnqPath +// + + +uno::Reference< XDynamicResultSet > SAL_CALL +shell::ls( sal_Int32 CommandId, + const rtl::OUString& aUnqPath, + const sal_Int32 OpenMode, + const uno::Sequence< beans::Property >& seq, + const uno::Sequence< NumberedSortingInfo >& seqSort ) + throw() +{ + XResultSet_impl* p = new XResultSet_impl( this,aUnqPath,OpenMode,seq,seqSort ); + + sal_Int32 ErrorCode = p->CtorSuccess(); + + if( ErrorCode != TASKHANDLER_NO_ERROR ) + { + installError( CommandId, + ErrorCode, + p->getMinorError() ); + + delete p; + p = 0; + } + + return uno::Reference< XDynamicResultSet > ( p ); +} + + + + +/*********************************************************************************/ +/* */ +/* info_c implementation */ +/* */ +/*********************************************************************************/ +// Info for commands + +uno::Reference< XCommandInfo > SAL_CALL +shell::info_c() + throw() +{ + XCommandInfo_impl* p = new XCommandInfo_impl( this ); + return uno::Reference< XCommandInfo >( p ); +} + + + + +/*********************************************************************************/ +/* */ +/* info_p-Implementation */ +/* */ +/*********************************************************************************/ +// Info for the properties + +uno::Reference< beans::XPropertySetInfo > SAL_CALL +shell::info_p( const rtl::OUString& aUnqPath ) + throw() +{ + osl::MutexGuard aGuard( m_aMutex ); + XPropertySetInfo_impl* p = new XPropertySetInfo_impl( this,aUnqPath ); + return uno::Reference< beans::XPropertySetInfo >( p ); +} + + + + +/*********************************************************************************/ +/* */ +/* setv-Implementation */ +/* */ +/*********************************************************************************/ +// +// Sets the values of the properties belonging to fileURL aUnqPath +// + + +uno::Sequence< uno::Any > SAL_CALL +shell::setv( const rtl::OUString& aUnqPath, + const uno::Sequence< beans::PropertyValue >& values ) + throw() +{ + osl::MutexGuard aGuard( m_aMutex ); + + sal_Int32 propChanged = 0; + uno::Sequence< uno::Any > ret( values.getLength() ); + uno::Sequence< beans::PropertyChangeEvent > seqChanged( values.getLength() ); + + shell::ContentMap::iterator it = m_aContent.find( aUnqPath ); + PropertySet& properties = *( it->second.properties ); + shell::PropertySet::iterator it1; + uno::Any aAny; + + for( sal_Int32 i = 0; i < values.getLength(); ++i ) + { + MyProperty toset( values[i].Name ); + it1 = properties.find( toset ); + if( it1 == properties.end() ) + { + ret[i] <<= beans::UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); + continue; + } + + aAny = it1->getValue(); + if( aAny == values[i].Value ) + continue; // nothing needs to be changed + + if( it1->getAttributes() & beans::PropertyAttribute::READONLY ) + { + ret[i] <<= lang::IllegalAccessException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); + continue; + } + + seqChanged[ propChanged ].PropertyName = values[i].Name; + seqChanged[ propChanged ].PropertyHandle = -1; + seqChanged[ propChanged ].Further = false; + seqChanged[ propChanged ].OldValue <<= aAny; + seqChanged[ propChanged++ ].NewValue = values[i].Value; + + it1->setValue( values[i].Value ); // Put the new value into the local cash + + if( ! it1->IsNative() ) + { + // Also put logical properties into storage + if( !it->second.xS.is() ) + load( it,true ); + + if( ( values[i].Name == ContentType ) && + it1->getState() == beans::PropertyState_DEFAULT_VALUE ) + { // Special logic for ContentType + // 09.07.01: Not reached anymore, because ContentType is readonly + it1->setState( beans::PropertyState_DIRECT_VALUE ); + it->second.xC->addProperty( values[i].Name, + beans::PropertyAttribute::MAYBEVOID, + values[i].Value ); + } + + try + { + it->second.xS->setPropertyValue( values[i].Name,values[i].Value ); + } + catch( const uno::Exception& e ) + { + --propChanged; // unsuccessful setting + ret[i] <<= e; + } + } + else + { + // native properties + // Setting of physical file properties + if( values[i].Name == Size ) + { + sal_Int64 newSize = 0; + if( values[i].Value >>= newSize ) + { // valid value for the size + osl::File aFile(aUnqPath); + bool err = + aFile.open(OpenFlag_Write) != osl::FileBase::E_None || + aFile.setSize(sal_uInt64(newSize)) != osl::FileBase::E_None || + aFile.close() != osl::FileBase::E_None; + + if( err ) + { + --propChanged; // unsuccessful setting + uno::Sequence< uno::Any > names( 1 ); + ret[0] <<= beans::PropertyValue( + rtl::OUString::createFromAscii("Uri"), -1, + uno::makeAny(aUnqPath), + beans::PropertyState_DIRECT_VALUE); + IOErrorCode ioError(IOErrorCode_GENERAL); + ret[i] <<= InteractiveAugmentedIOException( + rtl::OUString(), + 0, + task::InteractionClassification_ERROR, + ioError, + names ); + } + } + else + ret[i] <<= beans::IllegalTypeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); + } + else if(values[i].Name == IsReadOnly || + values[i].Name == IsHidden) + { + sal_Bool value = sal_False; + if( values[i].Value >>= value ) + { + osl::DirectoryItem aDirItem; + osl::FileBase::RC err = + osl::DirectoryItem::get(aUnqPath,aDirItem); + sal_uInt64 nAttributes(0); + if(err == osl::FileBase::E_None) + { + osl::FileStatus aFileStatus(FileStatusMask_Attributes); + err = aDirItem.getFileStatus(aFileStatus); + if(err == osl::FileBase::E_None && + aFileStatus.isValid(FileStatusMask_Attributes)) + nAttributes = aFileStatus.getAttributes(); + } + // now we have the attributes provided all went well. + if(err == osl::FileBase::E_None) { + if(values[i].Name == IsReadOnly) + { + nAttributes &= ~(Attribute_OwnWrite | + Attribute_GrpWrite | + Attribute_OthWrite | + Attribute_ReadOnly); + if(value) + nAttributes |= Attribute_ReadOnly; + else + nAttributes |= ( + Attribute_OwnWrite | + Attribute_GrpWrite | + Attribute_OthWrite); + } + else if(values[i].Name == IsHidden) + { + nAttributes &= ~(Attribute_Hidden); + if(value) + nAttributes |= Attribute_Hidden; + } + err = osl::File::setAttributes( + aUnqPath,nAttributes); + } + + if( err != osl::FileBase::E_None ) + { + --propChanged; // unsuccessful setting + uno::Sequence< uno::Any > names( 1 ); + names[0] <<= beans::PropertyValue( + rtl::OUString::createFromAscii("Uri"), -1, + uno::makeAny(aUnqPath), + beans::PropertyState_DIRECT_VALUE); + IOErrorCode ioError; + switch( err ) + { + case osl::FileBase::E_NOMEM: + // not enough memory for allocating structures <br> + ioError = IOErrorCode_OUT_OF_MEMORY; + break; + case osl::FileBase::E_INVAL: + // the format of the parameters was not valid<p> + ioError = IOErrorCode_INVALID_PARAMETER; + break; + case osl::FileBase::E_NAMETOOLONG: + // File name too long<br> + ioError = IOErrorCode_NAME_TOO_LONG; + break; + case osl::FileBase::E_NOENT: + // No such file or directory<br> + case osl::FileBase::E_NOLINK: + // Link has been severed<br> + ioError = IOErrorCode_NOT_EXISTING; + break; + case osl::FileBase::E_ROFS: + // #i4735# handle ROFS transparently + // as ACCESS_DENIED + case osl::FileBase::E_PERM: + case osl::FileBase::E_ACCES: + // permission denied<br> + ioError = IOErrorCode_ACCESS_DENIED; + break; + case osl::FileBase::E_LOOP: + // Too many symbolic links encountered<br> + case osl::FileBase::E_FAULT: + // Bad address<br> + case osl::FileBase::E_IO: + // I/O error<br> + case osl::FileBase::E_NOSYS: + // Function not implemented<br> + case osl::FileBase::E_MULTIHOP: + // Multihop attempted<br> + case osl::FileBase::E_INTR: + // function call was interrupted<p> + default: + ioError = IOErrorCode_GENERAL; + break; + } + ret[i] <<= InteractiveAugmentedIOException( + rtl::OUString(), + 0, + task::InteractionClassification_ERROR, + ioError, + names ); + } + } + else + ret[i] <<= beans::IllegalTypeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); + } + } + } // end for + + if( propChanged ) + { + seqChanged.realloc( propChanged ); + notifyPropertyChanges( getPropertyChangeNotifier( aUnqPath ),seqChanged ); + } + + return ret; +} + +/*********************************************************************************/ +/* */ +/* getv-Implementation */ +/* */ +/*********************************************************************************/ +// +// Reads the values of the properties belonging to fileURL aUnqPath; +// Returns an XRow object containing the values in the requested order. +// + + +uno::Reference< sdbc::XRow > SAL_CALL +shell::getv( sal_Int32 CommandId, + const rtl::OUString& aUnqPath, + const uno::Sequence< beans::Property >& properties ) + throw() +{ + uno::Sequence< uno::Any > seq( properties.getLength() ); + + sal_Int32 n_Mask; + getMaskFromProperties( n_Mask,properties ); + osl::FileStatus aFileStatus( n_Mask ); + + osl::DirectoryItem aDirItem; + osl::FileBase::RC nError1 = osl::DirectoryItem::get( aUnqPath,aDirItem ); + if( nError1 != osl::FileBase::E_None ) + installError(CommandId, + TASKHANDLING_OPEN_FILE_FOR_PAGING, // BEAWARE, REUSED + nError1); + + osl::FileBase::RC nError2 = aDirItem.getFileStatus( aFileStatus ); + if( nError1 == osl::FileBase::E_None && + nError2 != osl::FileBase::E_None ) + installError(CommandId, + TASKHANDLING_OPEN_FILE_FOR_PAGING, // BEAWARE, REUSED + nError2); + + { + osl::MutexGuard aGuard( m_aMutex ); + + shell::ContentMap::iterator it = m_aContent.find( aUnqPath ); + commit( it,aFileStatus ); + + shell::PropertySet::iterator it1; + PropertySet& propset = *(it->second.properties); + + for( sal_Int32 i = 0; i < seq.getLength(); ++i ) + { + MyProperty readProp( properties[i].Name ); + it1 = propset.find( readProp ); + if( it1 == propset.end() ) + seq[i] = uno::Any(); + else + seq[i] = it1->getValue(); + } + } + + XRow_impl* p = new XRow_impl( this,seq ); + return uno::Reference< sdbc::XRow >( p ); +} + + +/********************************************************************************/ +/* */ +/* transfer-commandos */ +/* */ +/********************************************************************************/ + + +/********************************************************************************/ +/* */ +/* move-implementation */ +/* */ +/********************************************************************************/ +// +// Moves the content belonging to fileURL srcUnqPath to fileURL dstUnqPath. +// + +void SAL_CALL +shell::move( sal_Int32 CommandId, + const rtl::OUString srcUnqPath, + const rtl::OUString dstUnqPathIn, + const sal_Int32 NameClash ) + throw() +{ + // --> #i88446# Method notifyContentExchanged( getContentExchangedEventListeners( srcUnqPath,dstUnqPath,!isDocument ) ); crashes if + // srcUnqPath and dstUnqPathIn are equal + if( srcUnqPath == dstUnqPathIn ) + return; + // <-- + // + osl::FileBase::RC nError; + rtl::OUString dstUnqPath( dstUnqPathIn ); + + switch( NameClash ) + { + case NameClash::KEEP: + { + nError = osl_File_move( srcUnqPath,dstUnqPath,true ); + if( nError != osl::FileBase::E_None && nError != osl::FileBase::E_EXIST ) + { + installError( CommandId, + TASKHANDLING_KEEPERROR_FOR_MOVE, + nError ); + return; + } + break; + } + case NameClash::OVERWRITE: + { + // stat to determine whether we have a symlink + rtl::OUString targetPath(dstUnqPath); + + osl::FileStatus aStatus(FileStatusMask_Type|FileStatusMask_LinkTargetURL); + osl::DirectoryItem aItem; + osl::DirectoryItem::get(dstUnqPath,aItem); + aItem.getFileStatus(aStatus); + + if( aStatus.isValid(FileStatusMask_Type) && + aStatus.isValid(FileStatusMask_LinkTargetURL) && + aStatus.getFileType() == osl::FileStatus::Link ) + targetPath = aStatus.getLinkTargetURL(); + + // Will do nothing if file does not exist. + osl::File::remove( targetPath ); + + nError = osl_File_move( srcUnqPath,targetPath ); + if( nError != osl::FileBase::E_None ) + { + installError( CommandId, + TASKHANDLING_OVERWRITE_FOR_MOVE, + nError ); + return; + } + break; + } + case NameClash::RENAME: + { + rtl::OUString newDstUnqPath; + nError = osl_File_move( srcUnqPath,dstUnqPath,true ); + if( nError == osl::FileBase::E_EXIST ) + { + // "invent" a new valid title. + + sal_Int32 nPos = -1; + sal_Int32 nLastDot = dstUnqPath.lastIndexOf( '.' ); + sal_Int32 nLastSlash = dstUnqPath.lastIndexOf( '/' ); + if( ( nLastSlash < nLastDot ) // dot is part of last(!) path segment + && ( nLastSlash != ( nLastDot - 1 ) ) ) // file name does not start with a dot + nPos = nLastDot; + else + nPos = dstUnqPath.getLength(); + + sal_Int32 nTry = 0; + + do + { + newDstUnqPath = dstUnqPath; + + rtl::OUString aPostFix( rtl::OUString::createFromAscii( "_" ) ); + aPostFix += rtl::OUString::valueOf( ++nTry ); + + newDstUnqPath = newDstUnqPath.replaceAt( nPos, 0, aPostFix ); + + nError = osl_File_move( srcUnqPath,newDstUnqPath,true ); + } + while( ( nError == osl::FileBase::E_EXIST ) && ( nTry < 10000 ) ); + } + + if( nError == osl::FileBase::E_EXIST ) + { + installError( CommandId, + TASKHANDLING_RENAME_FOR_MOVE ); + return; + } + else if( nError != osl::FileBase::E_None ) + { + installError( CommandId, + TASKHANDLING_RENAMEMOVE_FOR_MOVE, + nError ); + return; + } + else + dstUnqPath = newDstUnqPath; + + break; + } + case NameClash::ERROR: + { + nError = osl_File_move( srcUnqPath,dstUnqPath,true ); + if( nError == osl::FileBase::E_EXIST ) + { + installError( CommandId, + TASKHANDLING_NAMECLASH_FOR_MOVE ); + return; + } + else if( nError != osl::FileBase::E_None ) + { + installError( CommandId, + TASKHANDLING_NAMECLASHMOVE_FOR_MOVE, + nError ); + return; + } + break; + } + case NameClash::ASK: + default: + { + nError = osl_File_move( srcUnqPath,dstUnqPath,true ); + if( nError == osl::FileBase::E_EXIST ) + { + installError( CommandId, + TASKHANDLING_NAMECLASHSUPPORT_FOR_MOVE, + NameClash::ASK); + return; + } + } + break; + } + + // Determine, whether we have moved a file or a folder + osl::DirectoryItem aItem; + nError = osl::DirectoryItem::get( dstUnqPath,aItem ); + if( nError != osl::FileBase::E_None ) + { + installError( CommandId, + TASKHANDLING_TRANSFER_BY_MOVE_SOURCE, + nError ); + return; + } + osl::FileStatus aStatus( FileStatusMask_Type ); + nError = aItem.getFileStatus( aStatus ); + if( nError != osl::FileBase::E_None || ! aStatus.isValid( FileStatusMask_Type ) ) + { + installError( CommandId, + TASKHANDLING_TRANSFER_BY_MOVE_SOURCESTAT, + nError ); + return; + } + sal_Bool isDocument = ( aStatus.getFileType() == osl::FileStatus::Regular ); + + + copyPersistentSet( srcUnqPath,dstUnqPath,!isDocument ); + + rtl::OUString aDstParent = getParentName( dstUnqPath ); + rtl::OUString aDstTitle = getTitle( dstUnqPath ); + + rtl::OUString aSrcParent = getParentName( srcUnqPath ); + rtl::OUString aSrcTitle = getTitle( srcUnqPath ); + + notifyInsert( getContentEventListeners( aDstParent ),dstUnqPath ); + if( aDstParent != aSrcParent ) + notifyContentRemoved( getContentEventListeners( aSrcParent ),srcUnqPath ); + + notifyContentExchanged( getContentExchangedEventListeners( srcUnqPath,dstUnqPath,!isDocument ) ); + erasePersistentSet( srcUnqPath,!isDocument ); +} + + + +/********************************************************************************/ +/* */ +/* copy-implementation */ +/* */ +/********************************************************************************/ +// +// Copies the content belonging to fileURL srcUnqPath to fileURL dstUnqPath ( files and directories ) +// + +namespace { + +bool getType( + TaskManager & task, sal_Int32 id, rtl::OUString const & fileUrl, + osl::DirectoryItem * item, osl::FileStatus::Type * type) +{ + OSL_ASSERT(item != 0 && type != 0); + osl::FileBase::RC err = osl::DirectoryItem::get(fileUrl, *item); + if (err != osl::FileBase::E_None) { + task.installError(id, TASKHANDLING_TRANSFER_BY_COPY_SOURCE, err); + return false; + } + osl::FileStatus stat(FileStatusMask_Type); + err = item->getFileStatus(stat); + if (err != osl::FileBase::E_None) { + task.installError(id, TASKHANDLING_TRANSFER_BY_COPY_SOURCESTAT, err); + return false; + } + *type = stat.getFileType(); + return true; +} + +} + +void SAL_CALL +shell::copy( + sal_Int32 CommandId, + const rtl::OUString srcUnqPath, + const rtl::OUString dstUnqPathIn, + sal_Int32 NameClash ) + throw() +{ + osl::FileBase::RC nError; + rtl::OUString dstUnqPath( dstUnqPathIn ); + + // Resolve symbolic links within the source path. If srcUnqPath denotes a + // symbolic link (targeting either a file or a folder), the contents of the + // target is copied (recursively, in the case of a folder). However, if + // recursively copying the contents of a folder causes a symbolic link to be + // copied, the symbolic link itself is copied. + osl::DirectoryItem item; + osl::FileStatus::Type type; + if (!getType(*this, CommandId, srcUnqPath, &item, &type)) { + return; + } + rtl::OUString rslvdSrcUnqPath; + if (type == osl::FileStatus::Link) { + osl::FileStatus stat(FileStatusMask_LinkTargetURL); + nError = item.getFileStatus(stat); + if (nError != osl::FileBase::E_None) { + installError( + CommandId, TASKHANDLING_TRANSFER_BY_COPY_SOURCESTAT, nError); + return; + } + rslvdSrcUnqPath = stat.getLinkTargetURL(); + if (!getType(*this, CommandId, srcUnqPath, &item, &type)) { + return; + } + } else { + rslvdSrcUnqPath = srcUnqPath; + } + + sal_Bool isDocument + = type != osl::FileStatus::Directory && type != osl::FileStatus::Volume; + sal_Int32 IsWhat = isDocument ? -1 : 1; + + switch( NameClash ) + { + case NameClash::KEEP: + { + nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,true ); + if( nError != osl::FileBase::E_None && nError != osl::FileBase::E_EXIST ) + { + installError( CommandId, + TASKHANDLING_KEEPERROR_FOR_COPY, + nError ); + return; + } + break; + } + case NameClash::OVERWRITE: + { + // remove (..., MustExist = sal_False). + remove( CommandId, dstUnqPath, IsWhat, sal_False ); + + // copy. + nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,false ); + if( nError != osl::FileBase::E_None ) + { + installError( CommandId, + TASKHANDLING_OVERWRITE_FOR_COPY, + nError ); + return; + } + break; + } + case NameClash::RENAME: + { + rtl::OUString newDstUnqPath; + nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,true ); + + if( nError == osl::FileBase::E_EXIST ) + { + // "invent" a new valid title. + + sal_Int32 nPos = -1; + sal_Int32 nLastDot = dstUnqPath.lastIndexOf( '.' ); + sal_Int32 nLastSlash = dstUnqPath.lastIndexOf( '/' ); + if ( ( nLastSlash < nLastDot ) // dot is part of last(!) path segment + && ( nLastSlash != ( nLastDot - 1 ) ) ) // file name does not start with a dot + nPos = nLastDot; + else + nPos = dstUnqPath.getLength(); + + sal_Int32 nTry = 0; + + do + { + newDstUnqPath = dstUnqPath; + + rtl::OUString aPostFix( rtl::OUString::createFromAscii( "_" ) ); + aPostFix += rtl::OUString::valueOf( ++nTry ); + + newDstUnqPath = newDstUnqPath.replaceAt( nPos, 0, aPostFix ); + + nError = copy_recursive( rslvdSrcUnqPath,newDstUnqPath,IsWhat,true ); + } + while( ( nError == osl::FileBase::E_EXIST ) && ( nTry < 10000 ) ); + } + + if( nError == osl::FileBase::E_EXIST ) + { + installError( CommandId, + TASKHANDLING_RENAME_FOR_COPY ); + return; + } + else if( nError != osl::FileBase::E_None ) + { + installError( CommandId, + TASKHANDLING_RENAMEMOVE_FOR_COPY, + nError ); + return; + } + else + dstUnqPath = newDstUnqPath; + + break; + } + case NameClash::ERROR: + { + nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,true ); + + if( nError == osl::FileBase::E_EXIST ) + { + installError( CommandId, + TASKHANDLING_NAMECLASH_FOR_COPY ); + return; + } + else if( nError != osl::FileBase::E_None ) + { + installError( CommandId, + TASKHANDLING_NAMECLASHMOVE_FOR_COPY, + nError ); + return; + } + break; + } + case NameClash::ASK: + default: + { + nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,true ); + + if( nError == osl::FileBase::E_EXIST ) + { + installError( CommandId, + TASKHANDLING_NAMECLASHSUPPORT_FOR_COPY, + NameClash); + return; + } + break; + } + } + + copyPersistentSet( srcUnqPath,dstUnqPath, !isDocument ); + notifyInsert( getContentEventListeners( getParentName( dstUnqPath ) ),dstUnqPath ); +} + + + +/********************************************************************************/ +/* */ +/* remove-implementation */ +/* */ +/********************************************************************************/ +// +// Deletes the content belonging to fileURL aUnqPath( recursively in case of directory ) +// Return: success of operation +// + + +sal_Bool SAL_CALL +shell::remove( sal_Int32 CommandId, + const rtl::OUString& aUnqPath, + sal_Int32 IsWhat, + sal_Bool MustExist ) + throw() +{ + sal_Int32 nMask = FileStatusMask_Type | FileStatusMask_FileURL; + + osl::DirectoryItem aItem; + osl::FileStatus aStatus( nMask ); + osl::FileBase::RC nError; + + if( IsWhat == 0 ) // Determine whether we are removing a directory or a file + { + nError = osl::DirectoryItem::get( aUnqPath, aItem ); + if( nError != osl::FileBase::E_None ) + { + if (MustExist) + { + installError( CommandId, + TASKHANDLING_NOSUCHFILEORDIR_FOR_REMOVE, + nError ); + } + return (!MustExist); + } + + nError = aItem.getFileStatus( aStatus ); + if( nError != osl::FileBase::E_None || ! aStatus.isValid( nMask ) ) + { + installError( CommandId, + TASKHANDLING_VALIDFILESTATUS_FOR_REMOVE, + nError != osl::FileBase::E_None ? nError : TASKHANDLER_NO_ERROR ); + return sal_False; + } + + if( aStatus.getFileType() == osl::FileStatus::Regular || + aStatus.getFileType() == osl::FileStatus::Link ) + IsWhat = -1; // RemoveFile + else if( aStatus.getFileType() == osl::FileStatus::Directory || + aStatus.getFileType() == osl::FileStatus::Volume ) + IsWhat = +1; // RemoveDirectory + } + + + if( IsWhat == -1 ) // Removing a file + { + nError = osl::File::remove( aUnqPath ); + if( nError != osl::FileBase::E_None ) + { + if (MustExist) + { + installError( CommandId, + TASKHANDLING_DELETEFILE_FOR_REMOVE, + nError ); + } + return (!MustExist); + } + else + { + notifyContentDeleted( getContentDeletedEventListeners(aUnqPath) ); + erasePersistentSet( aUnqPath ); // Removes from XPersistentPropertySet + } + } + else if( IsWhat == +1 ) // Removing a directory + { + osl::Directory aDirectory( aUnqPath ); + + nError = aDirectory.open(); + if( nError != osl::FileBase::E_None ) + { + if (MustExist) + { + installError( CommandId, + TASKHANDLING_OPENDIRECTORY_FOR_REMOVE, + nError ); + } + return (!MustExist); + } + + sal_Bool whileSuccess = sal_True; + sal_Int32 recurse = 0; + rtl::OUString name; + + nError = aDirectory.getNextItem( aItem ); + while( nError == osl::FileBase::E_None ) + { + nError = aItem.getFileStatus( aStatus ); + if( nError != osl::FileBase::E_None || ! aStatus.isValid( nMask ) ) + { + installError( CommandId, + TASKHANDLING_VALIDFILESTATUSWHILE_FOR_REMOVE, + nError != osl::FileBase::E_None ? nError : TASKHANDLER_NO_ERROR ); + whileSuccess = sal_False; + break; + } + + if( aStatus.getFileType() == osl::FileStatus::Regular || + aStatus.getFileType() == osl::FileStatus::Link ) + recurse = -1; + else if( aStatus.getFileType() == osl::FileStatus::Directory || + aStatus.getFileType() == osl::FileStatus::Volume ) + recurse = +1; + + name = aStatus.getFileURL(); + whileSuccess = remove( + CommandId, name, recurse, MustExist ); + if( !whileSuccess ) + break; + + nError = aDirectory.getNextItem( aItem ); + } + + aDirectory.close(); + + if( ! whileSuccess ) + return sal_False; // error code is installed + + if( nError != osl::FileBase::E_NOENT ) + { + installError( CommandId, + TASKHANDLING_DIRECTORYEXHAUSTED_FOR_REMOVE, + nError ); + return sal_False; + } + + nError = osl::Directory::remove( aUnqPath ); + if( nError != osl::FileBase::E_None ) + { + if (MustExist) + { + installError( CommandId, + TASKHANDLING_DELETEDIRECTORY_FOR_REMOVE, + nError ); + } + return (!MustExist); + } + else + { + notifyContentDeleted( getContentDeletedEventListeners(aUnqPath) ); + erasePersistentSet( aUnqPath ); + } + } + else // Don't know what to remove + { + installError( CommandId, + TASKHANDLING_FILETYPE_FOR_REMOVE ); + return sal_False; + } + + return sal_True; +} + + +/********************************************************************************/ +/* */ +/* mkdir-implementation */ +/* */ +/********************************************************************************/ +// +// Creates new directory with given URL, recursively if necessary +// Return:: success of operation +// + +sal_Bool SAL_CALL +shell::mkdir( sal_Int32 CommandId, + const rtl::OUString& rUnqPath, + sal_Bool OverWrite ) + throw() +{ + rtl::OUString aUnqPath; + + // remove trailing slash + if ( rUnqPath[ rUnqPath.getLength() - 1 ] == sal_Unicode( '/' ) ) + aUnqPath = rUnqPath.copy( 0, rUnqPath.getLength() - 1 ); + else + aUnqPath = rUnqPath; + + osl::FileBase::RC nError = osl::Directory::create( aUnqPath ); + + switch ( nError ) + { + case osl::FileBase::E_EXIST: // Directory cannot be overwritten + { + if( !OverWrite ) + { + installError( CommandId, + TASKHANDLING_FOLDER_EXISTS_MKDIR ); + return sal_False; + } + else + return sal_True; + } + case osl::FileBase::E_INVAL: + { + installError(CommandId, + TASKHANDLING_INVALID_NAME_MKDIR); + return sal_False; + } + case osl::FileBase::E_None: + { + rtl::OUString aPrtPath = getParentName( aUnqPath ); + notifyInsert( getContentEventListeners( aPrtPath ),aUnqPath ); + return sal_True; + } + default: + return ensuredir( + CommandId, + aUnqPath, + TASKHANDLING_CREATEDIRECTORY_MKDIR ); + } +} + + +/********************************************************************************/ +/* */ +/* mkfil-implementation */ +/* */ +/********************************************************************************/ +// +// Creates new file with given URL. +// The content of aInputStream becomes the content of the file +// Return:: success of operation +// + +sal_Bool SAL_CALL +shell::mkfil( sal_Int32 CommandId, + const rtl::OUString& aUnqPath, + sal_Bool Overwrite, + const uno::Reference< io::XInputStream >& aInputStream ) + throw() +{ + // return value unimportant + sal_Bool bSuccess = write( CommandId, + aUnqPath, + Overwrite, + aInputStream ); + if ( bSuccess ) + { + rtl::OUString aPrtPath = getParentName( aUnqPath ); + notifyInsert( getContentEventListeners( aPrtPath ),aUnqPath ); + } + return bSuccess; +} + + +/********************************************************************************/ +/* */ +/* write-implementation */ +/* */ +/********************************************************************************/ +// +// writes to the file with given URL. +// The content of aInputStream becomes the content of the file +// Return:: success of operation +// + +sal_Bool SAL_CALL +shell::write( sal_Int32 CommandId, + const rtl::OUString& aUnqPath, + sal_Bool OverWrite, + const uno::Reference< io::XInputStream >& aInputStream ) + throw() +{ + if( ! aInputStream.is() ) + { + installError( CommandId, + TASKHANDLING_INPUTSTREAM_FOR_WRITE ); + return sal_False; + } + + // Create parent path, if necessary. + if ( ! ensuredir( CommandId, + getParentName( aUnqPath ), + TASKHANDLING_ENSUREDIR_FOR_WRITE ) ) + return sal_False; + + osl::FileBase::RC err; + osl::File aFile( aUnqPath ); + + if( OverWrite ) + { + err = aFile.open( OpenFlag_Write | OpenFlag_Create ); + + if( err != osl::FileBase::E_None ) + { + aFile.close(); + err = aFile.open( OpenFlag_Write ); + } + + if( err != osl::FileBase::E_None ) + { + installError( CommandId, + TASKHANDLING_NO_OPEN_FILE_FOR_OVERWRITE, + err ); + return sal_False; + } + } + else + { + err = aFile.open( OpenFlag_Read | OpenFlag_NoLock ); + if( err == osl::FileBase::E_None ) // The file exists and shall not be overwritten + { + installError( CommandId, + TASKHANDLING_NOREPLACE_FOR_WRITE, // Now an exception + err ); + + aFile.close(); + return sal_False; + } + + // as a temporary solution the creation does not lock the file at all + // in future it should be possible to create the file without lock explicitly + err = aFile.open( OpenFlag_Write | OpenFlag_Create | OpenFlag_NoLock ); + + if( err != osl::FileBase::E_None ) + { + aFile.close(); + installError( CommandId, + TASKHANDLING_NO_OPEN_FILE_FOR_WRITE, + err ); + return sal_False; + } + } + + sal_Bool bSuccess = sal_True; + + sal_uInt64 nTotalNumberOfBytes = 0; + sal_uInt64 nWrittenBytes; + sal_Int32 nReadBytes = 0, nRequestedBytes = 32768 /*32k*/; + uno::Sequence< sal_Int8 > seq( nRequestedBytes ); + + do + { + try + { + nReadBytes = aInputStream->readBytes( seq, + nRequestedBytes ); + } + catch( const io::NotConnectedException& ) + { + installError( CommandId, + TASKHANDLING_NOTCONNECTED_FOR_WRITE ); + bSuccess = sal_False; + break; + } + catch( const io::BufferSizeExceededException& ) + { + installError( CommandId, + TASKHANDLING_BUFFERSIZEEXCEEDED_FOR_WRITE ); + bSuccess = sal_False; + break; + } + catch( const io::IOException& ) + { + installError( CommandId, + TASKHANDLING_IOEXCEPTION_FOR_WRITE ); + bSuccess = sal_False; + break; + } + + if( nReadBytes ) + { + const sal_Int8* p = seq.getConstArray(); + + err = aFile.write( ((void*)(p)), + sal_uInt64( nReadBytes ), + nWrittenBytes ); + + if( err != osl::FileBase::E_None ) + { + installError( CommandId, + TASKHANDLING_FILEIOERROR_FOR_WRITE, + err ); + bSuccess = sal_False; + break; + } + else if( nWrittenBytes != sal_uInt64( nReadBytes ) ) + { + installError( CommandId, + TASKHANDLING_FILEIOERROR_FOR_NO_SPACE ); + bSuccess = sal_False; + break; + } + + nTotalNumberOfBytes += nWrittenBytes; + } + } while( nReadBytes == nRequestedBytes ); + + err = aFile.setSize( nTotalNumberOfBytes ); + if( err != osl::FileBase::E_None ) + { + installError( CommandId, + TASKHANDLING_FILESIZE_FOR_WRITE, + err ); + bSuccess = sal_False; + } + + err = aFile.close(); + if( err != osl::FileBase::E_None ) + { + installError( CommandId, + TASKHANDLING_FILEIOERROR_FOR_WRITE, + err ); + bSuccess = sal_False; + } + + return bSuccess; +} + + + +/*********************************************************************************/ +/* */ +/* insertDefaultProperties-Implementation */ +/* */ +/*********************************************************************************/ + + +void SAL_CALL shell::insertDefaultProperties( const rtl::OUString& aUnqPath ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + ContentMap::iterator it = + m_aContent.insert( ContentMap::value_type( aUnqPath,UnqPathData() ) ).first; + + load( it,false ); + + MyProperty ContentTProperty( ContentType ); + + PropertySet& properties = *(it->second.properties); + sal_Bool ContentNotDefau = properties.find( ContentTProperty ) != properties.end(); + + shell::PropertySet::iterator it1 = m_aDefaultProperties.begin(); + while( it1 != m_aDefaultProperties.end() ) + { + if( ContentNotDefau && it1->getPropertyName() == ContentType ) + { + // No insertion + } + else + properties.insert( *it1 ); + ++it1; + } +} + + + + +/******************************************************************************/ +/* */ +/* mapping of file urls */ +/* to uncpath and vice versa */ +/* */ +/******************************************************************************/ + + +sal_Bool SAL_CALL shell::getUnqFromUrl( const rtl::OUString& Url,rtl::OUString& Unq ) +{ + if( 0 == Url.compareToAscii( "file:///" ) || + 0 == Url.compareToAscii( "file://localhost/" ) || + 0 == Url.compareToAscii( "file://127.0.0.1/" ) ) + { + Unq = rtl::OUString::createFromAscii( "file:///" ); + return false; + } + + sal_Bool err = osl::FileBase::E_None != osl::FileBase::getSystemPathFromFileURL( Url,Unq ); + + Unq = Url; + + sal_Int32 l = Unq.getLength()-1; + if( ! err && Unq.getStr()[ l ] == '/' && + Unq.indexOf( '/', RTL_CONSTASCII_LENGTH("//") ) < l ) + Unq = Unq.copy(0, Unq.getLength() - 1); + + return err; +} + + + +sal_Bool SAL_CALL shell::getUrlFromUnq( const rtl::OUString& Unq,rtl::OUString& Url ) +{ + sal_Bool err = osl::FileBase::E_None != osl::FileBase::getSystemPathFromFileURL( Unq,Url ); + + Url = Unq; + + return err; +} + + + +// Helper function for public copy + +osl::FileBase::RC SAL_CALL +shell::copy_recursive( const rtl::OUString& srcUnqPath, + const rtl::OUString& dstUnqPath, + sal_Int32 TypeToCopy, + sal_Bool testExistBeforeCopy ) + throw() +{ + osl::FileBase::RC err = osl::FileBase::E_None; + + if( TypeToCopy == -1 ) // Document + { + err = osl_File_copy( srcUnqPath,dstUnqPath,testExistBeforeCopy ); + } + else if( TypeToCopy == +1 ) // Folder + { + osl::Directory aDir( srcUnqPath ); + aDir.open(); + + err = osl::Directory::create( dstUnqPath ); + osl::FileBase::RC next = err; + if( err == osl::FileBase::E_None ) + { + sal_Int32 n_Mask = FileStatusMask_FileURL | FileStatusMask_FileName | FileStatusMask_Type; + + osl::DirectoryItem aDirItem; + + while( err == osl::FileBase::E_None && ( next = aDir.getNextItem( aDirItem ) ) == osl::FileBase::E_None ) + { + sal_Bool IsDoc = false; + osl::FileStatus aFileStatus( n_Mask ); + aDirItem.getFileStatus( aFileStatus ); + if( aFileStatus.isValid( FileStatusMask_Type ) ) + IsDoc = aFileStatus.getFileType() == osl::FileStatus::Regular; + + // Getting the information for the next recursive copy + sal_Int32 newTypeToCopy = IsDoc ? -1 : +1; + + rtl::OUString newSrcUnqPath; + if( aFileStatus.isValid( FileStatusMask_FileURL ) ) + newSrcUnqPath = aFileStatus.getFileURL(); + + rtl::OUString newDstUnqPath = dstUnqPath; + rtl::OUString tit; + if( aFileStatus.isValid( FileStatusMask_FileName ) ) + tit = rtl::Uri::encode( aFileStatus.getFileName(), + rtl_UriCharClassPchar, + rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8 ); + + if( newDstUnqPath.lastIndexOf( sal_Unicode('/') ) != newDstUnqPath.getLength()-1 ) + newDstUnqPath += rtl::OUString::createFromAscii( "/" ); + + newDstUnqPath += tit; + + if ( newSrcUnqPath != dstUnqPath ) + err = copy_recursive( newSrcUnqPath,newDstUnqPath,newTypeToCopy,false ); + } + + if( err == osl::FileBase::E_None && next != osl::FileBase::E_NOENT ) + err = next; + } + aDir.close(); + } + + return err; +} + + + +// Helper function for mkfil,mkdir and write +// Creates whole path +// returns success of the operation + + +sal_Bool SAL_CALL shell::ensuredir( sal_Int32 CommandId, + const rtl::OUString& rUnqPath, + sal_Int32 errorCode ) + throw() +{ + rtl::OUString aPath; + + if ( rUnqPath.getLength() < 1 ) + return sal_False; + + if ( rUnqPath[ rUnqPath.getLength() - 1 ] == sal_Unicode( '/' ) ) + aPath = rUnqPath.copy( 0, rUnqPath.getLength() - 1 ); + else + aPath = rUnqPath; + + + // HACK: create directory on a mount point with nobrowse option + // returns ENOSYS in any case !! + osl::Directory aDirectory( aPath ); + osl::FileBase::RC nError = aDirectory.open(); + aDirectory.close(); + + if( nError == osl::File::E_None ) + return sal_True; + + nError = osl::Directory::create( aPath ); + + if( nError == osl::File::E_None ) + notifyInsert( getContentEventListeners( getParentName( aPath ) ),aPath ); + + sal_Bool bSuccess = ( nError == osl::File::E_None || nError == osl::FileBase::E_EXIST ); + + if( ! bSuccess ) + { + rtl::OUString aParentDir = getParentName( aPath ); + + if ( aParentDir != aPath ) + { // Create first the parent directory + bSuccess = ensuredir( CommandId, + getParentName( aPath ), + errorCode ); + + // After parent directory structure exists try it one's more + + if ( bSuccess ) + { // Parent directory exists, retry creation of directory + nError = osl::Directory::create( aPath ); + + if( nError == osl::File::E_None ) + notifyInsert( getContentEventListeners( getParentName( aPath ) ),aPath ); + + bSuccess =( nError == osl::File::E_None || nError == osl::FileBase::E_EXIST ); + } + } + } + + if( ! bSuccess ) + installError( CommandId, + errorCode, + nError ); + + return bSuccess; +} + + + + +// +// Given a sequence of properties seq, this method determines the mask +// used to instantiate a osl::FileStatus, so that a call to +// osl::DirectoryItem::getFileStatus fills the required fields. +// + + +void SAL_CALL +shell::getMaskFromProperties( + sal_Int32& n_Mask, + const uno::Sequence< beans::Property >& seq ) +{ + n_Mask = 0; + for(sal_Int32 j = 0; j < seq.getLength(); ++j) { + if(seq[j].Name == Title) + n_Mask |= FileStatusMask_FileName; + else if(seq[j].Name == CasePreservingURL) + n_Mask |= FileStatusMask_FileURL; + else if(seq[j].Name == IsDocument || + seq[j].Name == IsFolder || + seq[j].Name == IsVolume || + seq[j].Name == IsRemoveable || + seq[j].Name == IsRemote || + seq[j].Name == IsCompactDisc || + seq[j].Name == IsFloppy || + seq[j].Name == ContentType) + n_Mask |= (FileStatusMask_Type | FileStatusMask_LinkTargetURL); + else if(seq[j].Name == Size) + n_Mask |= (FileStatusMask_FileSize | + FileStatusMask_Type | + FileStatusMask_LinkTargetURL); + else if(seq[j].Name == IsHidden || + seq[j].Name == IsReadOnly) + n_Mask |= FileStatusMask_Attributes; + else if(seq[j].Name == DateModified) + n_Mask |= FileStatusMask_ModifyTime; +// n_Mask = FileStatusMask_FileURL; +// n_Mask |= FileStatusMask_LinkTargetURL; +// n_Mask |= FileStatusMask_FileName; +// n_Mask |= FileStatusMask_Type; +// n_Mask |= FileStatusMask_ModifyTime; +// n_Mask |= FileStatusMask_FileSize; +// n_Mask |= FileStatusMask_Attributes; + } +} + + + +/*********************************************************************************/ +/* */ +/* load-Implementation */ +/* */ +/*********************************************************************************/ +// +// Load the properties from configuration, if create == true create them. +// The Properties are stored under the url belonging to it->first. +// + +void SAL_CALL +shell::load( const ContentMap::iterator& it, sal_Bool create ) +{ + if( ! it->second.properties ) + it->second.properties = new PropertySet; + + if( ( ! it->second.xS.is() || + ! it->second.xC.is() || + ! it->second.xA.is() ) + && m_xFileRegistry.is() ) + { + + uno::Reference< ucb::XPersistentPropertySet > xS = m_xFileRegistry->openPropertySet( it->first,create ); + if( xS.is() ) + { + uno::Reference< beans::XPropertyContainer > xC( xS,uno::UNO_QUERY ); + uno::Reference< beans::XPropertyAccess > xA( xS,uno::UNO_QUERY ); + + it->second.xS = xS; + it->second.xC = xC; + it->second.xA = xA; + + // Now put in all values in the storage in the local hash; + + PropertySet& properties = *(it->second.properties); + uno::Sequence< beans::Property > seq = xS->getPropertySetInfo()->getProperties(); + + for( sal_Int32 i = 0; i < seq.getLength(); ++i ) + { + MyProperty readProp( false, + seq[i].Name, + seq[i].Handle, + seq[i].Type, + xS->getPropertyValue( seq[i].Name ), + beans::PropertyState_DIRECT_VALUE, + seq[i].Attributes ); + if( properties.find( readProp ) == properties.end() ) + properties.insert( readProp ); + } + } + else if( create ) + { + // Catastrophic error + } + } +} + + + + +/*********************************************************************************/ +/* */ +/* commit-Implementation */ +/* */ +/*********************************************************************************/ +// Commit inserts the determined properties in the filestatus object into +// the internal map, so that is possible to determine on a subsequent +// setting of file properties which properties have changed without filestat + + +void SAL_CALL +shell::commit( const shell::ContentMap::iterator& it, + const osl::FileStatus& aFileStatus ) +{ + uno::Any aAny; + uno::Any emptyAny; + shell::PropertySet::iterator it1; + + if( it->second.properties == 0 ) + { + rtl::OUString aPath = it->first; + insertDefaultProperties( aPath ); + } + + PropertySet& properties = *( it->second.properties ); + + it1 = properties.find( MyProperty( Title ) ); + if( it1 != properties.end() ) + { + if( aFileStatus.isValid( FileStatusMask_FileName ) ) + { + aAny <<= aFileStatus.getFileName(); + it1->setValue( aAny ); + } + } + + it1 = properties.find( MyProperty( CasePreservingURL ) ); + if( it1 != properties.end() ) + { + if( aFileStatus.isValid( FileStatusMask_FileURL ) ) + { + aAny <<= aFileStatus.getFileURL(); + it1->setValue( aAny ); + } + } + + + sal_Bool isDirectory,isFile,isVolume,isRemoveable,isRemote,isFloppy,isCompactDisc; + + sal_Int64 dirSize = 0; + + if( aFileStatus.isValid( FileStatusMask_FileSize ) ) + dirSize = aFileStatus.getFileSize(); + + if( aFileStatus.isValid( FileStatusMask_Type ) ) + { + if( osl::FileStatus::Link == aFileStatus.getFileType() && + aFileStatus.isValid( FileStatusMask_LinkTargetURL ) ) + { + osl::DirectoryItem aDirItem; + osl::FileStatus aFileStatus2( FileStatusMask_Type ); + if( osl::FileBase::E_None == osl::DirectoryItem::get( aFileStatus.getLinkTargetURL(),aDirItem ) && + osl::FileBase::E_None == aDirItem.getFileStatus( aFileStatus2 ) && + aFileStatus2.isValid( FileStatusMask_Type ) ) + { + isVolume = osl::FileStatus::Volume == aFileStatus2.getFileType(); + isDirectory = + osl::FileStatus::Volume == aFileStatus2.getFileType() || + osl::FileStatus::Directory == aFileStatus2.getFileType(); + isFile = + osl::FileStatus::Regular == aFileStatus2.getFileType(); + + if( aFileStatus2.isValid( FileStatusMask_FileSize ) ) + dirSize = aFileStatus2.getFileSize(); + } + else + { + // extremly ugly, but otherwise default construction + // of aDirItem and aFileStatus2 + // before the preciding if + isVolume = osl::FileStatus::Volume == aFileStatus.getFileType(); + isDirectory = + osl::FileStatus::Volume == aFileStatus.getFileType() || + osl::FileStatus::Directory == aFileStatus.getFileType(); + isFile = + osl::FileStatus::Regular == aFileStatus.getFileType(); + } + } + else + { + isVolume = osl::FileStatus::Volume == aFileStatus.getFileType(); + isDirectory = + osl::FileStatus::Volume == aFileStatus.getFileType() || + osl::FileStatus::Directory == aFileStatus.getFileType(); + isFile = + osl::FileStatus::Regular == aFileStatus.getFileType(); + } + + it1 = properties.find( MyProperty( IsVolume ) ); + if( it1 != properties.end() ) + it1->setValue( uno::makeAny( isVolume ) ); + + it1 = properties.find( MyProperty( IsFolder ) ); + if( it1 != properties.end() ) + it1->setValue( uno::makeAny( isDirectory ) ); + + it1 = properties.find( MyProperty( IsDocument ) ); + if( it1 != properties.end() ) + it1->setValue( uno::makeAny( isFile ) ); + + osl::VolumeInfo aVolumeInfo( VolumeInfoMask_Attributes ); + if( isVolume && + osl::FileBase::E_None == osl::Directory::getVolumeInfo( it->first,aVolumeInfo ) && + aVolumeInfo.isValid( VolumeInfoMask_Attributes ) ) + { + // Retrieve the flags; + isRemote = aVolumeInfo.getRemoteFlag(); + isRemoveable = aVolumeInfo.getRemoveableFlag(); + isCompactDisc = aVolumeInfo.getCompactDiscFlag(); + isFloppy = aVolumeInfo.getFloppyDiskFlag(); + + it1 = properties.find( MyProperty( IsRemote ) ); + if( it1 != properties.end() ) + it1->setValue( uno::makeAny( isRemote ) ); + + it1 = properties.find( MyProperty( IsRemoveable ) ); + if( it1 != properties.end() ) + it1->setValue( uno::makeAny( isRemoveable ) ); + + it1 = properties.find( MyProperty( IsCompactDisc ) ); + if( it1 != properties.end() ) + it1->setValue( uno::makeAny( isCompactDisc ) ); + + it1 = properties.find( MyProperty( IsFloppy ) ); + if( it1 != properties.end() ) + it1->setValue( uno::makeAny( isFloppy ) ); + } + else + { + sal_Bool dummy = false; + aAny <<= dummy; + it1 = properties.find( MyProperty( IsRemote ) ); + if( it1 != properties.end() ) + it1->setValue( aAny ); + + it1 = properties.find( MyProperty( IsRemoveable ) ); + if( it1 != properties.end() ) + it1->setValue( aAny ); + + it1 = properties.find( MyProperty( IsCompactDisc ) ); + if( it1 != properties.end() ) + it1->setValue( aAny ); + + it1 = properties.find( MyProperty( IsFloppy ) ); + if( it1 != properties.end() ) + it1->setValue( aAny ); + } + } + else + { + isDirectory = sal_False; + } + + it1 = properties.find( MyProperty( Size ) ); + if( it1 != properties.end() ) + it1->setValue( uno::makeAny( dirSize ) ); + + it1 = properties.find( MyProperty( IsReadOnly ) ); + if( it1 != properties.end() ) + { + if( aFileStatus.isValid( FileStatusMask_Attributes ) ) + { + sal_uInt64 Attr = aFileStatus.getAttributes(); + sal_Bool readonly = ( Attr & Attribute_ReadOnly ) != 0; + it1->setValue( uno::makeAny( readonly ) ); + } + } + + it1 = properties.find( MyProperty( IsHidden ) ); + if( it1 != properties.end() ) + { + if( aFileStatus.isValid( FileStatusMask_Attributes ) ) + { + sal_uInt64 Attr = aFileStatus.getAttributes(); + sal_Bool ishidden = ( Attr & Attribute_Hidden ) != 0; + it1->setValue( uno::makeAny( ishidden ) ); + } + } + + it1 = properties.find( MyProperty( DateModified ) ); + if( it1 != properties.end() ) + { + if( aFileStatus.isValid( FileStatusMask_ModifyTime ) ) + { + TimeValue temp = aFileStatus.getModifyTime(); + + // Convert system time to local time (for EA) + TimeValue myLocalTime; + osl_getLocalTimeFromSystemTime( &temp, &myLocalTime ); + + oslDateTime myDateTime; + osl_getDateTimeFromTimeValue( &myLocalTime, &myDateTime ); + util::DateTime aDateTime; + + aDateTime.HundredthSeconds = (unsigned short)(myDateTime.NanoSeconds / 10000000); + aDateTime.Seconds = myDateTime.Seconds; + aDateTime.Minutes = myDateTime.Minutes; + aDateTime.Hours = myDateTime.Hours; + aDateTime.Day = myDateTime.Day; + aDateTime.Month = myDateTime.Month; + aDateTime.Year = myDateTime.Year; + it1->setValue( uno::makeAny( aDateTime ) ); + } + } + + it1 = properties.find( MyProperty( CreatableContentsInfo ) ); + if( it1 != properties.end() ) + it1->setValue( uno::makeAny( + isDirectory || !aFileStatus.isValid( FileStatusMask_Type ) + ? queryCreatableContentsInfo() + : uno::Sequence< ucb::ContentInfo >() ) ); +} + + +// Special optimized method for getting the properties of a +// directoryitem, which is returned by osl::DirectoryItem::getNextItem() + + +uno::Reference< sdbc::XRow > SAL_CALL +shell::getv( + Notifier* pNotifier, + const uno::Sequence< beans::Property >& properties, + osl::DirectoryItem& aDirItem, + rtl::OUString& aUnqPath, + sal_Bool& aIsRegular ) +{ + uno::Sequence< uno::Any > seq( properties.getLength() ); + + sal_Int32 n_Mask; + getMaskFromProperties( n_Mask,properties ); + + // Always retrieve the type and the target URL because item might be a link + osl::FileStatus aFileStatus( n_Mask | + FileStatusMask_FileURL | + FileStatusMask_Type | + FileStatusMask_LinkTargetURL ); + aDirItem.getFileStatus( aFileStatus ); + aUnqPath = aFileStatus.getFileURL(); + + // If the directory item type is a link retrieve the type of the target + + if ( aFileStatus.getFileType() == osl::FileStatus::Link ) + { + // Assume failure + aIsRegular = false; + osl::FileBase::RC result = osl::FileBase::E_INVAL; + osl::DirectoryItem aTargetItem; + osl::DirectoryItem::get( aFileStatus.getLinkTargetURL(), aTargetItem ); + if ( aTargetItem.is() ) + { + osl::FileStatus aTargetStatus( FileStatusMask_Type ); + + if ( osl::FileBase::E_None == + ( result = aTargetItem.getFileStatus( aTargetStatus ) ) ) + aIsRegular = + aTargetStatus.getFileType() == osl::FileStatus::Regular; + } + } + else + aIsRegular = aFileStatus.getFileType() == osl::FileStatus::Regular; + + registerNotifier( aUnqPath,pNotifier ); + insertDefaultProperties( aUnqPath ); + { + osl::MutexGuard aGuard( m_aMutex ); + + shell::ContentMap::iterator it = m_aContent.find( aUnqPath ); + commit( it,aFileStatus ); + + shell::PropertySet::iterator it1; + PropertySet& propset = *(it->second.properties); + + for( sal_Int32 i = 0; i < seq.getLength(); ++i ) + { + MyProperty readProp( properties[i].Name ); + it1 = propset.find( readProp ); + if( it1 == propset.end() ) + seq[i] = uno::Any(); + else + seq[i] = it1->getValue(); + } + } + deregisterNotifier( aUnqPath,pNotifier ); + + XRow_impl* p = new XRow_impl( this,seq ); + return uno::Reference< sdbc::XRow >( p ); +} + + + + + + +// EventListener + + +std::list< ContentEventNotifier* >* SAL_CALL +shell::getContentEventListeners( const rtl::OUString& aName ) +{ + std::list< ContentEventNotifier* >* p = new std::list< ContentEventNotifier* >; + std::list< ContentEventNotifier* >& listeners = *p; + { + osl::MutexGuard aGuard( m_aMutex ); + shell::ContentMap::iterator it = m_aContent.find( aName ); + if( it != m_aContent.end() && it->second.notifier ) + { + std::list<Notifier*>& listOfNotifiers = *( it->second.notifier ); + std::list<Notifier*>::iterator it1 = listOfNotifiers.begin(); + while( it1 != listOfNotifiers.end() ) + { + Notifier* pointer = *it1; + ContentEventNotifier* notifier = pointer->cCEL(); + if( notifier ) + listeners.push_back( notifier ); + ++it1; + } + } + } + return p; +} + + + +std::list< ContentEventNotifier* >* SAL_CALL +shell::getContentDeletedEventListeners( const rtl::OUString& aName ) +{ + std::list< ContentEventNotifier* >* p = new std::list< ContentEventNotifier* >; + std::list< ContentEventNotifier* >& listeners = *p; + { + osl::MutexGuard aGuard( m_aMutex ); + shell::ContentMap::iterator it = m_aContent.find( aName ); + if( it != m_aContent.end() && it->second.notifier ) + { + std::list<Notifier*>& listOfNotifiers = *( it->second.notifier ); + std::list<Notifier*>::iterator it1 = listOfNotifiers.begin(); + while( it1 != listOfNotifiers.end() ) + { + Notifier* pointer = *it1; + ContentEventNotifier* notifier = pointer->cDEL(); + if( notifier ) + listeners.push_back( notifier ); + ++it1; + } + } + } + return p; +} + + +void SAL_CALL +shell::notifyInsert( std::list< ContentEventNotifier* >* listeners,const rtl::OUString& aChildName ) +{ + std::list< ContentEventNotifier* >::iterator it = listeners->begin(); + while( it != listeners->end() ) + { + (*it)->notifyChildInserted( aChildName ); + delete (*it); + ++it; + } + delete listeners; +} + + +void SAL_CALL +shell::notifyContentDeleted( std::list< ContentEventNotifier* >* listeners ) +{ + std::list< ContentEventNotifier* >::iterator it = listeners->begin(); + while( it != listeners->end() ) + { + (*it)->notifyDeleted(); + delete (*it); + ++it; + } + delete listeners; +} + + +void SAL_CALL +shell::notifyContentRemoved( std::list< ContentEventNotifier* >* listeners, + const rtl::OUString& aChildName ) +{ + std::list< ContentEventNotifier* >::iterator it = listeners->begin(); + while( it != listeners->end() ) + { + (*it)->notifyRemoved( aChildName ); + delete (*it); + ++it; + } + delete listeners; +} + + + + +std::list< PropertySetInfoChangeNotifier* >* SAL_CALL +shell::getPropertySetListeners( const rtl::OUString& aName ) +{ + std::list< PropertySetInfoChangeNotifier* >* p = new std::list< PropertySetInfoChangeNotifier* >; + std::list< PropertySetInfoChangeNotifier* >& listeners = *p; + { + osl::MutexGuard aGuard( m_aMutex ); + shell::ContentMap::iterator it = m_aContent.find( aName ); + if( it != m_aContent.end() && it->second.notifier ) + { + std::list<Notifier*>& listOfNotifiers = *( it->second.notifier ); + std::list<Notifier*>::iterator it1 = listOfNotifiers.begin(); + while( it1 != listOfNotifiers.end() ) + { + Notifier* pointer = *it1; + PropertySetInfoChangeNotifier* notifier = pointer->cPSL(); + if( notifier ) + listeners.push_back( notifier ); + ++it1; + } + } + } + return p; +} + + +void SAL_CALL +shell::notifyPropertyAdded( std::list< PropertySetInfoChangeNotifier* >* listeners, + const rtl::OUString& aPropertyName ) +{ + std::list< PropertySetInfoChangeNotifier* >::iterator it = listeners->begin(); + while( it != listeners->end() ) + { + (*it)->notifyPropertyAdded( aPropertyName ); + delete (*it); + ++it; + } + delete listeners; +} + + +void SAL_CALL +shell::notifyPropertyRemoved( std::list< PropertySetInfoChangeNotifier* >* listeners, + const rtl::OUString& aPropertyName ) +{ + std::list< PropertySetInfoChangeNotifier* >::iterator it = listeners->begin(); + while( it != listeners->end() ) + { + (*it)->notifyPropertyRemoved( aPropertyName ); + delete (*it); + ++it; + } + delete listeners; +} + + + +std::vector< std::list< ContentEventNotifier* >* >* SAL_CALL +shell::getContentExchangedEventListeners( const rtl::OUString aOldPrefix, + const rtl::OUString aNewPrefix, + sal_Bool withChilds ) +{ + + std::vector< std::list< ContentEventNotifier* >* >* aVectorOnHeap = + new std::vector< std::list< ContentEventNotifier* >* >; + std::vector< std::list< ContentEventNotifier* >* >& aVector = *aVectorOnHeap; + + sal_Int32 count; + rtl::OUString aOldName; + rtl::OUString aNewName; + std::vector< rtl::OUString > oldChildList; + + { + osl::MutexGuard aGuard( m_aMutex ); + + if( ! withChilds ) + { + aOldName = aOldPrefix; + aNewName = aNewPrefix; + count = 1; + } + else + { + ContentMap::iterator itnames = m_aContent.begin(); + while( itnames != m_aContent.end() ) + { + if( isChild( aOldPrefix,itnames->first ) ) + { + oldChildList.push_back( itnames->first ); + } + ++itnames; + } + count = oldChildList.size(); + } + + + for( sal_Int32 j = 0; j < count; ++j ) + { + std::list< ContentEventNotifier* >* p = new std::list< ContentEventNotifier* >; + std::list< ContentEventNotifier* >& listeners = *p; + + if( withChilds ) + { + aOldName = oldChildList[j]; + aNewName = newName( aNewPrefix,aOldPrefix,aOldName ); + } + + shell::ContentMap::iterator itold = m_aContent.find( aOldName ); + if( itold != m_aContent.end() ) + { + shell::ContentMap::iterator itnew = m_aContent.insert( + ContentMap::value_type( aNewName,UnqPathData() ) ).first; + + // copy Ownership also + delete itnew->second.properties; + itnew->second.properties = itold->second.properties; + itold->second.properties = 0; + + // copy existing list + std::list< Notifier* >* copyList = itnew->second.notifier; + itnew->second.notifier = itold->second.notifier; + itold->second.notifier = 0; + + m_aContent.erase( itold ); + + if( itnew != m_aContent.end() && itnew->second.notifier ) + { + std::list<Notifier*>& listOfNotifiers = *( itnew->second.notifier ); + std::list<Notifier*>::iterator it1 = listOfNotifiers.begin(); + while( it1 != listOfNotifiers.end() ) + { + Notifier* pointer = *it1; + ContentEventNotifier* notifier = pointer->cEXC( aNewName ); + if( notifier ) + listeners.push_back( notifier ); + ++it1; + } + } + + // Merge with preexisting notifiers + // However, these may be in status BaseContent::Deleted + if( copyList != 0 ) + { + std::list< Notifier* >::iterator copyIt = copyList->begin(); + while( copyIt != copyList->end() ) + { + itnew->second.notifier->push_back( *copyIt ); + ++copyIt; + } + } + delete copyList; + } + aVector.push_back( p ); + } + } + + return aVectorOnHeap; +} + + + +void SAL_CALL +shell::notifyContentExchanged( std::vector< std::list< ContentEventNotifier* >* >* listeners_vec ) +{ + std::list< ContentEventNotifier* >* listeners; + for( sal_uInt32 i = 0; i < listeners_vec->size(); ++i ) + { + listeners = (*listeners_vec)[i]; + std::list< ContentEventNotifier* >::iterator it = listeners->begin(); + while( it != listeners->end() ) + { + (*it)->notifyExchanged(); + delete (*it); + ++it; + } + delete listeners; + } + delete listeners_vec; +} + + + +std::list< PropertyChangeNotifier* >* SAL_CALL +shell::getPropertyChangeNotifier( const rtl::OUString& aName ) +{ + std::list< PropertyChangeNotifier* >* p = new std::list< PropertyChangeNotifier* >; + std::list< PropertyChangeNotifier* >& listeners = *p; + { + osl::MutexGuard aGuard( m_aMutex ); + shell::ContentMap::iterator it = m_aContent.find( aName ); + if( it != m_aContent.end() && it->second.notifier ) + { + std::list<Notifier*>& listOfNotifiers = *( it->second.notifier ); + std::list<Notifier*>::iterator it1 = listOfNotifiers.begin(); + while( it1 != listOfNotifiers.end() ) + { + Notifier* pointer = *it1; + PropertyChangeNotifier* notifier = pointer->cPCL(); + if( notifier ) + listeners.push_back( notifier ); + ++it1; + } + } + } + return p; +} + + +void SAL_CALL shell::notifyPropertyChanges( std::list< PropertyChangeNotifier* >* listeners, + const uno::Sequence< beans::PropertyChangeEvent >& seqChanged ) +{ + std::list< PropertyChangeNotifier* >::iterator it = listeners->begin(); + while( it != listeners->end() ) + { + (*it)->notifyPropertyChanged( seqChanged ); + delete (*it); + ++it; + } + delete listeners; +} + + + + +/********************************************************************************/ +/* remove persistent propertyset */ +/********************************************************************************/ + +void SAL_CALL +shell::erasePersistentSet( const rtl::OUString& aUnqPath, + sal_Bool withChilds ) +{ + if( ! m_xFileRegistry.is() ) + { + OSL_ASSERT( m_xFileRegistry.is() ); + return; + } + + uno::Sequence< rtl::OUString > seqNames; + + if( withChilds ) + { + uno::Reference< container::XNameAccess > xName( m_xFileRegistry,uno::UNO_QUERY ); + seqNames = xName->getElementNames(); + } + + sal_Int32 count = withChilds ? seqNames.getLength() : 1; + + rtl::OUString + old_Name = aUnqPath; + + for( sal_Int32 j = 0; j < count; ++j ) + { + if( withChilds && ! ( isChild( old_Name,seqNames[j] ) ) ) + continue; + + if( withChilds ) + { + old_Name = seqNames[j]; + } + + { + // Release possible references + osl::MutexGuard aGuard( m_aMutex ); + ContentMap::iterator it = m_aContent.find( old_Name ); + if( it != m_aContent.end() ) + { + it->second.xS = 0; + it->second.xC = 0; + it->second.xA = 0; + + delete it->second.properties; + it->second.properties = 0; + } + } + + if( m_xFileRegistry.is() ) + m_xFileRegistry->removePropertySet( old_Name ); + } +} + + + + +/********************************************************************************/ +/* copy persistent propertyset */ +/* from srcUnqPath to dstUnqPath */ +/********************************************************************************/ + + +void SAL_CALL +shell::copyPersistentSet( const rtl::OUString& srcUnqPath, + const rtl::OUString& dstUnqPath, + sal_Bool withChilds ) +{ + if( ! m_xFileRegistry.is() ) + { + OSL_ASSERT( m_xFileRegistry.is() ); + return; + } + + uno::Sequence< rtl::OUString > seqNames; + + if( withChilds ) + { + uno::Reference< container::XNameAccess > xName( m_xFileRegistry,uno::UNO_QUERY ); + seqNames = xName->getElementNames(); + } + + sal_Int32 count = withChilds ? seqNames.getLength() : 1; + + rtl::OUString + old_Name = srcUnqPath, + new_Name = dstUnqPath; + + for( sal_Int32 j = 0; j < count; ++j ) + { + if( withChilds && ! ( isChild( srcUnqPath,seqNames[j] ) ) ) + continue; + + if( withChilds ) + { + old_Name = seqNames[j]; + new_Name = newName( dstUnqPath,srcUnqPath,old_Name ); + } + + uno::Reference< XPersistentPropertySet > x_src; + + if( m_xFileRegistry.is() ) + { + x_src = m_xFileRegistry->openPropertySet( old_Name,false ); + m_xFileRegistry->removePropertySet( new_Name ); + } + + if( x_src.is() ) + { + uno::Sequence< beans::Property > seqProperty = + x_src->getPropertySetInfo()->getProperties(); + + if( seqProperty.getLength() ) + { + uno::Reference< XPersistentPropertySet > + x_dstS = m_xFileRegistry->openPropertySet( new_Name,true ); + uno::Reference< beans::XPropertyContainer > + x_dstC( x_dstS,uno::UNO_QUERY ); + + for( sal_Int32 i = 0; i < seqProperty.getLength(); ++i ) + { + x_dstC->addProperty( seqProperty[i].Name, + seqProperty[i].Attributes, + x_src->getPropertyValue( seqProperty[i].Name ) ); + } + } + } + } // end for( sal_Int... +} + +uno::Sequence< ucb::ContentInfo > shell::queryCreatableContentsInfo() +{ + uno::Sequence< ucb::ContentInfo > seq(2); + + // file + seq[0].Type = FileContentType; + seq[0].Attributes = ucb::ContentInfoAttribute::INSERT_WITH_INPUTSTREAM + | ucb::ContentInfoAttribute::KIND_DOCUMENT; + + uno::Sequence< beans::Property > props( 1 ); + props[0] = beans::Property( + rtl::OUString::createFromAscii( "Title" ), + -1, + getCppuType( static_cast< rtl::OUString* >( 0 ) ), + beans::PropertyAttribute::MAYBEVOID + | beans::PropertyAttribute::BOUND ); + seq[0].Properties = props; + + // folder + seq[1].Type = FolderContentType; + seq[1].Attributes = ucb::ContentInfoAttribute::KIND_FOLDER; + seq[1].Properties = props; + return seq; +} + +/*******************************************************************************/ +/* */ +/* some misceancellous static functions */ +/* */ +/*******************************************************************************/ + +void SAL_CALL +shell::getScheme( rtl::OUString& Scheme ) +{ + Scheme = rtl::OUString::createFromAscii( "file" ); +} + +rtl::OUString SAL_CALL +shell::getImplementationName_static( void ) +{ + return rtl::OUString::createFromAscii( "com.sun.star.comp.ucb.FileProvider" ); +} + + +uno::Sequence< rtl::OUString > SAL_CALL +shell::getSupportedServiceNames_static( void ) +{ + rtl::OUString Supported = rtl::OUString::createFromAscii( "com.sun.star.ucb.FileContentProvider" ) ; + com::sun::star::uno::Sequence< rtl::OUString > Seq( &Supported,1 ); + return Seq; +} diff --git a/ucb/source/ucp/file/shell.hxx b/ucb/source/ucp/file/shell.hxx new file mode 100644 index 000000000000..14e332959a26 --- /dev/null +++ b/ucb/source/ucp/file/shell.hxx @@ -0,0 +1,607 @@ +/************************************************************************* + * + * 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 _SHELL_HXX_ +#define _SHELL_HXX_ + + +#include <cppuhelper/weak.hxx> +#include <cppuhelper/interfacecontainer.hxx> +#include <cppuhelper/typeprovider.hxx> +#include <vector> +#include <hash_map> +#include <hash_set> +#include <list> +#include <osl/file.hxx> + +#include "osl/mutex.hxx" +#include <rtl/ustring.hxx> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/beans/PropertyChangeEvent.hpp> +#include <com/sun/star/ucb/XCommandInfo.hpp> +#include <com/sun/star/beans/Property.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/io/XStream.hpp> +#include <com/sun/star/beans/XPropertyChangeListener.hpp> +#include <com/sun/star/ucb/XCommandProcessor.hpp> +#include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/beans/XPropertySetInfo.hpp> +#include <com/sun/star/beans/XPropertiesChangeNotifier.hpp> +#include <com/sun/star/ucb/NumberedSortingInfo.hpp> +#include <com/sun/star/sdbc/XRow.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/ucb/XContentProvider.hpp> +#include <com/sun/star/ucb/XDynamicResultSet.hpp> +#include <com/sun/star/beans/XPropertyContainer.hpp> +#include <com/sun/star/beans/XPropertyAccess.hpp> +#include <com/sun/star/ucb/XPropertySetRegistryFactory.hpp> +#include <com/sun/star/ucb/TransferInfo.hpp> +#include <com/sun/star/ucb/ContentInfo.hpp> +#include "filtask.hxx" +#include "filnot.hxx" + +namespace fileaccess { + + class FileProvider; + class XPropertySetInfo_impl; + class XCommandInfo_impl; + class XResultSet_impl; + class BaseContent; + class shell; + + class shell + : public virtual TaskManager + { + friend class XPropertySetInfo_impl; + friend class XResultSet_impl; + friend class XCommandInfo_impl; + public: + // Type definitions + + typedef rtl::OUString UniquePath; + typedef equalOUString eUniquePath; + typedef hashOUString hUniquePath; + + class MyProperty + { + private: + rtl::OUString PropertyName; + sal_Int32 Handle; + sal_Bool isNative; + com::sun::star::uno::Type Typ; // Duplicates information in Value + com::sun::star::uno::Any Value; + com::sun::star::beans::PropertyState State; + sal_Int16 Attributes; + public: + MyProperty(); + MyProperty( const rtl::OUString& __PropertyName ); + MyProperty( const sal_Bool& __isNative, + const rtl::OUString& __PropertyName, + const sal_Int32& __Handle, + const com::sun::star::uno::Type& __Typ, + const com::sun::star::uno::Any& __Value, + const com::sun::star::beans::PropertyState& __State, + const sal_Int16& __Attributes ); + + ~MyProperty(); + inline const sal_Bool& SAL_CALL IsNative() const; + inline const rtl::OUString& SAL_CALL getPropertyName() const { return PropertyName; } + inline const sal_Int32& SAL_CALL getHandle() const; + inline const com::sun::star::uno::Type& SAL_CALL getType() const; + inline const com::sun::star::uno::Any& SAL_CALL getValue() const; + inline const com::sun::star::beans::PropertyState& SAL_CALL getState() const; + inline const sal_Int16& SAL_CALL getAttributes() const; + + // The set* functions are declared const, because the key of "this" stays intact + inline void SAL_CALL setHandle( const sal_Int32& __Handle ) const; + inline void SAL_CALL setType( const com::sun::star::uno::Type& __Type ) const; + inline void SAL_CALL setValue( const com::sun::star::uno::Any& __Value ) const; + inline void SAL_CALL setState( const com::sun::star::beans::PropertyState& __State ) const; + inline void SAL_CALL setAttributes( const sal_Int16& __Attributes ) const; + }; + + struct eMyProperty + { + bool operator()( const MyProperty& rKey1, const MyProperty& rKey2 ) const + { + return !!( rKey1.getPropertyName() == rKey2.getPropertyName() ); + } + }; + + struct hMyProperty + { + size_t operator()( const MyProperty& rName ) const + { + return rName.getPropertyName().hashCode(); + } + }; + + typedef std::hash_set< MyProperty,hMyProperty,eMyProperty > PropertySet; + typedef std::list< Notifier* > NotifierList; + + + class UnqPathData + { + public: + UnqPathData(); + ~UnqPathData(); + UnqPathData( const UnqPathData& ); + UnqPathData& operator=( UnqPathData& ); + + PropertySet* properties; + NotifierList* notifier; + + // Three views on the PersistentPropertySet + com::sun::star::uno::Reference< com::sun::star::ucb::XPersistentPropertySet > xS; + com::sun::star::uno::Reference< com::sun::star::beans::XPropertyContainer > xC; + com::sun::star::uno::Reference< com::sun::star::beans::XPropertyAccess > xA; + }; + + typedef std::hash_map< UniquePath,UnqPathData,hUniquePath,eUniquePath > ContentMap; + + public: + + // MethodenDefinitionen + shell( const com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >& xMultiServiceFactory, + FileProvider* pProvider,sal_Bool bWithConfig ); + + virtual ~shell(); + + + + /** + * This two methods register and deregister a change listener for the content belonging + * to URL aUnqPath + */ + + void SAL_CALL registerNotifier( const rtl::OUString& aUnqPath,Notifier* pNotifier ); + + void SAL_CALL deregisterNotifier( const rtl::OUString& aUnqPath,Notifier* pNotifier ); + + + + /** + * Used to associate and deassociate a new property with + * the content belonging to URL UnqPath. + * The default value and the the attributes are input + */ + + void SAL_CALL associate( const rtl::OUString& UnqPath, + const rtl::OUString& PropertyName, + const com::sun::star::uno::Any& DefaultValue, + const sal_Int16 Attributes ) + throw( com::sun::star::beans::PropertyExistException, + com::sun::star::beans::IllegalTypeException, + com::sun::star::uno::RuntimeException); + + + void SAL_CALL deassociate( const rtl::OUString& UnqPath, + const rtl::OUString& PropertyName ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::beans::NotRemoveableException, + com::sun::star::uno::RuntimeException); + + + + // + // Every method having a command id is not allowed to throw anything, + // but instead must install every error code in the task handler + // + + + /** + * Given an xOutputStream, this method writes the content of the file belonging to + * URL aUnqPath into the XOutputStream + */ + + void SAL_CALL page( sal_Int32 CommandId, + const rtl::OUString& aUnqPath, + const com::sun::star::uno::Reference< com::sun::star::io::XOutputStream >& xOutputStream ) + throw(); + + + /** + * Given a file URL aUnqPath, this methods returns a XInputStream which reads from the open file. + */ + + com::sun::star::uno::Reference< com::sun::star::io::XInputStream > SAL_CALL + open( sal_Int32 CommandId, + const rtl::OUString& aUnqPath, + sal_Bool bLock ) + throw(); + + + /** + * Given a file URL aUnqPath, this methods returns a XStream which can be used + * to read and write from/to the file. + */ + + com::sun::star::uno::Reference< com::sun::star::io::XStream > SAL_CALL + open_rw( sal_Int32 CommandId, + const rtl::OUString& aUnqPath, + sal_Bool bLock ) + throw(); + + + /** + * This method returns the result set containing the the children of the directory belonging + * to file URL aUnqPath + */ + + com::sun::star::uno::Reference< com::sun::star::ucb::XDynamicResultSet > SAL_CALL + ls( sal_Int32 CommandId, + const rtl::OUString& aUnqPath, + const sal_Int32 OpenMode, + const com::sun::star::uno::Sequence< com::sun::star::beans::Property >& sProperty, + const com::sun::star::uno::Sequence< com::sun::star::ucb::NumberedSortingInfo > & sSortingInfo ) + throw(); + + + /** + * Info methods + */ + + // Info for commands + com::sun::star::uno::Reference< com::sun::star::ucb::XCommandInfo > SAL_CALL + info_c() + throw(); + + // Info for the properties + com::sun::star::uno::Reference< com::sun::star::beans::XPropertySetInfo > SAL_CALL + info_p( const rtl::OUString& aUnqPath ) + throw(); + + + /** + * Sets the values of the properties belonging to fileURL aUnqPath + */ + + com::sun::star::uno::Sequence< com::sun::star::uno::Any > SAL_CALL + setv( const rtl::OUString& aUnqPath, + const com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >& values ) + throw(); + + + /** + * Reads the values of the properties belonging to fileURL aUnqPath; + * Returns an XRow object containing the values in the requested order. + */ + + com::sun::star::uno::Reference< com::sun::star::sdbc::XRow > SAL_CALL + getv( sal_Int32 CommandId, + const rtl::OUString& aUnqPath, + const com::sun::star::uno::Sequence< com::sun::star::beans::Property >& properties ) + throw(); + + + /********************************************************************************/ + /* transfer-commands */ + /********************************************************************************/ + + /** + * Moves the content belonging to fileURL srcUnqPath to fileURL dstUnqPath( files and directories ) + */ + + void SAL_CALL + move( sal_Int32 CommandId, + const rtl::OUString srcUnqPath, // Full file(folder)-path + const rtl::OUString dstUnqPath, // Path to the destination-directory + const sal_Int32 NameClash ) + throw(); + + /** + * Copies the content belonging to fileURL srcUnqPath to fileURL dstUnqPath ( files and directories ) + */ + + void SAL_CALL + copy( sal_Int32 CommandId, // See "move" + const rtl::OUString srcUnqPath, + const rtl::OUString dstUnqPath, + sal_Int32 NameClash ) + throw(); + +#define RemoveFolder 1 +#define RemoveFile -1 +#define RemoveUnknown 0 + + /** + * Deletes the content belonging to fileURL aUnqPath( recursively in case of directory ) + */ + + sal_Bool SAL_CALL + remove( sal_Int32 CommandId, + const rtl::OUString& aUnqPath, + sal_Int32 TypeToMove = RemoveUnknown, + sal_Bool MustExist = sal_True ) + throw(); + +#undef RemoveUnknown +#undef RemoveFile +#undef RemoveFolder + + + /********************************************************************************/ + /* write and create - commandos */ + /********************************************************************************/ + + /** + * Creates new directory with given URL, recursively if necessary + * Return:: success of operation + */ + + sal_Bool SAL_CALL + mkdir( sal_Int32 CommandId, + const rtl::OUString& aDirectoryName, + sal_Bool OverWrite ) + throw(); + + + /** + * Creates new file with given URL. + * The content of aInputStream becomes the content of the file + * Return:: success of operation + */ + + sal_Bool SAL_CALL + mkfil( sal_Int32 CommandId, + const rtl::OUString& aFileName, + sal_Bool OverWrite, + const com::sun::star::uno::Reference< com::sun::star::io::XInputStream >& aInputStream ) + throw(); + + + /** + * writes to the file with given URL. + * The content of aInputStream becomes the content of the file + * Return:: success of operation + */ + sal_Bool SAL_CALL + write( sal_Int32 CommandId, + const rtl::OUString& aUnqPath, + sal_Bool OverWrite, + const com::sun::star::uno::Reference< com::sun::star::io::XInputStream >& aInputStream ) + throw(); + + + + void SAL_CALL insertDefaultProperties( const rtl::OUString& aUnqPath ); + + com::sun::star::uno::Sequence< com::sun::star::ucb::ContentInfo > + queryCreatableContentsInfo(); + + + /******************************************************************************/ + /* */ + /* mapping of file urls */ + /* to uncpath and vice versa */ + /* */ + /******************************************************************************/ + + sal_Bool SAL_CALL getUnqFromUrl( const rtl::OUString& Url, rtl::OUString& Unq ); + + sal_Bool SAL_CALL getUrlFromUnq( const rtl::OUString& Unq, rtl::OUString& Url ); + + + sal_Bool m_bWithConfig; + FileProvider* m_pProvider; + com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory > m_xMultiServiceFactory; + com::sun::star::uno::Reference< com::sun::star::ucb::XPropertySetRegistry > m_xFileRegistry; + + private: + + /********************************************************************************/ + /* get eventListeners */ + /********************************************************************************/ + + std::list< ContentEventNotifier* >* SAL_CALL + getContentEventListeners( const rtl::OUString& aName ); + + std::list< ContentEventNotifier* >* SAL_CALL + getContentDeletedEventListeners( const rtl::OUString& aName ); + + std::vector< std::list< ContentEventNotifier* >* >* SAL_CALL + getContentExchangedEventListeners( const rtl::OUString aOldPrefix, + const rtl::OUString aNewPrefix, + sal_Bool withChilds ); + + std::list< PropertyChangeNotifier* >* SAL_CALL + getPropertyChangeNotifier( const rtl::OUString& aName ); + + std::list< PropertySetInfoChangeNotifier* >* SAL_CALL + getPropertySetListeners( const rtl::OUString& aName ); + + + /********************************************************************************/ + /* notify eventListeners */ + /********************************************************************************/ + + void SAL_CALL notifyPropertyChanges( + std::list< PropertyChangeNotifier* >* listeners, + const com::sun::star::uno::Sequence< com::sun::star::beans::PropertyChangeEvent >& seqChanged ); + + void SAL_CALL notifyContentExchanged( + std::vector< std::list< ContentEventNotifier* >* >* listeners_vec ); + + void SAL_CALL notifyInsert( + std::list< ContentEventNotifier* >* listeners,const rtl::OUString& aChildName ); + + void SAL_CALL notifyContentDeleted( + std::list< ContentEventNotifier* >* listeners ); + + void SAL_CALL notifyContentRemoved( + std::list< ContentEventNotifier* >* listeners, + const rtl::OUString& aChildName ); + + void SAL_CALL notifyPropertyAdded( + std::list< PropertySetInfoChangeNotifier* >* listeners, + const rtl::OUString& aPropertyName ); + + void SAL_CALL notifyPropertyRemoved( + std::list< PropertySetInfoChangeNotifier* >* listeners, + const rtl::OUString& aPropertyName ); + + + /********************************************************************************/ + /* remove persistent propertyset */ + /********************************************************************************/ + + void SAL_CALL erasePersistentSet( const rtl::OUString& aUnqPath, + sal_Bool withChilds = false ); + + /********************************************************************************/ + /* copy persistent propertyset */ + /* from srcUnqPath to dstUnqPath */ + /********************************************************************************/ + + void SAL_CALL copyPersistentSet( const rtl::OUString& srcUnqPath, + const rtl::OUString& dstUnqPath, + sal_Bool withChilds = false ); + + + // Special optimized method for getting the properties of a directoryitem, which + // is returned by osl::DirectoryItem::getNextItem() + + com::sun::star::uno::Reference< com::sun::star::sdbc::XRow > SAL_CALL + getv( Notifier* pNotifier, + const com::sun::star::uno::Sequence< com::sun::star::beans::Property >& properties, + osl::DirectoryItem& DirItem, + rtl::OUString& aUnqPath, + sal_Bool& bIsRegular ); + + + /** + * Load the properties from configuration, if create == true create them. + * The Properties are stored under the url belonging to it->first. + */ + + void SAL_CALL load( const shell::ContentMap::iterator& it, + sal_Bool create ); + + /** + * Commit inserts the determined properties in the filestatus object into + * the internal map, so that is possible to determine on a subsequent + * setting of file properties which properties have changed without filestat + */ + + void SAL_CALL + commit( + const shell::ContentMap::iterator& it, + const osl::FileStatus& aFileStatus ); + + /** + * Given a Sequence of properties seq, this method determines the mask + * used to instantiate a osl::FileStatus, so that a call to + * osl::DirectoryItem::getFileStatus fills the required fields. + */ + + void SAL_CALL + getMaskFromProperties( + sal_Int32& n_Mask, + const com::sun::star::uno::Sequence< com::sun::star::beans::Property >& seq ); + + + void SAL_CALL + setFileProperties( + const com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >& values, + sal_Int32 numberOfValues ) + throw(); + + + // Helper function for public copy + + osl::FileBase::RC SAL_CALL + copy_recursive( + const rtl::OUString& srcUnqPath, + const rtl::OUString& dstUnqPath, + sal_Int32 TypeToCopy, + sal_Bool testExistence ) + throw(); + + + // Helper function for mkfil,mkdir and write + // Creates whole path + // returns success of the operation + // The calle determines the errorCode, which should be used to install + // any error + + sal_Bool SAL_CALL + ensuredir( sal_Int32 CommandId, + const rtl::OUString& aDirectoryName, + sal_Int32 errorCode ) + throw(); + + // General + osl::Mutex m_aMutex; + ContentMap m_aContent; + + // Default properties + + const rtl::OUString Title; + const rtl::OUString CasePreservingURL; + const rtl::OUString IsDocument; + const rtl::OUString IsFolder; + const rtl::OUString DateModified; + const rtl::OUString Size; + const rtl::OUString IsVolume; + const rtl::OUString IsRemoveable; + const rtl::OUString IsRemote; + const rtl::OUString IsCompactDisc; + const rtl::OUString IsFloppy; + const rtl::OUString IsHidden; + const rtl::OUString ContentType; + const rtl::OUString IsReadOnly; + const rtl::OUString CreatableContentsInfo; + + public: + + const rtl::OUString FolderContentType; + const rtl::OUString FileContentType; + + + private: + + PropertySet m_aDefaultProperties; + com::sun::star::uno::Sequence< com::sun::star::ucb::CommandInfo > m_sCommandInfo; + + public: + // Misceancellous: + // Methods for "writeComponentInfo" and "createComponentFactory" + + static void SAL_CALL getScheme( rtl::OUString& Scheme ); + + static rtl::OUString SAL_CALL getImplementationName_static( void ); + + static com::sun::star::uno::Sequence< rtl::OUString > SAL_CALL getSupportedServiceNames_static( void ); + + }; // end class shell + +} // end namespace fileaccess + +#endif + diff --git a/ucb/source/ucp/file/ucpfile.xml b/ucb/source/ucp/file/ucpfile.xml new file mode 100644 index 000000000000..bd205639f476 --- /dev/null +++ b/ucb/source/ucp/file/ucpfile.xml @@ -0,0 +1,113 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE module-description PUBLIC "-//StarOffice//DTD ComponentDescription 1.0//EN" "module-description.dtd"> +<module-description xmlns:xlink="http://www.w3.org/1999/xlink"> + + <module-name> + ucpfile + </module-name> + + <component-description> + <author> + Andreas Bille + </author> + <name> + com.sun.star.comp.ucb.FileProvider + </name> + <description> + This component implements a Content Provider for the Universal + Content Broker. It provides access to file system contents. + </description> + <loader-name> + com.sun.star.loader.SharedLibrary + </loader-name> + <language> + c++ + </language> + <status value="final"/> + <supported-service> + com.sun.star.ucb.FileContentProvider + </supported-service> + + <service-dependency> + com.sun.star.config.SpecialConfigManager + </service-dependency> + <service-dependency> + com.sun.star.configuration.ConfigurationAccess + </service-dependency> + <service-dependency> + com.sun.star.configuration.ConfigurationProvider + </service-dependency> + <service-dependency> + com.sun.star.script.Converter + </service-dependency> + <service-dependency> + com.sun.star.ucb.CachedDynamicResultSetStubFactory + </service-dependency> + <service-dependency> + com.sun.star.ucb.Store + </service-dependency> + </component-description> + + <project-build-dependency> sal </project-build-dependency> + <project-build-dependency> cppu </project-build-dependency> + <project-build-dependency> cppuhelper </project-build-dependency> + <project-build-dependency> ucbhelper </project-build-dependency> + + <runtime-module-dependency> sal3 </runtime-module-dependency> + <runtime-module-dependency> cppu3 </runtime-module-dependency> + <runtime-module-dependency> cppuhelper3$(COM) </runtime-module-dependency> + <runtime-module-dependency> ucbhelper4$(COM) </runtime-module-dependency> + + <type> com.sun.star.beans.Property </type> + <type> com.sun.star.beans.PropertyAttribute </type> + <type> com.sun.star.beans.PropertySetInfoChange </type> + <type> com.sun.star.beans.PropertyState </type> + <type> com.sun.star.beans.PropertyValue </type> + <type> com.sun.star.beans.XPropertiesChangeNotifier </type> + <type> com.sun.star.beans.XPropertyAccess </type> + <type> com.sun.star.beans.XPropertyContainer </type> + <type> com.sun.star.beans.XPropertySetInfo </type> + <type> com.sun.star.beans.XPropertySetInfoChangeNotifier </type> + <type> com.sun.star.container.XChild </type> + <type> com.sun.star.container.XHierarchicalNameAccess </type> + <type> com.sun.star.frame.ConfigManager </type> + <type> com.sun.star.io.XActiveDataSink </type> + <type> com.sun.star.io.XActiveDataStreamer </type> + <type> com.sun.star.io.XSeekable </type> + <type> com.sun.star.io.XStream </type> + <type> com.sun.star.lang.XMultiServiceFactory </type> + <type> com.sun.star.lang.XServiceInfo </type> + <type> com.sun.star.lang.XSingleServiceFactory </type> + <type> com.sun.star.lang.XTypeProvider </type> + <type> com.sun.star.registry.XRegistryKey </type> + <type> com.sun.star.script.XTypeConverter </type> + <type> com/sun/star/sdbc/ColumnValue </type> + <type> com.sun.star.sdbc.XCloseable </type> + <type> com.sun.star.sdbc.XResultSetMetaDataSupplier </type> + <type> com.sun.star.sdbc.XRow </type> + <type> com.sun.star.ucb.ContentAction </type> + <type> com.sun.star.ucb.ContentInfoAttribute </type> + <type> com.sun.star.ucb.FileSystemNotation </type> + <type> com.sun.star.ucb.InsertCommandArgument </type> + <type> com.sun.star.ucb.InteractiveBadTransferURLException </type> + <type> com.sun.star.ucb.ListAction </type> + <type> com.sun.star.ucb.NameClash </type> + <type> com.sun.star.ucb.NumberedSortingInfo </type> + <type> com.sun.star.ucb.OpenCommandArgument2 </type> + <type> com.sun.star.ucb.OpenMode </type> + <type> com.sun.star.ucb.TransferInfo </type> + <type> com.sun.star.ucb.WelcomeDynamicResultSetStruct </type> + <type> com.sun.star.ucb.XCachedDynamicResultSetStubFactory </type> + <type> com.sun.star.ucb.XCommandInfo </type> + <type> com.sun.star.ucb.XCommandProcessor </type> + <type> com.sun.star.ucb.XContentAccess </type> + <type> com.sun.star.ucb.XContentCreator </type> + <type> com.sun.star.ucb.XContentIdentifier </type> + <type> com.sun.star.ucb.XContentIdentifierFactory </type> + <type> com.sun.star.ucb.XContentProvider </type> + <type> com.sun.star.ucb.XDynamicResultSet </type> + <type> com.sun.star.ucb.XFileIdentifierConverter </type> + <type> com.sun.star.ucb.XPropertySetRegistryFactory </type> + <type> com.sun.star.ucb.XSourceInitialization </type> + <type> com.sun.star.uno.XWeak </type> +</module-description> diff --git a/ucb/source/ucp/file/ucpfile1.component b/ucb/source/ucp/file/ucpfile1.component new file mode 100644 index 000000000000..28032451220a --- /dev/null +++ b/ucb/source/ucp/file/ucpfile1.component @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* 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. +* +**********************************************************************--> + +<component loader="com.sun.star.loader.SharedLibrary" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.ucb.FileProvider"> + <service name="com.sun.star.ucb.FileContentProvider"/> + </implementation> +</component> diff --git a/ucb/source/ucp/ftp/curl.hxx b/ucb/source/ucp/ftp/curl.hxx new file mode 100644 index 000000000000..70ace6e9fd76 --- /dev/null +++ b/ucb/source/ucp/ftp/curl.hxx @@ -0,0 +1,41 @@ +/************************************************************************* + * + * 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 INCLUDED_UCB_SOURCE_UCP_FTP_CURL_HXX +#define INCLUDED_UCB_SOURCE_UCP_FTP_CURL_HXX + +#if defined _MSC_VER +#pragma warning(push, 1) +#endif + +#include "curl/curl.h" + +#if defined _MSC_VER +#pragma warning(pop) +#endif + +#endif diff --git a/ucb/source/ucp/ftp/ftpcfunc.cxx b/ucb/source/ucp/ftp/ftpcfunc.cxx new file mode 100644 index 000000000000..24eafec542dd --- /dev/null +++ b/ucb/source/ucp/ftp/ftpcfunc.cxx @@ -0,0 +1,56 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ +#include <string.h> + +#include "ftpcontentidentifier.hxx" +#include "ftpinpstr.hxx" +#include <stdio.h> + +using namespace ftp; +using namespace com::sun::star::uno; + +extern "C" { + + int file_write(void *buffer,size_t size,size_t nmemb,void *stream) + { + FILE* file = + reinterpret_cast<FILE*>(stream); + if(!file) + return 0; + return fwrite(buffer,size,nmemb,file); + } + +} diff --git a/ucb/source/ucp/ftp/ftpcfunc.hxx b/ucb/source/ucp/ftp/ftpcfunc.hxx new file mode 100644 index 000000000000..3b0f63dd8a8d --- /dev/null +++ b/ucb/source/ucp/ftp/ftpcfunc.hxx @@ -0,0 +1,63 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ +#ifndef _FTP_FTPCFUNC_HXX_ +#define _FTP_FTPCFUNC_HXX_ + +#include <rtl/ustring.hxx> + + +namespace ftp { + + class FTPStreamContainer + { + public: + + virtual size_t write(void *buffer,size_t size,size_t nmemb) = 0; + }; + +} + + +extern "C" { + + /** callback for curl_easy_perform(), + * forwarding the written content to the stream. + * stream has to be of type 'FTPStreamContainer'. + */ + + + int file_write(void *buffer,size_t size,size_t nmemb,void *stream); + +} + +#endif diff --git a/ucb/source/ucp/ftp/ftpcontainer.hxx b/ucb/source/ucp/ftp/ftpcontainer.hxx new file mode 100644 index 000000000000..6c57bdf1e43f --- /dev/null +++ b/ucb/source/ucp/ftp/ftpcontainer.hxx @@ -0,0 +1,61 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ + +#include <sal/types.h> + +namespace ftp { + +class MemoryContainer { + +public: + + MemoryContainer(); + + ~MemoryContainer(); + + int append( + const void* pBuffer, + size_t size, + size_t nmemb + ) throw(); + + + sal_uInt32 m_nLen,m_nWritePos; + void *m_pBuffer; +}; + +} + + +extern "C" int memory_write( + void *buffer,size_t size,size_t nmemb,void *stream); + diff --git a/ucb/source/ucp/ftp/ftpcontent.cxx b/ucb/source/ucp/ftp/ftpcontent.cxx new file mode 100644 index 000000000000..4659197b81b5 --- /dev/null +++ b/ucb/source/ucp/ftp/ftpcontent.cxx @@ -0,0 +1,957 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ +#include <com/sun/star/beans/PropertyAttribute.hpp> + +#include "ftpdynresultset.hxx" +#include "ftpresultsetfactory.hxx" +#include "ftpresultsetI.hxx" +#include "ftpcontent.hxx" +#include "ftpcontentprovider.hxx" +#include "ftpinpstr.hxx" +#include "ftpdirp.hxx" +#include "ftpcontentidentifier.hxx" +#include "ftpcfunc.hxx" +#include "ftpstrcont.hxx" +#include "ftpintreq.hxx" + +#include <memory> +#include <vector> +#include <rtl/memory.h> +#include "curl.hxx" +#include <curl/easy.h> +#include <ucbhelper/cancelcommandexecution.hxx> +#include <ucbhelper/contentidentifier.hxx> +#include <ucbhelper/propertyvalueset.hxx> +#include <ucbhelper/contentidentifier.hxx> +#include <ucbhelper/cancelcommandexecution.hxx> +#include <ucbhelper/simpleauthenticationrequest.hxx> +#include <com/sun/star/lang/IllegalAccessException.hpp> +#include <com/sun/star/ucb/ContentInfoAttribute.hpp> +#include <com/sun/star/beans/UnknownPropertyException.hpp> +#include <com/sun/star/beans/Property.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/ucb/XCommandInfo.hpp> +#include <com/sun/star/io/XActiveDataSink.hpp> +#include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/io/XActiveDataStreamer.hpp> +#include <com/sun/star/ucb/UnsupportedDataSinkException.hpp> +#include <com/sun/star/ucb/OpenCommandArgument2.hpp> +#include <com/sun/star/ucb/UnsupportedOpenModeException.hpp> +#include <com/sun/star/ucb/InteractiveNetworkConnectException.hpp> +#include <com/sun/star/ucb/InteractiveNetworkResolveNameException.hpp> +#include <com/sun/star/ucb/InteractiveIOException.hpp> +#include <com/sun/star/ucb/MissingPropertiesException.hpp> +#include <com/sun/star/ucb/MissingInputStreamException.hpp> +#include <com/sun/star/ucb/UnsupportedNameClashException.hpp> +#include <com/sun/star/ucb/NameClashException.hpp> +//#include <com/sun/star/ucb/NameClash.hpp> +#include <com/sun/star/ucb/OpenMode.hpp> +#include <com/sun/star/ucb/IOErrorCode.hpp> + +using namespace ftp; +using namespace com::sun::star::task; +using namespace com::sun::star::container; +using namespace com::sun::star::lang; +using namespace com::sun::star::uno; +using namespace com::sun::star::ucb; +using namespace com::sun::star::beans; +using namespace com::sun::star::io; +using namespace com::sun::star::sdbc; + + + +//========================================================================= +//========================================================================= +// +// Content Implementation. +// +//========================================================================= +//========================================================================= + +FTPContent::FTPContent( const Reference< XMultiServiceFactory >& rxSMgr, + FTPContentProvider* pProvider, + const Reference< XContentIdentifier >& Identifier, + const FTPURL& aFTPURL) + : ContentImplHelper(rxSMgr,pProvider,Identifier), + m_pFCP(pProvider), + m_aFTPURL(aFTPURL), + m_bInserted(false), + m_bTitleSet(false) +{ +} + + + +FTPContent::FTPContent( const Reference< XMultiServiceFactory >& rxSMgr, + FTPContentProvider* pProvider, + const Reference< XContentIdentifier >& Identifier, + const ContentInfo& Info) + : ContentImplHelper(rxSMgr,pProvider,Identifier), + m_pFCP(pProvider), + m_aFTPURL(Identifier->getContentIdentifier(), + pProvider), + m_bInserted(true), + m_bTitleSet(false), + m_aInfo(Info) +{ +} + + + +//========================================================================= + +FTPContent::~FTPContent() +{ +} + + +//========================================================================= +// +// XInterface methods. +// +//========================================================================= + +XINTERFACE_IMPL_6( FTPContent, + XTypeProvider, + XServiceInfo, + XContent, + XCommandProcessor, + XContentCreator, + XChild); + +//========================================================================= +// +// XTypeProvider methods. +// +//========================================================================= + +XTYPEPROVIDER_IMPL_6( FTPContent, + XTypeProvider, + XServiceInfo, + XContent, + XCommandProcessor, + XContentCreator, + XChild); + +//========================================================================= +// +// XServiceInfo methods. +// +//========================================================================= + +// needed, because the service shall not be creatable!! +#undef XSERVICEINFO_CREATE_INSTANCE_IMPL +#define XSERVICEINFO_CREATE_INSTANCE_IMPL( Class ) + +XSERVICEINFO_IMPL_1( FTPContent, + rtl::OUString::createFromAscii( + "com.sun.star.comp.FTPContent"), + rtl::OUString::createFromAscii( + "com.sun.star.ucb.FTPContent")); + + + +//========================================================================= +// +// XContent methods. +// +//========================================================================= + +// virtual +rtl::OUString SAL_CALL FTPContent::getContentType() + throw( RuntimeException ) +{ + return rtl::OUString::createFromAscii(FTP_CONTENT_TYPE); +} + + +//========================================================================= +// +// XCommandProcessor methods. +// +//========================================================================= + + +//virtual +void SAL_CALL FTPContent::abort( sal_Int32 /*CommandId*/ ) + throw( RuntimeException ) +{ +} + + + +/***************************************************************************/ +/* */ +/* Internal implementation class. */ +/* */ +/***************************************************************************/ + + +class ResultSetFactoryI + : public ResultSetFactory +{ +public: + + ResultSetFactoryI(const Reference<XMultiServiceFactory >& xSMgr, + const Reference<XContentProvider >& xProvider, + sal_Int32 nOpenMode, + const Sequence<Property>& seq, + const Sequence<NumberedSortingInfo>& seqSort, + const std::vector<FTPDirentry>& dirvec) + : m_xSMgr(xSMgr), + m_xProvider(xProvider), + m_nOpenMode(nOpenMode), + m_seq(seq), + m_seqSort(seqSort), + m_dirvec(dirvec) + { + } + + virtual ResultSetBase* createResultSet() + { + return new ResultSetI(m_xSMgr, + m_xProvider, + m_nOpenMode, + m_seq, + m_seqSort, + m_dirvec); + } + +public: + + Reference< XMultiServiceFactory > m_xSMgr; + Reference< XContentProvider > m_xProvider; + sal_Int32 m_nOpenMode; + Sequence< Property > m_seq; + Sequence< NumberedSortingInfo > m_seqSort; + std::vector<FTPDirentry> m_dirvec; +}; + + + +//========================================================================= +// +// XCommandProcessor methods. +// +//========================================================================= + +enum ACTION { NOACTION, + THROWAUTHENTICATIONREQUEST, + THROWACCESSDENIED, + THROWINTERACTIVECONNECT, + THROWRESOLVENAME, + THROWQUOTE, + THROWNOFILE, + THROWGENERAL }; + + +// virtual +Any SAL_CALL FTPContent::execute( + const Command& aCommand, + sal_Int32 /*CommandId*/, + const Reference< + XCommandEnvironment >& Environment +) + throw( + Exception, + CommandAbortedException, + RuntimeException + ) +{ + ACTION action(NOACTION); + Any aRet; + + while(true) + try { + if(action == THROWAUTHENTICATIONREQUEST) { + // try to get a continuation first + rtl::OUString aRealm,aPassword,aAccount; + m_pFCP->forHost(m_aFTPURL.host(), + m_aFTPURL.port(), + m_aFTPURL.username(), + aPassword, + aAccount); + rtl::Reference<ucbhelper::SimpleAuthenticationRequest> + p( new ucbhelper::SimpleAuthenticationRequest( + m_aFTPURL.ident(false, false), + m_aFTPURL.host(), // ServerName + ucbhelper::SimpleAuthenticationRequest::ENTITY_NA, + aRealm, + ucbhelper::SimpleAuthenticationRequest + ::ENTITY_FIXED, + m_aFTPURL.username(), + ucbhelper::SimpleAuthenticationRequest + ::ENTITY_MODIFY, + aPassword)); + + Reference<XInteractionHandler> xInteractionHandler; + if(Environment.is()) + xInteractionHandler = + Environment->getInteractionHandler(); + + if( xInteractionHandler.is()) { + xInteractionHandler->handle(p.get()); + + Reference<XInterface> xSelection( + p->getSelection().get()); + + if(Reference<XInteractionRetry>( + xSelection,UNO_QUERY).is()) + action = NOACTION; + else if(Reference<XInteractionSupplyAuthentication>( + xSelection,UNO_QUERY).is()) { + m_pFCP->setHost( + m_aFTPURL.host(), + m_aFTPURL.port(), + m_aFTPURL.username(), + p->getAuthenticationSupplier()->getPassword(), + aAccount); + action = NOACTION; + } + } + aRet = p->getRequest(); + } + +// if(aCommand.Name.compareToAscii( +// "getPropertyValues") == 0 && +// action != NOACTION) { +// // It is not allowed to throw if +// // command is getPropertyValues +// rtl::Reference<ucbhelper::PropertyValueSet> xRow = +// new ucbhelper::PropertyValueSet(m_xSMgr); +// Sequence<Property> Properties; +// aCommand.Argument >>= Properties; +// for(int i = 0; i < Properties.getLength(); ++i) +// xRow->appendVoid(Properties[i]); +// aRet <<= Reference<XRow>(xRow.get()); +// return aRet; +// } + + switch (action) + { + case NOACTION: + break; + + case THROWAUTHENTICATIONREQUEST: + ucbhelper::cancelCommandExecution( + aRet, + Reference<XCommandEnvironment>(0)); + break; + + case THROWACCESSDENIED: + { + Sequence<Any> seq(1); + PropertyValue value; + value.Name = rtl::OUString::createFromAscii("Uri"); + value.Handle = -1; + value.Value <<= m_aFTPURL.ident(false,false); + value.State = PropertyState_DIRECT_VALUE; + seq[0] <<= value; + ucbhelper::cancelCommandExecution( + IOErrorCode_ACCESS_DENIED, + seq, + Environment); + break; + } + case THROWINTERACTIVECONNECT: + { + InteractiveNetworkConnectException excep; + excep.Server = m_aFTPURL.host(); + aRet <<= excep; + ucbhelper::cancelCommandExecution( + aRet, + Environment); + break; + } + case THROWRESOLVENAME: + { + InteractiveNetworkResolveNameException excep; + excep.Server = m_aFTPURL.host(); + aRet <<= excep; + ucbhelper::cancelCommandExecution( + aRet, + Environment); + break; + } + case THROWNOFILE: + { + Sequence<Any> seq(1); + PropertyValue value; + value.Name = rtl::OUString::createFromAscii("Uri"); + value.Handle = -1; + value.Value <<= m_aFTPURL.ident(false,false); + value.State = PropertyState_DIRECT_VALUE; + seq[0] <<= value; + ucbhelper::cancelCommandExecution( + IOErrorCode_NO_FILE, + seq, + Environment); + break; + } + case THROWQUOTE: + case THROWGENERAL: + ucbhelper::cancelCommandExecution( + IOErrorCode_GENERAL, + Sequence<Any>(0), + Environment); + break; + } + + if(aCommand.Name.compareToAscii("getPropertyValues") == 0) { + Sequence<Property> Properties; + if(!(aCommand.Argument >>= Properties)) + { + aRet <<= IllegalArgumentException( + rtl::OUString::createFromAscii( + "Wrong argument type!" ), + static_cast< cppu::OWeakObject * >(this), + -1); + ucbhelper::cancelCommandExecution(aRet,Environment); + } + + aRet <<= getPropertyValues(Properties,Environment); + } + else if(aCommand.Name.compareToAscii("setPropertyValues") == 0) + { + Sequence<PropertyValue> propertyValues; + + if( ! ( aCommand.Argument >>= propertyValues ) ) { + aRet <<= IllegalArgumentException( + rtl::OUString::createFromAscii( + "Wrong argument type!" ), + static_cast< cppu::OWeakObject * >(this), + -1); + ucbhelper::cancelCommandExecution(aRet,Environment); + } + + aRet <<= setPropertyValues(propertyValues); + } + else if(aCommand.Name.compareToAscii("getCommandInfo") == 0) { + // Note: Implemented by base class. + aRet <<= getCommandInfo(Environment); + } + else if(aCommand.Name.compareToAscii("getPropertySetInfo") == 0) { + // Note: Implemented by base class. + aRet <<= getPropertySetInfo(Environment); + } + else if(aCommand.Name.compareToAscii( "insert" ) == 0) + { + InsertCommandArgument aInsertArgument; + if ( ! ( aCommand.Argument >>= aInsertArgument ) ) { + aRet <<= IllegalArgumentException( + rtl::OUString::createFromAscii( + "Wrong argument type!" ), + static_cast< cppu::OWeakObject * >(this), + -1); + ucbhelper::cancelCommandExecution(aRet,Environment); + } + insert(aInsertArgument,Environment); + } + else if(aCommand.Name.compareToAscii("delete") == 0) { + m_aFTPURL.del(); + deleted(); + } + else if(aCommand.Name.compareToAscii( "open" ) == 0) { + OpenCommandArgument2 aOpenCommand; + if ( !( aCommand.Argument >>= aOpenCommand ) ) { + aRet <<= IllegalArgumentException( + rtl::OUString::createFromAscii( + "Wrong argument type!" ), + static_cast< cppu::OWeakObject * >(this), + -1); + + ucbhelper::cancelCommandExecution(aRet,Environment); + } + + if(aOpenCommand.Mode == OpenMode::DOCUMENT) { + // Open as a document + Reference<XActiveDataSink> + xActiveDataSink(aOpenCommand.Sink,UNO_QUERY); + Reference< XOutputStream > + xOutputStream(aOpenCommand.Sink,UNO_QUERY); + + if(xActiveDataSink.is()) { + xActiveDataSink->setInputStream( + new FTPInputStream(m_aFTPURL.open())); + } + else if(xOutputStream.is()) { + Reference<XInputStream> xStream( + new FTPInputStream(m_aFTPURL.open())); + Sequence<sal_Int8> byte_seq(4096); + sal_Int32 n = 1000; // value does not matter here + for (;;) { + n = xStream->readBytes(byte_seq,4096); + if (n == 0) { + break; + } + try { + if(byte_seq.getLength() != n) + byte_seq.realloc(n); + xOutputStream->writeBytes(byte_seq); + } catch(const NotConnectedException&) { + + } catch(const BufferSizeExceededException&) { + + } catch(const IOException&) { + + } + } + if(n) { + Sequence<Any> seq(1); + PropertyValue value; + value.Name = + rtl::OUString::createFromAscii("Uri"); + value.Handle = -1; + value.Value <<= m_aFTPURL.ident(false,false); + value.State = PropertyState_DIRECT_VALUE; + seq[0] <<= value; + ucbhelper::cancelCommandExecution( + IOErrorCode_UNKNOWN, + seq, + Environment); + } + } + else { + aRet <<= UnsupportedDataSinkException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >(this), + aOpenCommand.Sink); + ucbhelper::cancelCommandExecution(aRet,Environment); + } + } + else if(aOpenCommand.Mode == OpenMode::ALL || + aOpenCommand.Mode == OpenMode::DOCUMENTS || + aOpenCommand.Mode == OpenMode::FOLDERS ) { + std::vector<FTPDirentry> resvec = + m_aFTPURL.list(sal_Int16(aOpenCommand.Mode)); + Reference< XDynamicResultSet > xSet + = new DynamicResultSet( + m_xSMgr, + this, + aOpenCommand, + Environment, + new ResultSetFactoryI(m_xSMgr, + m_xProvider.get(), + aOpenCommand.Mode, + aOpenCommand.Properties, + aOpenCommand.SortingInfo, + resvec)); + aRet <<= xSet; + } + else if(aOpenCommand.Mode == + OpenMode::DOCUMENT_SHARE_DENY_NONE || + aOpenCommand.Mode == + OpenMode::DOCUMENT_SHARE_DENY_WRITE) { + // Unsupported OpenMode + aRet <<= UnsupportedOpenModeException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >(this), + static_cast< sal_Int16 >(aOpenCommand.Mode)); + ucbhelper::cancelCommandExecution(aRet,Environment); + } + else { + aRet <<= IllegalArgumentException( + rtl::OUString::createFromAscii( + "Unexpected OpenMode!" ), + static_cast< cppu::OWeakObject * >(this), + -1); + + ucbhelper::cancelCommandExecution(aRet,Environment); + } + } else if(aCommand.Name.compareToAscii("createNewContent") == 0) { + ContentInfo aArg; + if (!(aCommand.Argument >>= aArg)) { + ucbhelper::cancelCommandExecution( + makeAny( + IllegalArgumentException( + rtl::OUString::createFromAscii( + "Wrong argument type!" ), + static_cast< cppu::OWeakObject * >(this), + -1)), + Environment); + // Unreachable + } + aRet <<= createNewContent(aArg); + } else { + aRet <<= UnsupportedCommandException( + aCommand.Name, + static_cast< cppu::OWeakObject * >(this)); + ucbhelper::cancelCommandExecution(aRet,Environment); + } + + return aRet; + } catch(const curl_exception& e) { + if(e.code() == CURLE_COULDNT_CONNECT) + action = THROWINTERACTIVECONNECT; + else if(e.code() == CURLE_COULDNT_RESOLVE_HOST ) + action = THROWRESOLVENAME; + else if(e.code() == CURLE_FTP_USER_PASSWORD_INCORRECT || + e.code() == CURLE_LOGIN_DENIED || + e.code() == CURLE_BAD_PASSWORD_ENTERED || + e.code() == CURLE_FTP_WEIRD_PASS_REPLY) + action = THROWAUTHENTICATIONREQUEST; + else if(e.code() == CURLE_FTP_ACCESS_DENIED) + action = THROWACCESSDENIED; + else if(e.code() == CURLE_FTP_QUOTE_ERROR) + action = THROWQUOTE; + else if(e.code() == CURLE_FTP_COULDNT_RETR_FILE) + action = THROWNOFILE; + else + // nothing known about the cause of the error + action = THROWGENERAL; + } +} + +#define FTP_FILE rtl::OUString::createFromAscii( \ + "application/" \ + "vnd.sun.staroffice.ftp-file") + +#define FTP_FOLDER rtl::OUString::createFromAscii( \ + "application/" \ + "vnd.sun.staroffice.ftp-folder") + +Sequence<ContentInfo > SAL_CALL +FTPContent::queryCreatableContentsInfo( ) + throw (RuntimeException) +{ + return queryCreatableContentsInfo_Static(); +} + +// static +Sequence<ContentInfo > +FTPContent::queryCreatableContentsInfo_Static( ) + throw (RuntimeException) +{ + Sequence< ContentInfo > seq(2); + + seq[0].Type = FTP_FILE; + seq[0].Attributes = ContentInfoAttribute::INSERT_WITH_INPUTSTREAM + | ContentInfoAttribute::KIND_DOCUMENT; + Sequence< Property > props( 1 ); + props[0] = Property( + rtl::OUString::createFromAscii( "Title" ), + -1, + getCppuType( static_cast< rtl::OUString* >( 0 ) ), + PropertyAttribute::MAYBEVOID + | PropertyAttribute::BOUND ); + seq[0].Properties = props; + + // folder + seq[1].Type = FTP_FOLDER; + seq[1].Attributes = ContentInfoAttribute::KIND_FOLDER; + seq[1].Properties = props; + + return seq; +} + +Reference<XContent > SAL_CALL +FTPContent::createNewContent( const ContentInfo& Info ) + throw (RuntimeException) +{ + if(Info.Type.equalsAscii("application/" + "vnd.sun.staroffice.ftp-file") || + Info.Type.equalsAscii("application/" + "vnd.sun.staroffice.ftp-folder")) + return new FTPContent(m_xSMgr, + m_pFCP, + m_xIdentifier,Info); + else + return Reference<XContent>(0); +} + + + + +Reference<XInterface > SAL_CALL +FTPContent::getParent( ) + throw (RuntimeException) +{ + Reference<XContentIdentifier> + xIdent(new FTPContentIdentifier(m_aFTPURL.parent(false))); + Reference<XContent> xContent(m_xProvider->queryContent(xIdent)); + return Reference<XInterface>(xContent,UNO_QUERY); +} + + +void SAL_CALL +FTPContent::setParent(const Reference<XInterface >& /*Parent*/ ) + throw (NoSupportException, + RuntimeException) +{ + throw NoSupportException(); +} + + + +rtl::OUString FTPContent::getParentURL() +{ + return m_aFTPURL.parent(); +} + + +class InsertData + : public CurlInput { + +public: + + InsertData(const Reference<XInputStream>& xInputStream) + : m_xInputStream(xInputStream) { } + virtual ~InsertData() {} + + // returns the number of bytes actually read + virtual sal_Int32 read(sal_Int8 *dest,sal_Int32 nBytesRequested); + +private: + + Reference<XInputStream> m_xInputStream; +}; + + + +sal_Int32 InsertData::read(sal_Int8 *dest,sal_Int32 nBytesRequested) +{ + sal_Int32 m = 0; + + if(m_xInputStream.is()) { + Sequence<sal_Int8> seq(nBytesRequested); + m = m_xInputStream->readBytes(seq,nBytesRequested); + rtl_copyMemory(dest,seq.getConstArray(),m); + } + return m; +} + + +void FTPContent::insert(const InsertCommandArgument& aInsertCommand, + const Reference<XCommandEnvironment>& Env) +{ + osl::MutexGuard aGuard(m_aMutex); + + if(m_bInserted && !m_bTitleSet) { + MissingPropertiesException excep; + excep.Properties.realloc(1); + excep.Properties[0] = rtl::OUString::createFromAscii("Title"); + Any aAny; aAny <<= excep; + ucbhelper::cancelCommandExecution(aAny,Env); + } + + if(m_bInserted && + m_aInfo.Type == FTP_FILE && + !aInsertCommand.Data.is()) + { + MissingInputStreamException excep; + Any aAny; aAny <<= excep; + ucbhelper::cancelCommandExecution(aAny,Env); + } + + bool bReplace(aInsertCommand.ReplaceExisting); + + retry: + try { + if(m_aInfo.Type == FTP_FILE) { + InsertData data(aInsertCommand.Data); + m_aFTPURL.insert(bReplace,&data); + } else if(m_aInfo.Type == FTP_FOLDER) + m_aFTPURL.mkdir(bReplace); + } catch(const curl_exception& e) { + if(e.code() == FILE_EXIST_DURING_INSERT || + e.code() == FOLDER_EXIST_DURING_INSERT) { + // Deprecated, not used anymore: + NameClashException excep; + excep.Name = m_aFTPURL.child(); + Any aAny; + aAny <<= excep; + ucbhelper::cancelCommandExecution(aAny,Env); + } else if(e.code() == FOLDER_MIGHT_EXIST_DURING_INSERT || + e.code() == FILE_MIGHT_EXIST_DURING_INSERT) { + // Interact + Reference<XInteractionHandler> xInt; + if(Env.is()) + xInt = Env->getInteractionHandler(); + + UnsupportedNameClashException excep; + excep.NameClash = 0; //NameClash::ERROR; + + if(!xInt.is()) { + Any aAny; + aAny <<= excep; + ucbhelper::cancelCommandExecution(aAny,Env); + } + + XInteractionRequestImpl* p = + new XInteractionRequestImpl(m_aFTPURL.child()); + Reference<XInteractionRequest> req(p); + xInt->handle(req); + if(p->approved()) { + bReplace = true; + goto retry; + } + else + throw excep; + } + else + throw; + } + + // May not be reached, because both mkdir and insert can throw curl- + // exceptions + m_bInserted = false; + inserted(); +} + + + +Reference< XRow > FTPContent::getPropertyValues( + const Sequence< Property >& seqProp, + const Reference<XCommandEnvironment>& /*environment*/ +) +{ + rtl::Reference<ucbhelper::PropertyValueSet> xRow = + new ucbhelper::PropertyValueSet(m_xSMgr); + + FTPDirentry aDirEntry = m_aFTPURL.direntry(); + + for(sal_Int32 i = 0; i < seqProp.getLength(); ++i) { + const rtl::OUString& Name = seqProp[i].Name; + if(Name.compareToAscii("Title") == 0) + xRow->appendString(seqProp[i],aDirEntry.m_aName); + else if(Name.compareToAscii("CreatableContentsInfo") == 0) + xRow->appendObject(seqProp[i], + makeAny(queryCreatableContentsInfo())); + else if(aDirEntry.m_nMode != INETCOREFTP_FILEMODE_UNKNOWN) { + if(Name.compareToAscii("ContentType") == 0) + xRow->appendString(seqProp[i], + aDirEntry.m_nMode&INETCOREFTP_FILEMODE_ISDIR + ? FTP_FOLDER + : FTP_FILE ); + else if(Name.compareToAscii("IsReadOnly") == 0) + xRow->appendBoolean(seqProp[i], + aDirEntry.m_nMode + & INETCOREFTP_FILEMODE_WRITE + ? 0 + : 1 ); + else if(Name.compareToAscii("IsDocument") == 0) + xRow->appendBoolean(seqProp[i], + ! sal_Bool(aDirEntry.m_nMode & + INETCOREFTP_FILEMODE_ISDIR)); + else if(Name.compareToAscii("IsFolder") == 0) + xRow->appendBoolean(seqProp[i], + sal_Bool(aDirEntry.m_nMode & + INETCOREFTP_FILEMODE_ISDIR)); + else if(Name.compareToAscii("Size") == 0) + xRow->appendLong(seqProp[i], + aDirEntry.m_nSize); + else if(Name.compareToAscii("DateCreated") == 0) + xRow->appendTimestamp(seqProp[i], + aDirEntry.m_aDate); + else + xRow->appendVoid(seqProp[i]); + } else + xRow->appendVoid(seqProp[i]); + } + + return Reference<XRow>(xRow.get()); +} + + + +Sequence<Any> FTPContent::setPropertyValues( + const Sequence<PropertyValue>& seqPropVal) +{ + Sequence<Any> ret(seqPropVal.getLength()); + Sequence<PropertyChangeEvent > evt; + + osl::MutexGuard aGuard(m_aMutex); + for(sal_Int32 i = 0; i < ret.getLength(); ++i) { + if(seqPropVal[i].Name.equalsAscii("Title")) { + rtl::OUString Title; + if(!(seqPropVal[i].Value >>= Title)) { + ret[i] <<= IllegalTypeException(); + continue; + } else if(!Title.getLength()) { + ret[i] <<= IllegalArgumentException(); + continue; + } + + if(m_bInserted) { + m_aFTPURL.child(Title); + m_xIdentifier = + new FTPContentIdentifier(m_aFTPURL.ident(false,false)); + m_bTitleSet = true; + } else + try { + rtl::OUString OldTitle = m_aFTPURL.ren(Title); + evt.realloc(1); + evt[0].PropertyName = + rtl::OUString::createFromAscii("Title"); + evt[0].Further = false; + evt[0].PropertyHandle = -1; + evt[0].OldValue <<= OldTitle; + evt[0].NewValue <<= Title; + } catch(const curl_exception&) { + InteractiveIOException excep; + // any better possibility here? + // ( the error code is always CURLE_FTP_QUOTE_ERROR ) + excep.Code = IOErrorCode_ACCESS_DENIED; + ret[i] <<= excep; + } + } else { + Sequence<Property> props = + getProperties(Reference<XCommandEnvironment>(0)); + + // either unknown or read-only + ret[i] <<= UnknownPropertyException(); + for(sal_Int32 j = 0; j < props.getLength(); ++j) + if(props[j].Name == seqPropVal[i].Name) { + ret[i] <<= IllegalAccessException( + rtl::OUString::createFromAscii( + "Property is read-only!"), + //props[j].Attributes & PropertyAttribute::READONLY + // ? "Property is read-only!" + // : "Access denied!"), + static_cast< cppu::OWeakObject * >( this )); + break; + } + } + } + + if(evt.getLength()) { + // title has changed + notifyPropertiesChange(evt); + exchange(new FTPContentIdentifier(m_aFTPURL.ident(false,false))); + } + + return ret; +} diff --git a/ucb/source/ucp/ftp/ftpcontent.hxx b/ucb/source/ucp/ftp/ftpcontent.hxx new file mode 100644 index 000000000000..234810bd1eb9 --- /dev/null +++ b/ucb/source/ucp/ftp/ftpcontent.hxx @@ -0,0 +1,183 @@ +/************************************************************************* + * + * 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 _FTP_FTPCONTENT_HXX +#define _FTP_FTPCONTENT_HXX + +#include <ucbhelper/contenthelper.hxx> +#include <com/sun/star/ucb/InsertCommandArgument.hpp> +#include <com/sun/star/ucb/XContentCreator.hpp> +#include "ftpurl.hxx" + + +namespace com { namespace sun { namespace star { namespace beans { + struct Property; + struct PropertyValue; +} } } } + +namespace com { namespace sun { namespace star { namespace sdbc { + class XRow; +} } } } + + +namespace ftp +{ + +//========================================================================= + +// UNO service name for the content. +#define FTP_CONTENT_SERVICE_NAME "com.sun.star.ucb.FTPContent" + +//========================================================================= + + class FTPContentProvider; + +//========================================================================= + + class FTPContent + : public ::ucbhelper::ContentImplHelper, + public com::sun::star::ucb::XContentCreator + { + public: + + FTPContent( const ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + FTPContentProvider* pProvider, + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XContentIdentifier >& Identifier, + const FTPURL& FtpUrl); + + FTPContent( const ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + FTPContentProvider* pProvider, + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XContentIdentifier >& Identifier, + const com::sun::star::ucb::ContentInfo& aInfo); + + + virtual ~FTPContent(); + + // XInterface + XINTERFACE_DECL() + + // XTypeProvider + XTYPEPROVIDER_DECL() + + // XServiceInfo + XSERVICEINFO_DECL() + + // XContent + virtual rtl::OUString SAL_CALL + getContentType() + throw( com::sun::star::uno::RuntimeException ); + + // XCommandProcessor + virtual com::sun::star::uno::Any SAL_CALL + execute( const com::sun::star::ucb::Command& aCommand, + sal_Int32 CommandId, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment >& Environment ) + throw( com::sun::star::uno::Exception, + com::sun::star::ucb::CommandAbortedException, + com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL + abort(sal_Int32 CommandId) + throw( com::sun::star::uno::RuntimeException); + + // XContentCreator + virtual com::sun::star::uno::Sequence< + com::sun::star::ucb::ContentInfo > SAL_CALL + queryCreatableContentsInfo( ) + throw (com::sun::star::uno::RuntimeException); + + virtual com::sun::star::uno::Reference< + com::sun::star::ucb::XContent > SAL_CALL + createNewContent( const com::sun::star::ucb::ContentInfo& Info ) + throw (com::sun::star::uno::RuntimeException); + + // XChild + + virtual ::com::sun::star::uno::Reference< + ::com::sun::star::uno::XInterface > SAL_CALL + getParent( ) + throw (::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + setParent( const ::com::sun::star::uno::Reference< + ::com::sun::star::uno::XInterface >& Parent ) + throw (::com::sun::star::lang::NoSupportException, + ::com::sun::star::uno::RuntimeException); + + + static com::sun::star::uno::Sequence< + com::sun::star::ucb::ContentInfo > + queryCreatableContentsInfo_Static( ) + throw (com::sun::star::uno::RuntimeException); + + private: + + FTPContentProvider *m_pFCP; + FTPURL m_aFTPURL; + bool m_bInserted; + bool m_bTitleSet; + com::sun::star::ucb::ContentInfo m_aInfo; + + virtual com::sun::star::uno::Sequence< com::sun::star::beans::Property > + getProperties( const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv ); + + + virtual com::sun::star::uno::Sequence< + com::sun::star::ucb::CommandInfo> + getCommands(const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv); + + + virtual ::rtl::OUString getParentURL(); + + com::sun::star::uno::Reference<com::sun::star::sdbc::XRow> + getPropertyValues( + const com::sun::star::uno::Sequence< + com::sun::star::beans::Property>& seqProp, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment >& Environment + ); + + com::sun::star::uno::Sequence<com::sun::star::uno::Any> + setPropertyValues( + const ::com::sun::star::uno::Sequence< + ::com::sun::star::beans::PropertyValue>& seqPropVal); + + void insert(const com::sun::star::ucb::InsertCommandArgument&, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment>&); + }; + +} + +#endif diff --git a/ucb/source/ucp/ftp/ftpcontentcaps.cxx b/ucb/source/ucp/ftp/ftpcontentcaps.cxx new file mode 100644 index 000000000000..421d44401f6d --- /dev/null +++ b/ucb/source/ucp/ftp/ftpcontentcaps.cxx @@ -0,0 +1,187 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +#include <com/sun/star/beans/Property.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/ucb/CommandInfo.hpp> +#include <com/sun/star/ucb/OpenCommandArgument2.hpp> +#include <com/sun/star/ucb/InsertCommandArgument.hpp> +#include <com/sun/star/util/DateTime.hpp> +#include <com/sun/star/uno/Sequence.hxx> + +#include "ftpcontent.hxx" + +using namespace com::sun::star; +using namespace ftp; + +// virtual +uno::Sequence< beans::Property > FTPContent::getProperties( + const uno::Reference< ucb::XCommandEnvironment > & /*xEnv*/) +{ + #define PROPS_COUNT 8 + + static const beans::Property aPropsInfoTable[] = + { + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ContentType" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsDocument" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + // | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Size" ) ), + -1, + getCppuType( static_cast< const sal_Int64 * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DateCreated" ) ), + -1, + getCppuType( static_cast< util::DateTime * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsReadOnly" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "CreatableContentsInfo" ) ), + -1, + getCppuType( + static_cast< const uno::Sequence< ucb::ContentInfo > * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ) + }; + + return uno::Sequence< beans::Property >( aPropsInfoTable, PROPS_COUNT ); +} + +//========================================================================= +// virtual +uno::Sequence< ucb::CommandInfo > FTPContent::getCommands( + const uno::Reference< ucb::XCommandEnvironment > & /*xEnv*/ ) +{ +// osl::MutexGuard aGuard( m_aMutex ); + + //================================================================= + // + // Supported commands + // + //================================================================= + + #define COMMAND_COUNT 8 + + static const ucb::CommandInfo aCommandInfoTable[] = + { + /////////////////////////////////////////////////////////////// + // Required commands + /////////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getCommandInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertySetInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertyValues" ) ), + -1, + getCppuType( + static_cast< uno::Sequence< beans::Property > * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ), + -1, + getCppuType( + static_cast< uno::Sequence< beans::PropertyValue > * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "open" ) ), + -1, + getCppuType( + static_cast< ucb::OpenCommandArgument2 * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "insert" ) ), + -1, + getCppuType( + static_cast< ucb::InsertCommandArgument * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "delete" ) ), + -1, + getCppuBooleanType() + ), + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "createNewContent" ) ), + -1, + getCppuType( static_cast< ucb::ContentInfo * >( 0 ) ) + ) + }; + + return uno::Sequence< ucb::CommandInfo >( aCommandInfoTable, COMMAND_COUNT ); +} + diff --git a/ucb/source/ucp/ftp/ftpcontentidentifier.cxx b/ucb/source/ucp/ftp/ftpcontentidentifier.cxx new file mode 100644 index 000000000000..0d65c06a9281 --- /dev/null +++ b/ucb/source/ucp/ftp/ftpcontentidentifier.cxx @@ -0,0 +1,150 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ +#include "ftpcontentidentifier.hxx" +#include "ftpcontentprovider.hxx" + +using namespace ftp; +using namespace com::sun::star::uno; +using namespace com::sun::star::ucb; +using namespace com::sun::star::lang; + + +FTPContentIdentifier::FTPContentIdentifier( + const rtl::OUString& ident +) + : m_ident(ident) +{ +} + + +FTPContentIdentifier::~FTPContentIdentifier() +{ +} + + +Any SAL_CALL +FTPContentIdentifier::queryInterface( + const Type& rType +) + throw( + RuntimeException + ) +{ + Any aRet = + ::cppu::queryInterface(rType, + SAL_STATIC_CAST(XTypeProvider*,this), + SAL_STATIC_CAST(XContentIdentifier*,this)); + + return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ); +} + + +void SAL_CALL FTPContentIdentifier::acquire( void ) throw() { + OWeakObject::acquire(); +} + + +void SAL_CALL FTPContentIdentifier::release( void ) throw() { + OWeakObject::release(); +} + + +Sequence<sal_Int8> SAL_CALL +FTPContentIdentifier::getImplementationId() + throw(RuntimeException) +{ + static cppu::OImplementationId* pId = NULL; + if(!pId) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + if ( !pId ) + { + static cppu::OImplementationId id( sal_False ); + pId = &id; + } + } + return (*pId).getImplementationId(); +} + + +Sequence<Type> SAL_CALL +FTPContentIdentifier::getTypes( + void ) + throw(RuntimeException) +{ + static cppu::OTypeCollection* pCollection = NULL; + if ( !pCollection ) { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + if ( !pCollection ) + { + static cppu::OTypeCollection collection( + getCppuType( + static_cast<Reference<XTypeProvider>*>(0)), + getCppuType( + static_cast<Reference<XContentIdentifier>*>(0))); + pCollection = &collection; + } + } + return (*pCollection).getTypes(); +} + + +rtl::OUString SAL_CALL +FTPContentIdentifier::getContentIdentifier( +) + throw ( + com::sun::star::uno::RuntimeException + ) +{ + return m_ident; +} + + +rtl::OUString SAL_CALL +FTPContentIdentifier::getContentProviderScheme( +) + throw ( + com::sun::star::uno::RuntimeException + ) +{ + return rtl::OUString::createFromAscii("ftp"); +} + + + + + + diff --git a/ucb/source/ucp/ftp/ftpcontentidentifier.hxx b/ucb/source/ucp/ftp/ftpcontentidentifier.hxx new file mode 100644 index 000000000000..7827fc7148eb --- /dev/null +++ b/ucb/source/ucp/ftp/ftpcontentidentifier.hxx @@ -0,0 +1,118 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ +#ifndef _FTP_FTPCONTENTIDENTIFIER_HXX_ +#define _FTP_FTPCONTENTIDENTIFIER_HXX_ + +#include <vector> +#include "curl.hxx" +#include <curl/easy.h> +#include <cppuhelper/weak.hxx> +#include <cppuhelper/queryinterface.hxx> +#include <com/sun/star/ucb/XContentIdentifier.hpp> +#include <com/sun/star/lang/XTypeProvider.hpp> + +#include "ftpdirp.hxx" +#include "ftpurl.hxx" + + +namespace ftp { + + + class FTPContentProvider; + + + class FTPContentIdentifier + : public cppu::OWeakObject, + public com::sun::star::lang::XTypeProvider, + public com::sun::star::ucb::XContentIdentifier + { + public: + + FTPContentIdentifier(const rtl::OUString& ident); + + ~FTPContentIdentifier(); + + // XInterface + + virtual com::sun::star::uno::Any SAL_CALL + queryInterface( const com::sun::star::uno::Type& rType ) + throw( com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL acquire( void ) throw(); + + virtual void SAL_CALL release( void ) throw(); + + // XTypeProvider + + virtual + com::sun::star::uno::Sequence<com::sun::star::uno::Type> SAL_CALL + getTypes( + ) + throw( + com::sun::star::uno::RuntimeException + ); + + virtual com::sun::star::uno::Sequence<sal_Int8> SAL_CALL + getImplementationId( + ) + throw( + com::sun::star::uno::RuntimeException + ); + + + // XContentIdentifier + + virtual ::rtl::OUString SAL_CALL + getContentIdentifier( + ) + throw ( + com::sun::star::uno::RuntimeException + ); + + virtual ::rtl::OUString SAL_CALL + getContentProviderScheme( + ) + throw ( + ::com::sun::star::uno::RuntimeException + ); + + + private: + + rtl::OUString m_ident; + }; + +} + + +#endif diff --git a/ucb/source/ucp/ftp/ftpcontentprovider.cxx b/ucb/source/ucp/ftp/ftpcontentprovider.cxx new file mode 100644 index 000000000000..2cfc62afe440 --- /dev/null +++ b/ucb/source/ucp/ftp/ftpcontentprovider.cxx @@ -0,0 +1,280 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ + +#include <ucbhelper/contentbroker.hxx> +#include <osl/socket.hxx> +#include "ftpcontentprovider.hxx" +#include "ftpcontent.hxx" +#include "ftploaderthread.hxx" + + +using namespace ftp; +using namespace com::sun::star::lang; +using namespace com::sun::star::container; +using namespace com::sun::star::uno; +using namespace com::sun::star::ucb; +using namespace com::sun::star::beans; + + + +//========================================================================= +//========================================================================= +// +// ContentProvider Implementation. +// +//========================================================================= +//========================================================================= + +FTPContentProvider::FTPContentProvider( + const Reference< XMultiServiceFactory >& rSMgr) +: ::ucbhelper::ContentProviderImplHelper(rSMgr), + m_ftpLoaderThread(0), + m_pProxyDecider(0) +{ +} + +//========================================================================= +// virtual +FTPContentProvider::~FTPContentProvider() +{ + delete m_ftpLoaderThread; + delete m_pProxyDecider; +} + +//========================================================================= +// +// XInterface methods. +// +//========================================================================= + +XINTERFACE_IMPL_3(FTPContentProvider, + XTypeProvider, + XServiceInfo, + XContentProvider) + +//========================================================================= +// +// XTypeProvider methods. +// +//========================================================================= + +XTYPEPROVIDER_IMPL_3(FTPContentProvider, + XTypeProvider, + XServiceInfo, + XContentProvider) + +//========================================================================= +// +// XServiceInfo methods. +// +//========================================================================= + +XSERVICEINFO_IMPL_1( + FTPContentProvider, + rtl::OUString::createFromAscii("com.sun.star.comp.FTPContentProvider"), + rtl::OUString::createFromAscii(FTP_CONTENT_PROVIDER_SERVICE_NAME)); + +//========================================================================= +// +// Service factory implementation. +// +//========================================================================= + +ONE_INSTANCE_SERVICE_FACTORY_IMPL(FTPContentProvider); + + +//========================================================================= +// +// XContentProvider methods. +// +//========================================================================= + +// virtual +Reference<XContent> SAL_CALL +FTPContentProvider::queryContent( + const Reference< XContentIdentifier >& xCanonicId +) + throw( + IllegalIdentifierException, + RuntimeException + ) +{ + // Check, if a content with given id already exists... + Reference<XContent> xContent = queryExistingContent(xCanonicId).get(); + if(xContent.is()) + return xContent; + + // A new content has to be returned: + { + // Initialize + osl::MutexGuard aGuard( m_aMutex ); + if(!m_ftpLoaderThread || !m_pProxyDecider) + { + try { + init(); + } catch( ... ) { + throw RuntimeException(); + } + + if(!m_ftpLoaderThread || !m_pProxyDecider) + throw RuntimeException(); + } + } + + try { + FTPURL aURL(xCanonicId->getContentIdentifier(), + this); + + if(!m_pProxyDecider->shouldUseProxy( + rtl::OUString::createFromAscii("ftp"), + aURL.host(), + aURL.port().toInt32())) + { + xContent = new FTPContent(m_xSMgr,this,xCanonicId,aURL); + registerNewContent(xContent); + } + else { + Reference<XContentProvider> + xProvider(getHttpProvider()); + if(xProvider.is()) + return xProvider->queryContent(xCanonicId); + else + throw RuntimeException(); + } + } catch(const malformed_exception&) { + throw IllegalIdentifierException(); + } + + // may throw IllegalIdentifierException + return xContent; +} + + + + +void FTPContentProvider::init() { + m_ftpLoaderThread = new FTPLoaderThread(); + m_pProxyDecider = new ucbhelper::InternetProxyDecider(m_xSMgr); +} + + + +CURL* FTPContentProvider::handle() { + // Cannot be zero if called from here; + return m_ftpLoaderThread->handle(); +} + + +bool FTPContentProvider::forHost( + const rtl::OUString& host, + const rtl::OUString& port, + const rtl::OUString& username, + rtl::OUString& password, + rtl::OUString& account) +{ + osl::MutexGuard aGuard(m_aMutex); + for(unsigned int i = 0; i < m_ServerInfo.size(); ++i) + if(host == m_ServerInfo[i].host && + port == m_ServerInfo[i].port && + username == m_ServerInfo[i].username ) + { + password = m_ServerInfo[i].password; + account = m_ServerInfo[i].account; + return true; + } + + return false; +} + + +bool FTPContentProvider::setHost( + const rtl::OUString& host, + const rtl::OUString& port, + const rtl::OUString& username, + const rtl::OUString& password, + const rtl::OUString& account) +{ + ServerInfo inf; + inf.host = host; + inf.port = port; + inf.username = username; + inf.password = password; + inf.account = account; + + bool present(false); + osl::MutexGuard aGuard(m_aMutex); + for(unsigned int i = 0; i < m_ServerInfo.size(); ++i) + if(host == m_ServerInfo[i].host && + port == m_ServerInfo[i].port && + username == m_ServerInfo[i].username) + { + present = true; + m_ServerInfo[i].password = password; + m_ServerInfo[i].account = account; + } + + if(!present) + m_ServerInfo.push_back(inf); + + return !present; +} + + + +Reference<XContentProvider> +FTPContentProvider::getHttpProvider() + throw(RuntimeException) +{ + // used for access to ftp-proxy + ucbhelper::ContentBroker *pBroker = ucbhelper::ContentBroker::get(); + + if(pBroker) { + Reference<XContentProviderManager > xManager( + pBroker->getContentProviderManagerInterface()); + + if(xManager.is()) + return + xManager->queryContentProvider( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("http:"))); + else + throw RuntimeException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "bad ucbhelper::ContentBroker")), + *this); + } else + return 0; + +} diff --git a/ucb/source/ucp/ftp/ftpcontentprovider.hxx b/ucb/source/ucp/ftp/ftpcontentprovider.hxx new file mode 100644 index 000000000000..30b74a5f44c8 --- /dev/null +++ b/ucb/source/ucp/ftp/ftpcontentprovider.hxx @@ -0,0 +1,130 @@ +/************************************************************************* + * + * 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 _FTP_FTPCONTENTPROVIDER_HXX_ +#define _FTP_FTPCONTENTPROVIDER_HXX_ + +#include <vector> +#include <osl/mutex.hxx> +#include <ucbhelper/macros.hxx> +#include <ucbhelper/proxydecider.hxx> +#include <ucbhelper/providerhelper.hxx> +#include <com/sun/star/ucb/XContentProviderManager.hpp> +#include "ftphandleprovider.hxx" +#include "ftpurl.hxx" + +// UNO service name for the provider. This name will be used by the UCB to +// create instances of the provider. + +#define FTP_CONTENT_PROVIDER_SERVICE_NAME "com.sun.star.ucb.FTPContentProvider" +#define FTP_CONTENT_TYPE "application/ftp-content" + + +/** + * Definition of ftpcontentprovider + */ + + + +namespace ftp { + + + class FTPLoaderThread; + + + class FTPContentProvider: + public ::ucbhelper::ContentProviderImplHelper, + public FTPHandleProvider + { + public: + + FTPContentProvider( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory>& xMSF ); + + ~FTPContentProvider(); + + // XInterface + XINTERFACE_DECL() + + // XTypeProvider + XTYPEPROVIDER_DECL() + + // XServiceInfo + XSERVICEINFO_DECL() + + // XContentProvider + virtual com::sun::star::uno::Reference< com::sun::star::ucb::XContent > SAL_CALL + queryContent( + const com::sun::star::uno::Reference< com::sun::star::ucb::XContentIdentifier >& Identifier ) + throw( com::sun::star::ucb::IllegalIdentifierException, + com::sun::star::uno::RuntimeException ); + + // FTPHandleProvider. + + virtual CURL* handle(); + + virtual bool forHost(const rtl::OUString& host, + const rtl::OUString& port, + const rtl::OUString& username, + rtl::OUString& password, + rtl::OUString& account); + + virtual bool setHost(const rtl::OUString& host, + const rtl::OUString& port, + const rtl::OUString& username, + const rtl::OUString& password, + const rtl::OUString& account); + + + struct ServerInfo { + rtl::OUString host; + rtl::OUString port; + rtl::OUString username; + rtl::OUString password; + rtl::OUString account; + }; + + private: + + osl::Mutex m_aMutex; + FTPLoaderThread *m_ftpLoaderThread; + ucbhelper::InternetProxyDecider *m_pProxyDecider; + std::vector<ServerInfo> m_ServerInfo; + + void init(); + + com::sun::star::uno::Reference<com::sun::star::ucb::XContentProvider> + getHttpProvider() + throw(com::sun::star::uno::RuntimeException); + + }; // end class FTPContentProvider + +} // end namespace ftp + +#endif + diff --git a/ucb/source/ucp/ftp/ftpdirp.cxx b/ucb/source/ucp/ftp/ftpdirp.cxx new file mode 100644 index 000000000000..10f6fa88a6c0 --- /dev/null +++ b/ucb/source/ucp/ftp/ftpdirp.cxx @@ -0,0 +1,1292 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ +#include "ftpdirp.hxx" +#include <osl/time.h> + + +using namespace rtl; +using namespace ftp; + + +typedef sal_uInt32 ULONG; + + +inline sal_Bool ascii_isLetter( sal_Unicode ch ) +{ + return (( (ch >= 0x0041) && (ch <= 0x005A)) || + (( ch >= 0x0061) && (ch <= 0x007A))); +} + +inline sal_Bool ascii_isWhitespace( sal_Unicode ch ) +{ + return ((ch <= 0x20) && ch); +} + + + +/*======================================================================== + * + * FTPDirectoryParser implementation. + * + *======================================================================*/ +/* + * parseDOS. + * Accepts one of two styles: + * + * 1 *WSP 1*2DIGIT ("." / "-") 1*2DIGIT ("." / "-") 1*4DIGIT 1*WSP + * 1*2DIGIT ":" 1*2DIGIT [*WSP ("A" / "P") "M"] 1*WSP + * ((DIGIT *(DIGIT / "." / ",")) / "<DIR>") 1*WSP 1*OCTET + * + * interpreted as: mm.dd.yy hh:mm (size / <DIR>) name + * + * 2 *WSP 1*DIGIT 1*WSP *(1*CHAR *WSP) *1("DIR" 1*WSP) 1*2DIGIT "-" 1*2DIGIT + * "-" 1*4DIGIT 1*WSP 1*2DIGIT ":" 1*2DIGIT 1*WSP 1*OCTET + * + * interpreted as: size attribs DIR mm-dd-yy hh:mm name + */ + +sal_Bool FTPDirectoryParser::parseDOS ( + FTPDirentry &rEntry, + const sal_Char *pBuffer) +{ + sal_Bool bDirectory = false; + sal_uInt32 nSize = 0; + sal_uInt16 nYear = 0; + sal_uInt16 nMonth = 0; + sal_uInt16 nDay = 0; + sal_uInt16 nHour = 0; + sal_uInt16 nMinute = 0; + + enum StateType + { + STATE_INIT_LWS, + STATE_MONTH_OR_SIZE, + STATE_1_DAY, STATE_1_YEAR, STATE_1_YEAR_LWS, STATE_1_HOUR, + STATE_1_MINUTE, STATE_1_MINUTE_LWS, STATE_1_AP, + STATE_1_APM, STATE_1_LESS, STATE_1_D, STATE_1_DI, + STATE_1_DIR, STATE_1_SIZE, + STATE_2_SIZE, STATE_2_SIZE_LWS, STATE_2_ATTRIB, + STATE_2_D, STATE_2_DI, STATE_2_DIR_LWS, + STATE_2_MONTH, STATE_2_DAY, STATE_2_YEAR, STATE_2_YEAR_LWS, + STATE_2_HOUR, STATE_2_MINUTE, + STATE_LWS_NAME, + STATE_ERROR + }; + + int nDigits = 0; + enum StateType eState = STATE_INIT_LWS; + for (const sal_Char *p = pBuffer; + eState != STATE_ERROR && *p; + ++p) + { + switch (eState) + { + case STATE_INIT_LWS: + if (*p >= '0' && *p <= '9') + { + nMonth = *p - '0'; + nDigits = 1; + eState = STATE_MONTH_OR_SIZE; + } + else if (!ascii_isWhitespace(*p)) + eState = STATE_ERROR; + break; + + case STATE_MONTH_OR_SIZE: + if (*p >= '0' && *p <= '9') + { + nMonth = 10 * nMonth + (*p - '0'); + if (nDigits < 2) + ++nDigits; + else + { + nSize = nMonth; + nMonth = 0; + eState = STATE_2_SIZE; + } + } + else if (ascii_isWhitespace(*p)) + { + nSize = nMonth; + nMonth = 0; + eState = STATE_2_SIZE_LWS; + } + else if ((*p == '.' || *p == '-') && nMonth && nMonth <= 12) + { + nDigits = 0; + eState = STATE_1_DAY; + } + else + eState = STATE_ERROR; + break; + + case STATE_1_DAY: + if (*p >= '0' && *p <= '9') + if (nDigits < 2) + { + nDay = 10 * nDay + (*p - '0'); + ++nDigits; + } + else + eState = STATE_ERROR; + else if ((*p == '.' || *p == '-') && nDay && nDay <= 31) + { + nDigits = 0; + eState = STATE_1_YEAR; + } + else + eState = STATE_ERROR; + break; + + case STATE_1_YEAR: + if (*p >= '0' && *p <= '9') + { + if (nDigits < 4) + { + nYear = 10 * nYear + (*p - '0'); + ++nDigits; + } + else + eState = STATE_ERROR; + } + else + { + if (ascii_isWhitespace(*p)) + eState = STATE_1_YEAR_LWS; + else + eState = STATE_ERROR; + } + break; + + case STATE_1_YEAR_LWS: + if (*p >= '0' && *p <= '9') + { + nHour = *p - '0'; + nDigits = 1; + eState = STATE_1_HOUR; + } + else if (!ascii_isWhitespace(*p)) + eState = STATE_ERROR; + break; + + case STATE_1_HOUR: + if (*p >= '0' && *p <= '9') + if (nDigits < 2) + { + nHour = 10 * nHour + (*p - '0'); + ++nDigits; + } + else + eState = STATE_ERROR; + else if (*p == ':' && nHour < 24) + { + nDigits = 0; + eState = STATE_1_MINUTE; + } + else + eState = STATE_ERROR; + break; + + case STATE_1_MINUTE: + if (*p >= '0' && *p <= '9') + if (nDigits < 2) + { + nMinute = 10 * nMinute + (*p - '0'); + ++nDigits; + } + else + eState = STATE_ERROR; + else if ((*p == 'a' || *p == 'A') && nMinute < 60) + if (nHour >= 1 && nHour <= 11) + eState = STATE_1_AP; + else if (nHour == 12) + { + nHour = 0; + eState = STATE_1_AP; + } + else + eState = STATE_ERROR; + else if ((*p == 'p' || *p == 'P') && nMinute < 60) + if (nHour >= 1 && nHour <= 11) + { + nHour += 12; + eState = STATE_1_AP; + } + else if (nHour == 12) + eState = STATE_1_AP; + else + eState = STATE_ERROR; + else if (ascii_isWhitespace(*p) && (nMinute < 60)) + eState = STATE_1_MINUTE_LWS; + else + eState = STATE_ERROR; + break; + + case STATE_1_MINUTE_LWS: + if (*p == 'a' || *p == 'A') + if (nHour >= 1 && nHour <= 11) + eState = STATE_1_AP; + else if (nHour == 12) + { + nHour = 0; + eState = STATE_1_AP; + } + else + eState = STATE_ERROR; + else if (*p == 'p' || *p == 'P') + if (nHour >= 1 && nHour <= 11) + { + nHour += 12; + eState = STATE_1_AP; + } + else if (nHour == 12) + eState = STATE_1_AP; + else + eState = STATE_ERROR; + else if (*p == '<') + eState = STATE_1_LESS; + else if (*p >= '0' && *p <= '9') + { + nSize = *p - '0'; + eState = STATE_1_SIZE; + } + else if (!ascii_isWhitespace(*p)) + eState = STATE_ERROR; + break; + + case STATE_1_AP: + eState = *p == 'm' || *p == 'M' ? STATE_1_APM : STATE_ERROR; + break; + + case STATE_1_APM: + if (*p == '<') + eState = STATE_1_LESS; + else if (*p >= '0' && *p <= '9') + { + nSize = *p - '0'; + eState = STATE_1_SIZE; + } + else if (!ascii_isWhitespace(*p)) + eState = STATE_ERROR; + break; + + case STATE_1_LESS: + eState = *p == 'd' || *p == 'D' ? STATE_1_D : STATE_ERROR; + break; + + case STATE_1_D: + eState = *p == 'i' || *p == 'I' ? STATE_1_DI : STATE_ERROR; + break; + + case STATE_1_DI: + eState = *p == 'r' || *p == 'R' ? STATE_1_DIR : STATE_ERROR; + break; + + case STATE_1_DIR: + if (*p == '>') + { + bDirectory = true; + eState = STATE_LWS_NAME; + } + else + eState = STATE_ERROR; + break; + + case STATE_1_SIZE: + if (*p >= '0' && *p <= '9') + nSize = 10 * nSize + (*p - '0'); + else if (ascii_isWhitespace(*p)) + eState = STATE_LWS_NAME; + else + eState = STATE_ERROR; + break; + + case STATE_2_SIZE: + if (*p >= '0' && *p <= '9') + nSize = 10 * nSize + (*p - '0'); + else if (ascii_isWhitespace(*p)) + eState = STATE_2_SIZE_LWS; + else + eState = STATE_ERROR; + break; + + case STATE_2_SIZE_LWS: + if (*p == 'd' || *p == 'D') + eState = STATE_2_D; + else if ((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z')) + eState = STATE_2_ATTRIB; + else if (*p >= '0' && *p <= '9') + { + nMonth = *p - '0'; + nDigits = 1; + eState = STATE_2_MONTH; + } + else if (!ascii_isWhitespace(*p)) + eState = STATE_ERROR; + break; + + case STATE_2_ATTRIB: + if (ascii_isWhitespace(*p)) + eState = STATE_2_SIZE_LWS; + else if ((*p < 'a' || *p > 'z') && (*p < 'A' || *p > 'Z')) + eState = STATE_ERROR; + break; + + case STATE_2_D: + if (*p == 'i' || *p == 'I') + eState = STATE_2_DI; + else if ((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z')) + eState = STATE_2_ATTRIB; + else if (ascii_isWhitespace(*p)) + eState = STATE_2_SIZE_LWS; + else + eState = STATE_ERROR; + break; + + case STATE_2_DI: + if (*p == 'r' || *p == 'R') + { + bDirectory = true; + eState = STATE_2_DIR_LWS; + } + else + { + if ((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z')) + eState = STATE_2_ATTRIB; + else if (ascii_isWhitespace(*p)) + eState = STATE_2_SIZE_LWS; + else + eState = STATE_ERROR; + } + break; + + case STATE_2_DIR_LWS: + if (*p >= '0' && *p <= '9') + { + nMonth = *p - '0'; + nDigits = 1; + eState = STATE_2_MONTH; + } + else if (!ascii_isWhitespace(*p)) + eState = STATE_ERROR; + break; + + case STATE_2_MONTH: + if (*p >= '0' && *p <= '9') + if (nDigits < 2) + { + nMonth = 10 * nMonth + (*p - '0'); + ++nDigits; + } + else + eState = STATE_ERROR; + else if (*p == '-' && nMonth && nMonth <= 12) + { + nDigits = 0; + eState = STATE_2_DAY; + } + else + eState = STATE_ERROR; + break; + + case STATE_2_DAY: + if (*p >= '0' && *p <= '9') + if (nDigits < 2) + { + nDay = 10 * nDay + (*p - '0'); + ++nDigits; + } + else + eState = STATE_ERROR; + else if (*p == '-' && nDay && nDay <= 31) + { + nDigits = 0; + eState = STATE_2_YEAR; + } + else + eState = STATE_ERROR; + break; + + case STATE_2_YEAR: + if (*p >= '0' && *p <= '9') + { + if (nDigits < 4) + { + nYear = 10 * nYear + (*p - '0'); + ++nDigits; + } + else + eState = STATE_ERROR; + } + else + { + if (ascii_isWhitespace(*p)) + eState = STATE_2_YEAR_LWS; + else + eState = STATE_ERROR; + } + break; + + case STATE_2_YEAR_LWS: + if (*p >= '0' && *p <= '9') + { + nHour = *p - '0'; + nDigits = 1; + eState = STATE_2_HOUR; + } + else if (!ascii_isWhitespace(*p)) + eState = STATE_ERROR; + break; + + case STATE_2_HOUR: + if (*p >= '0' && *p <= '9') + if (nDigits < 2) + { + nHour = 10 * nHour + (*p - '0'); + ++nDigits; + } + else + eState = STATE_ERROR; + else if (*p == ':' && nHour < 24) + { + nDigits = 0; + eState = STATE_2_MINUTE; + } + else + eState = STATE_ERROR; + break; + + case STATE_2_MINUTE: + if (*p >= '0' && *p <= '9') + { + if (nDigits < 2) + { + nMinute = 10 * nMinute + (*p - '0'); + ++nDigits; + } + else + eState = STATE_ERROR; + } + else + { + if (ascii_isWhitespace(*p) && (nMinute < 60)) + eState = STATE_LWS_NAME; + else + eState = STATE_ERROR; + } + break; + + case STATE_LWS_NAME: + if (!ascii_isWhitespace(*p)) + { + setPath (rEntry.m_aName, p); + if (bDirectory) + rEntry.m_nMode |= INETCOREFTP_FILEMODE_ISDIR; + rEntry.m_nSize = nSize; + + setYear (rEntry.m_aDate, nYear); + + rEntry.m_aDate.SetMonth(nMonth); + rEntry.m_aDate.SetDay(nDay); + rEntry.m_aDate.SetHour(nHour); + rEntry.m_aDate.SetMin(nMinute); + + return sal_True; + } + break; + case STATE_ERROR: + break; + } + } + + return sal_False; +} + +/* + * parseVMS. + * Directory entries may span one or two lines: + * + * entry: *lws name *1(*lws <NEWLINE>) 1*lws size 1*lws datetime rest + * + * name: filename "." filetype ";" version + * filename: 1*39fchar + * filetype: 1*39fchar + * version: non0digit *digit + * + * size: "0" / non0digit *digit + * + * datetime: date 1*lwsp time + * date: day "-" month "-" year + * day: (*1"0" non0digit) / ("1"-"2" digit) / ("3" "0"-"1") + * month: "JAN" / "FEB" / "MAR" / "APR" / "MAY" / "JUN" / "JUL" / "AUG" + * / "SEP" / "OCT" / "NOV" / "DEC" ; all case insensitive + * year: 2digit / 4digit + * time: hour ":" minute + * hour: ((*1"0" / "1") digit) / ("2" "0"-"3") + * minute: "0"-"5" digit + * + * rest: *1(lws *<ANY>) + * + * lws: <TAB> / <SPACE> + * non0digit: "1"-"9" + * digit: "0" / non0digit + * fchar: "A"-"Z" / "a"-"z" / digit / "-" / "_" / "$" + * + * For directories, the returned name is the <filename> part; for non- + * directory files, the returned name is the <filename "." filetype> part. + * An entry is a directory iff its filetype is "DIR" (ignoring case). + * + * The READ, WRITE, and ISLINK mode bits are not supported. + * + * The returned size is the <size> part, multiplied by 512, and with the high + * order bits truncated to fit into a ULONG. + * + */ +sal_Bool FTPDirectoryParser::parseVMS ( + FTPDirentry &rEntry, + const sal_Char *pBuffer) +{ + static OUString aFirstLineName; + static sal_Bool bFirstLineDir = sal_False; + + for (sal_Bool bFirstLine = sal_True;; bFirstLine = sal_False) + { + const sal_Char *p = pBuffer; + if (bFirstLine) + { + // Skip <*lws> part: + while (*p == '\t' || *p == ' ') + ++p; + + // Parse <filename "."> part: + const sal_Char *pFileName = p; + while ((*p >= 'A' && *p <= 'Z') || + (*p >= 'a' && *p <= 'z') || + (*p >= '0' && *p <= '9') || + *p == '-' || *p == '_' || *p == '$') + ++p; + + if (*p != '.' || p == pFileName || p - pFileName > 39) + { + if (aFirstLineName.getLength()) + continue; + else + return sal_False; + } + + // Parse <filetype ";"> part: + const sal_Char *pFileType = ++p; + while ((*p >= 'A' && *p <= 'Z') || + (*p >= 'a' && *p <= 'z') || + (*p >= '0' && *p <= '9') || + *p == '-' || *p == '_' || *p == '$') + ++p; + + if (*p != ';' || p == pFileName || p - pFileName > 39) + { + if (aFirstLineName.getLength()) + continue; + else + return sal_False; + } + ++p; + + // Set entry's name and mode (ISDIR flag): + if ((p - pFileType == 4) && + (pFileType[0] == 'D' || pFileType[0] == 'd') && + (pFileType[1] == 'I' || pFileType[1] == 'i') && + (pFileType[2] == 'R' || pFileType[2] == 'r') ) + { + setPath (rEntry.m_aName, pFileName, (pFileType - pFileName)); + rEntry.m_nMode = INETCOREFTP_FILEMODE_ISDIR; + } + else + { + setPath (rEntry.m_aName, pFileName, (p - pFileName)); + rEntry.m_nMode = 0; + } + + // Skip <version> part: + if (*p < '1' || *p > '9') + { + if (aFirstLineName.getLength()) + continue; + else + return sal_False; + } + ++p; + while (*p >= '0' && *p <= '9') + ++p; + + // Parse <1*lws> or <*lws <NEWLINE>> part: + sal_Bool bLWS = false; + while (*p == '\t' || *p == ' ') + { + bLWS = true; + ++p; + } + if (*p) + { + if (!bLWS) + { + if (aFirstLineName.getLength()) + continue; + else + return sal_False; + } + } + else + { + /* + * First line of entry spanning two lines, + * wait for second line. + */ + aFirstLineName = rEntry.m_aName; + bFirstLineDir = + ((rEntry.m_nMode & INETCOREFTP_FILEMODE_ISDIR) != 0); + return sal_False; + } + } + else + { + /* + * Second line of entry spanning two lines, + * restore entry's name and mode (ISDIR flag). + */ + rEntry.m_aName = aFirstLineName; + rEntry.m_nMode = (bFirstLineDir ? INETCOREFTP_FILEMODE_ISDIR : 0); + + // Skip <1*lws> part: + if (*p != '\t' && *p != ' ') + return sal_False; + ++p; + while (*p == '\t' || *p == ' ') + ++p; + } + + // Parse <size> part and set entry's size: + if (*p < '0' || *p > '9') + return sal_False; + ULONG nSize = *p - '0'; + if (*p++ != '0') + while (*p >= '0' && *p <= '9') + nSize = 10 * rEntry.m_nSize + (*p++ - '0'); + rEntry.m_nSize = 512 * nSize; + + // Skip <1*lws> part: + if (*p != '\t' && *p != ' ') + return sal_False; + ++p; + while (*p == '\t' || *p == ' ') + ++p; + + // Parse <day "-"> part and set entry date's day: + sal_uInt16 nDay; + if (*p == '0') + { + ++p; + if (*p < '1' || *p > '9') + return sal_False; + nDay = *p++ - '0'; + } + else if (*p == '1' || *p == '2') + { + nDay = *p++ - '0'; + if (*p >= '0' && *p <= '9') + nDay = 10 * nDay + (*p++ - '0'); + } + else if (*p == '3') + { + ++p; + nDay = (*p == '0' || *p == '1') ? 30 + (*p++ - '0') : 3; + } + else if (*p >= '4' && *p <= '9') + nDay = *p++ - '0'; + else + return sal_False; + + rEntry.m_aDate.SetDay(nDay); + if (*p++ != '-') + return sal_False; + + // Parse <month "-"> part and set entry date's month: + sal_Char const * pMonth = p; + sal_Int32 const monthLen = 3; + for (int i = 0; i < monthLen; ++i) + { + if (!((*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z'))) + return sal_False; + ++p; + } + if (rtl_str_compareIgnoreAsciiCase_WithLength( + pMonth, monthLen, RTL_CONSTASCII_STRINGPARAM("JAN")) == 0) + rEntry.m_aDate.SetMonth(1); + else if (rtl_str_compareIgnoreAsciiCase_WithLength( + pMonth, monthLen, RTL_CONSTASCII_STRINGPARAM("FEB")) == 0) + rEntry.m_aDate.SetMonth(2); + else if (rtl_str_compareIgnoreAsciiCase_WithLength( + pMonth, monthLen, RTL_CONSTASCII_STRINGPARAM("MAR")) == 0) + rEntry.m_aDate.SetMonth(3); + else if (rtl_str_compareIgnoreAsciiCase_WithLength( + pMonth, monthLen, RTL_CONSTASCII_STRINGPARAM("APR")) == 0) + rEntry.m_aDate.SetMonth(4); + else if (rtl_str_compareIgnoreAsciiCase_WithLength( + pMonth, monthLen, RTL_CONSTASCII_STRINGPARAM("MAY")) == 0) + rEntry.m_aDate.SetMonth(5); + else if (rtl_str_compareIgnoreAsciiCase_WithLength( + pMonth, monthLen, RTL_CONSTASCII_STRINGPARAM("JUN")) == 0) + rEntry.m_aDate.SetMonth(6); + else if (rtl_str_compareIgnoreAsciiCase_WithLength( + pMonth, monthLen, RTL_CONSTASCII_STRINGPARAM("JUL")) == 0) + rEntry.m_aDate.SetMonth(7); + else if (rtl_str_compareIgnoreAsciiCase_WithLength( + pMonth, monthLen, RTL_CONSTASCII_STRINGPARAM("AUG")) == 0) + rEntry.m_aDate.SetMonth(8); + else if (rtl_str_compareIgnoreAsciiCase_WithLength( + pMonth, monthLen, RTL_CONSTASCII_STRINGPARAM("SEP")) == 0) + rEntry.m_aDate.SetMonth(9); + else if (rtl_str_compareIgnoreAsciiCase_WithLength( + pMonth, monthLen, RTL_CONSTASCII_STRINGPARAM("OCT")) == 0) + rEntry.m_aDate.SetMonth(10); + else if (rtl_str_compareIgnoreAsciiCase_WithLength( + pMonth, monthLen, RTL_CONSTASCII_STRINGPARAM("NOV")) == 0) + rEntry.m_aDate.SetMonth(11); + else if (rtl_str_compareIgnoreAsciiCase_WithLength( + pMonth, monthLen, RTL_CONSTASCII_STRINGPARAM("DEC")) == 0) + rEntry.m_aDate.SetMonth(12); + else + return sal_False; + if (*p++ != '-') + return sal_False; + + // Parse <year> part and set entry date's year: + sal_uInt16 nYear = 0; + {for (int i = 0; i < 2; ++i) + { + if (*p < '0' || *p > '9') + return sal_False; + nYear = 10 * nYear + (*p++ - '0'); + }} + if (*p >= '0' && *p <= '9') + { + nYear = 10 * nYear + (*p++ - '0'); + if (*p < '0' || *p > '9') + return sal_False; + nYear = 10 * nYear + (*p++ - '0'); + } + setYear (rEntry.m_aDate, nYear); + + // Skip <1*lws> part: + if (*p != '\t' && *p != ' ') + return sal_False; + ++p; + while (*p == '\t' || *p == ' ') + ++p; + + // Parse <hour ":"> part and set entry time's hour: + sal_uInt16 nHour; + if (*p == '0' || *p == '1') + { + nHour = *p++ - '0'; + if (*p >= '0' && *p <= '9') + nHour = 10 * nHour + (*p++ - '0'); + } + else if (*p == '2') + { + ++p; + nHour = (*p >= '0' && *p <= '3') ? 20 + (*p++ - '0') : 2; + } + else if (*p >= '3' && *p <= '9') + nHour = *p++ - '0'; + else + return sal_False; + + rEntry.m_aDate.SetHour(nHour); + if (*p++ != ':') + return sal_False; + + /* + * Parse <minute> part and set entry time's minutes, + * seconds (0), and 1/100 seconds (0). + */ + if (*p < '0' || *p > '5') + return sal_False; + + sal_uInt16 nMinute = *p++ - '0'; + if (*p < '0' || *p > '9') + return sal_False; + + nMinute = 10 * nMinute + (*p++ - '0'); + rEntry.m_aDate.SetMin(nMinute); + rEntry.m_aDate.SetSec(0); + rEntry.m_aDate.Set100Sec(0); + + // Skip <rest> part: + if (*p && (*p != '\t' && *p != ' ')) + return sal_False; + + return sal_True; + } +} + +/* + * parseUNIX + */ +sal_Bool FTPDirectoryParser::parseUNIX ( + FTPDirentry &rEntry, + const sal_Char *pBuffer) +{ + const sal_Char *p1, *p2; + p1 = p2 = pBuffer; + + if (!((*p1 == '-') || (*p1 == 'd') || (*p1 == 'l'))) + return sal_False; + + // 1st column: FileMode. + if (*p1 == 'd') + rEntry.m_nMode |= INETCOREFTP_FILEMODE_ISDIR; + + if (*p1 == 'l') + rEntry.m_nMode |= INETCOREFTP_FILEMODE_ISLINK; + + // Skip to end of column and set rights by the way + while (*p1 && !ascii_isWhitespace(*p1)) { + if(*p1 == 'r') + rEntry.m_nMode |= INETCOREFTP_FILEMODE_READ; + else if(*p1 == 'w') + rEntry.m_nMode |= INETCOREFTP_FILEMODE_WRITE; + p1++; + } + + /* + * Scan for the sequence of size and date fields: + * *LWS 1*DIGIT 1*LWS 3CHAR 1*LWS 1*2DIGIT 1*LWS + * (4DIGIT / (1*2DIGIT ":" 2DIGIT)) 1*LWS + */ + enum Mode + { + FOUND_NONE, FOUND_SIZE, FOUND_MONTH, FOUND_DAY, FOUND_YEAR_TIME + }; + + const sal_Char *pDayStart = 0; + const sal_Char *pDayEnd = 0; + Mode eMode; + for (eMode = FOUND_NONE; *p1 && eMode != FOUND_YEAR_TIME; p1 = p2 + 1) + { + while (*p1 && ascii_isWhitespace(*p1)) + ++p1; + p2 = p1; + while (*p2 && !ascii_isWhitespace(*p2)) + ++p2; + + switch (eMode) + { + case FOUND_NONE: + if (parseUNIX_isSizeField (p1, p2, rEntry.m_nSize)) + eMode = FOUND_SIZE; + break; + + case FOUND_SIZE: + if (parseUNIX_isMonthField (p1, p2, rEntry.m_aDate)) + eMode = FOUND_MONTH; + else if (!parseUNIX_isSizeField (p1, p2, rEntry.m_nSize)) + eMode = FOUND_NONE; + break; + + case FOUND_MONTH: + if (parseUNIX_isDayField (p1, p2, rEntry.m_aDate)) + { + pDayStart = p1; + pDayEnd = p2; + eMode = FOUND_DAY; + } + else if (parseUNIX_isSizeField (p1, p2, rEntry.m_nSize)) + eMode = FOUND_SIZE; + else + eMode = FOUND_NONE; + break; + + case FOUND_DAY: + if (parseUNIX_isYearTimeField (p1, p2, rEntry.m_aDate)) + eMode = FOUND_YEAR_TIME; + else if ( + parseUNIX_isSizeField ( + pDayStart, pDayEnd, rEntry.m_nSize) && + parseUNIX_isMonthField ( + p1, p2, rEntry.m_aDate)) + eMode = FOUND_MONTH; + else if (parseUNIX_isSizeField (p1, p2, rEntry.m_nSize)) + eMode = FOUND_SIZE; + else + eMode = FOUND_NONE; + break; + case FOUND_YEAR_TIME: + break; + } + } + + if (eMode == FOUND_YEAR_TIME) + { + // 9th column: FileName (rest of line). + while (*p1 && ascii_isWhitespace(*p1)) p1++; + setPath (rEntry.m_aName, p1); + + // Done. + return sal_True; + } + return sal_False; +} + +/* + * parseUNIX_isSizeField. + */ +sal_Bool FTPDirectoryParser::parseUNIX_isSizeField ( + const sal_Char *pStart, + const sal_Char *pEnd, + sal_uInt32 &rSize) +{ + if (!*pStart || !*pEnd || pStart == pEnd) + return sal_False; + + rSize = 0; + if (*pStart >= '0' && *pStart <= '9') + { + for (; pStart < pEnd; ++pStart) + if ((*pStart >= '0') && (*pStart <= '9')) + rSize = 10 * rSize + (*pStart - '0'); + else + return sal_False; + return sal_True; + } + else + { + /* + * For a combination of long group name and large file size, + * some FTPDs omit LWS between those two columns. + */ + int nNonDigits = 0; + int nDigits = 0; + + for (; pStart < pEnd; ++pStart) + if ((*pStart >= '1') && (*pStart <= '9')) + { + ++nDigits; + rSize = 10 * rSize + (*pStart - '0'); + } + else if ((*pStart == '0') && nDigits) + { + ++nDigits; + rSize *= 10; + } + else if ((*pStart > ' ') && (sal::static_int_cast<sal_uInt8>(*pStart) <= '\x7F')) + { + nNonDigits += nDigits + 1; + nDigits = 0; + rSize = 0; + } + else + return sal_False; + return ((nNonDigits >= 9) && (nDigits >= 7)); + } +} + +/* + * parseUNIX_isMonthField. + */ +sal_Bool FTPDirectoryParser::parseUNIX_isMonthField ( + const sal_Char *pStart, + const sal_Char *pEnd, + DateTime &rDateTime) +{ + if (!*pStart || !*pEnd || pStart + 3 != pEnd) + return sal_False; + + if ((pStart[0] == 'j' || pStart[0] == 'J') && + (pStart[1] == 'a' || pStart[1] == 'A') && + (pStart[2] == 'n' || pStart[2] == 'N') ) + { + rDateTime.SetMonth(1); + return sal_True; + } + if ((pStart[0] == 'f' || pStart[0] == 'F') && + (pStart[1] == 'e' || pStart[1] == 'E') && + (pStart[2] == 'b' || pStart[2] == 'B') ) + { + rDateTime.SetMonth(2); + return sal_True; + } + if ((pStart[0] == 'm' || pStart[0] == 'M') && + (pStart[1] == 'a' || pStart[1] == 'A') && + (pStart[2] == 'r' || pStart[2] == 'R') ) + { + rDateTime.SetMonth(3); + return sal_True; + } + if ((pStart[0] == 'a' || pStart[0] == 'A') && + (pStart[1] == 'p' || pStart[1] == 'P') && + (pStart[2] == 'r' || pStart[2] == 'R') ) + { + rDateTime.SetMonth(4); + return sal_True; + } + if ((pStart[0] == 'm' || pStart[0] == 'M') && + (pStart[1] == 'a' || pStart[1] == 'A') && + (pStart[2] == 'y' || pStart[2] == 'Y') ) + { + rDateTime.SetMonth(5); + return sal_True; + } + if ((pStart[0] == 'j' || pStart[0] == 'J') && + (pStart[1] == 'u' || pStart[1] == 'U') && + (pStart[2] == 'n' || pStart[2] == 'N') ) + { + rDateTime.SetMonth(6); + return sal_True; + } + if ((pStart[0] == 'j' || pStart[0] == 'J') && + (pStart[1] == 'u' || pStart[1] == 'U') && + (pStart[2] == 'l' || pStart[2] == 'L') ) + { + rDateTime.SetMonth(7); + return sal_True; + } + if ((pStart[0] == 'a' || pStart[0] == 'A') && + (pStart[1] == 'u' || pStart[1] == 'U') && + (pStart[2] == 'g' || pStart[2] == 'G') ) + { + rDateTime.SetMonth(8); + return sal_True; + } + if ((pStart[0] == 's' || pStart[0] == 'S') && + (pStart[1] == 'e' || pStart[1] == 'E') && + (pStart[2] == 'p' || pStart[2] == 'P') ) + { + rDateTime.SetMonth(9); + return sal_True; + } + if ((pStart[0] == 'o' || pStart[0] == 'O') && + (pStart[1] == 'c' || pStart[1] == 'C') && + (pStart[2] == 't' || pStart[2] == 'T') ) + { + rDateTime.SetMonth(10); + return sal_True; + } + if ((pStart[0] == 'n' || pStart[0] == 'N') && + (pStart[1] == 'o' || pStart[1] == 'O') && + (pStart[2] == 'v' || pStart[2] == 'V') ) + { + rDateTime.SetMonth(11); + return sal_True; + } + if ((pStart[0] == 'd' || pStart[0] == 'D') && + (pStart[1] == 'e' || pStart[1] == 'E') && + (pStart[2] == 'c' || pStart[2] == 'C') ) + { + rDateTime.SetMonth(12); + return sal_True; + } + return sal_False; +} + +/* + * parseUNIX_isDayField. + */ +sal_Bool FTPDirectoryParser::parseUNIX_isDayField ( + const sal_Char *pStart, + const sal_Char *pEnd, + DateTime &rDateTime) +{ + if (!*pStart || !*pEnd || pStart == pEnd) + return sal_False; + if (*pStart < '0' || *pStart > '9') + return sal_False; + + sal_uInt16 nDay = *pStart - '0'; + if (pStart + 1 < pEnd) + { + if (pStart + 2 != pEnd || pStart[1] < '0' || pStart[1] > '9') + return sal_False; + nDay = 10 * nDay + (pStart[1] - '0'); + } + if (!nDay || nDay > 31) + return sal_False; + + rDateTime.SetDay(nDay); + return sal_True; +} + +/* + * parseUNIX_isYearTimeField. + */ +sal_Bool FTPDirectoryParser::parseUNIX_isYearTimeField ( + const sal_Char *pStart, + const sal_Char *pEnd, + DateTime &rDateTime) +{ + if (!*pStart || !*pEnd || pStart == pEnd || + *pStart < '0' || *pStart > '9') + return sal_False; + + sal_uInt16 nNumber = *pStart - '0'; + ++pStart; + + if (pStart == pEnd) + return sal_False; + if (*pStart == ':') + return parseUNIX_isTime (pStart, pEnd, nNumber, rDateTime); + if (*pStart < '0' || *pStart > '9') + return sal_False; + + nNumber = 10 * nNumber + (*pStart - '0'); + ++pStart; + + if (pStart == pEnd) + return sal_False; + if (*pStart == ':') + return parseUNIX_isTime (pStart, pEnd, nNumber, rDateTime); + if (*pStart < '0' || *pStart > '9') + return sal_False; + + nNumber = 10 * nNumber + (*pStart - '0'); + ++pStart; + + if (pStart == pEnd || *pStart < '0' || *pStart > '9') + return sal_False; + + nNumber = 10 * nNumber + (*pStart - '0'); + if (pStart + 1 != pEnd || nNumber < 1970) + return sal_False; + + rDateTime.SetYear(nNumber); + rDateTime.SetTime(0); + return sal_True; +} + +/* + * parseUNIX_isTime. + */ +sal_Bool FTPDirectoryParser::parseUNIX_isTime ( + const sal_Char *pStart, + const sal_Char *pEnd, + sal_uInt16 nHour, + DateTime &rDateTime) +{ + if ((nHour > 23 ) || (pStart + 3 != pEnd) || + (pStart[1] < '0') || (pStart[1] > '5') || + (pStart[2] < '0') || (pStart[2] > '9') ) + return sal_False; + + sal_uInt16 nMin = 10 * (pStart[1] - '0') + (pStart[2] - '0'); + + rDateTime.SetHour (nHour); + rDateTime.SetMin (nMin); + rDateTime.SetSec (0); + rDateTime.Set100Sec (0); + +// Date aCurDate; +// if (rDateTime.GetMonth() > aCurDate.GetMonth()) +// rDateTime.SetYear(aCurDate.GetYear() - 1); +// else +// rDateTime.SetYear(aCurDate.GetYear()); +// return sal_True; + + TimeValue aTimeVal; + osl_getSystemTime(&aTimeVal); + oslDateTime aCurrDateTime; + osl_getDateTimeFromTimeValue(&aTimeVal,&aCurrDateTime); + + if (rDateTime.GetMonth() > aCurrDateTime.Month) + rDateTime.SetYear(aCurrDateTime.Year - 1); + else + rDateTime.SetYear(aCurrDateTime.Year); + return sal_True; +} + +/* + * setYear. + * + * Two-digit years are taken as within 50 years back and 49 years forward + * (both ends inclusive) from the current year. The returned date is not + * checked for validity of the given day in the given month and year. + * + */ +sal_Bool FTPDirectoryParser::setYear ( + DateTime &rDateTime, sal_uInt16 nYear) +{ + if (nYear < 100) + { + TimeValue aTimeVal; + osl_getSystemTime(&aTimeVal); + oslDateTime aCurrDateTime; + osl_getDateTimeFromTimeValue(&aTimeVal,&aCurrDateTime); + sal_uInt16 nCurrentYear = aCurrDateTime.Year; +// sal_uInt16 nCurrentYear = Date().GetYear(); + sal_uInt16 nCurrentCentury = nCurrentYear / 100; + nCurrentYear %= 100; + if (nCurrentYear < 50) + if (nYear <= nCurrentYear) + nYear += nCurrentCentury * 100; + else if (nYear < nCurrentYear + 50) + nYear += nCurrentCentury * 100; + else + nYear += (nCurrentCentury - 1) * 100; + else + if (nYear >= nCurrentYear) + nYear += nCurrentCentury * 100; + else if (nYear >= nCurrentYear - 50) + nYear += nCurrentCentury * 100; + else + nYear += (nCurrentCentury + 1) * 100; + } + + rDateTime.SetYear(nYear); + return sal_True; +} + +/* + * setPath. + */ +sal_Bool FTPDirectoryParser::setPath ( + OUString &rPath, const sal_Char *value, sal_Int32 length) +{ + if (value) + { + if (length < 0) + length = rtl_str_getLength (value); + rPath = OUString (value, length, RTL_TEXTENCODING_UTF8); + } + return (!!value); +} diff --git a/ucb/source/ucp/ftp/ftpdirp.hxx b/ucb/source/ucp/ftp/ftpdirp.hxx new file mode 100644 index 000000000000..aeb265dbf286 --- /dev/null +++ b/ucb/source/ucp/ftp/ftpdirp.hxx @@ -0,0 +1,189 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ +#ifndef _FTP_FTPDIRP_HXX_ +#define _FTP_FTPDIRP_HXX_ + +#include <osl/time.h> +#include <rtl/ustring.hxx> +#include <com/sun/star/util/DateTime.hpp> + + +namespace ftp { + + /*======================================================================== + * + * the DateTime structure + * + *======================================================================*/ + + struct DateTime + : public com::sun::star::util::DateTime + { + DateTime(const sal_uInt16& hundredthSeconds, + const sal_uInt16& seconds, + const sal_uInt16& minutes, + const sal_uInt16& hours, + const sal_uInt16& day, + const sal_uInt16& month, + const sal_uInt16& year) SAL_THROW( () ) + : com::sun::star::util::DateTime(hundredthSeconds, + seconds, + minutes, + hours, + day, + month, + year) { } + + void SetYear(sal_uInt16 year) { Year = year; } + void SetMonth(sal_uInt16 month) { Month = month; } + void SetDay(sal_uInt16 day) { Day = day; } + // Only zero allowed and used for time-argument + void SetTime(sal_uInt16) { Hours = Minutes = Seconds = HundredthSeconds = 0; } + void SetHour(sal_uInt16 hours) { Hours = hours; } + void SetMin(sal_uInt16 minutes) { Minutes = minutes; } + void SetSec(sal_uInt16 seconds) { Seconds = seconds; } + void Set100Sec(sal_uInt16 hundredthSec) { HundredthSeconds = hundredthSec; } + + sal_uInt16 GetMonth(void) { return Month; } + }; + + + +/*======================================================================== + * + * the directory information structure + * + *======================================================================*/ + + enum FTPDirentryMode { INETCOREFTP_FILEMODE_UNKNOWN = 0x00, + INETCOREFTP_FILEMODE_READ = 0x01, + INETCOREFTP_FILEMODE_WRITE = 0x02, + INETCOREFTP_FILEMODE_ISDIR = 0x04, + INETCOREFTP_FILEMODE_ISLINK = 0x08 }; + + struct FTPDirentry + { + rtl::OUString m_aURL; + rtl::OUString m_aName; + DateTime m_aDate; + sal_uInt32 m_nMode; + sal_uInt32 m_nSize; + + FTPDirentry(void) + : m_aDate(0,0,0,0,0,0,0), + m_nMode(INETCOREFTP_FILEMODE_UNKNOWN), + m_nSize((sal_uInt32)(-1)) { } + + void clear() { + m_aURL = m_aName = rtl::OUString(); + m_aDate = DateTime(0,0,0,0,0,0,0); + m_nMode = INETCOREFTP_FILEMODE_UNKNOWN; + m_nSize = sal_uInt32(-1); + } + + bool isDir() const { + return bool(m_nMode && INETCOREFTP_FILEMODE_ISDIR); + } + + bool isFile() const { + return ! bool(m_nMode && INETCOREFTP_FILEMODE_ISDIR); + } + }; + + +/*======================================================================== + * + * the directory parser + * + *======================================================================*/ + + + class FTPDirectoryParser + { + public: + static sal_Bool parseDOS ( + FTPDirentry &rEntry, + const sal_Char *pBuffer ); + + static sal_Bool parseVMS ( + FTPDirentry &rEntry, + const sal_Char *pBuffer ); + + static sal_Bool parseUNIX ( + FTPDirentry &rEntry, + const sal_Char *pBuffer ); + + + private: + + static sal_Bool parseUNIX_isSizeField ( + const sal_Char *pStart, + const sal_Char *pEnd, + sal_uInt32 &rSize); + + static sal_Bool parseUNIX_isMonthField ( + const sal_Char *pStart, + const sal_Char *pEnd, + DateTime& rDateTime); + + static sal_Bool parseUNIX_isDayField ( + const sal_Char *pStart, + const sal_Char *pEnd, + DateTime& rDateTime); + + static sal_Bool parseUNIX_isYearTimeField ( + const sal_Char *pStart, + const sal_Char *pEnd, + DateTime& rDateTime); + + static sal_Bool parseUNIX_isTime ( + const sal_Char *pStart, + const sal_Char *pEnd, + sal_uInt16 nHour, + DateTime& rDateTime); + + static sal_Bool setYear ( + DateTime& rDateTime, + sal_uInt16 nYear); + + static sal_Bool setPath ( + rtl::OUString& rPath, + const sal_Char *value, + sal_Int32 length = -1); + }; + + +} + + +#endif diff --git a/ucb/source/ucp/ftp/ftpdynresultset.cxx b/ucb/source/ucp/ftp/ftpdynresultset.cxx new file mode 100644 index 000000000000..93f274f1ac5f --- /dev/null +++ b/ucb/source/ucp/ftp/ftpdynresultset.cxx @@ -0,0 +1,91 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" +#include <com/sun/star/sdbc/XResultSet.hpp> +#ifndef _FTP_FTPDYNRESULTSET_HXX_ +#include "ftpdynresultset.hxx" +#endif +#include "ftpresultsetfactory.hxx" + +using namespace com::sun::star::lang; +using namespace com::sun::star::sdbc; +using namespace com::sun::star::ucb; +using namespace com::sun::star::uno; + + +using namespace ftp; + +//========================================================================= +//========================================================================= +// +// DynamicResultSet Implementation. +// +//========================================================================= +//========================================================================= + +DynamicResultSet::DynamicResultSet( + const Reference< XMultiServiceFactory >& rxSMgr, + const rtl::Reference< FTPContent >& rxContent, + const OpenCommandArgument2& rCommand, + const Reference< XCommandEnvironment >& rxEnv, + ResultSetFactory* pFactory ) + : ResultSetImplHelper( rxSMgr, rCommand ), + m_xContent( rxContent ), + m_xEnv( rxEnv ), + m_pFactory( pFactory ) +{ +} + +DynamicResultSet::~DynamicResultSet() +{ + delete m_pFactory; +} + +//========================================================================= +// +// Non-interface methods. +// +//========================================================================= + +void DynamicResultSet::initStatic() +{ + m_xResultSet1 = Reference< XResultSet >( m_pFactory->createResultSet() ); +} + +//========================================================================= +void DynamicResultSet::initDynamic() +{ + m_xResultSet1 = Reference< XResultSet >( m_pFactory->createResultSet() ); + + m_xResultSet2 = m_xResultSet1; +} + + + + diff --git a/ucb/source/ucp/ftp/ftpdynresultset.hxx b/ucb/source/ucp/ftp/ftpdynresultset.hxx new file mode 100644 index 000000000000..b1e92c15750a --- /dev/null +++ b/ucb/source/ucp/ftp/ftpdynresultset.hxx @@ -0,0 +1,67 @@ +/************************************************************************* + * + * 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 _FTP_FTPDYNRESULTSET_HXX +#define _FTP_FTPDYNRESULTSET_HXX + +#include "rtl/ref.hxx" +#include "ucbhelper/resultsethelper.hxx" + +#include "ftpcontent.hxx" + +namespace ftp { + + class ResultSetFactory; + + class DynamicResultSet : public ::ucbhelper::ResultSetImplHelper + { + rtl::Reference< FTPContent > m_xContent; + com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > m_xEnv; + ResultSetFactory* m_pFactory; + + private: + virtual void initStatic(); + virtual void initDynamic(); + + public: + DynamicResultSet( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + const rtl::Reference< FTPContent >& rxContent, + const com::sun::star::ucb::OpenCommandArgument2& rCommand, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment >& rxEnv, + ResultSetFactory* pFactory ); + + ~DynamicResultSet(); + }; + +} + +#endif + diff --git a/ucb/source/ucp/ftp/ftphandleprovider.hxx b/ucb/source/ucp/ftp/ftphandleprovider.hxx new file mode 100755 index 000000000000..1510f48e41a6 --- /dev/null +++ b/ucb/source/ucp/ftp/ftphandleprovider.hxx @@ -0,0 +1,29 @@ +#include <rtl/ustring.hxx> +#include "curl.hxx" + +namespace ftp { + + class FTPHandleProvider { + public: + + virtual CURL* handle() = 0; + + + /** host is in the form host:port. + */ + + virtual bool forHost(const rtl::OUString& host, + const rtl::OUString& port, + const rtl::OUString& username, + rtl::OUString& password, + rtl::OUString& account) = 0; + + virtual bool setHost(const rtl::OUString& host, + const rtl::OUString& port, + const rtl::OUString& username, + const rtl::OUString& password, + const rtl::OUString& account) = 0; + }; + + +} diff --git a/ucb/source/ucp/ftp/ftpinpstr.cxx b/ucb/source/ucp/ftp/ftpinpstr.cxx new file mode 100644 index 000000000000..5fe5c829f976 --- /dev/null +++ b/ucb/source/ucp/ftp/ftpinpstr.cxx @@ -0,0 +1,217 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ +#include "ftpinpstr.hxx" +#ifndef _RTL_ALLOC_H +#include <rtl/alloc.h> +#endif +#ifndef STD_ALGORITHM +#include <algorithm> +#define STD_ALGORITHM +#endif +#include <stdio.h> + +using namespace ftp; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::io; + + +FTPInputStream::FTPInputStream(FILE* tmpfl) + : m_tmpfl(tmpfl ? tmpfl : tmpfile()) +{ + fseek(m_tmpfl,0,SEEK_END); +// fpos_t pos; +// fgetpos(m_tmpfl,&pos); + long pos = ftell(m_tmpfl); + rewind(m_tmpfl); + m_nLength = sal_Int64(pos); +} + + + +FTPInputStream::~FTPInputStream() +{ + if ( 0 != m_tmpfl) + fclose(m_tmpfl); +} + + +Any SAL_CALL FTPInputStream::queryInterface( + const Type& rType +) + throw( + RuntimeException + ) +{ + Any aRet = ::cppu::queryInterface(rType, + SAL_STATIC_CAST( XInputStream*,this ), + SAL_STATIC_CAST( XSeekable*,this ) ); + + return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ); +} + + + +void SAL_CALL FTPInputStream::acquire( void ) throw() { + OWeakObject::acquire(); +} + + + +void SAL_CALL FTPInputStream::release( void ) throw() { + OWeakObject::release(); +} + + +sal_Int32 SAL_CALL FTPInputStream::readBytes(Sequence< sal_Int8 >& aData, + sal_Int32 nBytesToRead) + throw(NotConnectedException, + BufferSizeExceededException, + IOException, + RuntimeException) +{ + osl::MutexGuard aGuard(m_aMutex); + + if(0 <= nBytesToRead && aData.getLength() < nBytesToRead) + aData.realloc(nBytesToRead); + +// fpos_t bpos,epos; + +// fgetpos(m_tmpfl,&bpos); +// fread(aData.getArray(),nBytesToRead,1,m_tmpfl); +// fgetpos(m_tmpfl,&epos); + long bpos,epos; + + bpos = ftell(m_tmpfl); + if (fread(aData.getArray(),nBytesToRead,1,m_tmpfl) != 1) + throw IOException(); + + epos = ftell(m_tmpfl); + + return sal_Int32(epos-bpos); +} + + +sal_Int32 SAL_CALL FTPInputStream::readSomeBytes( Sequence< sal_Int8 >& aData, + sal_Int32 nMaxBytesToRead ) + throw( NotConnectedException, + BufferSizeExceededException, + IOException, + RuntimeException) +{ + return readBytes(aData,nMaxBytesToRead); +} + + + +void SAL_CALL FTPInputStream::skipBytes(sal_Int32 nBytesToSkip) + throw(NotConnectedException, + BufferSizeExceededException, + IOException, + RuntimeException) +{ + osl::MutexGuard aGuard(m_aMutex); + if(!m_tmpfl) + throw IOException(); + + fseek(m_tmpfl,long(nBytesToSkip),SEEK_CUR); +} + + + +sal_Int32 SAL_CALL FTPInputStream::available(void) + throw(NotConnectedException, + IOException, + RuntimeException) +{ + return sal::static_int_cast<sal_Int32>(m_nLength - getPosition()); +} + + + +void SAL_CALL FTPInputStream::closeInput(void) + throw(NotConnectedException, + IOException, + RuntimeException) +{ + osl::MutexGuard aGuard(m_aMutex); + if(m_tmpfl) + fclose(m_tmpfl),m_tmpfl = 0; +} + + + +void SAL_CALL FTPInputStream::seek(sal_Int64 location) + throw( IllegalArgumentException, + IOException, + RuntimeException ) +{ + osl::MutexGuard aGuard(m_aMutex); + if(!m_tmpfl) + throw IOException(); + + fseek(m_tmpfl,long(location),SEEK_SET); +} + + + +sal_Int64 SAL_CALL +FTPInputStream::getPosition( + void ) + throw( IOException, + RuntimeException ) +{ + osl::MutexGuard aGuard(m_aMutex); + if(!m_tmpfl) + throw IOException(); + +// fpos_t pos; +// fgetpos(m_tmpfl,&pos); + long pos; + pos = ftell(m_tmpfl); + return sal_Int64(pos); +} + + + +sal_Int64 SAL_CALL FTPInputStream::getLength( + void +) throw( + IOException,RuntimeException +) +{ + return m_nLength; +} diff --git a/ucb/source/ucp/ftp/ftpinpstr.hxx b/ucb/source/ucp/ftp/ftpinpstr.hxx new file mode 100644 index 000000000000..0d235be36e35 --- /dev/null +++ b/ucb/source/ucp/ftp/ftpinpstr.hxx @@ -0,0 +1,151 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ + +#ifndef _FTP_FTPINPSTR_HXX_ +#define _FTP_FTPINPSTR_HXX_ + + +#include <rtl/ustring.hxx> +#include <osl/mutex.hxx> +#include <cppuhelper/weak.hxx> +#include <cppuhelper/queryinterface.hxx> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/io/XSeekable.hpp> +#include <stdio.h> + + +namespace ftp { + + + /** Implements a seekable InputStream + * working on a buffer. + */ + + + namespace css = com::sun::star; + + + class FTPInputStream + : public cppu::OWeakObject, + public com::sun::star::io::XInputStream, + public com::sun::star::io::XSeekable + { + public: + + /** Defines the storage kind found + * on which the inputstream acts. + */ + + FTPInputStream(FILE* tmpfl = 0); + + ~FTPInputStream(); + + virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type& rType) + throw(css::uno::RuntimeException); + + virtual void SAL_CALL acquire(void) throw(); + + virtual void SAL_CALL release(void) throw(); + + virtual sal_Int32 SAL_CALL + readBytes(css::uno::Sequence< sal_Int8 >& aData, + sal_Int32 nBytesToRead) + throw( css::io::NotConnectedException, + css::io::BufferSizeExceededException, + css::io::IOException, + css::uno::RuntimeException); + + virtual sal_Int32 SAL_CALL + readSomeBytes(css::uno::Sequence< sal_Int8 >& aData, + sal_Int32 nMaxBytesToRead ) + throw( css::io::NotConnectedException, + css::io::BufferSizeExceededException, + css::io::IOException, + css::uno::RuntimeException); + + virtual void SAL_CALL + skipBytes(sal_Int32 nBytesToSkip) + throw(css::io::NotConnectedException, + css::io::BufferSizeExceededException, + css::io::IOException, + css::uno::RuntimeException ); + + virtual sal_Int32 SAL_CALL + available(void) + throw(css::io::NotConnectedException, + css::io::IOException, + css::uno::RuntimeException ); + + virtual void SAL_CALL + closeInput(void) + throw(css::io::NotConnectedException, + css::io::IOException, + css::uno::RuntimeException); + + + /** XSeekable + */ + + virtual void SAL_CALL + seek(sal_Int64 location) + throw(css::lang::IllegalArgumentException, + css::io::IOException, + css::uno::RuntimeException); + + + virtual sal_Int64 SAL_CALL + getPosition(void) + throw(css::io::IOException, + css::uno::RuntimeException); + + + virtual sal_Int64 SAL_CALL + getLength(void) + throw(css::io::IOException, + css::uno::RuntimeException); + + // additional + +// void append(const void* pBuffer,size_t size,size_t nmemb); + + private: + + osl::Mutex m_aMutex; + FILE* m_tmpfl; + sal_Int64 m_nLength; + }; + + +} + +#endif diff --git a/ucb/source/ucp/ftp/ftpintreq.cxx b/ucb/source/ucp/ftp/ftpintreq.cxx new file mode 100644 index 000000000000..2ee076d1e246 --- /dev/null +++ b/ucb/source/ucp/ftp/ftpintreq.cxx @@ -0,0 +1,230 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" +#include <com/sun/star/ucb/UnsupportedNameClashException.hpp> +#include <com/sun/star/ucb/NameClash.hpp> +#include "ftpintreq.hxx" + +using namespace cppu; +using namespace com::sun::star; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::ucb; +using namespace com::sun::star::task; +using namespace ftp; + + +XInteractionApproveImpl::XInteractionApproveImpl() + : m_bSelected(false) +{ +} + + +void SAL_CALL +XInteractionApproveImpl::acquire( void ) + throw() +{ + OWeakObject::acquire(); +} + + +void SAL_CALL +XInteractionApproveImpl::release( void ) + throw() +{ + OWeakObject::release(); +} + + + +Any SAL_CALL +XInteractionApproveImpl::queryInterface( const Type& rType ) + throw( RuntimeException ) +{ + Any aRet = cppu::queryInterface( + rType, + SAL_STATIC_CAST( lang::XTypeProvider*, this ), + SAL_STATIC_CAST( XInteractionApprove*,this) ); + return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ); +} + + +////////////////////////////////////////////////////////////////////////////// +// XTypeProvider +////////////////////////////////////////////////////////////////////////////// + +XTYPEPROVIDER_IMPL_2( XInteractionApproveImpl, + XTypeProvider, + XInteractionApprove ) + + +void SAL_CALL XInteractionApproveImpl::select() + throw (RuntimeException) +{ + m_bSelected = true; +} + + +bool XInteractionApproveImpl::isSelected() const +{ + return m_bSelected; +} + + +// XInteractionDisapproveImpl + +XInteractionDisapproveImpl::XInteractionDisapproveImpl() + : m_bSelected(false) +{ +} + + +void SAL_CALL +XInteractionDisapproveImpl::acquire( void ) + throw() +{ + OWeakObject::acquire(); +} + + +void SAL_CALL +XInteractionDisapproveImpl::release( void ) + throw() +{ + OWeakObject::release(); +} + + + +Any SAL_CALL +XInteractionDisapproveImpl::queryInterface( const Type& rType ) + throw( RuntimeException ) +{ + Any aRet = cppu::queryInterface( + rType, + SAL_STATIC_CAST( lang::XTypeProvider*, this ), + SAL_STATIC_CAST( XInteractionDisapprove*,this) ); + return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ); +} + + +////////////////////////////////////////////////////////////////////////////// +// XTypeProvider +////////////////////////////////////////////////////////////////////////////// + +XTYPEPROVIDER_IMPL_2( XInteractionDisapproveImpl, + XTypeProvider, + XInteractionDisapprove ) + + +void SAL_CALL XInteractionDisapproveImpl::select() + throw (RuntimeException) + +{ + m_bSelected = true; +} + + +// XInteractionRequestImpl + +XInteractionRequestImpl::XInteractionRequestImpl(const rtl::OUString& aName) + : p1( new XInteractionApproveImpl ), + p2( new XInteractionDisapproveImpl ), + m_aName(aName), + m_aSeq( 2 ) +{ + m_aSeq[0] = Reference<XInteractionContinuation>(p1); + m_aSeq[1] = Reference<XInteractionContinuation>(p2); +} + + +void SAL_CALL +XInteractionRequestImpl::acquire( void ) + throw() +{ + OWeakObject::acquire(); +} + + + +void SAL_CALL +XInteractionRequestImpl::release( void ) + throw() +{ + OWeakObject::release(); +} + + + +Any SAL_CALL +XInteractionRequestImpl::queryInterface( const Type& rType ) + throw( RuntimeException ) +{ + Any aRet = cppu::queryInterface( + rType, + SAL_STATIC_CAST( lang::XTypeProvider*, this ), + SAL_STATIC_CAST( XInteractionRequest*,this) ); + return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ); +} + + +////////////////////////////////////////////////////////////////////////////// +// XTypeProvider +///////////////////////////////////////////////////////////////////////////// + +XTYPEPROVIDER_IMPL_2( XInteractionRequestImpl, + XTypeProvider, + XInteractionRequest ) + + +Any SAL_CALL XInteractionRequestImpl::getRequest( ) + throw (RuntimeException) +{ + Any aAny; + UnsupportedNameClashException excep; + excep.NameClash = NameClash::ERROR; + aAny <<= excep; + return aAny; +} + + +Sequence<Reference<XInteractionContinuation > > SAL_CALL +XInteractionRequestImpl::getContinuations( ) + throw (RuntimeException) +{ + return m_aSeq; +} + + +bool XInteractionRequestImpl::approved() const +{ + return p1->isSelected(); +} + diff --git a/ucb/source/ucp/ftp/ftpintreq.hxx b/ucb/source/ucp/ftp/ftpintreq.hxx new file mode 100644 index 000000000000..1a772dc356e1 --- /dev/null +++ b/ucb/source/ucp/ftp/ftpintreq.hxx @@ -0,0 +1,181 @@ +/************************************************************************* + * + * 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 _FTP_FTPINTREQ_HXX +#define _FTP_FTPINTREQ_HXX + +#include <cppuhelper/weak.hxx> +#include <ucbhelper/macros.hxx> +#include <rtl/ustring.hxx> +#include <com/sun/star/uno/XInterface.hpp> +#include <com/sun/star/lang/XTypeProvider.hpp> +#include <com/sun/star/task/XInteractionDisapprove.hpp> +#include <com/sun/star/task/XInteractionApprove.hpp> +#include <com/sun/star/task/XInteractionRequest.hpp> + + +namespace ftp { + + + class XInteractionApproveImpl + : public cppu::OWeakObject, + public com::sun::star::lang::XTypeProvider, + public com::sun::star::task::XInteractionApprove + { + public: + + XInteractionApproveImpl(); + + virtual com::sun::star::uno::Any SAL_CALL + queryInterface( + const com::sun::star::uno::Type& rType ) + throw( com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + acquire( + void ) + throw(); + + virtual void SAL_CALL + release( + void ) + throw(); + + + // XTypeProvider + + XTYPEPROVIDER_DECL() + + virtual void SAL_CALL select() + throw (com::sun::star::uno::RuntimeException); + + bool isSelected() const; + + private: + + bool m_bSelected; + }; + + + + + class XInteractionDisapproveImpl + : public cppu::OWeakObject, + public com::sun::star::lang::XTypeProvider, + public com::sun::star::task::XInteractionDisapprove + { + public: + + XInteractionDisapproveImpl(); + + virtual com::sun::star::uno::Any SAL_CALL + queryInterface( + const com::sun::star::uno::Type& rType ) + throw( com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + acquire( + void ) + throw(); + + virtual void SAL_CALL + release( + void ) + throw(); + + + // XTypeProvider + + XTYPEPROVIDER_DECL() + + virtual void SAL_CALL select() + throw (com::sun::star::uno::RuntimeException); + + private: + + bool m_bSelected; + }; + + + + class XInteractionRequestImpl + : public cppu::OWeakObject, + public com::sun::star::lang::XTypeProvider, + public com::sun::star::task::XInteractionRequest + { + public: + + XInteractionRequestImpl(const rtl::OUString& aName); + + virtual com::sun::star::uno::Any SAL_CALL + queryInterface( + const com::sun::star::uno::Type& rType ) + throw( com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + acquire( + void ) + throw(); + + virtual void SAL_CALL + release( + void ) + throw(); + + + // XTypeProvider + + XTYPEPROVIDER_DECL() + + com::sun::star::uno::Any SAL_CALL + getRequest( ) + throw (com::sun::star::uno::RuntimeException); + + com::sun::star::uno::Sequence< + com::sun::star::uno::Reference< + com::sun::star::task::XInteractionContinuation > > SAL_CALL + getContinuations( ) + throw (com::sun::star::uno::RuntimeException); + + bool approved() const; + + private: + + XInteractionApproveImpl* p1; + XInteractionDisapproveImpl* p2; + + rtl::OUString m_aName; + + com::sun::star::uno::Sequence< + com::sun::star::uno::Reference< + com::sun::star::task::XInteractionContinuation > > m_aSeq; + }; + +} + + +#endif diff --git a/ucb/source/ucp/ftp/ftploaderthread.cxx b/ucb/source/ucp/ftp/ftploaderthread.cxx new file mode 100644 index 000000000000..727d056f7fe8 --- /dev/null +++ b/ucb/source/ucp/ftp/ftploaderthread.cxx @@ -0,0 +1,109 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ +#include "ftploaderthread.hxx" +#include "curl.hxx" + +using namespace ftp; + + +/********************************************************************************/ +/* */ +/* cleanup function for thread specific data */ +/* */ +/********************************************************************************/ + + +#ifdef __cplusplus +extern "C" { +#endif + + int memory_write_dummy(void *,size_t,size_t,void *) + { + return 0; + } + + void delete_CURL(void *pData) + { + // Otherwise response for QUIT will be sent to already destroyed + // MemoryContainer via non-dummy memory_write function. + curl_easy_setopt(static_cast<CURL*>(pData), + CURLOPT_HEADERFUNCTION, + memory_write_dummy); + curl_easy_cleanup(static_cast<CURL*>(pData)); + } + +#ifdef __cplusplus +} +#endif + + +/********************************************************************************/ +/* */ +/* Member part of FTPLoaderThread */ +/* */ +/********************************************************************************/ + + +FTPLoaderThread::FTPLoaderThread() + : m_threadKey(osl_createThreadKey(delete_CURL)) { +} + + + +FTPLoaderThread::~FTPLoaderThread() { + osl_destroyThreadKey(m_threadKey); +} + + + +CURL* FTPLoaderThread::handle() { + CURL* ret = osl_getThreadKeyData(m_threadKey); + if(!ret) { + ret = curl_easy_init(); + if (ret != 0) { + // Make sure curl is not internally using environment variables like + // "ftp_proxy": + if (curl_easy_setopt(ret, CURLOPT_PROXY, "") != CURLE_OK) { + curl_easy_cleanup(ret); + ret = 0; + } + } + osl_setThreadKeyData(m_threadKey,static_cast<void*>(ret)); + } + + return ret; +} + + diff --git a/ucb/source/ucp/ftp/ftploaderthread.hxx b/ucb/source/ucp/ftp/ftploaderthread.hxx new file mode 100644 index 000000000000..1b91a0885048 --- /dev/null +++ b/ucb/source/ucp/ftp/ftploaderthread.hxx @@ -0,0 +1,73 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ + +#ifndef _FTP_FTPLOADERTHREAD_HXX_ +#define _FTP_FTPLOADERTHREAD_HXX_ + +#include <osl/thread.h> +#include "curl.hxx" + +namespace ftp { + + /** A loaderthread acts as factory for CURL-handles, + * the key being ( implicit ) the threadid. + * Owner is a FTPContentProvider-instance + */ + + class FTPLoaderThread + { + public: + + FTPLoaderThread(); + ~FTPLoaderThread(); + + CURL* handle(); + + + private: + + /** Don't enable assignment and copy construction. + * Not defined: + */ + + FTPLoaderThread(const FTPLoaderThread&); + FTPLoaderThread& operator=(const FTPLoaderThread&); + + oslThreadKey m_threadKey; + + }; // end class FTPLoaderThread + +} + + +#endif diff --git a/ucb/source/ucp/ftp/ftpresultsetI.cxx b/ucb/source/ucp/ftp/ftpresultsetI.cxx new file mode 100644 index 000000000000..49976755f60c --- /dev/null +++ b/ucb/source/ucp/ftp/ftpresultsetI.cxx @@ -0,0 +1,105 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +#include "ucbhelper/propertyvalueset.hxx" +#include "rtl/ref.hxx" +#include "com/sun/star/ucb/Command.hpp" +#include "com/sun/star/ucb/XCommandEnvironment.hpp" +#include "com/sun/star/ucb/XCommandProcessor.hpp" +#include "com/sun/star/sdbc/XRow.hpp" +#include "ftpresultsetI.hxx" +#include "ftpcontent.hxx" + + +using namespace std; +using namespace ftp; +using namespace com::sun::star::ucb; +using namespace com::sun::star::lang; +using namespace com::sun::star::uno; +using namespace com::sun::star::beans; +using namespace com::sun::star::sdbc; + + +ResultSetI::ResultSetI(const Reference<XMultiServiceFactory>& xMSF, + const Reference<XContentProvider>& xProvider, + sal_Int32 nOpenMode, + const Sequence<Property>& seqProp, + const Sequence< NumberedSortingInfo >& seqSort, + const std::vector<FTPDirentry>& dirvec) + : ResultSetBase(xMSF,xProvider,nOpenMode,seqProp,seqSort) +{ + for( unsigned int i = 0; i < dirvec.size(); ++i) + m_aPath.push_back(dirvec[i].m_aURL); + + // m_aIdents holds the contentidentifiers + + m_aItems.resize( m_aPath.size() ); + m_aIdents.resize( m_aPath.size() ); + + for(unsigned n = 0; n < m_aItems.size(); ++n) { + rtl::Reference<ucbhelper::PropertyValueSet> xRow = + new ucbhelper::PropertyValueSet(xMSF); + + for( int i = 0; i < seqProp.getLength(); ++i) { + const rtl::OUString& Name = seqProp[i].Name; + if(Name.compareToAscii("ContentType") == 0 ) + xRow->appendString(seqProp[i], + rtl::OUString::createFromAscii( + "application/ftp" )); + else if(Name.compareToAscii("Title") == 0) + xRow->appendString(seqProp[i],dirvec[n].m_aName); + else if(Name.compareToAscii("IsReadOnly") == 0) + xRow->appendBoolean(seqProp[i], + sal_Bool(dirvec[n].m_nMode & + INETCOREFTP_FILEMODE_WRITE)); + else if(Name.compareToAscii("IsDocument") == 0) + xRow->appendBoolean(seqProp[i], + ! sal_Bool(dirvec[n].m_nMode & + INETCOREFTP_FILEMODE_ISDIR)); + else if(Name.compareToAscii("IsFolder") == 0) + xRow->appendBoolean(seqProp[i], + sal_Bool(dirvec[n].m_nMode & + INETCOREFTP_FILEMODE_ISDIR)); + else if(Name.compareToAscii("Size") == 0) + xRow->appendLong(seqProp[i], + dirvec[n].m_nSize); + else if(Name.compareToAscii("DateCreated") == 0) + xRow->appendTimestamp(seqProp[i], + dirvec[n].m_aDate); + else if(Name.compareToAscii("CreatableContentsInfo") == 0) + xRow->appendObject( + seqProp[i], + makeAny(FTPContent::queryCreatableContentsInfo_Static())); + else + xRow->appendVoid(seqProp[i]); + } + m_aItems[n] = Reference<XRow>(xRow.get()); + } +} diff --git a/ucb/source/ucp/ftp/ftpresultsetI.hxx b/ucb/source/ucp/ftp/ftpresultsetI.hxx new file mode 100644 index 000000000000..ded6613abdcc --- /dev/null +++ b/ucb/source/ucp/ftp/ftpresultsetI.hxx @@ -0,0 +1,63 @@ +/************************************************************************* + * + * 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 _FTP_FTPRESULTSETI_HXX_ +#define _FTP_FTPRESULTSETI_HXX_ + +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/ucb/XContentProvider.hpp> +#include <com/sun/star/beans/Property.hpp> +#include <com/sun/star/ucb/NumberedSortingInfo.hpp> +#include "ftpresultsetbase.hxx" +#include "ftpdirp.hxx" + + +namespace ftp { + + class ResultSetI + : public ResultSetBase + { + public: + + ResultSetI( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory>& xMSF, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentProvider>& xProvider, + sal_Int32 nOpenMode, + const com::sun::star::uno::Sequence< + com::sun::star::beans::Property >& seq, + const com::sun::star::uno::Sequence< + com::sun::star::ucb::NumberedSortingInfo >& seqSort, + const std::vector<FTPDirentry>& dirvec); + + private: + }; + +} + + +#endif diff --git a/ucb/source/ucp/ftp/ftpresultsetbase.cxx b/ucb/source/ucp/ftp/ftpresultsetbase.cxx new file mode 100644 index 000000000000..c83a34e251e8 --- /dev/null +++ b/ucb/source/ucp/ftp/ftpresultsetbase.cxx @@ -0,0 +1,662 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" +#include <ucbhelper/contentidentifier.hxx> +#include <com/sun/star/ucb/OpenMode.hpp> +#include <com/sun/star/uno/Reference.h> +#ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBBUTE_HPP_ +#include <com/sun/star/beans/PropertyAttribute.hpp> +#endif +#include <com/sun/star/ucb/ListActionType.hpp> +#include <com/sun/star/ucb/XSourceInitialization.hpp> +#include <ucbhelper/resultsetmetadata.hxx> +#include "ftpresultsetbase.hxx" + +using namespace ftp; +using namespace com::sun::star; + +ResultSetBase::ResultSetBase( + const uno::Reference< lang::XMultiServiceFactory >& xMSF, + const uno::Reference< ucb::XContentProvider >& xProvider, + sal_Int32 nOpenMode, + const uno::Sequence< beans::Property >& seq, + const uno::Sequence< ucb::NumberedSortingInfo >& seqSort ) + : m_xMSF( xMSF ), + m_xProvider( xProvider ), + m_nRow( -1 ), + m_nWasNull( true ), + m_nOpenMode( nOpenMode ), + m_bRowCountFinal( true ), + m_sProperty( seq ), + m_sSortingInfo( seqSort ), + m_pDisposeEventListeners( 0 ), + m_pRowCountListeners( 0 ), + m_pIsFinalListeners( 0 ) +{ +} + +ResultSetBase::~ResultSetBase() +{ + delete m_pIsFinalListeners; + delete m_pRowCountListeners; + delete m_pDisposeEventListeners; +} + + +// XInterface + +void SAL_CALL +ResultSetBase::acquire( + void ) + throw() +{ + OWeakObject::acquire(); +} + + +void SAL_CALL +ResultSetBase::release( + void ) + throw() +{ + OWeakObject::release(); +} + + + +uno::Any SAL_CALL +ResultSetBase::queryInterface( + const uno::Type& rType ) + throw( uno::RuntimeException ) +{ + uno::Any aRet = cppu::queryInterface( + rType, + SAL_STATIC_CAST( lang::XComponent*, this), + SAL_STATIC_CAST( sdbc::XRow*, this), + SAL_STATIC_CAST( sdbc::XResultSet*, this), + SAL_STATIC_CAST( sdbc::XResultSetMetaDataSupplier*, this), + SAL_STATIC_CAST( beans::XPropertySet*, this ), + SAL_STATIC_CAST( ucb::XContentAccess*, this) ); + return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ); +} + + + +// XComponent + + +void SAL_CALL +ResultSetBase::addEventListener( + const uno::Reference< lang::XEventListener >& Listener ) + throw( uno::RuntimeException ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + if ( ! m_pDisposeEventListeners ) + m_pDisposeEventListeners = + new cppu::OInterfaceContainerHelper( m_aMutex ); + + m_pDisposeEventListeners->addInterface( Listener ); +} + + +void SAL_CALL +ResultSetBase::removeEventListener( + const uno::Reference< lang::XEventListener >& Listener ) + throw( uno::RuntimeException ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + if ( m_pDisposeEventListeners ) + m_pDisposeEventListeners->removeInterface( Listener ); +} + + + +void SAL_CALL +ResultSetBase::dispose() + throw( uno::RuntimeException ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + lang::EventObject aEvt; + aEvt.Source = static_cast< lang::XComponent * >( this ); + + if ( m_pDisposeEventListeners && m_pDisposeEventListeners->getLength() ) + { + m_pDisposeEventListeners->disposeAndClear( aEvt ); + } + if( m_pRowCountListeners && m_pRowCountListeners->getLength() ) + { + m_pRowCountListeners->disposeAndClear( aEvt ); + } + if( m_pIsFinalListeners && m_pIsFinalListeners->getLength() ) + { + m_pIsFinalListeners->disposeAndClear( aEvt ); + } +} + + + +// XResultSet + +sal_Bool SAL_CALL +ResultSetBase::next( + void ) + throw( sdbc::SQLException, + uno::RuntimeException ) +{ + sal_Bool test; + if( ++m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + test = true; + else + test = false; + return test; +} + + +sal_Bool SAL_CALL +ResultSetBase::isBeforeFirst( + void ) + throw( sdbc::SQLException, + uno::RuntimeException ) +{ + return m_nRow == -1; +} + + +sal_Bool SAL_CALL +ResultSetBase::isAfterLast( + void ) + throw( sdbc::SQLException, + uno::RuntimeException ) +{ + return m_nRow >= sal::static_int_cast<sal_Int32>(m_aItems.size()); // Cannot happen, if m_aFolder.isOpen() +} + + +sal_Bool SAL_CALL +ResultSetBase::isFirst( + void ) + throw( sdbc::SQLException, + uno::RuntimeException ) +{ + return m_nRow == 0; +} + + +sal_Bool SAL_CALL +ResultSetBase::isLast( + void ) + throw( sdbc::SQLException, + uno::RuntimeException) +{ + if( m_nRow == sal::static_int_cast<sal_Int32>(m_aItems.size()) - 1 ) + return true; + else + return false; +} + + +void SAL_CALL +ResultSetBase::beforeFirst( + void ) + throw( sdbc::SQLException, + uno::RuntimeException) +{ + m_nRow = -1; +} + + +void SAL_CALL +ResultSetBase::afterLast( + void ) + throw( sdbc::SQLException, + uno::RuntimeException ) +{ + m_nRow = m_aItems.size(); +} + + +sal_Bool SAL_CALL +ResultSetBase::first( + void ) + throw( sdbc::SQLException, + uno::RuntimeException) +{ + m_nRow = -1; + return next(); +} + + +sal_Bool SAL_CALL +ResultSetBase::last( + void ) + throw( sdbc::SQLException, + uno::RuntimeException ) +{ + m_nRow = m_aItems.size() - 1; + return true; +} + + +sal_Int32 SAL_CALL +ResultSetBase::getRow( + void ) + throw( sdbc::SQLException, + uno::RuntimeException) +{ + // Test, whether behind last row + if( -1 == m_nRow || m_nRow >= sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + return 0; + else + return m_nRow+1; +} + + +sal_Bool SAL_CALL ResultSetBase::absolute( sal_Int32 row ) + throw( sdbc::SQLException, uno::RuntimeException) +{ + if( row >= 0 ) + m_nRow = row - 1; + else + { + last(); + m_nRow += ( row + 1 ); + if( m_nRow < -1 ) + m_nRow = -1; + } + + return 0<= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()); +} + + + + +sal_Bool SAL_CALL +ResultSetBase::relative( + sal_Int32 row ) + throw( sdbc::SQLException, + uno::RuntimeException) +{ + if( isAfterLast() || isBeforeFirst() ) + throw sdbc::SQLException(); + + if( row > 0 ) + while( row-- ) + next(); + else if( row < 0 ) + while( row++ && m_nRow > - 1 ) + previous(); + + return 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()); +} + + + +sal_Bool SAL_CALL +ResultSetBase::previous( + void ) + throw( sdbc::SQLException, + uno::RuntimeException) +{ + if( m_nRow > sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + m_nRow = m_aItems.size(); // Correct Handling of afterLast + if( 0 <= m_nRow ) -- m_nRow; + + return 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()); +} + + +void SAL_CALL +ResultSetBase::refreshRow( + void ) + throw( sdbc::SQLException, + uno::RuntimeException) +{ +} + + +sal_Bool SAL_CALL +ResultSetBase::rowUpdated( + void ) + throw( sdbc::SQLException, + uno::RuntimeException ) +{ + return false; +} + +sal_Bool SAL_CALL +ResultSetBase::rowInserted( + void ) + throw( sdbc::SQLException, + uno::RuntimeException ) +{ + return false; +} + +sal_Bool SAL_CALL +ResultSetBase::rowDeleted( + void ) + throw( sdbc::SQLException, + uno::RuntimeException ) +{ + return false; +} + + +uno::Reference< uno::XInterface > SAL_CALL +ResultSetBase::getStatement( + void ) + throw( sdbc::SQLException, + uno::RuntimeException ) +{ + uno::Reference< uno::XInterface > test( 0 ); + return test; +} + + +// XCloseable + +void SAL_CALL +ResultSetBase::close( + void ) + throw( sdbc::SQLException, + uno::RuntimeException) +{ +} + + +rtl::OUString SAL_CALL +ResultSetBase::queryContentIdentifierString( + void ) + throw( uno::RuntimeException ) +{ + if( 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + return m_aPath[m_nRow]; + else + return rtl::OUString(); +} + + +uno::Reference< ucb::XContentIdentifier > SAL_CALL +ResultSetBase::queryContentIdentifier( + void +) + throw( + uno::RuntimeException + ) +{ + if( 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + { + if(!m_aIdents[m_nRow].is()) { + rtl::OUString url = queryContentIdentifierString(); + if(url.getLength() ) + m_aIdents[m_nRow] = + uno::Reference< ucb::XContentIdentifier >( + new ::ucbhelper::ContentIdentifier(m_xMSF,url) ); + } + return m_aIdents[m_nRow]; + } + + return uno::Reference<ucb::XContentIdentifier>(); +} + + +uno::Reference< ucb::XContent > SAL_CALL +ResultSetBase::queryContent( + void ) + throw( uno::RuntimeException ) +{ + if( 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + return m_xProvider->queryContent(queryContentIdentifier()); + else + return uno::Reference< ucb::XContent >(); +} + + + +class XPropertySetInfoImpl + : public cppu::OWeakObject, + public beans::XPropertySetInfo +{ +public: + + XPropertySetInfoImpl( const uno::Sequence< beans::Property >& aSeq ) + : m_aSeq( aSeq ) + { + } + + void SAL_CALL acquire( void ) + throw() + { + OWeakObject::acquire(); + } + + + void SAL_CALL release( void ) + throw() + { + OWeakObject::release(); + } + + uno::Any SAL_CALL queryInterface( const uno::Type& rType ) + throw( uno::RuntimeException ) + { + uno::Any aRet = cppu::queryInterface( + rType, + SAL_STATIC_CAST( beans::XPropertySetInfo*, this ) ); + return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ); + } + + uno::Sequence< beans::Property > SAL_CALL getProperties() + throw( uno::RuntimeException ) + { + return m_aSeq; + } + + beans::Property SAL_CALL getPropertyByName( const ::rtl::OUString& aName ) + throw( beans::UnknownPropertyException, + uno::RuntimeException) + { + for( int i = 0; i < m_aSeq.getLength(); ++i ) + if( aName == m_aSeq[i].Name ) + return m_aSeq[i]; + throw beans::UnknownPropertyException(); + } + + sal_Bool SAL_CALL hasPropertyByName( const ::rtl::OUString& Name ) + throw( uno::RuntimeException ) + { + for( int i = 0; i < m_aSeq.getLength(); ++i ) + if( Name == m_aSeq[i].Name ) + return true; + return false; + } + +private: + + uno::Sequence< beans::Property > m_aSeq; +}; + + + +// XPropertySet +uno::Reference< beans::XPropertySetInfo > SAL_CALL +ResultSetBase::getPropertySetInfo() + throw( uno::RuntimeException) +{ + uno::Sequence< beans::Property > seq(2); + seq[0].Name = rtl::OUString::createFromAscii( "RowCount" ); + seq[0].Handle = -1; + seq[0].Type = getCppuType( static_cast< sal_Int32* >(0) ); + seq[0].Attributes = beans::PropertyAttribute::READONLY; + + seq[1].Name = rtl::OUString::createFromAscii( "IsRowCountFinal" ); + seq[1].Handle = -1; + seq[1].Type = getCppuType( static_cast< sal_Bool* >(0) ); + seq[1].Attributes = beans::PropertyAttribute::READONLY; + + //t + return uno::Reference< beans::XPropertySetInfo > ( + new XPropertySetInfoImpl( seq ) ); +} + + + +void SAL_CALL ResultSetBase::setPropertyValue( + const rtl::OUString& aPropertyName, const uno::Any& /*aValue*/ ) + throw( beans::UnknownPropertyException, + beans::PropertyVetoException, + lang::IllegalArgumentException, + lang::WrappedTargetException, + uno::RuntimeException) +{ + if( aPropertyName == rtl::OUString::createFromAscii( "IsRowCountFinal" ) || + aPropertyName == rtl::OUString::createFromAscii( "RowCount" ) ) + return; + + throw beans::UnknownPropertyException(); +} + + +uno::Any SAL_CALL ResultSetBase::getPropertyValue( + const rtl::OUString& PropertyName ) + throw( beans::UnknownPropertyException, + lang::WrappedTargetException, + uno::RuntimeException) +{ + if( PropertyName == rtl::OUString::createFromAscii( "IsRowCountFinal" ) ) + { + uno::Any aAny; + aAny <<= m_bRowCountFinal; + return aAny; + } + else if ( PropertyName == rtl::OUString::createFromAscii( "RowCount" ) ) + { + uno::Any aAny; + sal_Int32 count = m_aItems.size(); + aAny <<= count; + return aAny; + } + else + throw beans::UnknownPropertyException(); +} + + +void SAL_CALL ResultSetBase::addPropertyChangeListener( + const rtl::OUString& aPropertyName, + const uno::Reference< beans::XPropertyChangeListener >& xListener ) + throw( beans::UnknownPropertyException, + lang::WrappedTargetException, + uno::RuntimeException) +{ + if( aPropertyName == rtl::OUString::createFromAscii( "IsRowCountFinal" ) ) + { + osl::MutexGuard aGuard( m_aMutex ); + if ( ! m_pIsFinalListeners ) + m_pIsFinalListeners = + new cppu::OInterfaceContainerHelper( m_aMutex ); + + m_pIsFinalListeners->addInterface( xListener ); + } + else if ( aPropertyName == rtl::OUString::createFromAscii( "RowCount" ) ) + { + osl::MutexGuard aGuard( m_aMutex ); + if ( ! m_pRowCountListeners ) + m_pRowCountListeners = + new cppu::OInterfaceContainerHelper( m_aMutex ); + m_pRowCountListeners->addInterface( xListener ); + } + else + throw beans::UnknownPropertyException(); +} + + +void SAL_CALL ResultSetBase::removePropertyChangeListener( + const rtl::OUString& aPropertyName, + const uno::Reference< beans::XPropertyChangeListener >& aListener ) + throw( beans::UnknownPropertyException, + lang::WrappedTargetException, + uno::RuntimeException) +{ + if( aPropertyName == rtl::OUString::createFromAscii( "IsRowCountFinal" ) && + m_pIsFinalListeners ) + { + osl::MutexGuard aGuard( m_aMutex ); + m_pIsFinalListeners->removeInterface( aListener ); + } + else if ( aPropertyName == rtl::OUString::createFromAscii( "RowCount" ) && + m_pRowCountListeners ) + { + osl::MutexGuard aGuard( m_aMutex ); + m_pRowCountListeners->removeInterface( aListener ); + } + else + throw beans::UnknownPropertyException(); +} + + +void SAL_CALL ResultSetBase::addVetoableChangeListener( + const rtl::OUString& /*PropertyName*/, + const uno::Reference< beans::XVetoableChangeListener >& /*aListener*/ ) + throw( beans::UnknownPropertyException, + lang::WrappedTargetException, + uno::RuntimeException) +{ +} + + +void SAL_CALL ResultSetBase::removeVetoableChangeListener( + const rtl::OUString& /*PropertyName*/, + const uno::Reference< beans::XVetoableChangeListener >& /*aListener*/ ) + throw( beans::UnknownPropertyException, + lang::WrappedTargetException, + uno::RuntimeException) +{ +} + + + +// XResultSetMetaDataSupplier +uno::Reference< sdbc::XResultSetMetaData > SAL_CALL +ResultSetBase::getMetaData( + void ) + throw( sdbc::SQLException, + uno::RuntimeException ) +{ + ::ucbhelper::ResultSetMetaData* p = + new ::ucbhelper::ResultSetMetaData( + m_xMSF, m_sProperty ); + return uno::Reference< sdbc::XResultSetMetaData >( p ); +} + + + + diff --git a/ucb/source/ucp/ftp/ftpresultsetbase.hxx b/ucb/source/ucp/ftp/ftpresultsetbase.hxx new file mode 100644 index 000000000000..d82e38c14e03 --- /dev/null +++ b/ucb/source/ucp/ftp/ftpresultsetbase.hxx @@ -0,0 +1,608 @@ +/************************************************************************* + * + * 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 _FTP_FTPRESULTSETBASE_HXX_ +#define _FTP_FTPRESULTSETBASE_HXX_ + +#include <vector> +#include <cppuhelper/weak.hxx> +#include <cppuhelper/interfacecontainer.hxx> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/ucb/XContentAccess.hpp> +#include <com/sun/star/sdbc/XCloseable.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/sdbc/XResultSet.hpp> +#include <com/sun/star/sdbc/XRow.hpp> +#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp> +#include <com/sun/star/ucb/NumberedSortingInfo.hpp> +#include <com/sun/star/ucb/XContentProvider.hpp> +#include <com/sun/star/ucb/XContentIdentifier.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/beans/Property.hpp> + + +namespace ftp { + + class ResultSetBase + : public cppu::OWeakObject, + public com::sun::star::lang::XComponent, + public com::sun::star::sdbc::XRow, + public com::sun::star::sdbc::XResultSet, + public com::sun::star::sdbc::XCloseable, + public com::sun::star::sdbc::XResultSetMetaDataSupplier, + public com::sun::star::beans::XPropertySet, + public com::sun::star::ucb::XContentAccess + { + public: + + ResultSetBase(const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& xMSF, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentProvider >& xProvider, + sal_Int32 nOpenMode, + const com::sun::star::uno::Sequence< + com::sun::star::beans::Property >& seq, + const com::sun::star::uno::Sequence< + com::sun::star::ucb::NumberedSortingInfo >& seqSort); + + virtual ~ResultSetBase(); + + // XInterface + virtual com::sun::star::uno::Any SAL_CALL + queryInterface( + const com::sun::star::uno::Type& aType ) + throw( com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + acquire( + void ) + throw(); + + virtual void SAL_CALL + release( + void ) + throw(); + + // XComponent + virtual void SAL_CALL + dispose( + void ) + throw( com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL + addEventListener( + const com::sun::star::uno::Reference< + com::sun::star::lang::XEventListener >& xListener ) + throw( com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL + removeEventListener( const com::sun::star::uno::Reference< + com::sun::star::lang::XEventListener >& aListener ) + throw( com::sun::star::uno::RuntimeException ); + + + // XRow + virtual sal_Bool SAL_CALL + wasNull( + void ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ) + { + if( 0<= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + m_nWasNull = m_aItems[m_nRow]->wasNull(); + else + m_nWasNull = true; + return m_nWasNull; + } + + virtual rtl::OUString SAL_CALL + getString( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException) + { + rtl::OUString ret; + if( 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + ret = m_aItems[m_nRow]->getString( columnIndex ); + + return ret; + } + + virtual sal_Bool SAL_CALL + getBoolean( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException) + { + if( 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + return m_aItems[m_nRow]->getBoolean( columnIndex ); + else + return false; + } + + virtual sal_Int8 SAL_CALL + getByte( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException) + { + if( 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + return m_aItems[m_nRow]->getByte( columnIndex ); + else + return sal_Int8( 0 ); + } + + virtual sal_Int16 SAL_CALL + getShort( + sal_Int32 columnIndex ) + throw( + com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException) + { + if( 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + return m_aItems[m_nRow]->getShort( columnIndex ); + else + return sal_Int16( 0 ); + } + + virtual sal_Int32 SAL_CALL + getInt( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ) + { + if( 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + return m_aItems[m_nRow]->getInt( columnIndex ); + else + return sal_Int32( 0 ); + } + + virtual sal_Int64 SAL_CALL + getLong( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException) + { + if( 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + return m_aItems[m_nRow]->getLong( columnIndex ); + else + return sal_Int64( 0 ); + } + + virtual float SAL_CALL + getFloat( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ) + { + if( 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + return m_aItems[m_nRow]->getFloat( columnIndex ); + else + return float( 0 ); + } + + virtual double SAL_CALL + getDouble( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ) + { + if( 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + return m_aItems[m_nRow]->getDouble( columnIndex ); + else + return double( 0 ); + } + + virtual com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL + getBytes( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException ) + { + if( 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + return m_aItems[m_nRow]->getBytes( columnIndex ); + else + return com::sun::star::uno::Sequence< sal_Int8 >(); + } + + virtual com::sun::star::util::Date SAL_CALL + getDate( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException) + { + if( 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + return m_aItems[m_nRow]->getDate( columnIndex ); + else + return com::sun::star::util::Date(); + } + + virtual com::sun::star::util::Time SAL_CALL + getTime( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException) + { + if( 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + return m_aItems[m_nRow]->getTime( columnIndex ); + else + return com::sun::star::util::Time(); + } + + virtual com::sun::star::util::DateTime SAL_CALL + getTimestamp( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException) + { + if( 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + return m_aItems[m_nRow]->getTimestamp( columnIndex ); + else + return com::sun::star::util::DateTime(); + } + + + virtual com::sun::star::uno::Reference< + com::sun::star::io::XInputStream > SAL_CALL + getBinaryStream( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException) + { + if( 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + return m_aItems[m_nRow]->getBinaryStream( columnIndex ); + else + return com::sun::star::uno::Reference< + com::sun::star::io::XInputStream >(); + } + + virtual com::sun::star::uno::Reference< + com::sun::star::io::XInputStream > SAL_CALL + getCharacterStream( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException) + { + if( 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + return m_aItems[m_nRow]->getCharacterStream( columnIndex ); + else + return com::sun::star::uno::Reference< + com::sun::star::io::XInputStream >(); + } + + virtual com::sun::star::uno::Any SAL_CALL + getObject( + sal_Int32 columnIndex, + const com::sun::star::uno::Reference< + com::sun::star::container::XNameAccess >& typeMap ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException) + { + if( 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + return m_aItems[m_nRow]->getObject( columnIndex,typeMap ); + else + return com::sun::star::uno::Any(); + } + + virtual com::sun::star::uno::Reference< + com::sun::star::sdbc::XRef > SAL_CALL + getRef( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException) + { + if( 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + return m_aItems[m_nRow]->getRef( columnIndex ); + else + return com::sun::star::uno::Reference< com::sun::star::sdbc::XRef >(); + } + + virtual com::sun::star::uno::Reference< + com::sun::star::sdbc::XBlob > SAL_CALL + getBlob( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException) + { + if( 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + return m_aItems[m_nRow]->getBlob( columnIndex ); + else + return com::sun::star::uno::Reference< com::sun::star::sdbc::XBlob >(); + } + + virtual com::sun::star::uno::Reference< + com::sun::star::sdbc::XClob > SAL_CALL + getClob( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException) + { + if( 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + return m_aItems[m_nRow]->getClob( columnIndex ); + else + return com::sun::star::uno::Reference< + com::sun::star::sdbc::XClob >(); + } + + virtual com::sun::star::uno::Reference< + com::sun::star::sdbc::XArray > SAL_CALL + getArray( + sal_Int32 columnIndex ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException) + { + if( 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()) ) + return m_aItems[m_nRow]->getArray( columnIndex ); + else + return com::sun::star::uno::Reference< + com::sun::star::sdbc::XArray >(); + } + + + // XResultSet + + virtual sal_Bool SAL_CALL + next( + void ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL + isBeforeFirst( + void ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL + isAfterLast( + void ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL + isFirst( + void ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL + isLast( + void ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + beforeFirst( + void ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + afterLast( + void ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL + first( + void ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL + last( + void ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + virtual sal_Int32 SAL_CALL + getRow( + void ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL + absolute( + sal_Int32 row ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL + relative( + sal_Int32 rows ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL + previous( + void ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + refreshRow( + void ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL + rowUpdated( + void ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL + rowInserted( + void ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL + rowDeleted( + void ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + + virtual com::sun::star::uno::Reference< + com::sun::star::uno::XInterface > SAL_CALL + getStatement( + void ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + // XCloseable + + virtual void SAL_CALL + close( + void ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + // XContentAccess + + virtual rtl::OUString SAL_CALL + queryContentIdentifierString( + void ) + throw( com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier > SAL_CALL + queryContentIdentifier( + void ) + throw( com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::uno::Reference< + com::sun::star::ucb::XContent > SAL_CALL + queryContent( + void ) + throw( com::sun::star::uno::RuntimeException ); + + // XResultSetMetaDataSupplier + virtual com::sun::star::uno::Reference< + com::sun::star::sdbc::XResultSetMetaData > SAL_CALL + getMetaData( + void ) + throw( com::sun::star::sdbc::SQLException, + com::sun::star::uno::RuntimeException); + + + // XPropertySet + virtual com::sun::star::uno::Reference< + com::sun::star::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo() + throw( com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL setPropertyValue( + const rtl::OUString& aPropertyName, + const com::sun::star::uno::Any& aValue ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::beans::PropertyVetoException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException); + + virtual com::sun::star::uno::Any SAL_CALL + getPropertyValue( + const rtl::OUString& PropertyName ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + addPropertyChangeListener( + const rtl::OUString& aPropertyName, + const com::sun::star::uno::Reference< + com::sun::star::beans::XPropertyChangeListener >& xListener ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + removePropertyChangeListener( + const rtl::OUString& aPropertyName, + const com::sun::star::uno::Reference< + com::sun::star::beans::XPropertyChangeListener >& aListener ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + addVetoableChangeListener( + const rtl::OUString& PropertyName, + const com::sun::star::uno::Reference< + com::sun::star::beans::XVetoableChangeListener >& aListener ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL removeVetoableChangeListener( + const rtl::OUString& PropertyName, + const com::sun::star::uno::Reference< + com::sun::star::beans::XVetoableChangeListener >& aListener ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException); + + protected: + + com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory > m_xMSF; + com::sun::star::uno::Reference< + com::sun::star::ucb::XContentProvider > m_xProvider; + sal_Int32 m_nRow; + sal_Bool m_nWasNull; + sal_Int32 m_nOpenMode; + sal_Bool m_bRowCountFinal; + + typedef std::vector< com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier > > IdentSet; + typedef std::vector< com::sun::star::uno::Reference< + com::sun::star::sdbc::XRow > > ItemSet; + typedef std::vector< rtl::OUString > + PathSet; + + IdentSet m_aIdents; + ItemSet m_aItems; + PathSet m_aPath; + + com::sun::star::uno::Sequence< + com::sun::star::beans::Property > m_sProperty; + com::sun::star::uno::Sequence< + com::sun::star::ucb::NumberedSortingInfo > m_sSortingInfo; + + osl::Mutex m_aMutex; + cppu::OInterfaceContainerHelper* m_pDisposeEventListeners; + + cppu::OInterfaceContainerHelper* m_pRowCountListeners; + cppu::OInterfaceContainerHelper* m_pIsFinalListeners; + }; + + +} // end namespace fileaccess + + +#endif diff --git a/ucb/source/ucp/ftp/ftpresultsetfactory.hxx b/ucb/source/ucp/ftp/ftpresultsetfactory.hxx new file mode 100644 index 000000000000..24f14162e87e --- /dev/null +++ b/ucb/source/ucp/ftp/ftpresultsetfactory.hxx @@ -0,0 +1,57 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ +#ifndef _FTP_FTPRESULTSETFACTORY_HXX_ +#define _FTP_FTPRESULTSETFACTORY_HXX_ + +#include "ftpresultsetbase.hxx" + + + +namespace ftp { + + class ResultSetBase; + + class ResultSetFactory + { + public: + + virtual ~ResultSetFactory() { }; + + virtual ResultSetBase* createResultSet() = 0; + }; + +} + + + +#endif diff --git a/ucb/source/ucp/ftp/ftpservices.cxx b/ucb/source/ucp/ftp/ftpservices.cxx new file mode 100644 index 000000000000..8e5c88ad66c1 --- /dev/null +++ b/ucb/source/ucp/ftp/ftpservices.cxx @@ -0,0 +1,74 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <com/sun/star/registry/XRegistryKey.hpp> +#include "ftpcontentprovider.hxx" + +using namespace com::sun::star; +using namespace ftp; + +//========================================================================= +extern "C" void SAL_CALL component_getImplementationEnvironment( + const sal_Char ** ppEnvTypeName, uno_Environment ** /*ppEnv*/ ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + +//========================================================================= +extern "C" void * SAL_CALL component_getFactory( + const sal_Char * pImplName, void * pServiceManager, void * /*pRegistryKey*/ ) +{ + void * pRet = 0; + + uno::Reference< lang::XMultiServiceFactory > xSMgr( + reinterpret_cast< lang::XMultiServiceFactory * >( + pServiceManager ) ); + uno::Reference< lang::XSingleServiceFactory > xFactory; + + ////////////////////////////////////////////////////////////////////// + // FTP Content Provider. + ////////////////////////////////////////////////////////////////////// + + if ( FTPContentProvider::getImplementationName_Static(). + compareToAscii( pImplName ) == 0 ) + { + xFactory = FTPContentProvider::createServiceFactory( xSMgr ); + } + + if ( xFactory.is() ) + { + xFactory->acquire(); + pRet = xFactory.get(); + } + + return pRet; +} + diff --git a/ucb/source/ucp/ftp/ftpstrcont.hxx b/ucb/source/ucp/ftp/ftpstrcont.hxx new file mode 100644 index 000000000000..8598be8831ae --- /dev/null +++ b/ucb/source/ucp/ftp/ftpstrcont.hxx @@ -0,0 +1,87 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ +#ifndef _FTP_STRCONT_HXX_ +#define _FTP_STRCONT_HXX_ + +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/io/XOutputStream.hpp> +#include "ftpcfunc.hxx" + + +namespace ftp { + + + class FTPInputStream; + + + class FTPOutputStreamContainer + : public FTPStreamContainer + { + public: + + FTPOutputStreamContainer(const com::sun::star::uno::Reference< + com::sun::star::io::XOutputStream>& out); + virtual ~FTPOutputStreamContainer() {} + + virtual size_t write(void *buffer,size_t size,size_t nmemb); + + + private: + + com::sun::star::uno::Reference< + com::sun::star::io::XOutputStream> m_out; + }; + + + class FTPInputStreamContainer + : public FTPStreamContainer + { + public: + + FTPInputStreamContainer(FTPInputStream* out); + + virtual size_t write(void *buffer,size_t size,size_t nmemb); + + com::sun::star::uno::Reference< + com::sun::star::io::XInputStream> operator()(); + + private: + + FTPInputStream* m_out; + }; + + +} + + +#endif diff --git a/ucb/source/ucp/ftp/ftpurl.cxx b/ucb/source/ucp/ftp/ftpurl.cxx new file mode 100644 index 000000000000..c703e0942e8a --- /dev/null +++ b/ucb/source/ucp/ftp/ftpurl.cxx @@ -0,0 +1,838 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ + +#include <memory> +#include <rtl/ustrbuf.hxx> +#include <com/sun/star/ucb/OpenMode.hpp> +#include <string.h> +#include <rtl/uri.hxx> + +#include "ftpstrcont.hxx" +#include "ftpurl.hxx" +#include "ftphandleprovider.hxx" +#include "ftpinpstr.hxx" +#include "ftpcfunc.hxx" +#include "ftpcontainer.hxx" + +using namespace ftp; +using namespace com::sun::star::ucb; +using namespace com::sun::star::uno; +using namespace com::sun::star::io; + +namespace { + +rtl::OUString encodePathSegment(rtl::OUString const & decoded) { + return rtl::Uri::encode( + decoded, rtl_UriCharClassPchar, rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8); +} + +rtl::OUString decodePathSegment(rtl::OUString const & encoded) { + return rtl::Uri::decode( + encoded, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8); +} + +} + +MemoryContainer::MemoryContainer() + : m_nLen(0), + m_nWritePos(0), + m_pBuffer(0) +{ +} + +MemoryContainer::~MemoryContainer() +{ + rtl_freeMemory(m_pBuffer); +} + + +int MemoryContainer::append( + const void* pBuffer, + size_t size, + size_t nmemb +) throw() +{ + sal_uInt32 nLen = size*nmemb; + sal_uInt32 tmp(nLen + m_nWritePos); + + if(m_nLen < tmp) { // enlarge in steps of multiples of 1K + do { + m_nLen+=1024; + } while(m_nLen < tmp); + + m_pBuffer = rtl_reallocateMemory(m_pBuffer,m_nLen); + } + + rtl_copyMemory(static_cast<sal_Int8*>(m_pBuffer)+m_nWritePos, + pBuffer,nLen); + m_nWritePos = tmp; + return nLen; +} + + +extern "C" { + + int memory_write(void *buffer,size_t size,size_t nmemb,void *stream) + { + MemoryContainer *_stream = + reinterpret_cast<MemoryContainer*>(stream); + + if(!_stream) + return 0; + + return _stream->append(buffer,size,nmemb); + } + +} + + +FTPURL::FTPURL(const FTPURL& r) + : m_mutex(), + m_pFCP(r.m_pFCP), + m_aUsername(r.m_aUsername), + m_bShowPassword(r.m_bShowPassword), + m_aHost(r.m_aHost), + m_aPort(r.m_aPort), + m_aPathSegmentVec(r.m_aPathSegmentVec) + +{ +} + + +FTPURL::FTPURL(const rtl::OUString& url, + FTPHandleProvider* pFCP) + throw( + malformed_exception + ) + : m_pFCP(pFCP), + m_aUsername(rtl::OUString::createFromAscii("anonymous")), + m_bShowPassword(false), + m_aPort(rtl::OUString::createFromAscii("21")) +{ + parse(url); // can reset m_bShowPassword +} + + +FTPURL::~FTPURL() +{ +} + + +void FTPURL::parse(const rtl::OUString& url) + throw( + malformed_exception + ) +{ + rtl::OUString aPassword,aAccount; + rtl::OString aIdent(url.getStr(), + url.getLength(), + RTL_TEXTENCODING_UTF8); + + rtl::OString lower = aIdent.toAsciiLowerCase(); + if(lower.getLength() < 6 || + strncmp("ftp://",lower.getStr(),6)) + throw malformed_exception(); + + char *buffer = new char[1+aIdent.getLength()]; + const char* p2 = aIdent.getStr(); + p2 += 6; + + char ch; + char *p1 = buffer; // determine "username:password@host:port" + while((ch = *p2++) != '/' && ch) + *p1++ = ch; + *p1 = 0; + + rtl::OUString aExpr(rtl::OUString(buffer,strlen(buffer), + RTL_TEXTENCODING_UTF8)); + + sal_Int32 l = aExpr.indexOf(sal_Unicode('@')); + m_aHost = aExpr.copy(1+l); + + if(l != -1) { + // Now username and password. + aExpr = aExpr.copy(0,l); + l = aExpr.indexOf(sal_Unicode(':')); + if(l != -1) { + aPassword = aExpr.copy(1+l); + if(aPassword.getLength()) + m_bShowPassword = true; + } + if(l > 0) + // Overwritte only if the username is not empty. + m_aUsername = aExpr.copy(0,l); + else if(aExpr.getLength()) + m_aUsername = aExpr; + } + + l = m_aHost.lastIndexOf(sal_Unicode(':')); + sal_Int32 ipv6Back = m_aHost.lastIndexOf(sal_Unicode(']')); + if((ipv6Back == -1 && l != -1) // not ipv6, but a port + || + (ipv6Back != -1 && 1+ipv6Back == l) // ipv6, and a port + ) + { + if(1+l<m_aHost.getLength()) + m_aPort = m_aHost.copy(1+l); + m_aHost = m_aHost.copy(0,l); + } + + while(ch) { // now determine the pathsegments ... + p1 = buffer; + while((ch = *p2++) != '/' && ch) + *p1++ = ch; + *p1 = 0; + + if(buffer[0]) { + if(strcmp(buffer,"..") == 0 && + m_aPathSegmentVec.size() && + ! m_aPathSegmentVec.back().equalsAscii("..")) + m_aPathSegmentVec.pop_back(); + else if(strcmp(buffer,".") == 0) + ; // Ignore + else + // This is a legal name. + m_aPathSegmentVec.push_back( + rtl::OUString(buffer, + strlen(buffer), + RTL_TEXTENCODING_UTF8)); + } + } + + delete[] buffer; + + if(m_bShowPassword) + m_pFCP->setHost(m_aHost, + m_aPort, + m_aUsername, + aPassword, + aAccount); + + // now check for something like ";type=i" at end of url + if(m_aPathSegmentVec.size() && + (l = m_aPathSegmentVec.back().indexOf(sal_Unicode(';'))) != -1) { + m_aType = m_aPathSegmentVec.back().copy(l); + m_aPathSegmentVec.back() = m_aPathSegmentVec.back().copy(0,l); + } +} + + +rtl::OUString FTPURL::ident(bool withslash,bool internal) const +{ + // rebuild the url as one without ellipses, + // and more important, as one without username and + // password. ( These are set together with the command. ) + + rtl::OUStringBuffer bff; + bff.appendAscii("ftp://"); + + if(!m_aUsername.equalsAscii("anonymous")) { + bff.append(m_aUsername); + + rtl::OUString aPassword,aAccount; + m_pFCP->forHost(m_aHost, + m_aPort, + m_aUsername, + aPassword, + aAccount); + + if((m_bShowPassword || internal) && + aPassword.getLength() ) + bff.append(sal_Unicode(':')) + .append(aPassword); + + bff.append(sal_Unicode('@')); + } + bff.append(m_aHost); + + if(!m_aPort.equalsAscii("21")) + bff.append(sal_Unicode(':')) + .append(m_aPort) + .append(sal_Unicode('/')); + else + bff.append(sal_Unicode('/')); + + for(unsigned i = 0; i < m_aPathSegmentVec.size(); ++i) + if(i == 0) + bff.append(m_aPathSegmentVec[i]); + else + bff.append(sal_Unicode('/')).append(m_aPathSegmentVec[i]); + if(withslash) + if(bff.getLength() && bff[bff.getLength()-1] != sal_Unicode('/')) + bff.append(sal_Unicode('/')); + + bff.append(m_aType); + return bff.makeStringAndClear(); +} + + +rtl::OUString FTPURL::parent(bool internal) const +{ + rtl::OUStringBuffer bff; + + bff.appendAscii("ftp://"); + + if(!m_aUsername.equalsAscii("anonymous")) { + bff.append(m_aUsername); + + rtl::OUString aPassword,aAccount; + m_pFCP->forHost(m_aHost, + m_aPort, + m_aUsername, + aPassword, + aAccount); + + if((internal || m_bShowPassword) && aPassword.getLength()) + bff.append(sal_Unicode(':')) + .append(aPassword); + + bff.append(sal_Unicode('@')); + } + + bff.append(m_aHost); + + if(!m_aPort.equalsAscii("21")) + bff.append(sal_Unicode(':')) + .append(m_aPort) + .append(sal_Unicode('/')); + else + bff.append(sal_Unicode('/')); + + rtl::OUString last; + + for(unsigned int i = 0; i < m_aPathSegmentVec.size(); ++i) + if(1+i == m_aPathSegmentVec.size()) + last = m_aPathSegmentVec[i]; + else if(i == 0) + bff.append(m_aPathSegmentVec[i]); + else + bff.append(sal_Unicode('/')).append(m_aPathSegmentVec[i]); + + if(!last.getLength()) + bff.appendAscii(".."); + else if(last.equalsAscii("..")) + bff.append(last).appendAscii("/.."); + + bff.append(m_aType); + return bff.makeStringAndClear(); +} + + +void FTPURL::child(const rtl::OUString& title) +{ + m_aPathSegmentVec.push_back(encodePathSegment(title)); +} + + +rtl::OUString FTPURL::child() const +{ + return + m_aPathSegmentVec.size() ? + decodePathSegment(m_aPathSegmentVec.back()) : rtl::OUString(); +} + + + +/** Listing of a directory. + */ + +namespace ftp { + + enum OS { + FTP_DOS,FTP_UNIX,FTP_VMS,FTP_UNKNOWN + }; + +} + + +#define SET_CONTROL_CONTAINER \ + MemoryContainer control; \ + curl_easy_setopt(curl, \ + CURLOPT_HEADERFUNCTION, \ + memory_write); \ + curl_easy_setopt(curl, \ + CURLOPT_WRITEHEADER, \ + &control) + + +#define SET_DATA_CONTAINER \ + curl_easy_setopt(curl,CURLOPT_NOBODY,false); \ + MemoryContainer data; \ + curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,memory_write); \ + curl_easy_setopt(curl,CURLOPT_WRITEDATA,&data) + +#define SET_URL(url) \ + rtl::OString urlParAscii(url.getStr(), \ + url.getLength(), \ + RTL_TEXTENCODING_UTF8); \ + curl_easy_setopt(curl, \ + CURLOPT_URL, \ + urlParAscii.getStr()); + + // Setting username:password +#define SET_USER_PASSWORD(username,password) \ + rtl::OUString combi(username + \ + rtl::OUString::createFromAscii(":") + \ + password); \ + rtl::OString aUserPsswd(combi.getStr(), \ + combi.getLength(), \ + RTL_TEXTENCODING_UTF8); \ + curl_easy_setopt(curl, \ + CURLOPT_USERPWD, \ + aUserPsswd.getStr()) + + + +FILE* FTPURL::open() + throw(curl_exception) +{ + if(!m_aPathSegmentVec.size()) + throw curl_exception(CURLE_FTP_COULDNT_RETR_FILE); + + CURL *curl = m_pFCP->handle(); + + SET_CONTROL_CONTAINER; + rtl::OUString url(ident(false,true)); + SET_URL(url); + FILE *res = tmpfile(); + curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,file_write); + curl_easy_setopt(curl,CURLOPT_WRITEDATA,res); + + curl_easy_setopt(curl,CURLOPT_POSTQUOTE,0); + CURLcode err = curl_easy_perform(curl); + + if(err == CURLE_OK) + rewind(res); + else { + fclose(res),res = 0; + throw curl_exception(err); + } + + return res; +} + + +std::vector<FTPDirentry> FTPURL::list( + sal_Int16 nMode +) const + throw( + curl_exception + ) +{ + CURL *curl = m_pFCP->handle(); + + SET_CONTROL_CONTAINER; + SET_DATA_CONTAINER; + rtl::OUString url(ident(true,true)); + SET_URL(url); + curl_easy_setopt(curl,CURLOPT_POSTQUOTE,0); + + CURLcode err = curl_easy_perform(curl); + if(err != CURLE_OK) + throw curl_exception(err); + + // now evaluate the error messages + + sal_uInt32 len = data.m_nWritePos; + char* fwd = (char*) data.m_pBuffer; + rtl::OString str(fwd,len); + char *p1, *p2; + p1 = p2 = fwd; + + OS osKind(FTP_UNKNOWN); + std::vector<FTPDirentry> resvec; + FTPDirentry aDirEntry; + // ensure slash at the end + rtl::OUString viewurl(ident(true,false)); + + while(true) { + while(p2-fwd < int(len) && *p2 != '\n') ++p2; + if(p2-fwd == int(len)) break; + + *p2 = 0; + switch(osKind) { + // While FTP knows the 'system'-command, + // which returns the operating system type, + // this is not usable here: There are Windows-server + // formatting the output like UNIX-ls command. + case FTP_DOS: + FTPDirectoryParser::parseDOS(aDirEntry,p1); + break; + case FTP_UNIX: + FTPDirectoryParser::parseUNIX(aDirEntry,p1); + break; + case FTP_VMS: + FTPDirectoryParser::parseVMS(aDirEntry,p1); + break; + default: + if(FTPDirectoryParser::parseUNIX(aDirEntry,p1)) + osKind = FTP_UNIX; + else if(FTPDirectoryParser::parseDOS(aDirEntry,p1)) + osKind = FTP_DOS; + else if(FTPDirectoryParser::parseVMS(aDirEntry,p1)) + osKind = FTP_VMS; + } + aDirEntry.m_aName = aDirEntry.m_aName.trim(); + if(osKind != int(FTP_UNKNOWN) && + !aDirEntry.m_aName.equalsAscii("..") && + !aDirEntry.m_aName.equalsAscii(".")) { + aDirEntry.m_aURL = viewurl + encodePathSegment(aDirEntry.m_aName); + + sal_Bool isDir = + sal_Bool(aDirEntry.m_nMode&INETCOREFTP_FILEMODE_ISDIR); + switch(nMode) { + case OpenMode::DOCUMENTS: + if(!isDir) + resvec.push_back(aDirEntry); + break; + case OpenMode::FOLDERS: + if(isDir) + resvec.push_back(aDirEntry); + break; + default: + resvec.push_back(aDirEntry); + }; + } + aDirEntry.clear(); + p1 = p2 + 1; + } + + return resvec; +} + + +rtl::OUString FTPURL::net_title() const + throw(curl_exception) +{ + CURL *curl = m_pFCP->handle(); + + SET_CONTROL_CONTAINER; + curl_easy_setopt(curl,CURLOPT_NOBODY,true); // no data => no transfer + struct curl_slist *slist = 0; + // post request + slist = curl_slist_append(slist,"PWD"); + curl_easy_setopt(curl,CURLOPT_POSTQUOTE,slist); + + bool try_more(true); + CURLcode err; + rtl::OUString aNetTitle; + + while(true) { + rtl::OUString url(ident(false,true)); + + if(try_more && + 1+url.lastIndexOf(sal_Unicode('/')) != url.getLength()) + url += rtl::OUString::createFromAscii("/"); // add end-slash + else if(!try_more && + 1+url.lastIndexOf(sal_Unicode('/')) == url.getLength()) + url = url.copy(0,url.getLength()-1); // remove end-slash + + SET_URL(url); + err = curl_easy_perform(curl); + + if(err == CURLE_OK) { // get the title from the server + char* fwd = (char*) control.m_pBuffer; + sal_uInt32 len = (sal_uInt32) control.m_nWritePos; + + aNetTitle = rtl::OUString(fwd,len,RTL_TEXTENCODING_UTF8); + // the buffer now contains the name of the file; + // analyze the output: + // Format of current working directory: + // 257 "/bla/bla" is current directory + sal_Int32 index1 = aNetTitle.lastIndexOf( + rtl::OUString::createFromAscii("257")); + index1 = 1+aNetTitle.indexOf(sal_Unicode('"'),index1); + sal_Int32 index2 = aNetTitle.indexOf(sal_Unicode('"'),index1); + aNetTitle = aNetTitle.copy(index1,index2-index1); + if(!aNetTitle.equalsAscii("/")) { + index1 = aNetTitle.lastIndexOf(sal_Unicode('/')); + aNetTitle = aNetTitle.copy(1+index1); + } + try_more = false; + } else if(err == CURLE_BAD_PASSWORD_ENTERED) + // the client should retry after getting the correct + // username + password + throw curl_exception(err); +#if LIBCURL_VERSION_NUM>=0x070d01 /* 7.13.1 */ + else if(err == CURLE_LOGIN_DENIED) + // the client should retry after getting the correct + // username + password + throw curl_exception(err); +#endif + else if(try_more && err == CURLE_FTP_ACCESS_DENIED) { + // We were either denied access when trying to login to + // an FTP server or when trying to change working directory + // to the one given in the URL. + if(m_aPathSegmentVec.size()) + // determine title form url + aNetTitle = decodePathSegment(m_aPathSegmentVec.back()); + else + // must be root + aNetTitle = rtl::OUString::createFromAscii("/"); + try_more = false; + } + + if(try_more) + try_more = false; + else + break; + } + + curl_slist_free_all(slist); + return aNetTitle; +} + + +FTPDirentry FTPURL::direntry() const + throw(curl_exception) +{ + rtl::OUString nettitle = net_title(); + FTPDirentry aDirentry; + + aDirentry.m_aName = nettitle; // init aDirentry + if(nettitle.equalsAscii("/") || + nettitle.equalsAscii("..")) + aDirentry.m_nMode = INETCOREFTP_FILEMODE_ISDIR; + else + aDirentry.m_nMode = INETCOREFTP_FILEMODE_UNKNOWN; + + aDirentry.m_nSize = 0; + + if(!nettitle.equalsAscii("/")) { + // try to open the parent directory + FTPURL aURL(parent(),m_pFCP); + + std::vector<FTPDirentry> aList = aURL.list(OpenMode::ALL); + + for(unsigned i = 0; i < aList.size(); ++i) { + if(aList[i].m_aName == nettitle) { // the relevant file is found + aDirentry = aList[i]; + break; + } + } + } + return aDirentry; +} + + +extern "C" { + + size_t memory_read(void *ptr,size_t size,size_t nmemb,void *stream) + { + sal_Int32 nRequested = sal_Int32(size*nmemb); + CurlInput *curlInput = static_cast<CurlInput*>(stream); + if(curlInput) + return size_t(curlInput->read(((sal_Int8*)ptr),nRequested)); + else + return 0; + } + +} + + +void FTPURL::insert(bool replaceExisting,void* stream) const + throw(curl_exception) +{ + if(!replaceExisting) { +// FTPDirentry aDirentry(direntry()); +// if(aDirentry.m_nMode == INETCOREFTP_FILEMODE_UNKNOWN) + // throw curl_exception(FILE_EXIST_DURING_INSERT); + throw curl_exception(FILE_MIGHT_EXIST_DURING_INSERT); + } // else + // overwrite is default in libcurl + + CURL *curl = m_pFCP->handle(); + + SET_CONTROL_CONTAINER; + curl_easy_setopt(curl,CURLOPT_NOBODY,false); // no data => no transfer + curl_easy_setopt(curl,CURLOPT_POSTQUOTE,0); + curl_easy_setopt(curl,CURLOPT_QUOTE,0); + curl_easy_setopt(curl,CURLOPT_READFUNCTION,memory_read); + curl_easy_setopt(curl,CURLOPT_READDATA,stream); + curl_easy_setopt(curl, CURLOPT_UPLOAD,1); + + rtl::OUString url(ident(false,true)); + SET_URL(url); + + CURLcode err = curl_easy_perform(curl); + curl_easy_setopt(curl, CURLOPT_UPLOAD,false); + + if(err != CURLE_OK) + throw curl_exception(err); +} + + + +void FTPURL::mkdir(bool ReplaceExisting) const + throw(curl_exception) +{ + rtl::OString title; + if(m_aPathSegmentVec.size()) { + rtl::OUString titleOU = m_aPathSegmentVec.back(); + titleOU = decodePathSegment(titleOU); + title = rtl::OString(titleOU.getStr(), + titleOU.getLength(), + RTL_TEXTENCODING_UTF8); + } + else + // will give an error + title = rtl::OString("/"); + + rtl::OString aDel("del "); aDel += title; + rtl::OString mkd("mkd "); mkd += title; + + struct curl_slist *slist = 0; + + FTPDirentry aDirentry(direntry()); + if(!ReplaceExisting) { +// if(aDirentry.m_nMode != INETCOREFTP_FILEMODE_UNKNOWN) +// throw curl_exception(FOLDER_EXIST_DURING_INSERT); + throw curl_exception(FOLDER_MIGHT_EXIST_DURING_INSERT); + } else if(aDirentry.m_nMode != INETCOREFTP_FILEMODE_UNKNOWN) + slist = curl_slist_append(slist,aDel.getStr()); + + slist = curl_slist_append(slist,mkd.getStr()); + + CURL *curl = m_pFCP->handle(); + SET_CONTROL_CONTAINER; + curl_easy_setopt(curl,CURLOPT_NOBODY,true); // no data => no transfer + curl_easy_setopt(curl,CURLOPT_QUOTE,0); + + // post request + curl_easy_setopt(curl,CURLOPT_POSTQUOTE,slist); + + rtl::OUString url(parent(true)); + if(1+url.lastIndexOf(sal_Unicode('/')) != url.getLength()) + url += rtl::OUString::createFromAscii("/"); + SET_URL(url); + + CURLcode err = curl_easy_perform(curl); + curl_slist_free_all(slist); + if(err != CURLE_OK) + throw curl_exception(err); +} + + +rtl::OUString FTPURL::ren(const rtl::OUString& NewTitle) + throw(curl_exception) +{ + CURL *curl = m_pFCP->handle(); + + // post request + rtl::OString renamefrom("RNFR "); + rtl::OUString OldTitle = net_title(); + renamefrom += + rtl::OString(OldTitle.getStr(), + OldTitle.getLength(), + RTL_TEXTENCODING_UTF8); + + rtl::OString renameto("RNTO "); + renameto += + rtl::OString(NewTitle.getStr(), + NewTitle.getLength(), + RTL_TEXTENCODING_UTF8); + + struct curl_slist *slist = 0; + slist = curl_slist_append(slist,renamefrom.getStr()); + slist = curl_slist_append(slist,renameto.getStr()); + curl_easy_setopt(curl,CURLOPT_POSTQUOTE,slist); + + SET_CONTROL_CONTAINER; + curl_easy_setopt(curl,CURLOPT_NOBODY,true); // no data => no transfer + curl_easy_setopt(curl,CURLOPT_QUOTE,0); + + rtl::OUString url(parent(true)); + if(1+url.lastIndexOf(sal_Unicode('/')) != url.getLength()) + url += rtl::OUString::createFromAscii("/"); + SET_URL(url); + + CURLcode err = curl_easy_perform(curl); + curl_slist_free_all(slist); + if(err != CURLE_OK) + throw curl_exception(err); + else if(m_aPathSegmentVec.size() && + !m_aPathSegmentVec.back().equalsAscii("..")) + m_aPathSegmentVec.back() = encodePathSegment(NewTitle); + return OldTitle; +} + + + +void FTPURL::del() const + throw(curl_exception) +{ + FTPDirentry aDirentry(direntry()); + + rtl::OString dele(aDirentry.m_aName.getStr(), + aDirentry.m_aName.getLength(), + RTL_TEXTENCODING_UTF8); + + if(aDirentry.m_nMode & INETCOREFTP_FILEMODE_ISDIR) { + std::vector<FTPDirentry> vec = list(sal_Int16(OpenMode::ALL)); + for( unsigned int i = 0; i < vec.size(); ++i ) + try { + FTPURL url(vec[i].m_aURL,m_pFCP); + url.del(); + } catch(const curl_exception&) { + } + dele = rtl::OString("RMD ") + dele; + } + else if(aDirentry.m_nMode != INETCOREFTP_FILEMODE_UNKNOWN) + dele = rtl::OString("DELE ") + dele; + else + return; + + // post request + CURL *curl = m_pFCP->handle(); + struct curl_slist *slist = 0; + slist = curl_slist_append(slist,dele.getStr()); + curl_easy_setopt(curl,CURLOPT_POSTQUOTE,slist); + + SET_CONTROL_CONTAINER; + curl_easy_setopt(curl,CURLOPT_NOBODY,true); // no data => no transfer + curl_easy_setopt(curl,CURLOPT_QUOTE,0); + + rtl::OUString url(parent(true)); + if(1+url.lastIndexOf(sal_Unicode('/')) != url.getLength()) + url += rtl::OUString::createFromAscii("/"); + SET_URL(url); + + CURLcode err = curl_easy_perform(curl); + curl_slist_free_all(slist); + if(err != CURLE_OK) + throw curl_exception(err); +} + diff --git a/ucb/source/ucp/ftp/ftpurl.hxx b/ucb/source/ucp/ftp/ftpurl.hxx new file mode 100644 index 000000000000..fa2acdcc2770 --- /dev/null +++ b/ucb/source/ucp/ftp/ftpurl.hxx @@ -0,0 +1,178 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ + +#ifndef _FTP_FTPURL_HXX_ +#define _FTP_FTPURL_HXX_ + +#include "curl.hxx" +#include <curl/easy.h> +#include <com/sun/star/io/XOutputStream.hpp> + +#include <stdio.h> +#include <rtl/ustring.hxx> +#include <osl/mutex.hxx> +#include <vector> + +#include "ftpdirp.hxx" +#include "ftpcfunc.hxx" + +namespace ftp { + + /** Forward declarations. + */ + + class FTPHandleProvider; + + + enum FTPErrors { FILE_EXIST_DURING_INSERT = CURL_LAST +1, + FOLDER_EXIST_DURING_INSERT, + FOLDER_MIGHT_EXIST_DURING_INSERT, + FILE_MIGHT_EXIST_DURING_INSERT }; + + + class malformed_exception { }; + + + class curl_exception + { + public: + + curl_exception(sal_Int32 err) + : n_err(err) { } + + sal_Int32 code() const { return n_err; } + + + private: + + sal_Int32 n_err; + }; + + class CurlInput { + + public: + + // returns the number of bytes actually read + virtual sal_Int32 read(sal_Int8 *dest,sal_Int32 nBytesRequested) = 0; + }; + + + class FTPURL + { + public: + + FTPURL( + const rtl::OUString& aIdent, + FTPHandleProvider* pFCP = 0 + ) + throw( + malformed_exception + ); + + FTPURL(const FTPURL& r); + + ~FTPURL(); + + rtl::OUString host() const { return m_aHost; } + + rtl::OUString port() const { return m_aPort; } + + rtl::OUString username() const { return m_aUsername; } + + /** This returns the URL, but cleaned from + * unnessary ellipses. + */ + + rtl::OUString ident(bool withslash,bool internal) const; + + /** returns the parent url. + */ + + rtl::OUString parent(bool internal = false) const; + + /** sets the unencoded title */ + void child(const rtl::OUString& title); + + /** returns the unencoded title */ + rtl::OUString child(void) const; + + std::vector<FTPDirentry> list(sal_Int16 nMode) const + throw(curl_exception); + + // returns a pointer to an open tempfile, + // seeked to the beginning of. + FILE* open() throw(curl_exception); + + FTPDirentry direntry() const throw(curl_exception); + + void insert(bool ReplaceExisting,void* stream) const + throw(curl_exception); + + void mkdir(bool ReplaceExisting) const + throw(curl_exception); + + rtl::OUString ren(const rtl::OUString& NewTitle) + throw(curl_exception); + + void del() const + throw(curl_exception); + + + private: + + osl::Mutex m_mutex; + + FTPHandleProvider *m_pFCP; + + mutable rtl::OUString m_aUsername; + bool m_bShowPassword; + mutable rtl::OUString m_aHost; + mutable rtl::OUString m_aPort; + mutable rtl::OUString m_aType; + + /** Contains the encoded pathsegments of the url. + */ + std::vector<rtl::OUString> m_aPathSegmentVec; + + void parse(const rtl::OUString& url) + throw( + malformed_exception + ); + + rtl::OUString net_title() const throw(curl_exception); + }; + +} + + +#endif diff --git a/ucb/source/ucp/ftp/makefile.mk b/ucb/source/ucp/ftp/makefile.mk new file mode 100644 index 000000000000..c2f1ce154a56 --- /dev/null +++ b/ucb/source/ucp/ftp/makefile.mk @@ -0,0 +1,114 @@ +#************************************************************************* +# +# 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=ucb +TARGET=ucpftp +ENABLE_EXCEPTIONS=TRUE +USE_DEFFILE=TRUE +NO_BSYMBOLIC=TRUE + +# Version +UCPFTP_MAJOR=1 + + +# --- Settings --------------------------------------------------------- + +.INCLUDE: settings.mk + +# --- General ----------------------------------------------------- +.IF "$(L10N_framework)"=="" +# first target ( shared library ) + +SLOFILES1=\ + $(SLO)$/ftpservices.obj \ + $(SLO)$/ftpcontentprovider.obj \ + $(SLO)$/ftpcontent.obj \ + $(SLO)$/ftpcontentidentifier.obj \ + $(SLO)$/ftpcontentcaps.obj \ + $(SLO)$/ftpdynresultset.obj \ + $(SLO)$/ftpresultsetbase.obj \ + $(SLO)$/ftpresultsetI.obj \ + $(SLO)$/ftploaderthread.obj \ + $(SLO)$/ftpinpstr.obj \ + $(SLO)$/ftpdirp.obj \ + $(SLO)$/ftpcfunc.obj \ + $(SLO)$/ftpurl.obj \ + $(SLO)$/ftpintreq.obj + +LIB1TARGET=$(SLB)$/_$(TARGET).lib +LIB1OBJFILES=$(SLOFILES1) + +# --- Shared-Library 1 --------------------------------------------------- + +SHL1TARGET=$(TARGET)$(UCPFTP_MAJOR) +SHL1IMPLIB=i$(TARGET) + +SHL1VERSIONMAP=$(SOLARENV)/src/component.map + +SHL1STDLIBS=\ + $(CPPUHELPERLIB) \ + $(CPPULIB) \ + $(SALLIB) \ + $(UCBHELPERLIB) \ + $(CURLLIB) + +.IF "$(GUI)" == "OS2" +SHL1STDLIBS+=ssl.lib crypto.lib libz.lib +.ENDIF + +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +SHL1LIBS= \ + $(LIB1TARGET) + +# --- Def-File --------------------------------------------------------- + +DEF1NAME=$(SHL1TARGET) + +.ENDIF # L10N_framework +.INCLUDE: target.mk + + + + + + + + + + + + + + +ALLTAR : $(MISC)/ucpftp1.component + +$(MISC)/ucpftp1.component .ERRREMOVE : $(SOLARENV)/bin/createcomponent.xslt \ + ucpftp1.component + $(XSLTPROC) --nonet --stringparam uri \ + '$(COMPONENTPREFIX_BASIS_NATIVE)$(SHL1TARGETN:f)' -o $@ \ + $(SOLARENV)/bin/createcomponent.xslt ucpftp1.component diff --git a/ucb/source/ucp/ftp/test.cxx b/ucb/source/ucp/ftp/test.cxx new file mode 100644 index 000000000000..9bc6585400ba --- /dev/null +++ b/ucb/source/ucp/ftp/test.cxx @@ -0,0 +1,298 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ + +#include "test_ftpurl.hxx" +#include <stdio.h> +#include <unistd.h> + +// #include <osl/process.h> +// #include <osl/thread.hxx> + +// #include <ucbhelper/configurationkeys.hxx> +// #include <cppuhelper/bootstrap.hxx> +// #include <cppuhelper/servicefactory.hxx> +// #include <comphelper/processfactory.hxx> +// #include <comphelper/regpathhelper.hxx> +// #include <com/sun/star/lang/XComponent.hpp> +// #include <com/sun/star/lang/XMultiServiceFactory.hpp> +// #include <com/sun/star/ucb/XContentIdentifierFactory.hpp> +// #include <com/sun/star/ucb/XContent.hpp> +// #include <com/sun/star/ucb/XContentProvider.hpp> +// #include <com/sun/star/ucb/XCommandProcessor.hpp> +// #include <com/sun/star/ucb/OpenMode.hpp> +// #include <com/sun/star/ucb/Command.hpp> +// #include <com/sun/star/ucb/OpenCommandArgument2.hpp> +// #include <com/sun/star/io/XActiveDataSink.hpp> +// #include <com/sun/star/beans/Property.hpp> + + +// #include "debughelper.hxx" +// #include "test_activedatasink.hxx" +// #include "test_ftpurl.hxx" +// #include "test_multiservicefac.hxx" +// #include "ftpcontentprovider.hxx" +// #include "ftpcontentidentifier.hxx" + + +// using namespace test_ftp; +// using namespace rtl; +// using namespace com::sun::star::uno; +// using namespace com::sun::star::lang; +// using namespace com::sun::star::ucb; +// using namespace com::sun::star::beans; +// using namespace com::sun::star::io; + + + +// class FTPThread +// : public osl::Thread +// { +// public: + +// FTPThread(); + +// int number_of_errors() { return _number_of_errors; } + +// protected: + +// void SAL_CALL run(); + + +// private: + +// ftp::FTPContentProvider *pProvider; +// Reference<XContentProvider> xProvider; +// Reference<XMultiServiceFactory> xFac; + +// int _number_of_errors; +// }; + + +// Reference< XMultiServiceFactory > createApplicationServiceManager() +// { +// try +// { +// Reference<XComponentContext> xComponentContext = +// ::cppu::defaultBootstrap_InitialComponentContext(); +// Reference<XMultiServiceFactory> xMS( +// xComponentContext->getServiceManager(), +// UNO_QUERY); + +// return xMS; +// } +// catch( ::com::sun::star::uno::Exception& ) +// { +// return Reference< XMultiServiceFactory >(); +// } +// } + + +// FTPThread::FTPThread() +// : _number_of_errors(0), +// xFac(createApplicationServiceManager()) +// { +// pProvider = new ftp::FTPContentProvider(xFac); +// xProvider = Reference<XContentProvider>(pProvider); + +// if(!xProvider.is()) +// ++_number_of_errors; +// } + + +// void FTPThread::run() { +// if(!xFac.is()) { +// ++_number_of_errors; +// exit(1); +// } + +// Reference<XContentIdentifier> xIdent( +// new ftp::FTPContentIdentifier( +// rtl::OUString::createFromAscii("ftp://abi:psswd@abi-1/file"), +// pProvider)); + +// Reference<XContent> xContent = xProvider->queryContent(xIdent); +// if(!xContent.is()) +// { +// err_msg("no content",OUString()); +// exit(1); +// } + + +// Reference<XActiveDataSink> xActDS(new Test_ActiveDataSink()); +// OpenCommandArgument2 aOpenCommand(OpenMode::DOCUMENT, +// 0, +// Reference<XInterface>(xActDS,UNO_QUERY), +// Sequence<Property>(0), +// Sequence<NumberedSortingInfo>(0)); +// Any aAny; aAny <<= aOpenCommand; + +// Command aCommand(OUString::createFromAscii("open"), +// -1, +// aAny); + +// Reference<XCommandProcessor> xCommandProcessor(xContent,UNO_QUERY); +// if(!xCommandProcessor.is()) +// { +// err_msg("no command_processor",OUString()); +// exit(1); +// } +// xCommandProcessor->execute(aCommand, +// 0,Reference<XCommandEnvironment>(0)); + +// Reference<XInputStream> xInputStream = xActDS->getInputStream(); +// if(!xInputStream.is()) +// ; +// } + + +int main(int argc,char* argv[]) +{ +// FTPThread aThread; +// aThread.create(); +// aThread.join(); + + typedef int (*INT_FUNC)(void); + INT_FUNC tests[] = { test_ftpurl, + test_ftpparent, + test_ftpproperties, + test_ftpopen, + test_ftplist, + 0 }; // don't remove ending zero + + int err_level = 0; + + fprintf(stderr,"------- Testing ----------\n"); + + int i = -1; + do { + INT_FUNC f = tests[++i]; + if(f) { + err_level += (*f)(); + fprintf(stderr,"."); + } else + break; + } while(true); + + if(err_level) { + fprintf(stderr,"number of failed tests: %d\n",err_level); + fprintf(stderr,"----------------------------------\n"); + } else + fprintf(stderr,"no errors\n"); + + return err_level; +} + + + +// char *scefile = 0; +// if(strcmp(argv[1],"-sce") == 0) +// scefile = argv[2]; + +// if(!scefile) { +// fprintf(stderr,"usage: ftptest -sce filename\n"); +// return 1; +// } + +// rtl::OUString sceurl; +// osl::FileBase::RC err = +// osl::FileBase::getFileURLFromSystemPath( +// rtl::OUString(scefile, +// strlen(scefile), +// RTL_TEXTENCODING_UTF8), +// sceurl); + +// osl::File aFile(sceurl); +// err = aFile.open(OpenFlag_Read); +// if(err != osl::FileBase::E_None) { +// fprintf(stderr,"could not open sce-file %s\n",scefile); +// return 1; +// } + +// sal_uInt64 n; +// char buffer[256]; +// rtl::OUStringBuffer bff; +// do { +// err = aFile.read((void*)buffer,256,n); +// bff.appendAscii(buffer,sal_Int32(n)); +// } while(err == osl::FileBase::E_None && n == 256); + +// aFile.close(); + +// rtl::OUString sce = bff.makeStringAndClear(); + +// fprintf(stderr,rtl::OString(sce.getStr(), +// sce.getLength(), +// RTL_TEXTENCODING_UTF8).getStr()); + +// rtl::OUString lib,tmp,testlib; +// std::vector<rtl::OUString> tests; +// sal_Int32 TEST = sce.indexOf(rtl::OUString::createFromAscii("TEST")); +// sal_Int32 WITH = sce.indexOf(rtl::OUString::createFromAscii("WITH")); +// sal_Int32 FROM = sce.indexOf(rtl::OUString::createFromAscii("FROM")); +// lib = sce.copy(TEST+4,WITH-TEST-4).trim(); + +// tmp = sce.copy(WITH+4,FROM-WITH-4).trim(); +// sal_Int32 nIndex = 0; +// do +// { +// rtl::OUString token = tmp.getToken(0,';',nIndex).trim(); +// if(token.getLength()) +// tests.push_back(token); +// } while(nIndex >= 0); + +// testlib = sce.copy(FROM+4).trim(); + +// // fprintf(stderr,"%s\n", +// // rtl::OString(token.getStr(), +// // token.getLength(), +// // RTL_TEXTENCODING_UTF8).getStr()); + +// osl::Module testLib; +// if(!testLib.load(testlib)) { +// fprintf(stderr,"library not found: %s\n", +// rtl::OString(testlib.getStr(), +// testlib.getLength(), +// RTL_TEXTENCODING_UTF8).getStr()); +// return 1; +// } + +// osl::Module mathLib; +// mathLib.load(rtl::OUString::createFromAscii("libm.so")); +// typedef double (*DF)(double); +// DF func = (DF)mathLib.getSymbol(rtl::OUString::createFromAscii("cos")); +// fprintf(stderr,"-------double %f ----------\n",(*func)(2.0)); + +// fprintf(stderr,"-------testing %s ----------\n",scefile); diff --git a/ucb/source/ucp/ftp/test.py b/ucb/source/ucp/ftp/test.py new file mode 100644 index 000000000000..931d9a3ec8a5 --- /dev/null +++ b/ucb/source/ucp/ftp/test.py @@ -0,0 +1,25 @@ +#/usr/bin/env python + +import re,os + +def grep(pattern,dirname,names): + for name in names: + filename = os.path.join(dirname,name) + if os.path.isfile(filename): + lines = open(filename,"r").readlines() + for line in lines: + if pattern.search(line): + print filename + break + + +def find(pattern,directory = "."): + os.path.walk(directory,grep,re.compile(pattern)) + + +if __name__ == "__main__": + import sys + if len(sys.argv) == 2: + find(sys.argv[1]) + elif len(sys.argv) == 2: + find(sys.argv[2],sys.argv[1]) diff --git a/ucb/source/ucp/ftp/test_activedatasink.cxx b/ucb/source/ucp/ftp/test_activedatasink.cxx new file mode 100644 index 000000000000..5265dc530be9 --- /dev/null +++ b/ucb/source/ucp/ftp/test_activedatasink.cxx @@ -0,0 +1,64 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ + +#ifndef _TEST_ACTIVEDATASINK_HXX_ +#include "test_activedatasink.hxx" +#endif + + +using namespace test_ftp; +using namespace com::sun::star::uno; +using namespace com::sun::star::io; + + +Any SAL_CALL Test_ActiveDataSink::queryInterface( const Type& rType ) throw( RuntimeException ) { + Any aRet = ::cppu::queryInterface(rType, + SAL_STATIC_CAST( XActiveDataSink*,this )); + + return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ); +} + + + +void SAL_CALL Test_ActiveDataSink::acquire( void ) throw() { + OWeakObject::acquire(); +} + + + +void SAL_CALL Test_ActiveDataSink::release( void ) throw() { + OWeakObject::release(); +} diff --git a/ucb/source/ucp/ftp/test_activedatasink.hxx b/ucb/source/ucp/ftp/test_activedatasink.hxx new file mode 100644 index 000000000000..55e62d90f5a3 --- /dev/null +++ b/ucb/source/ucp/ftp/test_activedatasink.hxx @@ -0,0 +1,89 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ +#ifndef _TEST_ACTIVEDATASINK_HXX_ +#define _TEST_ACTIVEDATASINK_HXX_ + +#include <cppuhelper/weak.hxx> +#include <cppuhelper/queryinterface.hxx> +#include <com/sun/star/io/XActiveDataSink.hpp> +#include <com/sun/star/io/XInputStream.hpp> + +namespace test_ftp { + + + class Test_ActiveDataSink + : public cppu::OWeakObject, + public com::sun::star::io::XActiveDataSink + { + public: + + // XInterface + + virtual com::sun::star::uno::Any SAL_CALL + queryInterface( const com::sun::star::uno::Type& rType ) + throw( com::sun::star::uno::RuntimeException ); + + + virtual void SAL_CALL acquire( void ) throw(); + + virtual void SAL_CALL release( void ) throw(); + + + // XActiveDataSink + + virtual void SAL_CALL + setInputStream(const com::sun::star::uno::Reference<com::sun::star::io::XInputStream>& aStream ) + throw(com::sun::star::uno::RuntimeException) + { + m_xInputStream = aStream; + } + + + virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL + getInputStream( ) + throw(::com::sun::star::uno::RuntimeException) + { + return m_xInputStream; + } + + + private: + + com::sun::star::uno::Reference<com::sun::star::io::XInputStream> m_xInputStream; + + }; + +} + + +#endif diff --git a/ucb/source/ucp/ftp/test_ftpurl.cxx b/ucb/source/ucp/ftp/test_ftpurl.cxx new file mode 100755 index 000000000000..8e623c630aa8 --- /dev/null +++ b/ucb/source/ucp/ftp/test_ftpurl.cxx @@ -0,0 +1,284 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" +#include <com/sun/star/ucb/OpenMode.hpp> +#include "ftpurl.hxx" +#include "ftploaderthread.hxx" +#include "ftphandleprovider.hxx" +#include "debughelper.hxx" +#include <rtl/memory.h> +#include <vector> + +#define TESTEVAL \ + if(number_of_errors) \ + fprintf(stderr,"errors in %s: %d\n",name,number_of_errors); \ + return number_of_errors + + +namespace ccsu = com::sun::star::ucb; + + +struct ServerInfo { + rtl::OUString host; + rtl::OUString port; + rtl::OUString username; + rtl::OUString password; + rtl::OUString account; +}; + + +class FTPHandleProviderI + : public ftp::FTPHandleProvider { + +public: + + FTPHandleProviderI() + : p(new ftp::FTPLoaderThread) { + } + + ~FTPHandleProviderI() { + delete p; + } + + virtual CURL* handle() { + return p->handle(); + } + + bool forHost(const rtl::OUString& host, + const rtl::OUString& port, + const rtl::OUString& username, + rtl::OUString& password, + rtl::OUString& account) + { + for(unsigned int i = 0; i < m_ServerInfo.size(); ++i) + if(host == m_ServerInfo[i].host && + port == m_ServerInfo[i].port && + username == m_ServerInfo[i].username ) { + password = m_ServerInfo[i].password; + account = m_ServerInfo[i].account; + return true; + } + + return false; + } + + virtual bool setHost(const rtl::OUString& host, + const rtl::OUString& port, + const rtl::OUString& username, + const rtl::OUString& password, + const rtl::OUString& account) + { + ServerInfo inf; + inf.host = host; + inf.port = port; + inf.username = username; + inf.password = password; + inf.account = account; + + bool present(false); + for(unsigned int i = 0; i < m_ServerInfo.size(); ++i) + if(host == m_ServerInfo[i].host && + port == m_ServerInfo[i].port) { + m_ServerInfo[i] = inf; + present = true; + } + + if(!present) + m_ServerInfo.push_back(inf); + + return !present; + + } + + +private: + + std::vector<ServerInfo> m_ServerInfo; + ftp::FTPLoaderThread *p; +}; + + + +// Here are some test for the parsing of an url. + +#define TESTURL \ +{ \ +ftp::FTPURL url(rtl::OUString::createFromAscii(ascii),&prov); \ +if(!url.username().equalsAscii(n)) {\ +++number_of_errors; \ +err_msg("wrong username: ",url.username()); \ +}} + +int test_ftpurl(void) { + const char* name = "test_ftpurl"; + int number_of_errors = 0; + + FTPHandleProviderI prov; + char* ascii,*n,*p; + + ascii = "ftp://abi:psswd@host/eins/../drei", n = "abi", p = "psswd"; + TESTURL; + + ascii = "ftp://:psswd@host:22/eins/../drei", n = "anonymous", p = "psswd"; + TESTURL; + + ascii = "ftp://host/bla/../../test/", n = "anonymous", p = ""; + TESTURL; + + TESTEVAL; +} + + +int test_ftplist(void) { + int number_of_errors = 0; + const char* name = "test_ftplist"; + + FTPHandleProviderI provider; + + ftp::FTPURL url( + rtl::OUString::createFromAscii( + "ftp://abi:psswd@abi-1/dir"), + &provider); + + std::vector<ftp::FTPDirentry> vec = + url.list(com::sun::star::ucb::OpenMode::ALL); + + if(vec.size() != 3) + ++number_of_errors; + + if(!(vec[0].m_aName.equalsAscii("dir1") && + vec[1].m_aName.equalsAscii("dir2") && + vec[2].m_aName.equalsAscii("file1"))) + ++number_of_errors; + + TESTEVAL; +} + + +#define TESTPARENT \ + { \ + ftp::FTPURL url(rtl::OUString::createFromAscii(ascii),&prov); \ + urlStr = url.parent(); \ + if(!urlStr.equalsAscii(expect)) \ + ++number_of_errors; \ + } + + +int test_ftpparent(void) { + int number_of_errors = 0; + const char* name = "test_ftpparent"; + FTPHandleProviderI prov; + + rtl::OUString urlStr; + char *ascii,*expect; + + ascii = "ftp://abi:psswd@abi-1/file"; + expect = "ftp://abi:psswd@abi-1/"; + TESTPARENT; + + ascii = "ftp://abi:psswd@abi-1/dir/../file"; + expect = "ftp://abi:psswd@abi-1/"; + TESTPARENT; + + ascii = "ftp://abi:psswd@abi-1/.."; + expect = "ftp://abi:psswd@abi-1/../.."; + TESTPARENT; + + ascii = "ftp://abi:psswd@abi-1/../../dir"; + expect = "ftp://abi:psswd@abi-1/../.."; + TESTPARENT; + + ascii = "ftp://abi:psswd@abi-1/"; + expect = "ftp://abi:psswd@abi-1/.."; + TESTPARENT; + + TESTEVAL; +} + + +int test_ftpproperties(void) { + int number_of_errors = 0; + const char* name = "test_ftpproperties"; + FTPHandleProviderI provider; + + ftp::FTPURL url( + rtl::OUString::createFromAscii( + "ftp://abi:psswd@abi-1/file"), + &provider); + + ftp::FTPDirentry ade(url.direntry()); + + if(!(ade.m_aName.equalsAscii("file") && + ade.isFile())) + ++number_of_errors; + + TESTEVAL; +} + + +int test_ftpopen(void) +{ + int number_of_errors = 0; + const char* name = "test_ftpopen"; + + FTPHandleProviderI provider; + ftp::FTPURL url( + rtl::OUString::createFromAscii( + "ftp://abi:psswd@abi-1/file"), + &provider); + + FILE* file = url.open(); + if(file) { + int nbuf,ndest; + const int bffsz = 256; + char buff[bffsz]; + char *dest = (char*) malloc(sizeof(char)); + dest[0] = 0; + do { + rtl_zeroMemory((void*)buff,bffsz); + fread(buff,bffsz-1,1,file); + nbuf = strlen(buff); + ndest = strlen(dest); + dest = (char*)realloc(dest,ndest + nbuf + 1); + strncat(dest,buff,nbuf); + } while(nbuf == bffsz-1); + fclose(file); + + const char* expected = "You are now looking at the filecontent.\n"; + if(strcmp(expected,dest)) + ++number_of_errors; + free(dest); + } else + ++number_of_errors; + + TESTEVAL; +} + + diff --git a/ucb/source/ucp/ftp/test_ftpurl.hxx b/ucb/source/ucp/ftp/test_ftpurl.hxx new file mode 100755 index 000000000000..641e29fa8087 --- /dev/null +++ b/ucb/source/ucp/ftp/test_ftpurl.hxx @@ -0,0 +1,5 @@ +extern int test_ftpurl(void); +extern int test_ftpproperties(void); +extern int test_ftpopen(void); +extern int test_ftplist(void); +extern int test_ftpparent(void); diff --git a/ucb/source/ucp/ftp/test_interactionhandler.hxx b/ucb/source/ucp/ftp/test_interactionhandler.hxx new file mode 100644 index 000000000000..a0ea9f9ff75a --- /dev/null +++ b/ucb/source/ucp/ftp/test_interactionhandler.hxx @@ -0,0 +1,75 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ +#ifndef _TEST_ACTIVEDATASINK_HXX_ +#define _TEST_ACTIVEDATASINK_HXX_ + +#include <cppuhelper/weak.hxx> +#include <cppuhelper/queryinterface.hxx> +#include <com/sun/star/task/XInteractionHandler.hpp> + +namespace test_ftp { + + + class Test_InteractionHandler + : public cppu::OWeakObject, + public com::sun::star::task::XInteractionHandler + { + public: + + // XInterface + + virtual com::sun::star::uno::Any SAL_CALL + queryInterface( const com::sun::star::uno::Type& rType ) + throw( com::sun::star::uno::RuntimeException ); + + + virtual void SAL_CALL acquire( void ) throw(); + + virtual void SAL_CALL release( void ) throw(); + + + // XInteractionHandler + + virtual void SAL_CALL + handle( const ::com::sun::star::uno::Reference< + ::com::sun::star::task::XInteractionRequest >& Request ) + throw (::com::sun::star::uno::RuntimeException); + + private: + + }; + +} + + +#endif diff --git a/ucb/source/ucp/ftp/test_multiservicefac.cxx b/ucb/source/ucp/ftp/test_multiservicefac.cxx new file mode 100644 index 000000000000..3c9570516b99 --- /dev/null +++ b/ucb/source/ucp/ftp/test_multiservicefac.cxx @@ -0,0 +1,113 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ +#include "test_multiservicefac.hxx" + + +using namespace test_ftp; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; + + +Any SAL_CALL +Test_MultiServiceFactory::queryInterface( + const Type& rType +) + throw( + RuntimeException + ) +{ + Any aRet = ::cppu::queryInterface(rType, + SAL_STATIC_CAST( XMultiServiceFactory*, + this )); + + return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ); + +} + + +void SAL_CALL Test_MultiServiceFactory::acquire( void ) throw() +{ + OWeakObject::acquire(); +} + + +void SAL_CALL Test_MultiServiceFactory::release( void ) throw() +{ + OWeakObject::release(); +} + + // XMultiServiceFactory + + Reference< +XInterface > SAL_CALL +Test_MultiServiceFactory::createInstance( + const ::rtl::OUString& aServiceSpecifier +) + throw ( + Exception, + RuntimeException + ) +{ + return Reference< + XInterface >(0); +} + + +Reference< +XInterface > SAL_CALL +Test_MultiServiceFactory::createInstanceWithArguments( + const ::rtl::OUString& ServiceSpecifier, + const Sequence + < Any >& Arguments +) + throw ( + Exception, + RuntimeException + ) +{ + return Reference< + XInterface >(0); +} + +Sequence< ::rtl::OUString > SAL_CALL +Test_MultiServiceFactory::getAvailableServiceNames( +) + throw ( + RuntimeException + ) +{ + return Sequence< ::rtl::OUString >(0); +} diff --git a/ucb/source/ucp/ftp/test_multiservicefac.hxx b/ucb/source/ucp/ftp/test_multiservicefac.hxx new file mode 100644 index 000000000000..874a03f43a1c --- /dev/null +++ b/ucb/source/ucp/ftp/test_multiservicefac.hxx @@ -0,0 +1,96 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ +#ifndef _TEST_MULTISERVICEFAC_HXX_ +#define _TEST_MULTISERVICEFAC_HXX_ + +#include <cppuhelper/weak.hxx> +#include <cppuhelper/queryinterface.hxx> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> + + +namespace test_ftp { + + class Test_MultiServiceFactory + : public cppu::OWeakObject, + public com::sun::star::lang::XMultiServiceFactory + { + public: + + // XInterface + + virtual com::sun::star::uno::Any SAL_CALL + queryInterface( const com::sun::star::uno::Type& rType ) + throw( com::sun::star::uno::RuntimeException ); + + + virtual void SAL_CALL acquire( void ) throw(); + + virtual void SAL_CALL release( void ) throw(); + + // XMultiServiceFactory + + virtual ::com::sun::star::uno::Reference< + ::com::sun::star::uno::XInterface > SAL_CALL + createInstance( + const ::rtl::OUString& aServiceSpecifier + ) + throw ( + ::com::sun::star::uno::Exception, + ::com::sun::star::uno::RuntimeException + ); + + virtual + ::com::sun::star::uno::Reference< + ::com::sun::star::uno::XInterface > SAL_CALL + createInstanceWithArguments( + const ::rtl::OUString& ServiceSpecifier, + const ::com::sun::star::uno::Sequence + < ::com::sun::star::uno::Any >& Arguments + ) + throw ( + ::com::sun::star::uno::Exception, + ::com::sun::star::uno::RuntimeException + ); + + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL + getAvailableServiceNames( + ) + throw ( + ::com::sun::star::uno::RuntimeException + ); + }; + +} + +#endif + diff --git a/ucb/source/ucp/ftp/ucpftp.xml b/ucb/source/ucp/ftp/ucpftp.xml new file mode 100644 index 000000000000..041fa1e1abc1 --- /dev/null +++ b/ucb/source/ucp/ftp/ucpftp.xml @@ -0,0 +1,89 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE module-description PUBLIC "-//StarOffice//DTD ComponentDescription 1.0//EN" "module-description.dtd"> +<module-description xmlns:xlink="http://www.w3.org/1999/xlink"> + + <module-name> + ucpftp + </module-name> + + <component-description> + <author> + Andreas Bille + </author> + <name> + com.sun.star.comp.ucb.FTPContentProvider + </name> + <description> + This component implements a Content Provider for the Universal + Content Broker. It provides access to ftp servers. + </description> + <loader-name> + com.sun.star.loader.SharedLibrary + </loader-name> + <language> + c++ + </language> + <status value="final"/> + <supported-service> + com.sun.star.ucb.FTPContentProvider + </supported-service> + </component-description> + + <project-build-dependency> sal </project-build-dependency> + <project-build-dependency> cppu </project-build-dependency> + <project-build-dependency> cppuhelper </project-build-dependency> + <project-build-dependency> ucbhelper </project-build-dependency> + <project-build-dependency> curl </project-build-dependency> + + <runtime-module-dependency> sal3 </runtime-module-dependency> + <runtime-module-dependency> cppu3 </runtime-module-dependency> + <runtime-module-dependency> cppuhelper3$(COM) </runtime-module-dependency> + <runtime-module-dependency> ucbhelper4$(COM) </runtime-module-dependency> + <runtime-module-dependency> curl </runtime-module-dependency> + + <type> com.sun.star.beans.UnknownPropertyException </type> + <type> com.sun.star.beans.Property </type> + <type> com.sun.star.beans.PropertyValue </type> + <type> com.sun.star.beans.PropertyAttribute </type> + <type> com.sun.star.beans.XPropertySet </type> + <type> com.sun.star.io.XSeekable </type> + <type> com.sun.star.io.XActiveDataSink </type> + <type> com.sun.star.io.XInputStream </type> + <type> com.sun.star.io.XOutputStream </type> + <type> com.sun.star.io.XActiveDataStreamer </type> + <type> com.sun.star.lang.XMultiServiceFactory </type> + <type> com.sun.star.lang.IllegalAccessException </type> + <type> com.sun.star.lang.XTypeProvider </type> + <type> com.sun.star.lang.XComponent </type> + <type> com.sun.star.ucb.ContentInfoAttribute </type> + <type> com.sun.star.ucb.UnsupportedDataSinkException </type> + <type> com.sun.star.ucb.OpenCommandArgument2 </type> + <type> com.sun.star.ucb.UnsupportedOpenModeException </type> + <type> com.sun.star.ucb.InteractiveNetworkConnectException </type> + <type> com.sun.star.ucb.InteractiveNetworkResolveNameException </type> + <type> com.sun.star.ucb.InteractiveIOException </type> + <type> com.sun.star.ucb.MissingPropertiesException </type> + <type> com.sun.star.ucb.MissingInputStreamException </type> + <type> com.sun.star.ucb.NameClashException </type> + <type> com.sun.star.ucb.NumberedSortingInfo </type> + <type> com.sun.star.ucb.OpenMode </type> + <type> com.sun.star.ucb.IOErrorCode </type> + <type> com.sun.star.ucb.InsertCommandArgument </type> + <type> com.sun.star.ucb.ListActionType </type> + <type> com.sun.star.ucb.XContentCreator </type> + <type> com.sun.star.ucb.XContentProvider </type> + <type> com.sun.star.ucb.XContentProviderManager </type> + <type> com.sun.star.ucb.XCommandInfo </type> + <type> com.sun.star.ucb.CommandInfo </type> + <type> com.sun.star.ucb.XContentAccess </type> + <type> com.sun.star.ucb.Command </type> + <type> com.sun.star.ucb.XCommandEnvironment </type> + <type> com.sun.star.ucb.XCommandProcessor </type> + <type> com.sun.star.ucb.XContentIdentifier </type> + <type> com.sun.star.ucb.XSourceInitialization </type> + <type> com.sun.star.util.DateTime </type> + <type> com.sun.star.sdbc.XResultSet </type> + <type> com.sun.star.sdbc.XRow </type> + <type> com.sun.star.sdbc.XCloseable </type> + <type> com.sun.star.sdbc.XResultSetMetaDataSupplier </type> +</module-description> diff --git a/ucb/source/ucp/ftp/ucpftp1.component b/ucb/source/ucp/ftp/ucpftp1.component new file mode 100644 index 000000000000..fa4cfe6e7557 --- /dev/null +++ b/ucb/source/ucp/ftp/ucpftp1.component @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* 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. +* +**********************************************************************--> + +<component loader="com.sun.star.loader.SharedLibrary" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.FTPContentProvider"> + <service name="com.sun.star.ucb.FTPContentProvider"/> + </implementation> +</component> diff --git a/ucb/source/ucp/gio/gio_content.cxx b/ucb/source/ucp/gio/gio_content.cxx new file mode 100644 index 000000000000..bf0d16a654af --- /dev/null +++ b/ucb/source/ucp/gio/gio_content.cxx @@ -0,0 +1,1334 @@ +/************************************************************************* + * + * 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 <string.h> +#include <unistd.h> +#include <sys/types.h> + +#include <osl/time.h> + +#include <osl/diagnose.h> +#include <osl/doublecheckedlocking.h> + +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/beans/PropertySetInfoChange.hpp> +#include <com/sun/star/beans/PropertySetInfoChangeEvent.hpp> +#include <com/sun/star/io/XActiveDataSink.hpp> +#include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/lang/IllegalAccessException.hpp> +#include <com/sun/star/ucb/ContentInfoAttribute.hpp> +#include <com/sun/star/ucb/InsertCommandArgument.hpp> +#include <com/sun/star/ucb/InteractiveBadTransferURLException.hpp> +#include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp> +#include <com/sun/star/ucb/InteractiveNetworkWriteException.hpp> +#include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp> +#include <com/sun/star/ucb/InteractiveNetworkConnectException.hpp> +#include <com/sun/star/ucb/InteractiveNetworkGeneralException.hpp> +#include <com/sun/star/ucb/InteractiveNetworkReadException.hpp> +#include <com/sun/star/ucb/InteractiveNetworkResolveNameException.hpp> +#include <com/sun/star/ucb/InteractiveNetworkWriteException.hpp> +#include <com/sun/star/ucb/NameClash.hpp> +#include <com/sun/star/ucb/NameClashException.hpp> +#include <com/sun/star/ucb/OpenMode.hpp> +#include <com/sun/star/ucb/PostCommandArgument2.hpp> +#include <com/sun/star/ucb/XCommandInfo.hpp> +#include <com/sun/star/ucb/XPersistentPropertySet.hpp> +#include <com/sun/star/ucb/MissingInputStreamException.hpp> +#include <com/sun/star/ucb/MissingPropertiesException.hpp> +#include <com/sun/star/ucb/UnsupportedCommandException.hpp> +#include <com/sun/star/ucb/UnsupportedDataSinkException.hpp> +#include <com/sun/star/ucb/UnsupportedNameClashException.hpp> +#include <com/sun/star/ucb/UnsupportedOpenModeException.hpp> +#include <com/sun/star/ucb/UnsupportedOpenModeException.hpp> +#include <com/sun/star/ucb/NameClashException.hpp> +#include <com/sun/star/ucb/XDynamicResultSet.hpp> +#include <com/sun/star/ucb/XContentCreator.hpp> + +#include <ucbhelper/contentidentifier.hxx> +#include <ucbhelper/propertyvalueset.hxx> +#include <ucbhelper/interactionrequest.hxx> +#include <ucbhelper/cancelcommandexecution.hxx> + +#include <osl/conditn.hxx> + +#include "gio_content.hxx" +#include "gio_provider.hxx" +#include "gio_resultset.hxx" +#include "gio_inputstream.hxx" +#include "gio_outputstream.hxx" +#include "gio_mount.hxx" + +#include <stdio.h> + +using namespace com::sun::star; + +namespace gio +{ + +Content::Content( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + ContentProvider* pProvider, + const uno::Reference< ucb::XContentIdentifier >& Identifier) + throw ( ucb::ContentCreationException ) + : ContentImplHelper( rxSMgr, pProvider, Identifier ), + m_pProvider( pProvider ), mpFile (NULL), mpInfo( NULL ), mbTransient(false) +{ +#ifdef DEBUG + fprintf(stderr, "New Content ('%s')\n", rtl::OUStringToOString(m_xIdentifier->getContentIdentifier(), RTL_TEXTENCODING_UTF8).getStr()); +#endif +} + +Content::Content( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + ContentProvider* pProvider, + const uno::Reference< ucb::XContentIdentifier >& Identifier, + sal_Bool bIsFolder) + throw ( ucb::ContentCreationException ) + : ContentImplHelper( rxSMgr, pProvider, Identifier ), + m_pProvider( pProvider ), mpFile (NULL), mpInfo( NULL ), mbTransient(true) +{ +#ifdef DEBUG + fprintf(stderr, "Create Content ('%s')\n", rtl::OUStringToOString(m_xIdentifier->getContentIdentifier(), RTL_TEXTENCODING_UTF8).getStr()); +#endif + mpInfo = g_file_info_new(); + g_file_info_set_file_type(mpInfo, bIsFolder ? G_FILE_TYPE_DIRECTORY : G_FILE_TYPE_REGULAR); +} + +Content::~Content() +{ + if (mpInfo) g_object_unref(mpInfo); + if (mpFile) g_object_unref(mpFile); +} + +rtl::OUString Content::getParentURL() +{ + rtl::OUString sURL; + if (GFile* pFile = g_file_get_parent(getGFile())) + { + char* pPath = g_file_get_uri(pFile); + g_object_unref(pFile); + sURL = rtl::OUString::createFromAscii(pPath); + g_free(pPath); + } + return sURL; +} + +void SAL_CALL Content::abort( sal_Int32 /*CommandId*/ ) + throw( uno::RuntimeException ) +{ + //TODO + //stick a map from each CommandId to a new GCancellable and propogate + //it throughout the g_file_* calls +} + +rtl::OUString SAL_CALL Content::getContentType() throw( uno::RuntimeException ) +{ + return isFolder(uno::Reference< ucb::XCommandEnvironment >()) + ? rtl::OUString::createFromAscii( GIO_FOLDER_TYPE ) + : rtl::OUString::createFromAscii( GIO_FILE_TYPE ); +} + +#define EXCEPT(aExcept) \ +do { \ + if (bThrow) throw aExcept;\ + aRet = uno::makeAny( aExcept );\ +} while(0) + +uno::Any convertToException(GError *pError, const uno::Reference< uno::XInterface >& rContext, bool bThrow) +{ + uno::Any aRet; + + gint eCode = pError->code; + rtl::OUString sMessage(pError->message, strlen(pError->message), RTL_TEXTENCODING_UTF8); + g_error_free(pError); + + rtl::OUString sName; + rtl::OUString sHost; + + uno::Sequence< uno::Any > aArgs( 1 ); + aArgs[ 0 ] <<= sName; + + switch (eCode) + { + case G_IO_ERROR_FAILED: + { io::IOException aExcept(sMessage, rContext); + EXCEPT(aExcept); } + break; + case G_IO_ERROR_NOT_MOUNTED: + { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext, + task::InteractionClassification_ERROR, ucb::IOErrorCode_NOT_EXISTING_PATH, aArgs); + EXCEPT(aExcept); } + break; + case G_IO_ERROR_NOT_FOUND: + { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext, + task::InteractionClassification_ERROR, ucb::IOErrorCode_NOT_EXISTING, aArgs); + EXCEPT(aExcept); } + break; + case G_IO_ERROR_EXISTS: + { ucb::NameClashException aExcept(sMessage, rContext, + task::InteractionClassification_ERROR, sName); + EXCEPT(aExcept); } + break; + case G_IO_ERROR_INVALID_ARGUMENT: + { lang::IllegalArgumentException aExcept(sMessage, rContext, -1 ); + EXCEPT(aExcept); } + break; + case G_IO_ERROR_PERMISSION_DENIED: + { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext, + task::InteractionClassification_ERROR, ucb::IOErrorCode_ACCESS_DENIED, aArgs); + EXCEPT(aExcept); } + break; + case G_IO_ERROR_IS_DIRECTORY: + { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext, + task::InteractionClassification_ERROR, ucb::IOErrorCode_NO_FILE, aArgs); + EXCEPT(aExcept); } + break; + case G_IO_ERROR_NOT_REGULAR_FILE: + { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext, + task::InteractionClassification_ERROR, ucb::IOErrorCode_NO_FILE, aArgs); + EXCEPT(aExcept); } + break; + case G_IO_ERROR_NOT_DIRECTORY: + { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext, + task::InteractionClassification_ERROR, ucb::IOErrorCode_NO_DIRECTORY, aArgs); + EXCEPT(aExcept); } + break; + case G_IO_ERROR_FILENAME_TOO_LONG: + { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext, + task::InteractionClassification_ERROR, ucb::IOErrorCode_NAME_TOO_LONG, aArgs); + EXCEPT(aExcept); } + break; + case G_IO_ERROR_PENDING: + { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext, + task::InteractionClassification_ERROR, ucb::IOErrorCode_PENDING, aArgs); + EXCEPT(aExcept); } + break; + case G_IO_ERROR_CLOSED: + case G_IO_ERROR_CANCELLED: + case G_IO_ERROR_TOO_MANY_LINKS: + case G_IO_ERROR_WRONG_ETAG: + { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext, + task::InteractionClassification_ERROR, ucb::IOErrorCode_GENERAL, aArgs); + EXCEPT(aExcept); } + break; + case G_IO_ERROR_NOT_SUPPORTED: + case G_IO_ERROR_CANT_CREATE_BACKUP: + case G_IO_ERROR_WOULD_MERGE: + { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext, + task::InteractionClassification_ERROR, ucb::IOErrorCode_NOT_SUPPORTED, aArgs); + EXCEPT(aExcept); } + break; + case G_IO_ERROR_NO_SPACE: + { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext, + task::InteractionClassification_ERROR, ucb::IOErrorCode_OUT_OF_DISK_SPACE, aArgs); + EXCEPT(aExcept); } + break; + case G_IO_ERROR_INVALID_FILENAME: + { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext, + task::InteractionClassification_ERROR, ucb::IOErrorCode_INVALID_CHARACTER, aArgs); + EXCEPT(aExcept); } + break; + case G_IO_ERROR_READ_ONLY: + { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext, + task::InteractionClassification_ERROR, ucb::IOErrorCode_WRITE_PROTECTED, aArgs); + EXCEPT(aExcept); } + break; + case G_IO_ERROR_TIMED_OUT: + { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext, + task::InteractionClassification_ERROR, ucb::IOErrorCode_DEVICE_NOT_READY, aArgs); + EXCEPT(aExcept); } + break; + case G_IO_ERROR_WOULD_RECURSE: + { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext, + task::InteractionClassification_ERROR, ucb::IOErrorCode_RECURSIVE, aArgs); + EXCEPT(aExcept); } + break; + case G_IO_ERROR_BUSY: + case G_IO_ERROR_WOULD_BLOCK: + { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext, + task::InteractionClassification_ERROR, ucb::IOErrorCode_LOCKING_VIOLATION, aArgs); + EXCEPT(aExcept); } + break; + case G_IO_ERROR_HOST_NOT_FOUND: + { ucb::InteractiveNetworkResolveNameException aExcept(sMessage, rContext, + task::InteractionClassification_ERROR, sHost); + EXCEPT(aExcept);} + break; + default: + case G_IO_ERROR_ALREADY_MOUNTED: + case G_IO_ERROR_NOT_EMPTY: + case G_IO_ERROR_NOT_SYMBOLIC_LINK: + case G_IO_ERROR_NOT_MOUNTABLE_FILE: + case G_IO_ERROR_FAILED_HANDLED: + { ucb::InteractiveNetworkGeneralException aExcept(sMessage, rContext, + task::InteractionClassification_ERROR); + EXCEPT(aExcept);} + break; + } + return aRet; +} + +uno::Any Content::mapGIOError( GError *pError ) +{ + if (!pError) + return getBadArgExcept(); + + return convertToException(pError, static_cast< cppu::OWeakObject * >(this), false); +} + +uno::Any Content::getBadArgExcept() +{ + return uno::makeAny( lang::IllegalArgumentException( + rtl::OUString::createFromAscii( "Wrong argument type!" ), + static_cast< cppu::OWeakObject * >( this ), -1) ); +} + +class MountOperation +{ + GMainLoop *mpLoop; + GMountOperation *mpAuthentication; + GError *mpError; + static void Completed(GObject *source, GAsyncResult *res, gpointer user_data); +public: + MountOperation(const uno::Reference< ucb::XCommandEnvironment >& xEnv); + ~MountOperation(); + GError *Mount(GFile *pFile); +}; + +MountOperation::MountOperation(const uno::Reference< ucb::XCommandEnvironment >& xEnv) : mpError(NULL) +{ + mpLoop = g_main_loop_new(NULL, FALSE); + mpAuthentication = ooo_mount_operation_new(xEnv); +} + +void MountOperation::Completed(GObject *source, GAsyncResult *res, gpointer user_data) +{ + MountOperation *pThis = (MountOperation*)user_data; + g_file_mount_enclosing_volume_finish(G_FILE(source), res, &(pThis->mpError)); + g_main_loop_quit(pThis->mpLoop); +} + +GError *MountOperation::Mount(GFile *pFile) +{ + g_file_mount_enclosing_volume(pFile, G_MOUNT_MOUNT_NONE, mpAuthentication, NULL, MountOperation::Completed, this); + g_main_loop_run(mpLoop); + return mpError; +} + +MountOperation::~MountOperation() +{ + g_object_unref(mpAuthentication); + g_main_loop_unref(mpLoop); +} + +GFileInfo* Content::getGFileInfo(const uno::Reference< ucb::XCommandEnvironment >& xEnv, GError **ppError) +{ + /*If we don't have it already, and we're not a "pre-creation" content then query for the info"*/ + if (!mpInfo && !mbTransient) + { + if (!(mpInfo = g_file_query_info(getGFile(), "*", G_FILE_QUERY_INFO_NONE, NULL, ppError))) + { + //Try and mount if unmounted + if (ppError && (*ppError)->code == G_IO_ERROR_NOT_MOUNTED) + { + g_error_free(*ppError); + + MountOperation aMounter(xEnv); + *ppError = aMounter.Mount(getGFile()); + + //No Mount error, reattempt query + if (!*ppError) + mpInfo = g_file_query_info(getGFile(), "*", G_FILE_QUERY_INFO_NONE, NULL, ppError); + } + } + } + return mpInfo; +} + +GFile* Content::getGFile() +{ + if (!mpFile) + mpFile = g_file_new_for_uri(rtl::OUStringToOString(m_xIdentifier->getContentIdentifier(), RTL_TEXTENCODING_UTF8).getStr()); + return mpFile; +} + +bool Content::isFolder(const uno::Reference< ucb::XCommandEnvironment >& xEnv) +{ + GFileInfo *pInfo = getGFileInfo(xEnv); + return pInfo && (g_file_info_get_file_type(pInfo) == G_FILE_TYPE_DIRECTORY); +} + +static util::DateTime getDateFromUnix (time_t t) +{ + TimeValue tv; + tv.Nanosec = 0; + tv.Seconds = t; + oslDateTime dt; + + if ( osl_getDateTimeFromTimeValue( &tv, &dt ) ) + return util::DateTime( 0, dt.Seconds, dt.Minutes, dt.Hours, + dt.Day, dt.Month, dt.Year); + else + return util::DateTime(); +} + +uno::Reference< sdbc::XRow > Content::getPropertyValuesFromGFileInfo(GFileInfo *pInfo, + const uno::Reference< lang::XMultiServiceFactory >& rSMgr, + const uno::Reference< ucb::XCommandEnvironment > & xEnv, + const uno::Sequence< beans::Property >& rProperties) +{ + rtl::Reference< ::ucbhelper::PropertyValueSet > xRow = new ::ucbhelper::PropertyValueSet( rSMgr ); + + sal_Int32 nProps; + const beans::Property* pProps; + + nProps = rProperties.getLength(); + pProps = rProperties.getConstArray(); + + for( sal_Int32 n = 0; n < nProps; ++n ) + { + const beans::Property& rProp = pProps[ n ]; + + if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) ) + { + if (g_file_info_has_attribute(pInfo, G_FILE_ATTRIBUTE_STANDARD_TYPE)) + xRow->appendBoolean( rProp, ( g_file_info_get_file_type( pInfo ) == G_FILE_TYPE_REGULAR || + g_file_info_get_file_type( pInfo ) == G_FILE_TYPE_UNKNOWN ) ); + else + xRow->appendVoid( rProp ); + } + else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) ) + { + if( g_file_info_has_attribute( pInfo, G_FILE_ATTRIBUTE_STANDARD_TYPE) ) + xRow->appendBoolean( rProp, ( g_file_info_get_file_type( pInfo ) == G_FILE_TYPE_DIRECTORY )); + else + xRow->appendVoid( rProp ); + } + else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Title" ) ) ) + { + if (g_file_info_has_attribute(pInfo, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME)) + { + const char *pName = g_file_info_get_display_name(pInfo); + xRow->appendString( rProp, rtl::OUString(pName, strlen(pName), RTL_TEXTENCODING_UTF8) ); + } + else + xRow->appendVoid( rProp ); + } + else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsReadOnly" ) ) ) + { + if( g_file_info_has_attribute( pInfo, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE ) ) + xRow->appendBoolean( rProp, !g_file_info_get_attribute_boolean( pInfo, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE) ); + else + xRow->appendVoid( rProp ); + } + else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "DateCreated" ) ) ) + { + if( g_file_info_has_attribute( pInfo, G_FILE_ATTRIBUTE_TIME_CREATED ) ) + xRow->appendTimestamp( rProp, getDateFromUnix(g_file_info_get_attribute_uint64(pInfo, G_FILE_ATTRIBUTE_TIME_CREATED)) ); + else + xRow->appendVoid( rProp ); + } + else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "DateModified" ) ) ) + { + if( g_file_info_has_attribute( pInfo, G_FILE_ATTRIBUTE_TIME_CHANGED ) ) + xRow->appendTimestamp( rProp, getDateFromUnix(g_file_info_get_attribute_uint64(pInfo, G_FILE_ATTRIBUTE_TIME_CHANGED)) ); + else + xRow->appendVoid( rProp ); + } + else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Size" ) ) ) + { + if( g_file_info_has_attribute( pInfo, G_FILE_ATTRIBUTE_STANDARD_SIZE) ) + xRow->appendLong( rProp, ( g_file_info_get_size( pInfo ) )); + else + xRow->appendVoid( rProp ); + } + else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsVolume" ) ) ) + { + //What do we use this for ? + xRow->appendBoolean( rProp, sal_False ); + } + else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsCompactDisc" ) ) ) + { + if( g_file_info_has_attribute( pInfo, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_EJECT ) ) + xRow->appendBoolean( rProp, g_file_info_get_attribute_boolean(pInfo, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_EJECT) ); + else + xRow->appendVoid( rProp ); + } + else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsRemoveable" ) ) ) + { + if( g_file_info_has_attribute( pInfo, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT ) ) + xRow->appendBoolean( rProp, g_file_info_get_attribute_boolean(pInfo, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT ) ); + else + xRow->appendVoid( rProp ); + } + else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsFloppy" ) ) ) + { + xRow->appendBoolean( rProp, sal_False ); + } + else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsHidden" ) ) ) + { + if( g_file_info_has_attribute( pInfo, G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN) ) + xRow->appendBoolean( rProp, ( g_file_info_get_is_hidden ( pInfo ) ) ); + else + xRow->appendVoid( rProp ); + } + else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "CreatableContentsInfo" ) ) ) + { + xRow->appendObject( rProp, uno::makeAny( queryCreatableContentsInfo( xEnv ) ) ); + } +#ifdef DEBUG + else + { + fprintf(stderr, "Looking for unsupported property %s\n", + rtl::OUStringToOString(rProp.Name, RTL_TEXTENCODING_UTF8).getStr()); + } +#endif + } + + return uno::Reference< sdbc::XRow >( xRow.get() ); +} + +uno::Reference< sdbc::XRow > Content::getPropertyValues( + const uno::Sequence< beans::Property >& rProperties, + const uno::Reference< ucb::XCommandEnvironment >& xEnv ) +{ + GError *pError = NULL; + GFileInfo *pInfo = getGFileInfo(xEnv, &pError); + if (!pInfo) + ucbhelper::cancelCommandExecution(mapGIOError(pError), xEnv); + + return getPropertyValuesFromGFileInfo(pInfo, m_xSMgr, xEnv, rProperties); +} + +static lang::IllegalAccessException +getReadOnlyException( const uno::Reference< uno::XInterface >& rContext ) +{ + return lang::IllegalAccessException ( rtl::OUString::createFromAscii( "Property is read-only!" ), rContext ); +} + +void Content::queryChildren( ContentRefList& rChildren ) +{ + // Obtain a list with a snapshot of all currently instanciated contents + // from provider and extract the contents which are direct children + // of this content. + + ucbhelper::ContentRefList aAllContents; + m_xProvider->queryExistingContents( aAllContents ); + + rtl::OUString aURL = m_xIdentifier->getContentIdentifier(); + sal_Int32 nURLPos = aURL.lastIndexOf( '/' ); + + if ( nURLPos != ( aURL.getLength() - 1 ) ) + aURL += rtl::OUString::createFromAscii( "/" ); + + sal_Int32 nLen = aURL.getLength(); + + ucbhelper::ContentRefList::const_iterator it = aAllContents.begin(); + ucbhelper::ContentRefList::const_iterator end = aAllContents.end(); + + while ( it != end ) + { + ucbhelper::ContentImplHelperRef xChild = (*it); + rtl::OUString aChildURL = xChild->getIdentifier()->getContentIdentifier(); + + // Is aURL a prefix of aChildURL? + if ( ( aChildURL.getLength() > nLen ) && ( aChildURL.compareTo( aURL, nLen ) == 0 ) ) + { + sal_Int32 nPos = nLen; + nPos = aChildURL.indexOf( '/', nPos ); + + if ( ( nPos == -1 ) || ( nPos == ( aChildURL.getLength() - 1 ) ) ) + { + // No further slashes / only a final slash. It's a child! + rChildren.push_back( ::gio::Content::ContentRef (static_cast< ::gio::Content * >(xChild.get() ) ) ); + } + } + ++it; + } +} + +sal_Bool Content::exchangeIdentity( const uno::Reference< ucb::XContentIdentifier >& xNewId ) +{ + if ( !xNewId.is() ) + return sal_False; + + uno::Reference< ucb::XContent > xThis = this; + + if ( mbTransient ) + { + m_xIdentifier = xNewId; + return sal_False; + } + + rtl::OUString aOldURL = m_xIdentifier->getContentIdentifier(); + + // Exchange own identitity. + if ( exchange( xNewId ) ) + { + // Process instanciated children... + ContentRefList aChildren; + queryChildren( aChildren ); + + ContentRefList::const_iterator it = aChildren.begin(); + ContentRefList::const_iterator end = aChildren.end(); + + while ( it != end ) + { + ContentRef xChild = (*it); + + // Create new content identifier for the child... + uno::Reference< ucb::XContentIdentifier > xOldChildId = xChild->getIdentifier(); + rtl::OUString aOldChildURL = xOldChildId->getContentIdentifier(); + rtl::OUString aNewChildURL = aOldChildURL.replaceAt( + 0, aOldURL.getLength(), xNewId->getContentIdentifier() ); + + uno::Reference< ucb::XContentIdentifier > xNewChildId + = new ::ucbhelper::ContentIdentifier( m_xSMgr, aNewChildURL ); + + if ( !xChild->exchangeIdentity( xNewChildId ) ) + return sal_False; + + ++it; + } + return sal_True; + } + + return sal_False; +} + +uno::Sequence< uno::Any > Content::setPropertyValues( + const uno::Sequence< beans::PropertyValue >& rValues, + const uno::Reference< ucb::XCommandEnvironment >& xEnv ) +{ + GError *pError=NULL; + GFileInfo *pNewInfo=NULL; + GFileInfo *pInfo = getGFileInfo(xEnv, &pError); + if (pInfo) + pNewInfo = g_file_info_dup(pInfo); + else + { + if (!mbTransient) + ucbhelper::cancelCommandExecution(mapGIOError(pError), xEnv); + else + { + if (pError) + g_error_free(pError); + pNewInfo = g_file_info_new(); + } + } + + sal_Int32 nCount = rValues.getLength(); + + beans::PropertyChangeEvent aEvent; + aEvent.Source = static_cast< cppu::OWeakObject * >( this ); + aEvent.Further = sal_False; + aEvent.PropertyHandle = -1; + + sal_Int32 nChanged = 0, nTitlePos = -1; + const char *newName = NULL; + uno::Sequence< beans::PropertyChangeEvent > aChanges(nCount); + + uno::Sequence< uno::Any > aRet( nCount ); + const beans::PropertyValue* pValues = rValues.getConstArray(); + for ( sal_Int32 n = 0; n < nCount; ++n ) + { + const beans::PropertyValue& rValue = pValues[ n ]; +#ifdef DEBUG + g_warning("Set prop '%s'", rtl::OUStringToOString(rValue.Name, RTL_TEXTENCODING_UTF8).getStr()); +#endif + if ( rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) || + rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "MediaType" ) ) || + rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) || + rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) || + rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Size" ) ) || + rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "CreatableContentsInfo" ) ) ) + { + aRet[ n ] <<= getReadOnlyException( static_cast< cppu::OWeakObject * >(this) ); + } + else if ( rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Title" ) ) ) + { + rtl::OUString aNewTitle; + if (!( rValue.Value >>= aNewTitle )) + { + aRet[ n ] <<= beans::IllegalTypeException + ( rtl::OUString::createFromAscii( "Property value has wrong type!" ), + static_cast< cppu::OWeakObject * >( this ) ); + continue; + } + + if ( aNewTitle.getLength() <= 0 ) + { + aRet[ n ] <<= lang::IllegalArgumentException + ( rtl::OUString::createFromAscii( "Empty title not allowed!" ), + static_cast< cppu::OWeakObject * >( this ), -1 ); + continue; + + } + + rtl::OString sNewTitle = OUStringToOString(aNewTitle, RTL_TEXTENCODING_UTF8); + newName = sNewTitle.getStr(); + const char *oldName = g_file_info_get_name( pInfo); + + if (!newName || !oldName || strcmp(newName, oldName)) + { +#ifdef DEBUG + g_warning ("Set new name to '%s'", newName); +#endif + + aEvent.PropertyName = rtl::OUString::createFromAscii( "Title" ); + if (oldName) + aEvent.OldValue = uno::makeAny(rtl::OUString(oldName, strlen(oldName), RTL_TEXTENCODING_UTF8)); + aEvent.NewValue = uno::makeAny(aNewTitle); + aChanges.getArray()[ nChanged ] = aEvent; + nTitlePos = nChanged++; + + g_file_info_set_name(pNewInfo, newName); + } + } + else + { +#ifdef DEBUG + fprintf(stderr, "Unknown property %s\n", rtl::OUStringToOString(rValue.Name, RTL_TEXTENCODING_UTF8).getStr()); +#endif + aRet[ n ] <<= getReadOnlyException( static_cast< cppu::OWeakObject * >(this) ); + //TODO + } + } + + if (nChanged) + { + bool bOk = true; + if (!mbTransient) + { + if ((bOk = doSetFileInfo(pNewInfo))) + { + for (sal_Int32 i = 0; i < nChanged; ++i) + aRet[ i ] <<= getBadArgExcept(); + } + } + + if (bOk) + { + if (nTitlePos > -1) + { + rtl::OUString aNewURL = getParentURL(); + aNewURL += rtl::OUString( newName, strlen(newName), RTL_TEXTENCODING_UTF8 ); + uno::Reference< ucb::XContentIdentifier > xNewId + = new ::ucbhelper::ContentIdentifier( m_xSMgr, aNewURL ); + + if (!exchangeIdentity( xNewId ) ) + { + aRet[ nTitlePos ] <<= uno::Exception + ( rtl::OUString::createFromAscii( "Exchange failed!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + } + + if (!mbTransient) //Discard and refetch + { + g_object_unref(mpInfo); + mpInfo = NULL; + } + + if (mpInfo) + { + g_file_info_copy_into(pNewInfo, mpInfo); + g_object_unref(pNewInfo); + } + else + mpInfo = pNewInfo; + + if (mpFile) //Discard and refetch + { + g_object_unref(mpFile); + mpFile = NULL; + } + } + + aChanges.realloc( nChanged ); + notifyPropertiesChange( aChanges ); + } + + return aRet; +} + +bool Content::doSetFileInfo(GFileInfo *pNewInfo) +{ + g_assert (!mbTransient); + + bool bOk = true; + GFile *pFile = getGFile(); + if(!g_file_set_attributes_from_info(pFile, pNewInfo, G_FILE_QUERY_INFO_NONE, NULL, NULL)) + bOk = false; + return bOk; +} + +const int TRANSFER_BUFFER_SIZE = 65536; + +void Content::copyData( uno::Reference< io::XInputStream > xIn, + uno::Reference< io::XOutputStream > xOut ) +{ + uno::Sequence< sal_Int8 > theData( TRANSFER_BUFFER_SIZE ); + + g_return_if_fail( xIn.is() && xOut.is() ); + + while ( xIn->readBytes( theData, TRANSFER_BUFFER_SIZE ) > 0 ) + xOut->writeBytes( theData ); + + xOut->closeOutput(); +} + +sal_Bool Content::feedSink( uno::Reference< uno::XInterface > xSink, + const uno::Reference< ucb::XCommandEnvironment >& /*xEnv*/ ) +{ + if ( !xSink.is() ) + return sal_False; + + uno::Reference< io::XOutputStream > xOut = uno::Reference< io::XOutputStream >(xSink, uno::UNO_QUERY ); + uno::Reference< io::XActiveDataSink > xDataSink = uno::Reference< io::XActiveDataSink >(xSink, uno::UNO_QUERY ); + + if ( !xOut.is() && !xDataSink.is() ) + return sal_False; + + GError *pError=NULL; + GFileInputStream *pStream = g_file_read(getGFile(), NULL, &pError); + if (!pStream) + convertToException(pError, static_cast< cppu::OWeakObject * >(this)); + + uno::Reference< io::XInputStream > xIn = new ::gio::InputStream(pStream); + if ( !xIn.is() ) + return sal_False; + + if ( xOut.is() ) + copyData( xIn, xOut ); + + if ( xDataSink.is() ) + xDataSink->setInputStream( xIn ); + + return sal_True; +} + +uno::Any Content::open(const ucb::OpenCommandArgument2 & rOpenCommand, + const uno::Reference< ucb::XCommandEnvironment > & xEnv ) + throw( uno::Exception ) +{ + bool bIsFolder = isFolder(xEnv); + + if (!g_file_query_exists(getGFile(), NULL)) + { + uno::Sequence< uno::Any > aArgs( 1 ); + aArgs[ 0 ] <<= m_xIdentifier->getContentIdentifier(); + uno::Any aErr = uno::makeAny( + ucb::InteractiveAugmentedIOException(rtl::OUString(), static_cast< cppu::OWeakObject * >( this ), + task::InteractionClassification_ERROR, + bIsFolder ? ucb::IOErrorCode_NOT_EXISTING_PATH : ucb::IOErrorCode_NOT_EXISTING, aArgs) + ); + + ucbhelper::cancelCommandExecution(aErr, xEnv); + } + + uno::Any aRet; + + sal_Bool bOpenFolder = ( + ( rOpenCommand.Mode == ucb::OpenMode::ALL ) || + ( rOpenCommand.Mode == ucb::OpenMode::FOLDERS ) || + ( rOpenCommand.Mode == ucb::OpenMode::DOCUMENTS ) + ); + + if ( bOpenFolder && bIsFolder ) + { + uno::Reference< ucb::XDynamicResultSet > xSet + = new DynamicResultSet(m_xSMgr, this, rOpenCommand, xEnv ); + aRet <<= xSet; + } + else if ( rOpenCommand.Sink.is() ) + { + if ( + ( rOpenCommand.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_NONE ) || + ( rOpenCommand.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE ) + ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny ( ucb::UnsupportedOpenModeException + ( rtl::OUString(), static_cast< cppu::OWeakObject * >( this ), + sal_Int16( rOpenCommand.Mode ) ) ), + xEnv ); + } + + if ( !feedSink( rOpenCommand.Sink, xEnv ) ) + { + // Note: rOpenCommand.Sink may contain an XStream + // implementation. Support for this type of + // sink is optional... +#ifdef DEBUG + g_warning ("Failed to load data from '%s'", + rtl::OUStringToOString(m_xIdentifier->getContentIdentifier(), RTL_TEXTENCODING_UTF8).getStr()); +#endif + + ucbhelper::cancelCommandExecution( + uno::makeAny (ucb::UnsupportedDataSinkException + ( rtl::OUString(), static_cast< cppu::OWeakObject * >( this ), + rOpenCommand.Sink ) ), + xEnv ); + } + } + else + g_warning ("Open falling through ..."); + return aRet; +} + +uno::Any SAL_CALL Content::execute( + const ucb::Command& aCommand, + sal_Int32 /*CommandId*/, + const uno::Reference< ucb::XCommandEnvironment >& xEnv ) + throw( uno::Exception, + ucb::CommandAbortedException, + uno::RuntimeException ) +{ +#ifdef DEBUG + fprintf(stderr, "Content::execute %s\n", rtl::OUStringToOString(aCommand.Name, RTL_TEXTENCODING_UTF8).getStr()); +#endif + uno::Any aRet; + + if (aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "getPropertyValues" ) )) + { + uno::Sequence< beans::Property > Properties; + if ( !( aCommand.Argument >>= Properties ) ) + ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv ); + aRet <<= getPropertyValues( Properties, xEnv ); + } + else if (aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "getPropertySetInfo" ) )) + aRet <<= getPropertySetInfo( xEnv, sal_False ); + else if (aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "getCommandInfo" ) )) + aRet <<= getCommandInfo( xEnv, sal_False ); + else if (aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "open" ) )) + { + ucb::OpenCommandArgument2 aOpenCommand; + if ( !( aCommand.Argument >>= aOpenCommand ) ) + ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv ); + aRet = open( aOpenCommand, xEnv ); + } + else if (aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "transfer" ) )) + { + ucb::TransferInfo transferArgs; + if ( !( aCommand.Argument >>= transferArgs ) ) + ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv ); + transfer( transferArgs, xEnv ); + } + else if (aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "setPropertyValues" ) )) + { + uno::Sequence< beans::PropertyValue > aProperties; + if ( !( aCommand.Argument >>= aProperties ) || !aProperties.getLength() ) + ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv ); + aRet <<= setPropertyValues( aProperties, xEnv ); + } + else if (aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "createNewContent" ) ) + && isFolder( xEnv ) ) + { + ucb::ContentInfo arg; + if ( !( aCommand.Argument >>= arg ) ) + ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv ); + aRet <<= createNewContent( arg ); + } + else if (aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "insert" ) )) + { + ucb::InsertCommandArgument arg; + if ( !( aCommand.Argument >>= arg ) ) + ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv ); + insert( arg.Data, arg.ReplaceExisting, xEnv ); + } + else if (aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "delete" ) )) + { + sal_Bool bDeletePhysical = sal_False; + aCommand.Argument >>= bDeletePhysical; + + //If no delete physical, try and trashcan it, if that doesn't work go + //ahead and try and delete it anyway + if (!bDeletePhysical && !g_file_trash(getGFile(), NULL, NULL)) + bDeletePhysical = true; + + if (bDeletePhysical) + { + GError *pError = NULL; + if (!g_file_delete( getGFile(), NULL, &pError)) + ucbhelper::cancelCommandExecution(mapGIOError(pError), xEnv); + } + + destroy( bDeletePhysical ); + } + else + { +#ifdef DEBUG + fprintf(stderr, "UNKNOWN COMMAND\n"); + //TODO +#endif + + ucbhelper::cancelCommandExecution + ( uno::makeAny( ucb::UnsupportedCommandException + ( rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ) ) ), + xEnv ); + } + + return aRet; +} + +void Content::destroy( sal_Bool bDeletePhysical ) + throw( uno::Exception ) +{ + uno::Reference< ucb::XContent > xThis = this; + + deleted(); + + ::gio::Content::ContentRefList aChildren; + queryChildren( aChildren ); + + ContentRefList::const_iterator it = aChildren.begin(); + ContentRefList::const_iterator end = aChildren.end(); + + while ( it != end ) + { + (*it)->destroy( bDeletePhysical ); + ++it; + } +} + +void Content::insert(const uno::Reference< io::XInputStream > &xInputStream, + sal_Bool bReplaceExisting, const uno::Reference< ucb::XCommandEnvironment > &xEnv ) + throw( uno::Exception ) +{ + GError *pError = NULL; + GFileInfo *pInfo = getGFileInfo(xEnv); + + if ( g_file_info_has_attribute(pInfo, G_FILE_ATTRIBUTE_STANDARD_TYPE) && + g_file_info_get_file_type(pInfo) == G_FILE_TYPE_DIRECTORY ) + { +#ifdef DEBUG + g_warning ("Make directory"); +#endif + if( !g_file_make_directory( getGFile(), NULL, &pError)) + ucbhelper::cancelCommandExecution(mapGIOError(pError), xEnv); + return; + } + + if ( !xInputStream.is() ) + { + ucbhelper::cancelCommandExecution( uno::makeAny + ( ucb::MissingInputStreamException + ( rtl::OUString(), static_cast< cppu::OWeakObject * >( this ) ) ), + xEnv ); + } + + GFileOutputStream* pOutStream = NULL; + if ( bReplaceExisting ) + { + if (!(pOutStream = g_file_replace(getGFile(), NULL, false, G_FILE_CREATE_PRIVATE, NULL, &pError))) + ucbhelper::cancelCommandExecution(mapGIOError(pError), xEnv); + } + else + { + if (!(pOutStream = g_file_create (getGFile(), G_FILE_CREATE_PRIVATE, NULL, &pError))) + ucbhelper::cancelCommandExecution(mapGIOError(pError), xEnv); + } + + uno::Reference < io::XOutputStream > xOutput = new ::gio::OutputStream(pOutStream); + copyData( xInputStream, xOutput ); + + if (mbTransient) + { + mbTransient = sal_False; + inserted(); + } +} + +void Content::transfer( const ucb::TransferInfo& aTransferInfo, const uno::Reference< ucb::XCommandEnvironment >& xEnv ) + throw( uno::Exception ) +{ + rtl::OUString sDest = m_xIdentifier->getContentIdentifier(); + if (aTransferInfo.NewTitle.getLength()) + sDest += aTransferInfo.NewTitle; + else + sDest += rtl::OUString::createFromAscii(g_file_get_basename(getGFile())); + + GFile *pDest = g_file_new_for_uri(rtl::OUStringToOString(sDest, RTL_TEXTENCODING_UTF8).getStr()); + GFile *pSource = g_file_new_for_uri(rtl::OUStringToOString(aTransferInfo.SourceURL, RTL_TEXTENCODING_UTF8).getStr()); + + gboolean bSuccess = false; + GError *pError = NULL; + if (aTransferInfo.MoveData) + bSuccess = g_file_move(pSource, pDest, G_FILE_COPY_OVERWRITE, NULL, NULL, 0, &pError); + else + bSuccess = g_file_copy(pSource, pDest, G_FILE_COPY_OVERWRITE, NULL, NULL, 0, &pError); + g_object_unref(pSource); + g_object_unref(pDest); + if (!bSuccess) + ucbhelper::cancelCommandExecution(mapGIOError(pError), xEnv); +} + +uno::Sequence< ucb::ContentInfo > Content::queryCreatableContentsInfo( + const uno::Reference< ucb::XCommandEnvironment >& xEnv) + throw( uno::RuntimeException ) +{ + if ( isFolder( xEnv ) ) + { + uno::Sequence< ucb::ContentInfo > seq(2); + + // Minimum set of props we really need + uno::Sequence< beans::Property > props( 1 ); + props[0] = beans::Property( + rtl::OUString::createFromAscii( "Title" ), + -1, + getCppuType( static_cast< rtl::OUString* >( 0 ) ), + beans::PropertyAttribute::MAYBEVOID | beans::PropertyAttribute::BOUND ); + + // file + seq[0].Type = rtl::OUString::createFromAscii( GIO_FILE_TYPE ); + seq[0].Attributes = ( ucb::ContentInfoAttribute::INSERT_WITH_INPUTSTREAM | + ucb::ContentInfoAttribute::KIND_DOCUMENT ); + seq[0].Properties = props; + + // folder + seq[1].Type = rtl::OUString::createFromAscii( GIO_FOLDER_TYPE ); + seq[1].Attributes = ucb::ContentInfoAttribute::KIND_FOLDER; + seq[1].Properties = props; + + return seq; + } + else + { + return uno::Sequence< ucb::ContentInfo >(); + } +} + +uno::Sequence< ucb::ContentInfo > SAL_CALL Content::queryCreatableContentsInfo() + throw( uno::RuntimeException ) +{ + return queryCreatableContentsInfo( uno::Reference< ucb::XCommandEnvironment >() ); +} + +uno::Reference< ucb::XContent > + SAL_CALL Content::createNewContent( const ucb::ContentInfo& Info ) + throw( uno::RuntimeException ) +{ + bool create_document; + const char *name; + + if ( Info.Type.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( GIO_FILE_TYPE ) ) ) + create_document = true; + else if ( Info.Type.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( GIO_FOLDER_TYPE ) ) ) + create_document = false; + else + { +#ifdef DEBUG + g_warning( "Failed to create new content '%s'", rtl::OUStringToOString(Info.Type, + RTL_TEXTENCODING_UTF8).getStr() ); +#endif + return uno::Reference< ucb::XContent >(); + } + +#ifdef DEBUG + g_warning( "createNewContent (%d)", (int) create_document ); +#endif + + rtl::OUString aURL = m_xIdentifier->getContentIdentifier(); + + if ( ( aURL.lastIndexOf( '/' ) + 1 ) != aURL.getLength() ) + aURL += rtl::OUString::createFromAscii( "/" ); + + name = create_document ? "[New_Content]" : "[New_Collection]"; + aURL += rtl::OUString::createFromAscii( name ); + + uno::Reference< ucb::XContentIdentifier > xId(new ::ucbhelper::ContentIdentifier(m_xSMgr, aURL)); + + try + { + return new ::gio::Content( m_xSMgr, m_pProvider, xId, !create_document ); + } catch ( ucb::ContentCreationException & ) + { + return uno::Reference< ucb::XContent >(); + } +} + +uno::Sequence< uno::Type > SAL_CALL Content::getTypes() + throw( uno::RuntimeException ) +{ + if ( isFolder( uno::Reference< ucb::XCommandEnvironment >() ) ) + { + static cppu::OTypeCollection aFolderCollection + (CPPU_TYPE_REF( lang::XTypeProvider ), + CPPU_TYPE_REF( lang::XServiceInfo ), + CPPU_TYPE_REF( lang::XComponent ), + CPPU_TYPE_REF( ucb::XContent ), + CPPU_TYPE_REF( ucb::XCommandProcessor ), + CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ), + CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ), + CPPU_TYPE_REF( beans::XPropertyContainer ), + CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ), + CPPU_TYPE_REF( container::XChild ), + CPPU_TYPE_REF( ucb::XContentCreator ) ); + return aFolderCollection.getTypes(); + } + else + { + static cppu::OTypeCollection aFileCollection + (CPPU_TYPE_REF( lang::XTypeProvider ), + CPPU_TYPE_REF( lang::XServiceInfo ), + CPPU_TYPE_REF( lang::XComponent ), + CPPU_TYPE_REF( ucb::XContent ), + CPPU_TYPE_REF( ucb::XCommandProcessor ), + CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ), + CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ), + CPPU_TYPE_REF( beans::XPropertyContainer ), + CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ), + CPPU_TYPE_REF( container::XChild ) ); + + return aFileCollection.getTypes(); + } +} + +uno::Sequence< beans::Property > Content::getProperties( + const uno::Reference< ucb::XCommandEnvironment > & /*xEnv*/ ) +{ + static const beans::Property aGenericProperties[] = + { + beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsDocument" ) ), + -1, getCppuBooleanType(), + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ), + beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ), + -1, getCppuBooleanType(), + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ), + beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ), + -1, getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND ), + beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsReadOnly" ) ), + -1, getCppuBooleanType(), + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ), + beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DateCreated" ) ), + -1, getCppuType( static_cast< const util::DateTime * >( 0 ) ), + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ), + beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DateModified" ) ), + -1, getCppuType( static_cast< const util::DateTime * >( 0 ) ), + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ), + beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Size" ) ), + -1, getCppuType( static_cast< const sal_Int64 * >( 0 ) ), + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ), + beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsVolume" ) ), + -1, getCppuBooleanType(), + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ), + beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsCompactDisc" ) ), + -1, getCppuBooleanType(), + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ), + beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsRemoveable" ) ), + -1, getCppuBooleanType(), + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ), + beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsHidden" ) ), + -1, getCppuBooleanType(), + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ), + beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CreatableContentsInfo" ) ), + -1, getCppuType( static_cast< const uno::Sequence< ucb::ContentInfo > * >( 0 ) ), + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ) + }; + + const int nProps = sizeof (aGenericProperties) / sizeof (aGenericProperties[0]); + return uno::Sequence< beans::Property > ( aGenericProperties, nProps ); +} + +uno::Sequence< ucb::CommandInfo > Content::getCommands( const uno::Reference< ucb::XCommandEnvironment > & xEnv) +{ + static ucb::CommandInfo aCommandInfoTable[] = + { + // Required commands + ucb::CommandInfo + ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getCommandInfo" ) ), + -1, getCppuVoidType() ), + ucb::CommandInfo + ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getPropertySetInfo" ) ), + -1, getCppuVoidType() ), + ucb::CommandInfo + ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getPropertyValues" ) ), + -1, getCppuType( static_cast<uno::Sequence< beans::Property > * >( 0 ) ) ), + ucb::CommandInfo + ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ), + -1, getCppuType( static_cast<uno::Sequence< beans::PropertyValue > * >( 0 ) ) ), + + // Optional standard commands + ucb::CommandInfo + ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "delete" ) ), + -1, getCppuBooleanType() ), + ucb::CommandInfo + ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "insert" ) ), + -1, getCppuType( static_cast<ucb::InsertCommandArgument * >( 0 ) ) ), + ucb::CommandInfo + ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "open" ) ), + -1, getCppuType( static_cast<ucb::OpenCommandArgument2 * >( 0 ) ) ), + + // Folder Only, omitted if not a folder + ucb::CommandInfo + ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "transfer" ) ), + -1, getCppuType( static_cast<ucb::TransferInfo * >( 0 ) ) ), + ucb::CommandInfo + ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "createNewContent" ) ), + -1, getCppuType( static_cast<ucb::ContentInfo * >( 0 ) ) ) + }; + + const int nProps = sizeof (aCommandInfoTable) / sizeof (aCommandInfoTable[0]); + return uno::Sequence< ucb::CommandInfo >(aCommandInfoTable, isFolder(xEnv) ? nProps : nProps - 2); +} + +XTYPEPROVIDER_COMMON_IMPL( Content ); + +void SAL_CALL Content::acquire() throw() +{ + ContentImplHelper::acquire(); +} + +void SAL_CALL Content::release() throw() +{ + ContentImplHelper::release(); +} + +uno::Any SAL_CALL Content::queryInterface( const uno::Type & rType ) throw ( uno::RuntimeException ) +{ + uno::Any aRet = cppu::queryInterface( rType, static_cast< ucb::XContentCreator * >( this ) ); + return aRet.hasValue() ? aRet : ContentImplHelper::queryInterface(rType); +} + +rtl::OUString SAL_CALL Content::getImplementationName() throw( uno::RuntimeException ) +{ + return rtl::OUString::createFromAscii("com.sun.star.comp.GIOContent" ); +} + +uno::Sequence< rtl::OUString > SAL_CALL Content::getSupportedServiceNames() + throw( uno::RuntimeException ) +{ + uno::Sequence< rtl::OUString > aSNS( 1 ); + aSNS.getArray()[ 0 ] = rtl::OUString::createFromAscii("com.sun.star.ucb.GIOContent" ); + return aSNS; +} + +} diff --git a/ucb/source/ucp/gio/gio_content.hxx b/ucb/source/ucp/gio/gio_content.hxx new file mode 100644 index 000000000000..1c00f8c79d6e --- /dev/null +++ b/ucb/source/ucp/gio/gio_content.hxx @@ -0,0 +1,200 @@ +/************************************************************************* + * + * 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 GIO_CONTENT_HXX +#define GIO_CONTENT_HXX + +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/ucb/ContentCreationException.hpp> +#include <com/sun/star/ucb/OpenCommandArgument2.hpp> +#include <com/sun/star/ucb/TransferInfo.hpp> +#include <com/sun/star/ucb/XContentCreator.hpp> +#include <ucbhelper/contenthelper.hxx> +#include <gio/gio.h> + +#include <list> + +namespace com { namespace sun { namespace star { + namespace beans { + struct Property; + struct PropertyValue; + } + namespace sdbc { + class XRow; + } +}}} +namespace ucbhelper +{ + class Content; +} + + +namespace gio +{ + +#define GIO_CONTENT_SERVICE_NAME "com.sun.star.ucb.GIOContent" + +#define GIO_FILE_TYPE "application/vnd.sun.staroffice.gio-file" +#define GIO_FOLDER_TYPE "application/vnd.sun.staroffice.gio-folder" + +com::sun::star::uno::Any convertToException(GError *pError, + const com::sun::star::uno::Reference< com::sun::star::uno::XInterface >& rContext, bool bThrow=true); + +class ContentProvider; +class ContentProperties; +class Content : public ::ucbhelper::ContentImplHelper, public com::sun::star::ucb::XContentCreator +{ +private: + ContentProvider *m_pProvider; + GFile* mpFile; + GFileInfo *mpInfo; + bool mbTransient; + + GFileInfo *getGFileInfo(const com::sun::star::uno::Reference< com::sun::star::ucb::XCommandEnvironment >& xEnv, + GError **ppError=NULL); + bool isFolder(const com::sun::star::uno::Reference< com::sun::star::ucb::XCommandEnvironment >& xEnv); + + com::sun::star::uno::Any mapGIOError( GError *error ); + com::sun::star::uno::Any getBadArgExcept(); + + com::sun::star::uno::Reference< com::sun::star::sdbc::XRow > + getPropertyValues( + const com::sun::star::uno::Sequence< com::sun::star::beans::Property >& rProperties, + const com::sun::star::uno::Reference< com::sun::star::ucb::XCommandEnvironment >& xEnv ); +private: + typedef rtl::Reference< Content > ContentRef; + typedef std::list< ContentRef > ContentRefList; + + void queryChildren( ContentRefList& rChildren ); + + bool doSetFileInfo ( GFileInfo *pNewInfo ); + + com::sun::star::uno::Any open(const com::sun::star::ucb::OpenCommandArgument2 & rArg, + const com::sun::star::uno::Reference< com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw( com::sun::star::uno::Exception ); + + void transfer( const com::sun::star::ucb::TransferInfo& rTransferInfo, + const com::sun::star::uno::Reference< com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw( com::sun::star::uno::Exception ); + + void insert( const com::sun::star::uno::Reference< com::sun::star::io::XInputStream > & xInputStream, + sal_Bool bReplaceExisting, const com::sun::star::uno::Reference< com::sun::star::ucb::XCommandEnvironment >& xEnv ) + throw( com::sun::star::uno::Exception ); + + void destroy( sal_Bool bDeletePhysical ) throw( com::sun::star::uno::Exception ); + + void copyData( com::sun::star::uno::Reference< com::sun::star::io::XInputStream > xIn, + com::sun::star::uno::Reference< com::sun::star::io::XOutputStream > xOut ); + + com::sun::star::uno::Sequence< com::sun::star::uno::Any > + setPropertyValues( const com::sun::star::uno::Sequence< + com::sun::star::beans::PropertyValue >& rValues, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment >& xEnv ); + + sal_Bool feedSink( com::sun::star::uno::Reference< com::sun::star::uno::XInterface> aSink, + const com::sun::star::uno::Reference< com::sun::star::ucb::XCommandEnvironment >& xEnv ); + + com::sun::star::uno::Reference< com::sun::star::io::XInputStream > + createInputStream(const com::sun::star::uno::Reference< com::sun::star::ucb::XCommandEnvironment >& xEnv ) + throw( com::sun::star::uno::Exception ); + + sal_Bool exchangeIdentity(const com::sun::star::uno::Reference< com::sun::star::ucb::XContentIdentifier >& xNewId); + +public: + Content( const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, ContentProvider *pProvider, + const com::sun::star::uno::Reference< com::sun::star::ucb::XContentIdentifier >& Identifier) + throw ( com::sun::star::ucb::ContentCreationException ); + + Content( const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, ContentProvider *pProvider, + const com::sun::star::uno::Reference< com::sun::star::ucb::XContentIdentifier >& Identifier, + sal_Bool bIsFolder) + throw ( com::sun::star::ucb::ContentCreationException ); + + virtual ~Content(); + + com::sun::star::uno::Reference< com::sun::star::sdbc::XRow > getPropertyValuesFromGFileInfo( + GFileInfo *pInfo, const com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >& rSMgr, + const com::sun::star::uno::Reference< com::sun::star::ucb::XCommandEnvironment > & xEnv, + const com::sun::star::uno::Sequence< com::sun::star::beans::Property >& rProperties); + + virtual com::sun::star::uno::Sequence< com::sun::star::beans::Property > + getProperties( const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv ); + + virtual com::sun::star::uno::Sequence< com::sun::star::ucb::CommandInfo > + getCommands( const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv ); + + virtual ::rtl::OUString getParentURL(); + + XINTERFACE_DECL() + + XTYPEPROVIDER_DECL() + + virtual ::rtl::OUString SAL_CALL + getImplementationName() + throw( com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL + getSupportedServiceNames() + throw( com::sun::star::uno::RuntimeException ); + + virtual rtl::OUString SAL_CALL + getContentType() + throw( com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::uno::Any SAL_CALL + execute( const com::sun::star::ucb::Command& aCommand, + sal_Int32 CommandId, + const com::sun::star::uno::Reference< com::sun::star::ucb::XCommandEnvironment >& Environment ) + throw( com::sun::star::uno::Exception, com::sun::star::ucb::CommandAbortedException, com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL abort( sal_Int32 CommandId ) + throw( com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::uno::Sequence< com::sun::star::ucb::ContentInfo > + SAL_CALL queryCreatableContentsInfo() + throw( com::sun::star::uno::RuntimeException ); + virtual com::sun::star::uno::Reference< com::sun::star::ucb::XContent > + SAL_CALL createNewContent( const com::sun::star::ucb::ContentInfo& Info ) + throw( com::sun::star::uno::RuntimeException ); + + com::sun::star::uno::Sequence< com::sun::star::ucb::ContentInfo > + queryCreatableContentsInfo( + const com::sun::star::uno::Reference< com::sun::star::ucb::XCommandEnvironment >& xEnv) + throw( com::sun::star::uno::RuntimeException ); + + GFile* getGFile(); +}; + +} + +#endif diff --git a/ucb/source/ucp/gio/gio_datasupplier.cxx b/ucb/source/ucp/gio/gio_datasupplier.cxx new file mode 100644 index 000000000000..22cd4afa08fe --- /dev/null +++ b/ucb/source/ucp/gio/gio_datasupplier.cxx @@ -0,0 +1,282 @@ +/************************************************************************* + * + * 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 <vector> + +#include <ucbhelper/contentidentifier.hxx> +#include <ucbhelper/providerhelper.hxx> + +#include <com/sun/star/ucb/OpenMode.hpp> + +#include "gio_datasupplier.hxx" +#include "gio_content.hxx" +#include "gio_provider.hxx" + +#include <stdio.h> + +using namespace com::sun::star; + +using namespace gio; + +namespace gio +{ + +typedef std::vector< ResultListEntry* > ResultList; + +DataSupplier::DataSupplier( const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + const uno::Reference< ::gio::Content >& rContent, sal_Int32 nOpenMode ) + : mxContent(rContent), m_xSMgr(rxSMgr), mnOpenMode(nOpenMode), mbCountFinal(false) +{ +} + +bool DataSupplier::getData() +{ + if (mbCountFinal) + return true; + + GFile *pFile = mxContent->getGFile(); + + GFileEnumerator* pEnumerator = g_file_enumerate_children(pFile, "*", + G_FILE_QUERY_INFO_NONE, NULL, NULL); + + if (!pEnumerator) + return sal_False; + + GFileInfo *pInfo = NULL; + while ((pInfo = g_file_enumerator_next_file (pEnumerator, NULL, NULL))) + { + switch ( mnOpenMode ) + { + case ucb::OpenMode::FOLDERS: + if (g_file_info_get_file_type(pInfo) != G_FILE_TYPE_DIRECTORY) + continue; + break; + case ucb::OpenMode::DOCUMENTS: + if (g_file_info_get_file_type(pInfo) != G_FILE_TYPE_REGULAR) + continue; + break; + case ucb::OpenMode::ALL: + default: + break; + } + + maResults.push_back( new ResultListEntry( pInfo ) ); + g_object_unref(pInfo); + } + + mbCountFinal = sal_True; + + g_file_enumerator_close(pEnumerator, NULL, NULL); + return true; +} + +DataSupplier::~DataSupplier() +{ + ResultList::const_iterator it = maResults.begin(); + ResultList::const_iterator end = maResults.end(); + + while ( it != end ) + { + delete (*it); + it++; + } +} + +::rtl::OUString DataSupplier::queryContentIdentifierString( sal_uInt32 nIndex ) +{ + if ( nIndex < maResults.size() ) + { + ::rtl::OUString aId = maResults[ nIndex ]->aId; + if ( aId.getLength() ) + { + // Already cached. + return aId; + } + } + + if ( getResult( nIndex ) ) + { + GFile *pFile = mxContent->getGFile(); + char* parent = g_file_get_uri(pFile); + rtl::OUString aId = rtl::OUString::createFromAscii( parent ); + g_free(parent); + + char *escaped_name = + g_uri_escape_string( g_file_info_get_name(maResults[ nIndex ]->pInfo) , NULL, false); + + if ( ( aId.lastIndexOf( '/' ) + 1 ) != aId.getLength() ) + aId += rtl::OUString::createFromAscii( "/" ); + + aId += rtl::OUString::createFromAscii( escaped_name ); + + g_free( escaped_name ); + + maResults[ nIndex ]->aId = aId; + return aId; + + return aId; + } + + return ::rtl::OUString(); +} + +uno::Reference< ucb::XContentIdentifier > DataSupplier::queryContentIdentifier( sal_uInt32 nIndex ) +{ + if ( nIndex < maResults.size() ) + { + uno::Reference< ucb::XContentIdentifier > xId = maResults[ nIndex ]->xId; + if ( xId.is() ) + { + // Already cached. + return xId; + } + } + + ::rtl::OUString aId = queryContentIdentifierString( nIndex ); + if ( aId.getLength() ) + { + uno::Reference< ucb::XContentIdentifier > xId = new ucbhelper::ContentIdentifier( aId ); + maResults[ nIndex ]->xId = xId; + return xId; + } + + return uno::Reference< ucb::XContentIdentifier >(); +} + +uno::Reference< ucb::XContent > DataSupplier::queryContent( sal_uInt32 nIndex ) +{ + if ( nIndex < maResults.size() ) + { + uno::Reference< ucb::XContent > xContent = maResults[ nIndex ]->xContent; + if ( xContent.is() ) + { + // Already cached. + return xContent; + } + } + + uno::Reference< ucb::XContentIdentifier > xId = queryContentIdentifier( nIndex ); + if ( xId.is() ) + { + try + { + uno::Reference< ucb::XContent > xContent = mxContent->getProvider()->queryContent( xId ); + maResults[ nIndex ]->xContent = xContent; + return xContent; + } + catch ( ucb::IllegalIdentifierException& ) + { + } + } + return uno::Reference< ucb::XContent >(); +} + +sal_Bool DataSupplier::getResult( sal_uInt32 nIndex ) +{ + if ( maResults.size() > nIndex ) // Result already present. + return sal_True; + + if ( getData() && maResults.size() > nIndex ) + return sal_True; + + return sal_False; +} + +sal_uInt32 DataSupplier::totalCount() +{ + getData(); + return maResults.size(); +} + +sal_uInt32 DataSupplier::currentCount() +{ + return maResults.size(); +} + +sal_Bool DataSupplier::isCountFinal() +{ + return mbCountFinal; +} + +uno::Reference< sdbc::XRow > DataSupplier::queryPropertyValues( sal_uInt32 nIndex ) +{ + if ( nIndex < maResults.size() ) + { + uno::Reference< sdbc::XRow > xRow = maResults[ nIndex ]->xRow; + if ( xRow.is() ) + { + // Already cached. + return xRow; + } + } + + if ( getResult( nIndex ) ) + { + uno::Reference< ucb::XContent > xContent( queryContent( nIndex ) ); + if ( xContent.is() ) + { + try + { + uno::Reference< ucb::XCommandProcessor > xCmdProc( + xContent, uno::UNO_QUERY_THROW ); + sal_Int32 nCmdId( xCmdProc->createCommandIdentifier() ); + ucb::Command aCmd; + aCmd.Name = rtl::OUString::createFromAscii( "getPropertyValues" ); + aCmd.Handle = -1; + aCmd.Argument <<= getResultSet()->getProperties(); + uno::Any aResult( xCmdProc->execute( + aCmd, nCmdId, getResultSet()->getEnvironment() ) ); + uno::Reference< sdbc::XRow > xRow; + if ( aResult >>= xRow ) + { + maResults[ nIndex ]->xRow = xRow; + return xRow; + } + } + catch ( uno::Exception const & ) + { + } + } + } + return uno::Reference< sdbc::XRow >(); +} + +void DataSupplier::releasePropertyValues( sal_uInt32 nIndex ) +{ + if ( nIndex < maResults.size() ) + maResults[ nIndex ]->xRow = uno::Reference< sdbc::XRow >(); +} + +void DataSupplier::close() +{ +} + +void DataSupplier::validate() throw( ucb::ResultSetException ) +{ +} + +} diff --git a/ucb/source/ucp/gio/gio_datasupplier.hxx b/ucb/source/ucp/gio/gio_datasupplier.hxx new file mode 100644 index 000000000000..b39d7c913ffa --- /dev/null +++ b/ucb/source/ucp/gio/gio_datasupplier.hxx @@ -0,0 +1,99 @@ +/************************************************************************* + * + * 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 GIO_DATASUPPLIER_HXX +#define GIO_DATASUPPLIER_HXX + +#include <ucbhelper/resultset.hxx> +#include "gio_content.hxx" +#include <vector> + +namespace gio +{ + +class Content; + +struct ResultListEntry +{ + ::rtl::OUString aId; + com::sun::star::uno::Reference< com::sun::star::ucb::XContentIdentifier > xId; + com::sun::star::uno::Reference< com::sun::star::ucb::XContent > xContent; + com::sun::star::uno::Reference< com::sun::star::sdbc::XRow > xRow; + GFileInfo *pInfo; + + ResultListEntry( GFileInfo *pInInfo ) : pInfo(pInInfo) + { + g_object_ref( pInfo ); + } + + ~ResultListEntry() + { + g_object_unref( pInfo ); + } +}; + +typedef std::vector< ResultListEntry* > ResultList; + +class DataSupplier : public ucbhelper::ResultSetDataSupplier +{ +private: + com::sun::star::uno::Reference< ::gio::Content > mxContent; + com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory > m_xSMgr; + sal_Int32 mnOpenMode; + bool mbCountFinal; + bool getData(); + ResultList maResults; +public: + DataSupplier( const com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + const com::sun::star::uno::Reference< Content >& rContent, sal_Int32 nOpenMode ); + virtual ~DataSupplier(); + + virtual rtl::OUString queryContentIdentifierString( sal_uInt32 nIndex ); + virtual com::sun::star::uno::Reference< com::sun::star::ucb::XContentIdentifier > + queryContentIdentifier( sal_uInt32 nIndex ); + virtual com::sun::star::uno::Reference< com::sun::star::ucb::XContent > + queryContent( sal_uInt32 nIndex ); + + virtual sal_Bool getResult( sal_uInt32 nIndex ); + + virtual sal_uInt32 totalCount(); + virtual sal_uInt32 currentCount(); + virtual sal_Bool isCountFinal(); + + virtual com::sun::star::uno::Reference< com::sun::star::sdbc::XRow > + queryPropertyValues( sal_uInt32 nIndex ); + virtual void releasePropertyValues( sal_uInt32 nIndex ); + + virtual void close(); + + virtual void validate() + throw( com::sun::star::ucb::ResultSetException ); +}; + +} + +#endif diff --git a/ucb/source/ucp/gio/gio_inputstream.cxx b/ucb/source/ucp/gio/gio_inputstream.cxx new file mode 100644 index 000000000000..b5295a71bcd2 --- /dev/null +++ b/ucb/source/ucp/gio/gio_inputstream.cxx @@ -0,0 +1,120 @@ +/************************************************************************* + * + * 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 <rtl/memory.h> +#include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp> +#include <ucbhelper/cancelcommandexecution.hxx> +#include <string.h> + +#include "gio_inputstream.hxx" +#include "gio_content.hxx" + +using namespace com::sun::star; + +namespace gio +{ + +InputStream::InputStream(GFileInputStream *pStream) : Seekable(G_SEEKABLE(pStream)), mpStream(pStream) +{ + if (!mpStream) + throw io::NotConnectedException(); +} + +InputStream::~InputStream( void ) +{ + closeInput(); +} + +sal_Int32 SAL_CALL InputStream::available() + throw( io::NotConnectedException, io::IOException, uno::RuntimeException ) +{ + return 0; +} + +void SAL_CALL InputStream::closeInput() + throw( io::NotConnectedException, io::IOException, uno::RuntimeException ) +{ + if (mpStream) + g_input_stream_close(G_INPUT_STREAM(mpStream), NULL, NULL); +} + +void SAL_CALL InputStream::skipBytes( sal_Int32 nBytesToSkip ) + throw( io::NotConnectedException, io::BufferSizeExceededException, + io::IOException, uno::RuntimeException ) +{ + if (!mpStream) + throw io::NotConnectedException(); + + if (!g_seekable_can_seek(G_SEEKABLE(mpStream))) + throw io::IOException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Seek unsupported")), + static_cast< cppu::OWeakObject * >(this)); + + GError *pError=NULL; + if (!g_seekable_seek(G_SEEKABLE(mpStream), nBytesToSkip, G_SEEK_CUR, NULL, &pError)) + convertToException(pError, static_cast< cppu::OWeakObject * >(this)); +} + +sal_Int32 SAL_CALL InputStream::readBytes( uno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead ) + throw( io::NotConnectedException, io::BufferSizeExceededException, + io::IOException, uno::RuntimeException ) +{ + if (!mpStream) + throw io::NotConnectedException(); + + try + { + aData.realloc( nBytesToRead ); + } + catch ( const uno::Exception &e ) + { + throw io::BufferSizeExceededException(); + } + + gsize nBytesRead = 0; + GError *pError=NULL; + if (!g_input_stream_read_all(G_INPUT_STREAM(mpStream), aData.getArray(), nBytesToRead, &nBytesRead, NULL, &pError)) + convertToException(pError, static_cast< cppu::OWeakObject * >(this)); + aData.realloc(nBytesRead); + return nBytesRead; +} + +sal_Int32 SAL_CALL InputStream::readSomeBytes( uno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead ) + throw( io::NotConnectedException, io::BufferSizeExceededException, + io::IOException, uno::RuntimeException ) +{ + return readBytes(aData, nMaxBytesToRead); +} + +uno::Any InputStream::queryInterface( const uno::Type &type ) throw( uno::RuntimeException ) +{ + uno::Any aRet = ::cppu::queryInterface ( type, + static_cast< XInputStream * >( this ) ); + + return aRet.hasValue() ? aRet : Seekable::queryInterface( type ); +} + +} diff --git a/ucb/source/ucp/gio/gio_inputstream.hxx b/ucb/source/ucp/gio/gio_inputstream.hxx new file mode 100644 index 000000000000..467a14a9a94c --- /dev/null +++ b/ucb/source/ucp/gio/gio_inputstream.hxx @@ -0,0 +1,94 @@ +/************************************************************************* + * + * 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 GIO_INPUTSTREAM_HXX +#define GIO_INPUTSTREAM_HXX + +#include <sal/types.h> +#include <rtl/ustring.hxx> +#include <cppuhelper/weak.hxx> + +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/io/XTruncate.hpp> +#include <com/sun/star/io/XSeekable.hpp> + +#include "gio_seekable.hxx" + +namespace gio +{ + +class InputStream : + public ::com::sun::star::io::XInputStream, + public Seekable +{ +private: + GFileInputStream *mpStream; + +public: + InputStream ( GFileInputStream *pStream ); + virtual ~InputStream(); + + // XInterface + virtual com::sun::star::uno::Any SAL_CALL queryInterface(const ::com::sun::star::uno::Type & type ) + throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL acquire( void ) throw () { OWeakObject::acquire(); } + virtual void SAL_CALL release( void ) throw() { OWeakObject::release(); } + + // XInputStream + virtual sal_Int32 SAL_CALL readBytes( ::com::sun::star::uno::Sequence< sal_Int8 > & aData, + sal_Int32 nBytesToRead ) + throw( ::com::sun::star::io::NotConnectedException, + ::com::sun::star::io::BufferSizeExceededException, + ::com::sun::star::io::IOException, + ::com::sun::star::uno::RuntimeException ); + + virtual sal_Int32 SAL_CALL readSomeBytes( ::com::sun::star::uno::Sequence< sal_Int8 > & aData, + sal_Int32 nMaxBytesToRead ) + throw( ::com::sun::star::io::NotConnectedException, + ::com::sun::star::io::BufferSizeExceededException, + ::com::sun::star::io::IOException, + ::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip ) + throw( ::com::sun::star::io::NotConnectedException, + ::com::sun::star::io::BufferSizeExceededException, + ::com::sun::star::io::IOException, + ::com::sun::star::uno::RuntimeException ); + + virtual sal_Int32 SAL_CALL available( void ) + throw( ::com::sun::star::io::NotConnectedException, + ::com::sun::star::io::IOException, + ::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL closeInput( void ) + throw( ::com::sun::star::io::NotConnectedException, + ::com::sun::star::io::IOException, + ::com::sun::star::uno::RuntimeException ); +}; + +} // namespace gio +#endif diff --git a/ucb/source/ucp/gio/gio_mount.cxx b/ucb/source/ucp/gio/gio_mount.cxx new file mode 100644 index 000000000000..a32457c81a75 --- /dev/null +++ b/ucb/source/ucp/gio/gio_mount.cxx @@ -0,0 +1,183 @@ +/************************************************************************* + * + * 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 "gio_mount.hxx" +#include <ucbhelper/simpleauthenticationrequest.hxx> +#include <stdio.h> +#include <string.h> + +G_DEFINE_TYPE (OOoMountOperation, ooo_mount_operation, G_TYPE_MOUNT_OPERATION); + +static void ooo_mount_operation_ask_password (GMountOperation *op, + const char *message, const char *default_user, const char *default_domain, + GAskPasswordFlags flags); + +static void ooo_mount_operation_init (OOoMountOperation *op) +{ + op->m_pPrevPassword = NULL; + op->m_pPrevUsername = NULL; +} + +static void ooo_mount_operation_finalize (GObject *object) +{ + OOoMountOperation *mount_op = OOO_MOUNT_OPERATION (object); + if (mount_op->m_pPrevUsername) + free(mount_op->m_pPrevUsername); + if (mount_op->m_pPrevPassword) + free(mount_op->m_pPrevPassword); + + G_OBJECT_CLASS (ooo_mount_operation_parent_class)->finalize (object); +} + +static void ooo_mount_operation_class_init (OOoMountOperationClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + object_class->finalize = ooo_mount_operation_finalize; + + GMountOperationClass *mount_op_class = G_MOUNT_OPERATION_CLASS (klass); + mount_op_class->ask_password = ooo_mount_operation_ask_password; +} + +using namespace com::sun::star; + +static void ooo_mount_operation_ask_password (GMountOperation *op, + const char * /*message*/, const char *default_user, + const char *default_domain, GAskPasswordFlags flags) +{ + uno::Reference< task::XInteractionHandler > xIH; + + OOoMountOperation *pThis = (OOoMountOperation*)op; + + const com::sun::star::uno::Reference< com::sun::star::ucb::XCommandEnvironment > &xEnv = *(pThis->pEnv); + + if (xEnv.is()) + xIH = xEnv->getInteractionHandler(); + + if (!xIH.is()) + { + g_mount_operation_reply (op, G_MOUNT_OPERATION_ABORTED); + return; + } + + ::rtl::OUString aHostName, aDomain, aUserName, aPassword; + + ucbhelper::SimpleAuthenticationRequest::EntityType eUserName = + (flags & G_ASK_PASSWORD_NEED_USERNAME) + ? ucbhelper::SimpleAuthenticationRequest::ENTITY_MODIFY + : ucbhelper::SimpleAuthenticationRequest::ENTITY_NA; + + if (default_user) + aUserName = rtl::OUString(default_user, strlen(default_user), RTL_TEXTENCODING_UTF8); + + ucbhelper::SimpleAuthenticationRequest::EntityType ePassword = + (flags & G_ASK_PASSWORD_NEED_PASSWORD) + ? ucbhelper::SimpleAuthenticationRequest::ENTITY_MODIFY + : ucbhelper::SimpleAuthenticationRequest::ENTITY_NA; + + rtl::OUString aPrevPassword, aPrevUsername; + if (pThis->m_pPrevUsername) + aPrevUsername = rtl::OUString(pThis->m_pPrevUsername, strlen(pThis->m_pPrevUsername), RTL_TEXTENCODING_UTF8); + if (pThis->m_pPrevPassword) + aPrevPassword = rtl::OUString(pThis->m_pPrevPassword, strlen(pThis->m_pPrevPassword), RTL_TEXTENCODING_UTF8); + + //The damn dialog is stupidly broken, so do like webdav, i.e. "#102871#" + if ( aUserName.getLength() == 0 ) + aUserName = aPrevUsername; + + if ( aPassword.getLength() == 0 ) + aPassword = aPrevPassword; + + ucbhelper::SimpleAuthenticationRequest::EntityType eDomain = + (flags & G_ASK_PASSWORD_NEED_DOMAIN) + ? ucbhelper::SimpleAuthenticationRequest::ENTITY_MODIFY + : ucbhelper::SimpleAuthenticationRequest::ENTITY_NA; + + if (default_domain) + aDomain = rtl::OUString(default_domain, strlen(default_domain), RTL_TEXTENCODING_UTF8); + + uno::Reference< ucbhelper::SimpleAuthenticationRequest > xRequest + = new ucbhelper::SimpleAuthenticationRequest (rtl::OUString() /* FIXME: provide URL here */, aHostName, eDomain, aDomain, eUserName, aUserName, ePassword, aPassword); + + xIH->handle( xRequest.get() ); + + rtl::Reference< ucbhelper::InteractionContinuation > xSelection = xRequest->getSelection(); + + if ( !xSelection.is() ) + { + g_mount_operation_reply (op, G_MOUNT_OPERATION_ABORTED); + return; + } + + uno::Reference< task::XInteractionAbort > xAbort(xSelection.get(), uno::UNO_QUERY ); + if ( xAbort.is() ) + { + g_mount_operation_reply (op, G_MOUNT_OPERATION_ABORTED); + return; + } + + const rtl::Reference< ucbhelper::InteractionSupplyAuthentication > & xSupp = xRequest->getAuthenticationSupplier(); + aUserName = xSupp->getUserName(); + aPassword = xSupp->getPassword(); + + if (flags & G_ASK_PASSWORD_NEED_USERNAME) + g_mount_operation_set_username(op, rtl::OUStringToOString(aUserName, RTL_TEXTENCODING_UTF8).getStr()); + + if (flags & G_ASK_PASSWORD_NEED_PASSWORD) + g_mount_operation_set_password(op, rtl::OUStringToOString(aPassword, RTL_TEXTENCODING_UTF8).getStr()); + + if (flags & G_ASK_PASSWORD_NEED_DOMAIN) + g_mount_operation_set_domain(op, rtl::OUStringToOString(xSupp->getRealm(), RTL_TEXTENCODING_UTF8).getStr()); + + switch (xSupp->getRememberPasswordMode()) + { + default: + case ucb::RememberAuthentication_NO: + g_mount_operation_set_password_save(op, G_PASSWORD_SAVE_NEVER); + break; + case ucb::RememberAuthentication_SESSION: + g_mount_operation_set_password_save(op, G_PASSWORD_SAVE_FOR_SESSION); + break; + case ucb::RememberAuthentication_PERSISTENT: + g_mount_operation_set_password_save(op, G_PASSWORD_SAVE_PERMANENTLY); + break; + } + + if (pThis->m_pPrevPassword) + free(pThis->m_pPrevPassword); + pThis->m_pPrevPassword = strdup(rtl::OUStringToOString(aPassword, RTL_TEXTENCODING_UTF8).getStr()); + if (pThis->m_pPrevUsername) + free(pThis->m_pPrevUsername); + pThis->m_pPrevUsername = strdup(rtl::OUStringToOString(aUserName, RTL_TEXTENCODING_UTF8).getStr()); + g_mount_operation_reply (op, G_MOUNT_OPERATION_HANDLED); +} + +GMountOperation *ooo_mount_operation_new(const uno::Reference< ucb::XCommandEnvironment >& rEnv) +{ + OOoMountOperation *pRet = (OOoMountOperation*)g_object_new (OOO_TYPE_MOUNT_OPERATION, NULL); + pRet->pEnv = &rEnv; + return (GMountOperation*)pRet; +} diff --git a/ucb/source/ucp/gio/gio_mount.hxx b/ucb/source/ucp/gio/gio_mount.hxx new file mode 100644 index 000000000000..e88ef01651a3 --- /dev/null +++ b/ucb/source/ucp/gio/gio_mount.hxx @@ -0,0 +1,72 @@ +/************************************************************************* + * + * 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 GIO_MOUNT_HXX +#define GIO_MOUNT_HXX + +#include <com/sun/star/ucb/XCommandEnvironment.hpp> +#include <gio/gio.h> + +G_BEGIN_DECLS + +#define OOO_TYPE_MOUNT_OPERATION (ooo_mount_operation_get_type ()) +#define OOO_MOUNT_OPERATION(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), OOO_TYPE_MOUNT_OPERATION, OOoMountOperation)) +#define OOO_MOUNT_OPERATION_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), OOO_TYPE_MOUNT_OPERATION, OOoMountOperationClass)) +#define OOO_IS_MOUNT_OPERATION(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), OOO_TYPE_MOUNT_OPERATION)) +#define OOO_IS_MOUNT_OPERATION_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), OOO_TYPE_MOUNT_OPERATION)) +#define OOO_MOUNT_OPERATION_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), OOO_TYPE_MOUNT_OPERATION, OOoMountOperationClass)) + +typedef struct OOoMountOperation OOoMountOperation; +typedef struct OOoMountOperationClass OOoMountOperationClass; +typedef struct OOoMountOperationPrivate OOoMountOperationPrivate; + +struct OOoMountOperation +{ + GMountOperation parent_instance; + + const com::sun::star::uno::Reference< com::sun::star::ucb::XCommandEnvironment > *pEnv; + char *m_pPrevUsername; + char *m_pPrevPassword; +}; + +struct OOoMountOperationClass +{ + GMountOperationClass parent_class; + + /* Padding for future expansion */ + void (*_gtk_reserved1) (void); + void (*_gtk_reserved2) (void); + void (*_gtk_reserved3) (void); + void (*_gtk_reserved4) (void); +}; + + +GType ooo_mount_operation_get_type (void); +GMountOperation *ooo_mount_operation_new(const com::sun::star::uno::Reference< com::sun::star::ucb::XCommandEnvironment >& rEnv); + +G_END_DECLS +#endif diff --git a/ucb/source/ucp/gio/gio_outputstream.cxx b/ucb/source/ucp/gio/gio_outputstream.cxx new file mode 100644 index 000000000000..ddd0d19e7f2b --- /dev/null +++ b/ucb/source/ucp/gio/gio_outputstream.cxx @@ -0,0 +1,92 @@ +/************************************************************************* + * + * 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 <rtl/memory.h> +#include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp> +#include <ucbhelper/cancelcommandexecution.hxx> +#include <string.h> + +#include "gio_outputstream.hxx" +#include "gio_content.hxx" + +using namespace com::sun::star; + +namespace gio +{ + +OutputStream::OutputStream(GFileOutputStream *pStream) : Seekable(G_SEEKABLE(pStream)), mpStream(pStream) +{ + if (!mpStream) + throw io::NotConnectedException(); +} + +OutputStream::~OutputStream( void ) +{ + closeOutput(); +} + +void SAL_CALL OutputStream::writeBytes( const com::sun::star::uno::Sequence< sal_Int8 >& rData ) + throw( io::NotConnectedException, io::BufferSizeExceededException, + io::IOException, uno::RuntimeException) +{ + if (!mpStream) + throw io::NotConnectedException(); + + GError *pError=NULL; + if (!g_output_stream_write_all(G_OUTPUT_STREAM(mpStream), rData.getConstArray(), rData.getLength(), NULL, NULL, &pError)) + convertToException(pError, static_cast< cppu::OWeakObject * >(this)); +} + +void SAL_CALL OutputStream::flush( void ) + throw( io::NotConnectedException, io::BufferSizeExceededException, + io::IOException, uno::RuntimeException ) +{ + if (!mpStream) + throw io::NotConnectedException(); + + GError *pError=NULL; + if (!g_output_stream_flush(G_OUTPUT_STREAM(mpStream), NULL, &pError)) + convertToException(pError, static_cast< cppu::OWeakObject * >(this)); +} + +void SAL_CALL OutputStream::closeOutput( void ) + throw( io::NotConnectedException, io::IOException, + uno::RuntimeException ) +{ + if (mpStream) + g_output_stream_close(G_OUTPUT_STREAM(mpStream), NULL, NULL); +} + +uno::Any OutputStream::queryInterface( const uno::Type &type ) throw( uno::RuntimeException ) +{ + uno::Any aRet = ::cppu::queryInterface ( type, + static_cast< XOutputStream * >( this ) ); + + return aRet.hasValue() ? aRet : Seekable::queryInterface( type ); +} + +} diff --git a/ucb/source/ucp/gio/gio_outputstream.hxx b/ucb/source/ucp/gio/gio_outputstream.hxx new file mode 100644 index 000000000000..d1328fc58e3e --- /dev/null +++ b/ucb/source/ucp/gio/gio_outputstream.hxx @@ -0,0 +1,82 @@ +/************************************************************************* + * + * 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 GIO_OUTPUTSTREAM_HXX +#define GIO_OUTPUTSTREAM_HXX + +#include <sal/types.h> +#include <rtl/ustring.hxx> +#include <cppuhelper/weak.hxx> + +#include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/io/XTruncate.hpp> +#include <com/sun/star/io/XSeekable.hpp> + +#include "gio_seekable.hxx" + +namespace gio +{ + +class OutputStream : + public ::com::sun::star::io::XOutputStream, + public Seekable +{ +private: + GFileOutputStream *mpStream; + +public: + OutputStream ( GFileOutputStream *pStream ); + virtual ~OutputStream(); + + // XInterface + virtual com::sun::star::uno::Any SAL_CALL queryInterface(const ::com::sun::star::uno::Type & type ) + throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL acquire( void ) throw () { OWeakObject::acquire(); } + virtual void SAL_CALL release( void ) throw() { OWeakObject::release(); } + + // XOutputStream + virtual void SAL_CALL writeBytes( const com::sun::star::uno::Sequence< sal_Int8 >& aData ) + throw( com::sun::star::io::NotConnectedException, + com::sun::star::io::BufferSizeExceededException, + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL flush( void ) + throw( com::sun::star::io::NotConnectedException, + com::sun::star::io::BufferSizeExceededException, + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException); + + + virtual void SAL_CALL closeOutput( void ) + throw( com::sun::star::io::NotConnectedException, + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException ); +}; + +} // namespace gio +#endif diff --git a/ucb/source/ucp/gio/gio_provider.cxx b/ucb/source/ucp/gio/gio_provider.cxx new file mode 100644 index 000000000000..b8b16ba72c24 --- /dev/null +++ b/ucb/source/ucp/gio/gio_provider.cxx @@ -0,0 +1,140 @@ +/************************************************************************* + * + * 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 <ucbhelper/contentidentifier.hxx> +#include <ucbhelper/contenthelper.hxx> +#include <com/sun/star/ucb/ContentCreationException.hpp> +#include "gio_provider.hxx" +#include "gio_content.hxx" + +#include <stdio.h> + +using namespace com::sun::star; + +namespace gio +{ +uno::Reference< com::sun::star::ucb::XContent > SAL_CALL +ContentProvider::queryContent( + const uno::Reference< + com::sun::star::ucb::XContentIdentifier >& Identifier ) + throw( com::sun::star::ucb::IllegalIdentifierException, + uno::RuntimeException ) +{ +#ifdef DEBUG + fprintf(stderr, "QueryContent: '%s'", + (const sal_Char *)rtl::OUStringToOString + (Identifier->getContentIdentifier(), RTL_TEXTENCODING_UTF8)); +#endif + + osl::MutexGuard aGuard( m_aMutex ); + + // Check, if a content with given id already exists... + uno::Reference< ucb::XContent > xContent = queryExistingContent( Identifier ).get(); + if ( xContent.is() ) + return xContent; + + try + { + xContent = new ::gio::Content(m_xSMgr, this, Identifier); + } + catch ( com::sun::star::ucb::ContentCreationException const & ) + { + throw com::sun::star::ucb::IllegalIdentifierException(); + } + + if ( !xContent->getIdentifier().is() ) + throw com::sun::star::ucb::IllegalIdentifierException(); + + return xContent; +} + +ContentProvider::ContentProvider( + const uno::Reference< lang::XMultiServiceFactory >& rSMgr ) +: ::ucbhelper::ContentProviderImplHelper( rSMgr ) +{ +} + +ContentProvider::~ContentProvider() +{ +} + +XINTERFACE_IMPL_3( ContentProvider, + lang::XTypeProvider, + lang::XServiceInfo, + com::sun::star::ucb::XContentProvider ); + +XTYPEPROVIDER_IMPL_3( ContentProvider, + lang::XTypeProvider, + lang::XServiceInfo, + com::sun::star::ucb::XContentProvider ); + +XSERVICEINFO_IMPL_1( ContentProvider, + rtl::OUString::createFromAscii( + "com.sun.star.comp.GIOContentProvider" ), + rtl::OUString::createFromAscii( + "com.sun.star.ucb.GIOContentProvider" ) ); + +ONE_INSTANCE_SERVICE_FACTORY_IMPL( ContentProvider ); + +} + +extern "C" void SAL_CALL component_getImplementationEnvironment( + const sal_Char **ppEnvTypeName, uno_Environment **) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + +extern "C" sal_Bool SAL_CALL component_writeInfo( void *, void *pRegistryKey ) +{ + return pRegistryKey && + writeInfo( pRegistryKey, + ::gio::ContentProvider::getImplementationName_Static(), + ::gio::ContentProvider::getSupportedServiceNames_Static() ); +} + +extern "C" void * SAL_CALL component_getFactory( const sal_Char *pImplName, + void *pServiceManager, void * ) +{ + void * pRet = 0; + + uno::Reference< lang::XMultiServiceFactory > xSMgr + (reinterpret_cast< lang::XMultiServiceFactory * >( pServiceManager ) ); + uno::Reference< lang::XSingleServiceFactory > xFactory; + + g_type_init(); + + if ( !::gio::ContentProvider::getImplementationName_Static().compareToAscii( pImplName ) ) + xFactory = ::gio::ContentProvider::createServiceFactory( xSMgr ); + + if ( xFactory.is() ) + { + xFactory->acquire(); + pRet = xFactory.get(); + } + + return pRet; +} diff --git a/ucb/source/ucp/gio/gio_provider.hxx b/ucb/source/ucp/gio/gio_provider.hxx new file mode 100644 index 000000000000..4fa2fba1807d --- /dev/null +++ b/ucb/source/ucp/gio/gio_provider.hxx @@ -0,0 +1,66 @@ +/************************************************************************* + * + * 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 GIO_PROVIDER_HXX +#define GIO_PROVIDER_HXX + +#include <com/sun/star/beans/Property.hpp> +#include <ucbhelper/providerhelper.hxx> + +#define GIO_CONTENT_PROVIDER_SERVICE_NAME "com.sun.star.ucb.GIOContentProvider" + +namespace gio +{ + +class ContentProvider : public ::ucbhelper::ContentProviderImplHelper +{ +public: + ContentProvider( const ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XMultiServiceFactory >& rSMgr ); + virtual ~ContentProvider(); + + // XInterface + XINTERFACE_DECL() + + // XTypeProvider + XTYPEPROVIDER_DECL() + + // XServiceInfo + XSERVICEINFO_DECL() + + // XContentProvider + virtual ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XContent > SAL_CALL + queryContent( const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XContentIdentifier >& Identifier ) + throw( ::com::sun::star::ucb::IllegalIdentifierException, + ::com::sun::star::uno::RuntimeException ); +}; + +} + +#endif diff --git a/ucb/source/ucp/gio/gio_resultset.cxx b/ucb/source/ucp/gio/gio_resultset.cxx new file mode 100644 index 000000000000..68c3654915f6 --- /dev/null +++ b/ucb/source/ucp/gio/gio_resultset.cxx @@ -0,0 +1,59 @@ +/************************************************************************* + * + * 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 "gio_datasupplier.hxx" +#include "gio_resultset.hxx" + +using namespace com::sun::star::lang; +using namespace com::sun::star::ucb; +using namespace com::sun::star::uno; + +using namespace gio; + +DynamicResultSet::DynamicResultSet( + const Reference< XMultiServiceFactory >& rxSMgr, + const Reference< Content >& rxContent, + const OpenCommandArgument2& rCommand, + const Reference< XCommandEnvironment >& rxEnv ) + : ResultSetImplHelper( rxSMgr, rCommand ), + m_xContent( rxContent ), + m_xEnv( rxEnv ) +{ +} + +void DynamicResultSet::initStatic() +{ + m_xResultSet1 = new ::ucbhelper::ResultSet( + m_xSMgr, m_aCommand.Properties, + new DataSupplier( m_xSMgr, m_xContent, m_aCommand.Mode ), m_xEnv ); +} + +void DynamicResultSet::initDynamic() +{ + initStatic(); + m_xResultSet2 = m_xResultSet1; +} diff --git a/ucb/source/ucp/gio/gio_resultset.hxx b/ucb/source/ucp/gio/gio_resultset.hxx new file mode 100644 index 000000000000..620c58cf7edb --- /dev/null +++ b/ucb/source/ucp/gio/gio_resultset.hxx @@ -0,0 +1,56 @@ +/************************************************************************* + * + * 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 GIO_RESULTSET_HXX +#define GIO_RESULTSET_HXX + +#include <ucbhelper/resultsethelper.hxx> +#include "gio_content.hxx" + +namespace gio +{ + + class DynamicResultSet : public ::ucbhelper::ResultSetImplHelper + { + com::sun::star::uno::Reference< Content > m_xContent; + com::sun::star::uno::Reference< com::sun::star::ucb::XCommandEnvironment > m_xEnv; + + private: + virtual void initStatic(); + virtual void initDynamic(); + + public: + DynamicResultSet( + const com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + const com::sun::star::uno::Reference< Content >& rxContent, + const com::sun::star::ucb::OpenCommandArgument2& rCommand, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment >& rxEnv ); + }; +} + +#endif diff --git a/ucb/source/ucp/gio/gio_seekable.cxx b/ucb/source/ucp/gio/gio_seekable.cxx new file mode 100644 index 000000000000..3bfce6b9b6b9 --- /dev/null +++ b/ucb/source/ucp/gio/gio_seekable.cxx @@ -0,0 +1,140 @@ +/************************************************************************* + * + * 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 <rtl/memory.h> +#include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp> +#include <ucbhelper/cancelcommandexecution.hxx> +#include <string.h> + +#include "gio_seekable.hxx" +#include "gio_content.hxx" + +using namespace com::sun::star; + +namespace gio +{ + +Seekable::Seekable(GSeekable *pStream) : mpStream(pStream) +{ + if (!mpStream) + throw io::NotConnectedException(); +} + +Seekable::~Seekable( void ) +{ +} + +void SAL_CALL Seekable::truncate( void ) + throw( io::IOException, uno::RuntimeException ) +{ + if (!mpStream) + throw io::NotConnectedException(); + + if (!g_seekable_can_truncate(mpStream)) + throw io::IOException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Truncate unsupported")), + static_cast< cppu::OWeakObject * >(this)); + + GError *pError=NULL; + if (!g_seekable_truncate(mpStream, 0, NULL, &pError)) + convertToException(pError, static_cast< cppu::OWeakObject * >(this)); +} + +void SAL_CALL Seekable::seek( sal_Int64 location ) + throw( lang::IllegalArgumentException, io::IOException, uno::RuntimeException ) +{ + if (!mpStream) + throw io::NotConnectedException(); + + if (!g_seekable_can_seek(mpStream)) + throw io::IOException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Seek unsupported")), + static_cast< cppu::OWeakObject * >(this)); + + GError *pError=NULL; + if (!g_seekable_seek(mpStream, location, G_SEEK_SET, NULL, &pError)) + convertToException(pError, static_cast< cppu::OWeakObject * >(this)); +} + +sal_Int64 SAL_CALL Seekable::getPosition() throw( io::IOException, uno::RuntimeException ) +{ + if (!mpStream) + throw io::NotConnectedException(); + + return g_seekable_tell(mpStream); +} + +sal_Int64 SAL_CALL Seekable::getLength() throw( io::IOException, uno::RuntimeException ) +{ + if (!mpStream) + throw io::NotConnectedException(); + + bool bOk = false; + sal_uInt64 nSize = 0; + + GFileInfo* pInfo = G_IS_FILE_INPUT_STREAM(mpStream) + ? g_file_input_stream_query_info(G_FILE_INPUT_STREAM(mpStream), const_cast<char*>(G_FILE_ATTRIBUTE_STANDARD_SIZE), NULL, NULL) + : g_file_output_stream_query_info(G_FILE_OUTPUT_STREAM(mpStream), const_cast<char*>(G_FILE_ATTRIBUTE_STANDARD_SIZE), NULL, NULL); + + if (pInfo) + { + if (g_file_info_has_attribute(pInfo, G_FILE_ATTRIBUTE_STANDARD_SIZE)) + { + nSize = g_file_info_get_size(pInfo); + bOk = true; + } + g_object_unref(pInfo); + } + + if (!bOk) + { + GError *pError=NULL; + sal_Int64 nCurr = getPosition(); + if (!g_seekable_seek(mpStream, 0, G_SEEK_END, NULL, &pError)) + convertToException(pError, static_cast< cppu::OWeakObject * >(this)); + nSize = getPosition(); + seek(nCurr); + bOk = true; + } + + if (!bOk) + throw io::IOException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Getting size unsupported")), + static_cast< cppu::OWeakObject * >(this)); + + return nSize; +} + +uno::Any Seekable::queryInterface( const uno::Type &type ) throw( uno::RuntimeException ) +{ + uno::Any aRet = ::cppu::queryInterface ( type, + static_cast< XSeekable * >( this ) ); + + if (!aRet.hasValue() && g_seekable_can_truncate(mpStream)) + aRet = ::cppu::queryInterface ( type, static_cast< XTruncate * >( this ) ); + + return aRet.hasValue() ? aRet : OWeakObject::queryInterface( type ); +} + +} diff --git a/ucb/source/ucp/gio/gio_seekable.hxx b/ucb/source/ucp/gio/gio_seekable.hxx new file mode 100644 index 000000000000..43324b0651a1 --- /dev/null +++ b/ucb/source/ucp/gio/gio_seekable.hxx @@ -0,0 +1,80 @@ +/************************************************************************* + * + * 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 GIO_SEEKABLE_HXX +#define GIO_SEEKABLE_HXX + +#include <sal/types.h> +#include <rtl/ustring.hxx> +#include <cppuhelper/weak.hxx> + +#include <com/sun/star/io/XTruncate.hpp> +#include <com/sun/star/io/XSeekable.hpp> + +#include <gio/gio.h> + +namespace gio +{ + +class Seekable : public ::com::sun::star::io::XTruncate, + public ::com::sun::star::io::XSeekable, + public ::cppu::OWeakObject +{ +private: + GSeekable *mpStream; +public: + Seekable( GSeekable *pStream ); + virtual ~Seekable(); + + // XInterface + virtual com::sun::star::uno::Any SAL_CALL queryInterface(const ::com::sun::star::uno::Type & type ) + throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL acquire( void ) throw () { OWeakObject::acquire(); } + virtual void SAL_CALL release( void ) throw() { OWeakObject::release(); } + + // XSeekable + virtual void SAL_CALL seek( sal_Int64 location ) + throw( ::com::sun::star::lang::IllegalArgumentException, + ::com::sun::star::io::IOException, + ::com::sun::star::uno::RuntimeException ); + + virtual sal_Int64 SAL_CALL getPosition() + throw( ::com::sun::star::io::IOException, + ::com::sun::star::uno::RuntimeException ); + + virtual sal_Int64 SAL_CALL getLength() + throw( ::com::sun::star::io::IOException, + ::com::sun::star::uno::RuntimeException ); + + // XTruncate + virtual void SAL_CALL truncate( void ) + throw( com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException ); +}; + +} // namespace gio +#endif diff --git a/ucb/source/ucp/gio/makefile.mk b/ucb/source/ucp/gio/makefile.mk new file mode 100644 index 000000000000..4cca611c7ece --- /dev/null +++ b/ucb/source/ucp/gio/makefile.mk @@ -0,0 +1,87 @@ +#************************************************************************* +# +# 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=ucb +# Version +UCPGIO_MAJOR=1 +TARGET=ucpgio +ENABLE_EXCEPTIONS=TRUE +USE_DEFFILE=TRUE +NO_BSYMBOLIC=TRUE + +.INCLUDE: settings.mk +.IF "$(L10N_framework)"=="" + +.IF "$(ENABLE_GIO)"!="" +COMPILER_WARN_ALL=TRUE +PKGCONFIG_MODULES=gio-2.0 +.INCLUDE: pkg_config.mk + +.IF "$(OS)" == "SOLARIS" +LINKFLAGS+=-z nodefs +.ENDIF # "$(OS)" == "SOLARIS" + +# no "lib" prefix +DLLPRE = + +SLOFILES=$(SLO)$/gio_provider.obj\ + $(SLO)$/gio_content.obj\ + $(SLO)$/gio_resultset.obj\ + $(SLO)$/gio_datasupplier.obj\ + $(SLO)$/gio_seekable.obj\ + $(SLO)$/gio_inputstream.obj\ + $(SLO)$/gio_outputstream.obj\ + $(SLO)$/gio_mount.obj + +SHL1TARGET=$(TARGET)$(UCPGIO_MAJOR).uno +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +SHL1LIBS=$(SLB)$/$(TARGET).lib +SHL1IMPLIB=i$(TARGET) +SHL1STDLIBS=\ + $(CPPUHELPERLIB) \ + $(CPPULIB) \ + $(SALLIB) \ + $(SALHELPERLIB) \ + $(UCBHELPERLIB) + +SHL1STDLIBS+=$(PKGCONFIG_LIBS) + +SHL1VERSIONMAP=$(SOLARENV)/src/component.map + +.ENDIF # "$(ENABLE_GIO)"!="" +.ENDIF # L10N_framework + +.INCLUDE: target.mk + +ALLTAR : $(MISC)/ucpgio.component + +$(MISC)/ucpgio.component .ERRREMOVE : $(SOLARENV)/bin/createcomponent.xslt \ + ucpgio.component + $(XSLTPROC) --nonet --stringparam uri \ + '$(COMPONENTPREFIX_BASIS_NATIVE)$(SHL1TARGETN:f)' -o $@ \ + $(SOLARENV)/bin/createcomponent.xslt ucpgio.component diff --git a/ucb/source/ucp/gio/ucpgio.component b/ucb/source/ucp/gio/ucpgio.component new file mode 100644 index 000000000000..caa8fc361f7f --- /dev/null +++ b/ucb/source/ucp/gio/ucpgio.component @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* 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. +* +**********************************************************************--> + +<component loader="com.sun.star.loader.SharedLibrary" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.GIOContentProvider"> + <service name="com.sun.star.ucb.GIOContentProvider"/> + </implementation> +</component> diff --git a/ucb/source/ucp/gio/ucpgio.xml b/ucb/source/ucp/gio/ucpgio.xml new file mode 100644 index 000000000000..20bfe43e5a6f --- /dev/null +++ b/ucb/source/ucp/gio/ucpgio.xml @@ -0,0 +1,100 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE module-description PUBLIC "-//StarOffice//DTD ComponentDescription 1.0//EN" "module-description.dtd"> +<module-description xmlns:xlink="http://www.w3.org/1999/xlink"> + + <module-name> + ucpgio + </module-name> + + <component-description> + <author> + Caolán McNamara &;amp; Jan Navrati + </author> + <name> + com.sun.star.comp.ucb.GIOContentProvider + </name> + <description> + This component implements a Content Provider for the Universal + Content Broker. It provides access to contents stored on an GIO + location. + </description> + <loader-name> + com.sun.star.loader.SharedLibrary + </loader-name> + <language> + c++ + </language> + <status value="final"/> + <supported-service> + com.sun.star.ucb.GIOContentProvider + </supported-service> + + <service-dependency> + com.sun.star.configuration.ConfigurationAccess + </service-dependency> + <service-dependency> + com.sun.star.configuration.ConfigurationProvider + </service-dependency> + </component-description> + + <project-build-dependency> external </project-build-dependency> + <project-build-dependency> sal </project-build-dependency> + <project-build-dependency> cppu </project-build-dependency> + <project-build-dependency> cppuhelper </project-build-dependency> + <project-build-dependency> ucbhelper </project-build-dependency> + + <runtime-module-dependency> sal3 </runtime-module-dependency> + <runtime-module-dependency> cppu3 </runtime-module-dependency> + <runtime-module-dependency> cppuhelper3$(COM) </runtime-module-dependency> + <runtime-module-dependency> ucbhelper4$(COM) </runtime-module-dependency> + + <type> com.sun.star.beans.PropertyAttribute </type> + <type> com.sun.star.beans.PropertyValue </type> + <type> com.sun.star.beans.XPropertiesChangeNotifier </type> + <type> com.sun.star.beans.XPropertyAccess </type> + <type> com.sun.star.beans.XPropertyContainer </type> + <type> com.sun.star.beans.XPropertySetInfoChangeNotifier </type> + <type> com.sun.star.container.XChild </type> + <type> com.sun.star.container.XNameAccess </type> + <type> com.sun.star.io.XActiveDataSink </type> + <type> com.sun.star.io.XInputStream </type> + <type> com.sun.star.io.XOutputStream </type> + <type> com.sun.star.io.XSeekable </type> + <type> com.sun.star.lang.IllegalAccessException </type> + <type> com.sun.star.lang.XComponent </type> + <type> com.sun.star.lang.XMultiServiceFactory </type> + <type> com.sun.star.lang.XServiceInfo </type> + <type> com.sun.star.lang.XSingleServiceFactory </type> + <type> com.sun.star.lang.XTypeProvider </type> + <type> com.sun.star.registry.XRegistryKey </type> + <type> com.sun.star.sdbc.XCloseable </type> + <type> com.sun.star.sdbc.XColumnLocate </type> + <type> com.sun.star.sdbc.XResultSetMetaDataSupplier </type> + <type> com.sun.star.sdbc.XRow </type> + <type> com.sun.star.ucb.ContentCreationException </type> + <type> com.sun.star.ucb.ContentInfoAttribute </type> + <type> com.sun.star.ucb.InsertCommandArgument </type> + <type> com.sun.star.ucb.MissingInputStreamException </type> + <type> com.sun.star.ucb.MissingPropertiesException </type> + <type> com.sun.star.ucb.NameClash </type> + <type> com.sun.star.ucb.NameClashException </type> + <type> com.sun.star.ucb.OpenCommandArgument2 </type> + <type> com.sun.star.ucb.OpenMode </type> + <type> com.sun.star.ucb.PostCommandArgument2 </type> + <type> com.sun.star.ucb.RememberAuthentication </type> + <type> com.sun.star.ucb.ResultSetException </type> + <type> com.sun.star.ucb.TransferInfo </type> + <type> com.sun.star.ucb.XCommandEnvironment </type> + <type> com.sun.star.ucb.UnsupportedCommandException </type> + <type> com.sun.star.ucb.UnsupportedDataSinkException </type> + <type> com.sun.star.ucb.UnsupportedNameClashException </type> + <type> com.sun.star.ucb.UnsupportedOpenModeException </type> + <type> com.sun.star.ucb.XCommandInfo </type> + <type> com.sun.star.ucb.XCommandInfoChangeNotifier </type> + <type> com.sun.star.ucb.XCommandProcessor </type> + <type> com.sun.star.ucb.XContentAccess </type> + <type> com.sun.star.ucb.XContentProvider </type> + <type> com.sun.star.ucb.XDynamicResultSet </type> + <type> com.sun.star.ucb.XPersistentPropertySet </type> + <type> com.sun.star.util.DateTime </type> +</module-description> diff --git a/ucb/source/ucp/gvfs/gvfs_content.cxx b/ucb/source/ucp/gvfs/gvfs_content.cxx new file mode 100644 index 000000000000..3b1d726f9304 --- /dev/null +++ b/ucb/source/ucp/gvfs/gvfs_content.cxx @@ -0,0 +1,1817 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" +#include <string.h> +#include <unistd.h> +#include <sys/types.h> + +#include "osl/time.h" +#include <osl/diagnose.h> + +#include "osl/doublecheckedlocking.h" + +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/beans/PropertySetInfoChange.hpp> +#include <com/sun/star/beans/PropertySetInfoChangeEvent.hpp> +#include <com/sun/star/io/XActiveDataSink.hpp> +#include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/lang/IllegalAccessException.hpp> +#include <com/sun/star/ucb/ContentInfoAttribute.hpp> +#include <com/sun/star/ucb/InsertCommandArgument.hpp> +#include <com/sun/star/ucb/InteractiveBadTransferURLException.hpp> +#include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp> +#include <com/sun/star/ucb/InteractiveNetworkConnectException.hpp> +#include <com/sun/star/ucb/InteractiveNetworkGeneralException.hpp> +#include <com/sun/star/ucb/InteractiveNetworkReadException.hpp> +#include <com/sun/star/ucb/InteractiveNetworkResolveNameException.hpp> +#include <com/sun/star/ucb/InteractiveNetworkWriteException.hpp> +#include <com/sun/star/ucb/NameClash.hpp> +#include <com/sun/star/ucb/NameClashException.hpp> +#include <com/sun/star/ucb/OpenCommandArgument2.hpp> +#include <com/sun/star/ucb/OpenMode.hpp> +#include <com/sun/star/ucb/PostCommandArgument2.hpp> +#include <com/sun/star/ucb/TransferInfo.hpp> +#include <com/sun/star/ucb/XCommandInfo.hpp> +#include <com/sun/star/ucb/XPersistentPropertySet.hpp> +#include <com/sun/star/ucb/MissingInputStreamException.hpp> +#include <com/sun/star/ucb/MissingPropertiesException.hpp> +#include <com/sun/star/ucb/UnsupportedCommandException.hpp> +#include <com/sun/star/ucb/UnsupportedDataSinkException.hpp> +#include <com/sun/star/ucb/UnsupportedNameClashException.hpp> +#include <com/sun/star/ucb/UnsupportedOpenModeException.hpp> +#include <com/sun/star/ucb/UnsupportedOpenModeException.hpp> +#include <com/sun/star/ucb/NameClashException.hpp> +#include <ucbhelper/contentidentifier.hxx> +#include <ucbhelper/propertyvalueset.hxx> +#include <ucbhelper/interactionrequest.hxx> +#include <ucbhelper/cancelcommandexecution.hxx> +#include <ucbhelper/simpleauthenticationrequest.hxx> + +const int TRANSFER_BUFFER_SIZE = 65536; + +/* + * NB. Name escaping is done only for URIs + * the 'Title' property is unescaped on set/get + */ +#include <libgnomevfs/gnome-vfs-utils.h> +#include <libgnomevfs/gnome-vfs-result.h> +#include <libgnomevfs/gnome-vfs-standard-callbacks.h> +extern "C" { // missing in the header: doh. +# include <libgnomevfs/gnome-vfs-module-callback.h> +} + +#include "gvfs_content.hxx" +#include "gvfs_provider.hxx" +#include "gvfs_directory.hxx" +#include "gvfs_stream.hxx" + +using namespace gvfs; +using namespace com::sun::star; + +#define CLEAR_INFO(info) memset((info), 0, sizeof ((info)[0])) + + +static char * +OUStringToGnome( const rtl::OUString &str ) +{ + rtl::OString aTempStr = rtl::OUStringToOString( str, RTL_TEXTENCODING_UTF8 ); + return g_strdup( (const sal_Char *) aTempStr ); +} + +static rtl::OUString +GnomeToOUString( const char *utf8_str) +{ + if (!utf8_str) + return rtl::OUString(); + else + return rtl::OUString( utf8_str, strlen( utf8_str ), RTL_TEXTENCODING_UTF8 ); +} + + +Content::Content( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + ContentProvider* pProvider, + const uno::Reference< ucb::XContentIdentifier >& Identifier) + throw ( ucb::ContentCreationException ) + : ContentImplHelper( rxSMgr, pProvider, Identifier ), + m_pProvider( pProvider ), + m_bTransient( sal_False ) +{ + CLEAR_INFO (&m_info); +#ifdef DEBUG + g_warning ("New Content ('%s')", getURI()); +#endif +} + +Content::Content( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + ContentProvider * pProvider, + const uno::Reference< ucb::XContentIdentifier >& Identifier, + sal_Bool IsFolder) + throw ( ucb::ContentCreationException ) + : ContentImplHelper( rxSMgr, pProvider, Identifier ), + m_pProvider( pProvider ), + m_bTransient( sal_True ) +{ + CLEAR_INFO (&m_info); + +#ifdef DEBUG + g_warning ("New Transient content ('%s') (%d)", getURI(), IsFolder); +#endif +// m_info.name = FIXME: set name ? + m_info.valid_fields = GNOME_VFS_FILE_INFO_FIELDS_TYPE; + m_info.type = IsFolder ? GNOME_VFS_FILE_TYPE_DIRECTORY : + GNOME_VFS_FILE_TYPE_REGULAR; +} + +// virtual +Content::~Content() +{ + gnome_vfs_file_info_clear( &m_info ); +} + +// +// XInterface methods. +// + +void SAL_CALL Content::acquire() + throw( ) +{ + ContentImplHelper::acquire(); +} +void SAL_CALL Content::release() + throw( ) +{ + ContentImplHelper::release(); +} +uno::Any SAL_CALL Content::queryInterface( const uno::Type & rType ) + throw ( uno::RuntimeException ) +{ + // Note: isFolder may require network activities! So call it only + // if it is really necessary!!! + uno::Any aRet = cppu::queryInterface( rType, + static_cast< ucb::XContentCreator * >( this ) ); + if ( aRet.hasValue() ) + return isFolder( uno::Reference< ucb::XCommandEnvironment >() ) + ? aRet : uno::Any(); + else + return aRet.hasValue() ? aRet : ContentImplHelper::queryInterface( rType ); +} + +// +// XTypeProvider methods. +// + +XTYPEPROVIDER_COMMON_IMPL( Content ); + +uno::Sequence< uno::Type > SAL_CALL Content::getTypes() + throw( uno::RuntimeException ) +{ + static cppu::OTypeCollection *pFolderCollection = NULL; + static cppu::OTypeCollection *pFileCollection = NULL; + + if (!pFolderCollection) { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + + if (!pFolderCollection) { + static cppu::OTypeCollection aFolderCollection + (CPPU_TYPE_REF( lang::XTypeProvider ), + CPPU_TYPE_REF( lang::XServiceInfo ), + CPPU_TYPE_REF( lang::XComponent ), + CPPU_TYPE_REF( ucb::XContent ), + CPPU_TYPE_REF( ucb::XCommandProcessor ), + CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ), + CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ), + CPPU_TYPE_REF( beans::XPropertyContainer ), + CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ), + CPPU_TYPE_REF( container::XChild ), + CPPU_TYPE_REF( ucb::XContentCreator ) ); // !! + static cppu::OTypeCollection aFileCollection + (CPPU_TYPE_REF( lang::XTypeProvider ), + CPPU_TYPE_REF( lang::XServiceInfo ), + CPPU_TYPE_REF( lang::XComponent ), + CPPU_TYPE_REF( ucb::XContent ), + CPPU_TYPE_REF( ucb::XCommandProcessor ), + CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ), + CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ), + CPPU_TYPE_REF( beans::XPropertyContainer ), + CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ), + CPPU_TYPE_REF( container::XChild ) ); + + pFolderCollection = &aFolderCollection; + pFileCollection = &aFileCollection; + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + } + } + else { + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + } + + if ( isFolder( uno::Reference< ucb::XCommandEnvironment >() ) ) + return pFolderCollection->getTypes(); + else + return pFileCollection->getTypes(); +} + +// +// XServiceInfo methods. +// + +rtl::OUString SAL_CALL Content::getImplementationName() + throw( uno::RuntimeException ) +{ + return rtl::OUString::createFromAscii("com.sun.star.comp.GnomeVFSContent" ); +} + +uno::Sequence< rtl::OUString > SAL_CALL Content::getSupportedServiceNames() + throw( uno::RuntimeException ) +{ + uno::Sequence< rtl::OUString > aSNS( 1 ); + aSNS.getArray()[ 0 ] = rtl::OUString::createFromAscii( + "com.sun.star.ucb.GnomeVFSContent" ); + return aSNS; +} + +// +// XContent methods. +// + +rtl::OUString SAL_CALL Content::getContentType() + throw( uno::RuntimeException ) +{ + if ( isFolder( uno::Reference< ucb::XCommandEnvironment >() ) ) + return rtl::OUString::createFromAscii( GVFS_FOLDER_TYPE ); + else + return rtl::OUString::createFromAscii( GVFS_FILE_TYPE ); +} + +// +// XCommandProcessor methods. +// + +uno::Any Content::getBadArgExcept() +{ + return uno::makeAny( lang::IllegalArgumentException + ( rtl::OUString::createFromAscii( "Wrong argument type!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ); +} + +#include <stdio.h> + +uno::Any SAL_CALL Content::execute( + const ucb::Command& aCommand, + sal_Int32 /*CommandId*/, + const uno::Reference< ucb::XCommandEnvironment >& xEnv ) + throw( uno::Exception, + ucb::CommandAbortedException, + uno::RuntimeException ) +{ + uno::Any aRet; + +#ifdef DEBUG + { + uno::Reference< task::XInteractionHandler > xIH; + + if ( xEnv.is() ) + xIH = xEnv->getInteractionHandler(); + g_warning( "Execute command: '%s' with %s interaction env", + OUStringToGnome( aCommand.Name ), + xIH.is() ? "" : "NO" ); + } +#endif + +#define COMMAND_IS(cmd,name) ( (cmd).Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( name ) ) ) + + if ( COMMAND_IS( aCommand, "getPropertyValues" ) ) { + uno::Sequence< beans::Property > Properties; + + if ( !( aCommand.Argument >>= Properties ) ) + ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv ); + + aRet <<= getPropertyValues( Properties, xEnv ); + + } else if ( COMMAND_IS( aCommand, "setPropertyValues" ) ) { + uno::Sequence< beans::PropertyValue > aProperties; + + if ( !( aCommand.Argument >>= aProperties ) || + !aProperties.getLength() ) + ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv ); + + aRet <<= setPropertyValues( aProperties, xEnv ); + + } else if ( COMMAND_IS( aCommand, "getPropertySetInfo" ) ) { + aRet <<= getPropertySetInfo( xEnv, sal_False ); + + } else if ( COMMAND_IS( aCommand, "getCommandInfo" ) ) { + aRet <<= getCommandInfo( xEnv, sal_False ); + + } else if ( COMMAND_IS( aCommand, "open" ) ) { + rtl::OUString str = m_xIdentifier->getContentIdentifier(); + rtl::OString stra( + str.getStr(), + str.getLength(), + RTL_TEXTENCODING_UTF8); + + ucb::OpenCommandArgument2 aOpenCommand; + if ( !( aCommand.Argument >>= aOpenCommand ) ) + ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv ); + + sal_Bool bOpenFolder = + ( ( aOpenCommand.Mode == ucb::OpenMode::ALL ) || + ( aOpenCommand.Mode == ucb::OpenMode::FOLDERS ) || + ( aOpenCommand.Mode == ucb::OpenMode::DOCUMENTS ) ); + + if ( bOpenFolder && isFolder( xEnv ) ) { + uno::Reference< ucb::XDynamicResultSet > xSet + = new DynamicResultSet(m_xSMgr, this, aOpenCommand, xEnv ); + aRet <<= xSet; + + } else if ( aOpenCommand.Sink.is() ) { + + if ( ( aOpenCommand.Mode + == ucb::OpenMode::DOCUMENT_SHARE_DENY_NONE ) || + ( aOpenCommand.Mode + == ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE ) ) { + ucbhelper::cancelCommandExecution + ( uno::makeAny ( ucb::UnsupportedOpenModeException + ( rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + sal_Int16( aOpenCommand.Mode ) ) ), + xEnv ); + } + if ( !feedSink( aOpenCommand.Sink, xEnv ) ) { + // Note: aOpenCommand.Sink may contain an XStream + // implementation. Support for this type of + // sink is optional... +#ifdef DEBUG + g_warning ("Failed to load data from '%s'", getURI()); +#endif + ucbhelper::cancelCommandExecution + ( uno::makeAny (ucb::UnsupportedDataSinkException + ( rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + aOpenCommand.Sink ) ), + xEnv ); + } + } +#ifdef DEBUG + else + g_warning ("Open falling through ..."); +#endif + + } else if ( COMMAND_IS( aCommand, "createNewContent" ) && isFolder( xEnv ) ) { + ucb::ContentInfo arg; + if ( !( aCommand.Argument >>= arg ) ) + ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv ); + + aRet <<= createNewContent( arg ); + + } else if ( COMMAND_IS( aCommand, "insert" ) ) { + ucb::InsertCommandArgument arg; + if ( !( aCommand.Argument >>= arg ) ) + ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv ); + + insert( arg.Data, arg.ReplaceExisting, xEnv ); + + } else if ( COMMAND_IS( aCommand, "delete" ) ) { + + sal_Bool bDeletePhysical = sal_False; + aCommand.Argument >>= bDeletePhysical; + + ::rtl::OString aURI = getOURI(); + GnomeVFSResult result = gnome_vfs_unlink ((const sal_Char *) aURI); + + if (result != GNOME_VFS_OK) + cancelCommandExecution( result, xEnv, sal_True ); + + destroy( bDeletePhysical ); + + } else if ( COMMAND_IS( aCommand, "transfer" ) && isFolder( xEnv ) ) { + ucb::TransferInfo transferArgs; + + if ( !( aCommand.Argument >>= transferArgs ) ) + ucbhelper::cancelCommandExecution( getBadArgExcept(), xEnv ); + + transfer( transferArgs, xEnv ); + + } else { // Unsuported +#ifdef DEBUG + g_warning( "Unsupported command: '%s'", + OUStringToGnome( aCommand.Name ) ); +#endif + ucbhelper::cancelCommandExecution + ( uno::makeAny( ucb::UnsupportedCommandException + ( rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ) ) ), + xEnv ); + } +#undef COMMAND_IS + + return aRet; +} + +void SAL_CALL Content::abort( sal_Int32 /*CommandId*/ ) + throw( uno::RuntimeException ) +{ + // FIXME: we should use the GnomeVFSCancellation APIs here ... +} + +// +// XContentCreator methods. +// + +uno::Sequence< ucb::ContentInfo > Content::queryCreatableContentsInfo( + const uno::Reference< ucb::XCommandEnvironment >& xEnv) + throw( uno::RuntimeException ) +{ + if ( isFolder( xEnv ) ) + { + uno::Sequence< ucb::ContentInfo > seq(2); + + // Minimum set of props we really need + uno::Sequence< beans::Property > props( 1 ); + props[0] = beans::Property( + rtl::OUString::createFromAscii( "Title" ), + -1, + getCppuType( static_cast< rtl::OUString* >( 0 ) ), + beans::PropertyAttribute::MAYBEVOID | beans::PropertyAttribute::BOUND ); + + // file + seq[0].Type = rtl::OUString::createFromAscii( GVFS_FILE_TYPE ); + seq[0].Attributes = ( ucb::ContentInfoAttribute::INSERT_WITH_INPUTSTREAM | + ucb::ContentInfoAttribute::KIND_DOCUMENT ); + seq[0].Properties = props; + + // folder + seq[1].Type = rtl::OUString::createFromAscii( GVFS_FOLDER_TYPE ); + seq[1].Attributes = ucb::ContentInfoAttribute::KIND_FOLDER; + seq[1].Properties = props; + + return seq; + } + else + { + return uno::Sequence< ucb::ContentInfo >(); + } +} + +uno::Sequence< ucb::ContentInfo > SAL_CALL Content::queryCreatableContentsInfo() + throw( uno::RuntimeException ) +{ + return queryCreatableContentsInfo( uno::Reference< ucb::XCommandEnvironment >() ); +} + +uno::Reference< ucb::XContent > SAL_CALL +Content::createNewContent( const ucb::ContentInfo& Info ) + throw( uno::RuntimeException ) +{ + bool create_document; + const char *name; + + if ( Info.Type.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( GVFS_FILE_TYPE ) ) ) + create_document = true; + else if ( Info.Type.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( GVFS_FOLDER_TYPE ) ) ) + create_document = false; + else { +#ifdef DEBUG + g_warning( "Failed to create new content '%s'", + OUStringToGnome( Info.Type ) ); +#endif + return uno::Reference< ucb::XContent >(); + } + +#ifdef DEBUG + g_warning( "createNewContent (%d)", (int) create_document ); +#endif + + rtl::OUString aURL = getOUURI(); + + if ( ( aURL.lastIndexOf( '/' ) + 1 ) != aURL.getLength() ) + aURL += rtl::OUString::createFromAscii( "/" ); + + name = create_document ? "[New_Content]" : "[New_Collection]"; + // This looks problematic to me cf. webdav + aURL += rtl::OUString::createFromAscii( name ); + + uno::Reference< ucb::XContentIdentifier > xId + ( new ::ucbhelper::ContentIdentifier( m_xSMgr, aURL ) ); + + try { + return new ::gvfs::Content( m_xSMgr, m_pProvider, xId, !create_document ); + } catch ( ucb::ContentCreationException & ) { + return uno::Reference< ucb::XContent >(); + } +} + +rtl::OUString Content::getParentURL() +{ + rtl::OUString aParentURL; + // <scheme>:// -> "" + // <scheme>://foo -> "" + // <scheme>://foo/ -> "" + // <scheme>://foo/bar -> <scheme>://foo/ + // <scheme>://foo/bar/ -> <scheme>://foo/ + // <scheme>://foo/bar/abc -> <scheme>://foo/bar/ + + rtl::OUString aURL = getOUURI(); + + sal_Int32 nPos = aURL.lastIndexOf( '/' ); + if ( nPos == ( aURL.getLength() - 1 ) ) { + // Trailing slash found. Skip. + nPos = aURL.lastIndexOf( '/', nPos ); + } + + sal_Int32 nPos1 = aURL.lastIndexOf( '/', nPos ); + if ( nPos1 != -1 ) + nPos1 = aURL.lastIndexOf( '/', nPos1 ); + + if ( nPos1 != -1 ) + aParentURL = rtl::OUString( aURL.copy( 0, nPos + 1 ) ); + +#ifdef DEBUG + g_warning ("getParentURL '%s' -> '%s'", + getURI(), (const sal_Char *) rtl::OUStringToOString + ( aParentURL, RTL_TEXTENCODING_UTF8 ) ); +#endif + + return aParentURL; +} + +static util::DateTime +getDateFromUnix (time_t t) +{ + TimeValue tv; + tv.Nanosec = 0; + tv.Seconds = t; + oslDateTime dt; + + if ( osl_getDateTimeFromTimeValue( &tv, &dt ) ) + return util::DateTime( 0, dt.Seconds, dt.Minutes, dt.Hours, + dt.Day, dt.Month, dt.Year); + else + return util::DateTime(); +} + +uno::Reference< sdbc::XRow > Content::getPropertyValues( + const uno::Sequence< beans::Property >& rProperties, + const uno::Reference< ucb::XCommandEnvironment >& xEnv ) +{ + int nProps; + GnomeVFSResult result; + uno::Sequence< beans::Property > allProperties; + + if( ( result = getInfo( xEnv ) ) != GNOME_VFS_OK ) + cancelCommandExecution( result, xEnv, sal_False ); + + const beans::Property* pProps; + + if( rProperties.getLength() ) { + nProps = rProperties.getLength(); + pProps = rProperties.getConstArray(); + } else { + allProperties = getPropertySetInfo( xEnv )->getProperties(); + nProps = allProperties.getLength(); + pProps = allProperties.getConstArray(); + } + + rtl::Reference< ::ucbhelper::PropertyValueSet > xRow + = new ::ucbhelper::PropertyValueSet( m_xSMgr ); + + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + for( sal_Int32 n = 0; n < nProps; ++n ) { + const beans::Property& rProp = pProps[ n ]; + + if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Title" ) ) ) { + if (m_info.name && m_info.name[0] == '/') + g_warning ("Odd NFS title on item '%s' == '%s'", + getURI(), m_info.name); + xRow->appendString( rProp, GnomeToOUString( m_info.name ) ); + } + + else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) ) + xRow->appendString( rProp, getContentType () ); + + else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) ) { + if (m_info.valid_fields & GNOME_VFS_FILE_INFO_FIELDS_TYPE) + xRow->appendBoolean( rProp, ( m_info.type == GNOME_VFS_FILE_TYPE_REGULAR || + m_info.type == GNOME_VFS_FILE_TYPE_UNKNOWN ) ); + else + xRow->appendVoid( rProp ); + } + else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) ) { + if (m_info.valid_fields & GNOME_VFS_FILE_INFO_FIELDS_TYPE) + xRow->appendBoolean( rProp, ( m_info.type == GNOME_VFS_FILE_TYPE_DIRECTORY ) ); + else + xRow->appendVoid( rProp ); + } + else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsReadOnly" ) ) ) { + + GnomeVFSFileInfo* fileInfo = gnome_vfs_file_info_new (); + + ::rtl::OString aURI = getOURI(); + gnome_vfs_get_file_info + ( (const sal_Char *)aURI, fileInfo, + GNOME_VFS_FILE_INFO_GET_ACCESS_RIGHTS ); + + if (fileInfo->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_ACCESS) { + bool read_only = true; + + if (fileInfo->permissions & GNOME_VFS_PERM_ACCESS_WRITABLE) + read_only = false; + + xRow->appendBoolean( rProp, read_only ); + } else + xRow->appendVoid( rProp ); + gnome_vfs_file_info_unref (fileInfo); + } + else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Size" ) ) ) { + if (m_info.valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) + xRow->appendLong( rProp, m_info.size ); + else + xRow->appendVoid( rProp ); + } + else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsHidden" ) ) ) + xRow->appendBoolean( rProp, ( m_info.name && m_info.name[0] == '.' ) ); + + else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsVolume" ) ) || + rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsCompactDisk" ) ) ) + xRow->appendBoolean( rProp, sal_False ); + + else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "DateCreated" ) ) ) { + if (m_info.valid_fields & GNOME_VFS_FILE_INFO_FIELDS_CTIME) + xRow->appendTimestamp( rProp, getDateFromUnix( m_info.ctime ) ); + else + xRow->appendVoid( rProp ); + } + + else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "DateModified" ) ) ) { + if (m_info.valid_fields & GNOME_VFS_FILE_INFO_FIELDS_MTIME) + xRow->appendTimestamp( rProp, getDateFromUnix( m_info.mtime ) ); + else + xRow->appendVoid( rProp ); + } + + else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "MediaType" ) ) ) { + // We do this by sniffing in gnome-vfs; rather expensively. +#ifdef DEBUG + g_warning ("FIXME: Requested mime-type - an expensive op. indeed!"); +#endif + xRow->appendVoid( rProp ); + } else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "CreatableContentsInfo" ) ) ) + xRow->appendObject( rProp, uno::makeAny( queryCreatableContentsInfo( xEnv ) ) ); + + else { + xRow->appendVoid( rProp ); + } + } +#ifdef DEBUG + g_warning ("getPropertyValues on '%s' %d properties returned (of %d)", + getURI(), (int)xRow->getLength(), (int)nProps); +#endif + + return uno::Reference< sdbc::XRow >( xRow.get() ); +} + +static lang::IllegalAccessException +getReadOnlyException( Content *ctnt ) +{ + return lang::IllegalAccessException + ( rtl::OUString::createFromAscii( "Property is read-only!" ), + static_cast< cppu::OWeakObject * >( ctnt ) ); +} + +rtl::OUString +Content::makeNewURL( const char */*newName*/ ) +{ + rtl::OUString aNewURL = getParentURL(); + if ( aNewURL.lastIndexOf( '/' ) != ( aNewURL.getLength() - 1 ) ) + aNewURL += rtl::OUString::createFromAscii( "/" ); + + char *name = gnome_vfs_escape_string( m_info.name ); + aNewURL += GnomeToOUString( name ); + g_free( name ); + + return aNewURL; +} + +// This is slightly complicated by needing to support either 'move' or 'setname' +GnomeVFSResult +Content::doSetFileInfo( const GnomeVFSFileInfo *newInfo, + GnomeVFSSetFileInfoMask setMask, + const uno::Reference< ucb::XCommandEnvironment >& /*xEnv*/ ) +{ + GnomeVFSResult result = GNOME_VFS_OK; + + g_assert (!m_bTransient); + + ::rtl::OString aURI = getOURI(); + + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + // The simple approach: + if( setMask != GNOME_VFS_SET_FILE_INFO_NONE ) + result = gnome_vfs_set_file_info // missed a const in the API there + ( (const sal_Char *) aURI, (GnomeVFSFileInfo *)newInfo, setMask ); + + if ( result == GNOME_VFS_ERROR_NOT_SUPPORTED && + ( setMask & GNOME_VFS_SET_FILE_INFO_NAME ) ) { + // Try a move instead +#ifdef DEBUG + g_warning( "SetFileInfo not supported on '%s'", getURI() ); +#endif + + char *newURI = OUStringToGnome( makeNewURL( newInfo->name ) ); + + result = gnome_vfs_move ((const sal_Char *)aURI, newURI, FALSE); + + g_free (newURI); + } + + return result; +} + + +uno::Sequence< uno::Any > Content::setPropertyValues( + const uno::Sequence< beans::PropertyValue >& rValues, + const uno::Reference< ucb::XCommandEnvironment >& xEnv ) +{ + rtl::OUString aNewTitle; + GnomeVFSFileInfo newInfo; + int setMask = GNOME_VFS_SET_FILE_INFO_NONE; + + getInfo( xEnv ); + + osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); + + gnome_vfs_file_info_copy( &newInfo, &m_info ); + + Authentication aAuth( xEnv ); + + int nChanged = 0, nTitlePos = 0; + uno::Sequence< uno::Any > aRet( rValues.getLength() ); + uno::Sequence< beans::PropertyChangeEvent > aChanges( rValues.getLength() ); + + beans::PropertyChangeEvent aEvent; + aEvent.Source = static_cast< cppu::OWeakObject * >( this ); + aEvent.Further = sal_False; + aEvent.PropertyHandle = -1; + // aEvent.PropertyName = fill in later ... + // aEvent.OldValue = + // aEvent.NewValue = + + int nCount = rValues.getLength(); + const beans::PropertyValue* pValues = rValues.getConstArray(); + + for ( sal_Int32 n = 0; n < nCount; ++n ) { + const beans::PropertyValue& rValue = pValues[ n ]; + +#ifdef DEBUG + g_warning( "Set prop '%s'", OUStringToGnome( rValue.Name ) ); +#endif + if ( rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) || + rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "MediaType" ) ) || + rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) || + rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) || + rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Size" ) ) || + rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "CreatableContentsInfo" ) ) ) + aRet[ n ] <<= getReadOnlyException( this ); + + else if ( rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Title" ) ) ) { + if ( rValue.Value >>= aNewTitle ) { + if ( aNewTitle.getLength() <= 0 ) + aRet[ n ] <<= lang::IllegalArgumentException + ( rtl::OUString::createFromAscii( "Empty title not allowed!" ), + static_cast< cppu::OWeakObject * >( this ), -1 ); + else { + char *newName = OUStringToGnome( aNewTitle ); + + if( !newName || !m_info.name || strcmp( newName, m_info.name ) ) { +#ifdef DEBUG + g_warning ("Set new name to '%s'", newName); +#endif + + aEvent.PropertyName = rtl::OUString::createFromAscii( "Title" ); + aEvent.OldValue = uno::makeAny( GnomeToOUString( newInfo.name ) ); + aEvent.NewValue = uno::makeAny( aNewTitle ); + aChanges.getArray()[ nChanged ] = aEvent; + nTitlePos = nChanged++; + + newInfo.name = newName; + setMask |= GNOME_VFS_SET_FILE_INFO_NAME; + } else // same name + g_free (newName); + } + } else + aRet[ n ] <<= beans::IllegalTypeException + ( rtl::OUString::createFromAscii( "Property value has wrong type!" ), + static_cast< cppu::OWeakObject * >( this ) ); + + } else if ( rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "DateCreated" ) ) || + rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "DateModified" ) ) ) { + // FIXME: should be able to set the timestamps + aRet[ n ] <<= getReadOnlyException( this ); + } else { +#ifdef DEBUG + g_warning( "Unhandled property '%s'", OUStringToGnome( rValue.Name ) ); +#endif + aRet[ n ] <<= getReadOnlyException( this ); + } + } + + GnomeVFSResult result = GNOME_VFS_OK; + + if ( !m_bTransient && + ( result = doSetFileInfo( &newInfo, + (GnomeVFSSetFileInfoMask) setMask, + xEnv ) ) != GNOME_VFS_OK ) { + for (int i = 0; i < nChanged; i++) + aRet[ i ] <<= mapVFSException( result, sal_True ); + + } + + if ( result == GNOME_VFS_OK) { + gnome_vfs_file_info_copy( &m_info, &newInfo ); + + if ( setMask & GNOME_VFS_SET_FILE_INFO_NAME ) { + uno::Reference< ucb::XContentIdentifier > xNewId + = new ::ucbhelper::ContentIdentifier( + m_xSMgr, makeNewURL( newInfo.name ) ); + + aGuard.clear(); + if (!exchangeIdentity( xNewId ) ) + aRet[ nTitlePos ] <<= uno::Exception + ( rtl::OUString::createFromAscii( "Exchange failed!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + } + + gnome_vfs_file_info_clear( &newInfo ); + + if ( nChanged > 0 ) { + aGuard.clear(); + aChanges.realloc( nChanged ); + notifyPropertiesChange( aChanges ); + } + + return aRet; +} + +void Content::queryChildren( ContentRefList& rChildren ) +{ + // Obtain a list with a snapshot of all currently instanciated contents + // from provider and extract the contents which are direct children + // of this content. + + ::ucbhelper::ContentRefList aAllContents; + m_xProvider->queryExistingContents( aAllContents ); + + rtl::OUString aURL = getOUURI(); + sal_Int32 nURLPos = aURL.lastIndexOf( '/' ); + + if ( nURLPos != ( aURL.getLength() - 1 ) ) + aURL += rtl::OUString::createFromAscii( "/" ); + + sal_Int32 nLen = aURL.getLength(); + + ::ucbhelper::ContentRefList::const_iterator it = aAllContents.begin(); + ::ucbhelper::ContentRefList::const_iterator end = aAllContents.end(); + + while ( it != end ) { + ::ucbhelper::ContentImplHelperRef xChild = (*it); + rtl::OUString aChildURL + = xChild->getIdentifier()->getContentIdentifier(); + + // Is aURL a prefix of aChildURL? + if ( ( aChildURL.getLength() > nLen ) && + ( aChildURL.compareTo( aURL, nLen ) == 0 ) ) { + sal_Int32 nPos = nLen; + nPos = aChildURL.indexOf( '/', nPos ); + + if ( ( nPos == -1 ) || + ( nPos == ( aChildURL.getLength() - 1 ) ) ) { + // No further slashes / only a final slash. It's a child! + rChildren.push_back( ::gvfs::Content::ContentRef + (static_cast< ::gvfs::Content * >(xChild.get() ) ) ); + } + } + ++it; + } +} + +void Content::insert( + const uno::Reference< io::XInputStream > &xInputStream, + sal_Bool bReplaceExisting, + const uno::Reference< ucb::XCommandEnvironment > &xEnv ) + throw( uno::Exception ) +{ + osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); + +#ifdef DEBUG + g_warning( "Insert '%s' (%d) (0x%x:%d)", getURI(), bReplaceExisting, + m_info.valid_fields, m_info.type ); +#endif + + GnomeVFSResult result = getInfo( xEnv ); + // a racy design indeed. + if( !bReplaceExisting && !m_bTransient && + result != GNOME_VFS_ERROR_NOT_FOUND) { +#ifdef DEBUG + g_warning ("Nasty error inserting to '%s' ('%s')", + getURI(), gnome_vfs_result_to_string( result )); +#endif + cancelCommandExecution( GNOME_VFS_ERROR_FILE_EXISTS, xEnv, sal_True ); + } + + if ( m_info.valid_fields & GNOME_VFS_FILE_INFO_FIELDS_TYPE && + m_info.type == GNOME_VFS_FILE_TYPE_DIRECTORY ) { + ::rtl::OString aURI = getOURI(); + int perm; + + perm = ( GNOME_VFS_PERM_USER_ALL | + GNOME_VFS_PERM_GROUP_READ | + GNOME_VFS_PERM_OTHER_READ ); + +#ifdef DEBUG + g_warning ("Make directory"); +#endif + result = gnome_vfs_make_directory( (const sal_Char *) aURI, perm ); + + if( result != GNOME_VFS_OK ) + cancelCommandExecution( result, xEnv, sal_True ); + + return; + } + + if ( !xInputStream.is() ) { + // FIXME: slightly unclear whether to accept this and create an empty file + ucbhelper::cancelCommandExecution + ( uno::makeAny + ( ucb::MissingInputStreamException + ( rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ) ) ), + xEnv ); + } + + GnomeVFSHandle *handle = NULL; + ::rtl::OString aURI = getOURI(); + + result = GNOME_VFS_OK; + if ( bReplaceExisting ) { + Authentication aAuth( xEnv ); + result = gnome_vfs_open( &handle, (const sal_Char *)aURI, + GNOME_VFS_OPEN_WRITE ); + } + + if ( result != GNOME_VFS_OK ) { + int perm; + Authentication aAuth( xEnv ); + + perm = ( ( GNOME_VFS_PERM_USER_WRITE | GNOME_VFS_PERM_USER_READ ) | + ( GNOME_VFS_PERM_GROUP_WRITE | GNOME_VFS_PERM_GROUP_READ ) ); + + result = gnome_vfs_create + ( &handle, (const sal_Char *)aURI, GNOME_VFS_OPEN_WRITE, TRUE, perm ); + } + + if( result != GNOME_VFS_OK ) + cancelCommandExecution( result, xEnv, sal_True ); + + if ( !xInputStream.is() ) { + result = gnome_vfs_close( handle ); + if (result != GNOME_VFS_OK) + cancelCommandExecution( result, xEnv, sal_True ); + + } else { // copy it over + uno::Reference < io::XOutputStream > xOutput = + new gvfs::Stream( handle, &m_info ); + + copyData( xInputStream, xOutput ); + } + + if (m_bTransient) { + m_bTransient = sal_False; + aGuard.clear(); + inserted(); + } +} + +void Content::transfer(const ucb::TransferInfo & /*rArgs*/, + const uno::Reference< ucb::XCommandEnvironment >& xEnv ) + throw( uno::Exception ) +{ + // FIXME: see gnome-vfs-xfer.h - but we need to be able to easily + // detect which are gnome-vfs owned URI types ... + ucbhelper::cancelCommandExecution + ( uno::makeAny + ( ucb::InteractiveBadTransferURLException + ( rtl::OUString::createFromAscii( "Unsupported URL scheme!" ), + static_cast< cppu::OWeakObject * >( this ) ) ), + xEnv ); +} + +void Content::destroy( sal_Bool bDeletePhysical ) + throw( uno::Exception ) +{ + // @@@ take care about bDeletePhysical -> trashcan support + rtl::OUString aURL = getOUURI(); + + uno::Reference< ucb::XContent > xThis = this; + + deleted(); + + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + // Process instanciated children... + ::gvfs::Content::ContentRefList aChildren; + queryChildren( aChildren ); + + ContentRefList::const_iterator it = aChildren.begin(); + ContentRefList::const_iterator end = aChildren.end(); + + while ( it != end ) { + (*it)->destroy( bDeletePhysical ); + ++it; + } +} + +// Used by the 'setPropertyValues' method for +// propagating the renaming of a Content. +sal_Bool Content::exchangeIdentity( + const uno::Reference< ucb::XContentIdentifier >& xNewId ) +{ + if ( !xNewId.is() ) + return sal_False; + + uno::Reference< ucb::XContent > xThis = this; + +#ifdef DEBUG + g_warning( "exchangeIdentity from '%s' to '%s'", + getURI(), OUStringToGnome( xNewId->getContentIdentifier() ) ); +#endif + + if ( m_bTransient ) { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + /* FIXME: can we not screw up an identically named + * Content pointing to ourself here ? */ + m_xIdentifier = xNewId; + return sal_False; + } + + rtl::OUString aOldURL = getOUURI(); + + // Exchange own identitity. + if ( exchange( xNewId ) ) { + + // Process instanciated children... + ContentRefList aChildren; + queryChildren( aChildren ); + + ContentRefList::const_iterator it = aChildren.begin(); + ContentRefList::const_iterator end = aChildren.end(); + + while ( it != end ) { + ContentRef xChild = (*it); + + // Create new content identifier for the child... + uno::Reference< ucb::XContentIdentifier > + xOldChildId = xChild->getIdentifier(); + rtl::OUString aOldChildURL + = xOldChildId->getContentIdentifier(); + rtl::OUString aNewChildURL + = aOldChildURL.replaceAt( + 0, + aOldURL.getLength(), + xNewId->getContentIdentifier() ); + uno::Reference< ucb::XContentIdentifier > + xNewChildId + = new ::ucbhelper::ContentIdentifier( m_xSMgr, aNewChildURL ); + + if ( !xChild->exchangeIdentity( xNewChildId ) ) + return sal_False; + + ++it; + } + return sal_True; + } + + return sal_False; +} + +GnomeVFSResult +Content::getInfo( const uno::Reference< ucb::XCommandEnvironment >& xEnv ) +{ + GnomeVFSResult result; + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + if (m_bTransient) + result = GNOME_VFS_OK; + + else if ( !m_info.valid_fields ) { + ::rtl::OString aURI = getOURI(); + Authentication aAuth( xEnv ); + result = gnome_vfs_get_file_info + ( (const sal_Char *)aURI, &m_info, GNOME_VFS_FILE_INFO_DEFAULT ); + if (result != GNOME_VFS_OK) + gnome_vfs_file_info_clear( &m_info ); + } else + result = GNOME_VFS_OK; +#ifdef DEBUG + g_warning( "getInfo on '%s' returns '%s' (%d) (0x%x)", + getURI(), gnome_vfs_result_to_string( result ), + result, m_info.valid_fields ); +#endif + return result; +} + +sal_Bool +Content::isFolder(const uno::Reference< ucb::XCommandEnvironment >& xEnv ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + getInfo( xEnv ); + return (m_info.valid_fields & GNOME_VFS_FILE_INFO_FIELDS_TYPE && + m_info.type == GNOME_VFS_FILE_TYPE_DIRECTORY); +} + +uno::Any Content::mapVFSException( const GnomeVFSResult result, sal_Bool bWrite ) +{ + uno::Any aException; + const char *gvfs_message; + rtl::OUString message; + uno::Sequence< uno::Any > aArgs( 1 ); + +#ifdef DEBUG + g_warning ("Map VFS exception '%s' (%d)", + gnome_vfs_result_to_string( result ), result ); +#endif + + if ((gvfs_message = gnome_vfs_result_to_string (result))) + message = GnomeToOUString( gvfs_message ); + + switch (result) { + case GNOME_VFS_OK: + g_error ("VFS_OK mapped to exception."); + break; + case GNOME_VFS_ERROR_EOF: + g_warning ("VFS_EOF not handled somewhere."); + break; + case GNOME_VFS_ERROR_NOT_FOUND: + aArgs[ 0 ] <<= m_xIdentifier->getContentIdentifier(); + aException <<= + ucb::InteractiveAugmentedIOException + ( rtl::OUString::createFromAscii( "Not found!" ), + static_cast< cppu::OWeakObject * >( this ), + task::InteractionClassification_ERROR, + ucb::IOErrorCode_NOT_EXISTING, + aArgs ); + break; + case GNOME_VFS_ERROR_BAD_PARAMETERS: + aException <<= + lang::IllegalArgumentException + ( rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + -1 ); + break; + case GNOME_VFS_ERROR_GENERIC: + case GNOME_VFS_ERROR_INTERNAL: + case GNOME_VFS_ERROR_NOT_SUPPORTED: +#ifdef DEBUG + g_warning ("Internal - un-mapped error"); +#endif + aException <<= io::IOException(); + break; + case GNOME_VFS_ERROR_IO: + if ( bWrite ) + aException <<= + ucb::InteractiveNetworkWriteException + ( rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + task::InteractionClassification_ERROR, + message ); + else + aException <<= + ucb::InteractiveNetworkReadException + ( rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + task::InteractionClassification_ERROR, + message ); + break; + case GNOME_VFS_ERROR_HOST_NOT_FOUND: + case GNOME_VFS_ERROR_INVALID_HOST_NAME: + aException <<= + ucb::InteractiveNetworkResolveNameException + ( rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + task::InteractionClassification_ERROR, + message ); + break; + case GNOME_VFS_ERROR_SERVICE_NOT_AVAILABLE: + case GNOME_VFS_ERROR_SERVICE_OBSOLETE: + case GNOME_VFS_ERROR_PROTOCOL_ERROR: + case GNOME_VFS_ERROR_NO_MASTER_BROWSER: + aException <<= + ucb::InteractiveNetworkConnectException + ( rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + task::InteractionClassification_ERROR, + message ); + break; + + case GNOME_VFS_ERROR_FILE_EXISTS: + aException <<= ucb::NameClashException + ( rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + task::InteractionClassification_ERROR, + message ); + break; + + case GNOME_VFS_ERROR_INVALID_OPEN_MODE: + aException <<= ucb::UnsupportedOpenModeException(); + break; + + case GNOME_VFS_ERROR_CORRUPTED_DATA: + case GNOME_VFS_ERROR_WRONG_FORMAT: + case GNOME_VFS_ERROR_BAD_FILE: + case GNOME_VFS_ERROR_TOO_BIG: + case GNOME_VFS_ERROR_NO_SPACE: + case GNOME_VFS_ERROR_READ_ONLY: + case GNOME_VFS_ERROR_INVALID_URI: + case GNOME_VFS_ERROR_NOT_OPEN: + case GNOME_VFS_ERROR_ACCESS_DENIED: + case GNOME_VFS_ERROR_TOO_MANY_OPEN_FILES: + case GNOME_VFS_ERROR_NOT_A_DIRECTORY: + case GNOME_VFS_ERROR_IN_PROGRESS: + case GNOME_VFS_ERROR_INTERRUPTED: + case GNOME_VFS_ERROR_LOOP: + case GNOME_VFS_ERROR_NOT_PERMITTED: + case GNOME_VFS_ERROR_IS_DIRECTORY: + case GNOME_VFS_ERROR_NO_MEMORY: + case GNOME_VFS_ERROR_HOST_HAS_NO_ADDRESS: + case GNOME_VFS_ERROR_LOGIN_FAILED: + case GNOME_VFS_ERROR_CANCELLED: + case GNOME_VFS_ERROR_DIRECTORY_BUSY: + case GNOME_VFS_ERROR_DIRECTORY_NOT_EMPTY: + case GNOME_VFS_ERROR_TOO_MANY_LINKS: + case GNOME_VFS_ERROR_READ_ONLY_FILE_SYSTEM: + case GNOME_VFS_ERROR_NOT_SAME_FILE_SYSTEM: + case GNOME_VFS_ERROR_NAME_TOO_LONG: +#ifdef DEBUG + g_warning( "FIXME: Un-mapped VFS exception '%s' (%d)", + gnome_vfs_result_to_string( result ), result ); +#endif + default: + aException <<= ucb::InteractiveNetworkGeneralException + ( rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + task::InteractionClassification_ERROR ); + break; + } + + return aException; +} + +void Content::cancelCommandExecution( + GnomeVFSResult result, + const uno::Reference< ucb::XCommandEnvironment > & xEnv, + sal_Bool bWrite /* = sal_False */ ) + throw ( uno::Exception ) +{ + ucbhelper::cancelCommandExecution( mapVFSException( result, bWrite ), xEnv ); + // Unreachable +} + +uno::Sequence< beans::Property > Content::getProperties( + const uno::Reference< ucb::XCommandEnvironment > & /*xEnv*/ ) +{ + static const beans::Property aGenericProperties[] = { + beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ContentType" ) ), + -1, getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ), + beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsDocument" ) ), + -1, getCppuBooleanType(), + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ), + beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ), + -1, getCppuBooleanType(), + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ), + beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ), + -1, getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND ), + // Optional ... + beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DateCreated" ) ), + -1, getCppuType( static_cast< const util::DateTime * >( 0 ) ), + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ), + beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DateModified" ) ), + -1, getCppuType( static_cast< const util::DateTime * >( 0 ) ), + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ), +// FIXME: Too expensive for now (?) +// beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ), +// -1, getCppuType( static_cast< const rtl::OUString * >( 0 ) ), +// beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ), + beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Size" ) ), + -1, getCppuType( static_cast< const sal_Int64 * >( 0 ) ), + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ), + beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsReadOnly" ) ), + -1, getCppuBooleanType(), + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ), + beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsVolume" ) ), + -1, getCppuBooleanType(), + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ), + beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsCompactDisk" ) ), + -1, getCppuBooleanType(), + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ), + beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsHidden" ) ), + -1, getCppuBooleanType(), + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ), + beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CreatableContentsInfo" ) ), + -1, getCppuType( static_cast< const uno::Sequence< ucb::ContentInfo > * >( 0 ) ), + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ) + }; + + const int nProps = sizeof (aGenericProperties) / sizeof (aGenericProperties[0]); + + return uno::Sequence< beans::Property > ( aGenericProperties, nProps ); + +} + +uno::Sequence< ucb::CommandInfo > Content::getCommands( + const uno::Reference< ucb::XCommandEnvironment > & xEnv ) +{ + static ucb::CommandInfo aCommandInfoTable[] = { + // Required commands + ucb::CommandInfo + ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getCommandInfo" ) ), + -1, getCppuVoidType() ), + ucb::CommandInfo + ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getPropertySetInfo" ) ), + -1, getCppuVoidType() ), + ucb::CommandInfo + ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getPropertyValues" ) ), + -1, getCppuType( static_cast<uno::Sequence< beans::Property > * >( 0 ) ) ), + ucb::CommandInfo + ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ), + -1, getCppuType( static_cast<uno::Sequence< beans::PropertyValue > * >( 0 ) ) ), + + // Optional standard commands + ucb::CommandInfo + ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "delete" ) ), + -1, getCppuBooleanType() ), + ucb::CommandInfo + ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "insert" ) ), + -1, getCppuType( static_cast<ucb::InsertCommandArgument * >( 0 ) ) ), + ucb::CommandInfo + ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "open" ) ), + -1, getCppuType( static_cast<ucb::OpenCommandArgument2 * >( 0 ) ) ), + + // Folder Only, omitted if not a folder + ucb::CommandInfo + ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "transfer" ) ), + -1, getCppuType( static_cast<ucb::TransferInfo * >( 0 ) ) ), + ucb::CommandInfo + ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "createNewContent" ) ), + -1, getCppuType( static_cast<ucb::ContentInfo * >( 0 ) ) ) + }; + + const int nProps + = sizeof( aCommandInfoTable ) / sizeof( aCommandInfoTable[ 0 ] ); + return uno::Sequence< ucb::CommandInfo >( + aCommandInfoTable, isFolder( xEnv ) ? nProps : nProps - 2 ); +} + +rtl::OUString +Content::getOUURI () +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + return m_xIdentifier->getContentIdentifier(); +} + +rtl::OString +Content::getOURI () +{ + return rtl::OUStringToOString( getOUURI(), RTL_TEXTENCODING_UTF8 ); +} + +char * +Content::getURI () +{ + return OUStringToGnome( getOUURI() ); +} + +void +Content::copyData( uno::Reference< io::XInputStream > xIn, + uno::Reference< io::XOutputStream > xOut ) +{ + uno::Sequence< sal_Int8 > theData( TRANSFER_BUFFER_SIZE ); + + g_return_if_fail( xIn.is() && xOut.is() ); + + while ( xIn->readBytes( theData, TRANSFER_BUFFER_SIZE ) > 0 ) + xOut->writeBytes( theData ); + + xOut->closeOutput(); +} + +// Inherits an authentication context +uno::Reference< io::XInputStream > +Content::createTempStream( + const uno::Reference< ucb::XCommandEnvironment >& xEnv ) + throw( uno::Exception ) +{ + GnomeVFSResult result; + GnomeVFSHandle *handle = NULL; + ::rtl::OString aURI = getOURI(); + + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + // Something badly wrong happened - can't seek => stream to a temporary file + const rtl::OUString sServiceName ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.io.TempFile" ) ); + uno::Reference < io::XOutputStream > xTempOut = + uno::Reference < io::XOutputStream > + ( m_xSMgr->createInstance( sServiceName ), uno::UNO_QUERY ); + + if ( !xTempOut.is() ) + cancelCommandExecution( GNOME_VFS_ERROR_IO, xEnv ); + + result = gnome_vfs_open + ( &handle, (const sal_Char *)aURI, GNOME_VFS_OPEN_READ ); + if (result != GNOME_VFS_OK) + cancelCommandExecution( result, xEnv ); + + uno::Reference < io::XInputStream > pStream = new ::gvfs::Stream( handle, &m_info ); + copyData( pStream, xTempOut ); + + return uno::Reference < io::XInputStream > ( xTempOut, uno::UNO_QUERY ); +} + +uno::Reference< io::XInputStream > +Content::createInputStream( + const uno::Reference< ucb::XCommandEnvironment >& xEnv ) + throw( uno::Exception ) +{ + GnomeVFSHandle *handle = NULL; + GnomeVFSResult result; + uno::Reference<io::XInputStream > xIn; + + Authentication aAuth( xEnv ); + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + getInfo( xEnv ); + ::rtl::OString aURI = getOURI(); + + if ( !(m_info.valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) ) + return createTempStream( xEnv ); + + result = gnome_vfs_open + ( &handle, (const sal_Char *)aURI, + (GnomeVFSOpenMode) (GNOME_VFS_OPEN_READ | GNOME_VFS_OPEN_RANDOM ) ); + + if (result == GNOME_VFS_ERROR_INVALID_OPEN_MODE || + result == GNOME_VFS_ERROR_NOT_SUPPORTED) + return createTempStream( xEnv ); + + if (result != GNOME_VFS_OK) + cancelCommandExecution( result, xEnv ); + + // Try a seek just to make sure it's Random access: some lie. + result = gnome_vfs_seek( handle, GNOME_VFS_SEEK_START, 0); + if (result == GNOME_VFS_ERROR_NOT_SUPPORTED) { + gnome_vfs_close( handle ); + return createTempStream( xEnv ); + } + + if (result != GNOME_VFS_OK) + cancelCommandExecution( result, xEnv ); + + if (handle != NULL) + xIn = new ::gvfs::Stream( handle, &m_info ); + + return xIn; +} + +sal_Bool +Content::feedSink( uno::Reference< uno::XInterface > aSink, + const uno::Reference< ucb::XCommandEnvironment >& xEnv ) +{ + if ( !aSink.is() ) + return sal_False; + + uno::Reference< io::XOutputStream > xOut + = uno::Reference< io::XOutputStream >(aSink, uno::UNO_QUERY ); + uno::Reference< io::XActiveDataSink > xDataSink + = uno::Reference< io::XActiveDataSink >(aSink, uno::UNO_QUERY ); + + if ( !xOut.is() && !xDataSink.is() ) + return sal_False; + + uno::Reference< io::XInputStream > xIn = createInputStream( xEnv ); + if ( !xIn.is() ) + return sal_False; + + if ( xOut.is() ) + copyData( xIn, xOut ); + + if ( xDataSink.is() ) + xDataSink->setInputStream( xIn ); + + return sal_True; +} + +extern "C" { + +#ifndef GNOME_VFS_MODULE_CALLBACK_FULL_AUTHENTICATION +# error "We require Gnome VFS 2.6.x to compile (will run fine with < 2.6)" +#endif + + static void + vfs_authentication_callback (gconstpointer in_void, + gsize in_size, + gpointer out_void, + gsize out_size, + gpointer callback_data) + { + task::XInteractionHandler *xIH; + +#ifdef DEBUG + g_warning ("Full authentication callback (%p) ...", callback_data); +#endif + + if( !( xIH = (task::XInteractionHandler *) callback_data ) ) + return; + + const GnomeVFSModuleCallbackFullAuthenticationIn *in = + (const GnomeVFSModuleCallbackFullAuthenticationIn *) in_void; + GnomeVFSModuleCallbackFullAuthenticationOut *out = + (GnomeVFSModuleCallbackFullAuthenticationOut *) out_void; + + g_return_if_fail (in != NULL && out != NULL); + g_return_if_fail (sizeof (GnomeVFSModuleCallbackFullAuthenticationIn) == in_size && + sizeof (GnomeVFSModuleCallbackFullAuthenticationOut) == out_size); + +#ifdef DEBUG +# define NNIL(x) (x?x:"<Null>") + g_warning (" InComing data 0x%x uri '%s' prot '%s' server '%s' object '%s' " + "port %d auth_t '%s' user '%s' domain '%s' " + "def user '%s', def domain '%s'", + (int) in->flags, NNIL(in->uri), NNIL(in->protocol), + NNIL(in->server), NNIL(in->object), + (int) in->port, NNIL(in->authtype), NNIL(in->username), NNIL(in->domain), + NNIL(in->default_user), NNIL(in->default_domain)); +# undef NNIL +#endif + + ucbhelper::SimpleAuthenticationRequest::EntityType + eDomain, eUserName, ePassword; + ::rtl::OUString aHostName, aDomain, aUserName, aPassword; + + aHostName = GnomeToOUString( in->server ); + + if (in->flags & GNOME_VFS_MODULE_CALLBACK_FULL_AUTHENTICATION_NEED_DOMAIN) + { + aDomain = GnomeToOUString( in->domain ); + eDomain = ucbhelper::SimpleAuthenticationRequest::ENTITY_MODIFY; + if (!aDomain.getLength()) + aDomain = GnomeToOUString( in->default_domain ); + } + else // no underlying capability to display realm otherwise + eDomain = ucbhelper::SimpleAuthenticationRequest::ENTITY_NA; + + aUserName = GnomeToOUString( in->username ); + if (!aUserName.getLength()) + aUserName = GnomeToOUString( in->default_user ); + eUserName = (in->flags & GNOME_VFS_MODULE_CALLBACK_FULL_AUTHENTICATION_NEED_USERNAME) ? + ucbhelper::SimpleAuthenticationRequest::ENTITY_MODIFY : + (aUserName.getLength() ? + ucbhelper::SimpleAuthenticationRequest::ENTITY_FIXED : + ucbhelper::SimpleAuthenticationRequest::ENTITY_NA); + + // No suggested password. + ePassword = (in->flags & GNOME_VFS_MODULE_CALLBACK_FULL_AUTHENTICATION_NEED_PASSWORD) ? + ucbhelper::SimpleAuthenticationRequest::ENTITY_MODIFY : + ucbhelper::SimpleAuthenticationRequest::ENTITY_FIXED; + + // Really, really bad things happen if we don't provide + // the same user/password as was entered last time if + // we failed to authenticate - infinite looping / flickering + // madness etc. [ nice infrastructure ! ] + static rtl::OUString aLastUserName, aLastPassword; + if (in->flags & GNOME_VFS_MODULE_CALLBACK_FULL_AUTHENTICATION_PREVIOUS_ATTEMPT_FAILED) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + aUserName = aLastUserName; + aPassword = aLastPassword; + } + + rtl::Reference< ucbhelper::SimpleAuthenticationRequest > xRequest + = new ucbhelper::SimpleAuthenticationRequest (GnomeToOUString(in->uri), + aHostName, eDomain, aDomain, + eUserName, aUserName, + ePassword, aPassword); + + xIH->handle( xRequest.get() ); + + rtl::Reference< ucbhelper::InteractionContinuation > xSelection + = xRequest->getSelection(); + + if ( xSelection.is() ) { + // Handler handled the request. + uno::Reference< task::XInteractionAbort > xAbort(xSelection.get(), uno::UNO_QUERY ); + if ( !xAbort.is() ) { + const rtl::Reference< + ucbhelper::InteractionSupplyAuthentication > & xSupp + = xRequest->getAuthenticationSupplier(); + + aUserName = xSupp->getUserName(); + aDomain = xSupp->getRealm(); + aPassword = xSupp->getPassword(); + + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + aLastUserName = aUserName; + aLastPassword = aPassword; + } + + out->username = OUStringToGnome( aUserName ); + out->domain = OUStringToGnome( aDomain ); + out->password = OUStringToGnome( aPassword ); + out->save_password = xSupp->getRememberPasswordMode(); + +#ifdef DEBUG + g_warning ("Got valid user/domain/password '%s' '%s' '%s', %s password", + out->username, out->domain, out->password, + out->save_password ? "save" : "don't save"); +#endif + } + else + out->abort_auth = TRUE; + } + else + out->abort_auth = TRUE; + } + + static void + vfs_authentication_old_callback (gconstpointer in_void, + gsize in_size, + gpointer out_void, + gsize out_size, + gpointer callback_data) + { +#ifdef DEBUG + g_warning ("Old authentication callback (%p) [ UNTESTED ] ...", callback_data); +#endif + const GnomeVFSModuleCallbackAuthenticationIn *in = + (const GnomeVFSModuleCallbackAuthenticationIn *) in_void; + GnomeVFSModuleCallbackAuthenticationOut *out = + (GnomeVFSModuleCallbackAuthenticationOut *) out_void; + + g_return_if_fail (in != NULL && out != NULL); + g_return_if_fail (sizeof (GnomeVFSModuleCallbackAuthenticationIn) == in_size && + sizeof (GnomeVFSModuleCallbackAuthenticationOut) == out_size); + + GnomeVFSModuleCallbackFullAuthenticationIn mapped_in = { + (GnomeVFSModuleCallbackFullAuthenticationFlags) + (GNOME_VFS_MODULE_CALLBACK_FULL_AUTHENTICATION_NEED_PASSWORD | + GNOME_VFS_MODULE_CALLBACK_FULL_AUTHENTICATION_NEED_USERNAME | + GNOME_VFS_MODULE_CALLBACK_FULL_AUTHENTICATION_NEED_DOMAIN), + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + GnomeVFSModuleCallbackFullAuthenticationOut mapped_out = { 0, 0, 0, 0, 0, 0, 0, 0 }; + + // Map the old style input auth. data to the new style structure. + if (in->previous_attempt_failed) + mapped_in.flags = (GnomeVFSModuleCallbackFullAuthenticationFlags) + (mapped_in.flags | + GNOME_VFS_MODULE_CALLBACK_FULL_AUTHENTICATION_PREVIOUS_ATTEMPT_FAILED); + + GnomeVFSURI *pURI = NULL; + // Urk - parse all this from the URL ... + mapped_in.uri = in->uri; + if (in->uri) + { + pURI = gnome_vfs_uri_new( in->uri ); + mapped_in.protocol = (char *) gnome_vfs_uri_get_scheme (pURI); + mapped_in.server = (char *) gnome_vfs_uri_get_host_name (pURI); + mapped_in.port = gnome_vfs_uri_get_host_port (pURI); + mapped_in.username = (char *) gnome_vfs_uri_get_user_name (pURI); + } + mapped_in.domain = in->realm; + mapped_in.default_user = mapped_in.username; + mapped_in.default_domain = mapped_in.domain; + + vfs_authentication_callback ((gconstpointer) &mapped_in, + sizeof (mapped_in), + (gpointer) &mapped_out, + sizeof (mapped_out), + callback_data); + + if (pURI) + gnome_vfs_uri_unref (pURI); + + // Map the new style auth. out data to the old style out structure. + out->username = mapped_out.username; + out->password = mapped_out.password; + g_free (mapped_out.domain); + g_free (mapped_out.keyring); + } + + + static void + auth_destroy (gpointer data) + { + task::XInteractionHandler *xIH; + if( ( xIH = ( task::XInteractionHandler * )data ) ) + xIH->release(); + } + + // This sucks, but gnome-vfs doesn't much like + // repeated set / unsets - so we have to compensate. + GPrivate *auth_queue = NULL; + + void auth_queue_destroy( gpointer data ) + { + GList *l; + GQueue *vq = (GQueue *) data; + + for (l = vq->head; l; l = l->next) + auth_destroy (l->data); + g_queue_free (vq); + } +} + +static void +refresh_auth( GQueue *vq ) +{ + GList *l; + + gnome_vfs_module_callback_pop( GNOME_VFS_MODULE_CALLBACK_AUTHENTICATION ); + gnome_vfs_module_callback_pop( GNOME_VFS_MODULE_CALLBACK_FULL_AUTHENTICATION ); + + for (l = vq->head; l; l = l->next) { + if (l->data) { + gnome_vfs_module_callback_push + ( GNOME_VFS_MODULE_CALLBACK_AUTHENTICATION, + vfs_authentication_old_callback, l->data, NULL ); + gnome_vfs_module_callback_push + ( GNOME_VFS_MODULE_CALLBACK_FULL_AUTHENTICATION, + vfs_authentication_callback, l->data, NULL ); + break; + } + } +} + +gvfs::Authentication::Authentication( + const uno::Reference< ucb::XCommandEnvironment > & xEnv ) +{ + GQueue *vq; + uno::Reference< task::XInteractionHandler > xIH; + + if ( xEnv.is() ) + xIH = xEnv->getInteractionHandler(); + + if ( xIH.is() ) + xIH->acquire(); + + if( !(vq = (GQueue *)g_private_get( auth_queue ) ) ) { + vq = g_queue_new(); + g_private_set( auth_queue, vq ); + } + + g_queue_push_head( vq, (gpointer) xIH.get() ); + refresh_auth( vq ); +} + +gvfs::Authentication::~Authentication() +{ + GQueue *vq; + gpointer data; + + vq = (GQueue *)g_private_get( auth_queue ); + + data = g_queue_pop_head( vq ); + auth_destroy (data); + + refresh_auth( vq ); +} diff --git a/ucb/source/ucp/gvfs/gvfs_content.hxx b/ucb/source/ucp/gvfs/gvfs_content.hxx new file mode 100644 index 000000000000..b2f6bec4ca11 --- /dev/null +++ b/ucb/source/ucp/gvfs/gvfs_content.hxx @@ -0,0 +1,271 @@ +/************************************************************************* + * + * 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 _GVFS_UCP_CONTENT_HXX +#define _GVFS_UCP_CONTENT_HXX + +#include <memory> +#include <list> +#include <rtl/ref.hxx> +#include <com/sun/star/ucb/ContentCreationException.hpp> +#include <com/sun/star/ucb/XContentCreator.hpp> +#include <ucbhelper/contenthelper.hxx> + +#include <glib/gthread.h> +#include <libgnomevfs/gnome-vfs-ops.h> +#include <libgnomevfs/gnome-vfs-directory.h> + +namespace com { namespace sun { namespace star { namespace beans { + struct Property; + struct PropertyValue; +} } } } + +namespace com { namespace sun { namespace star { namespace io { + class XInputStream; + class XOutputStream; +} } } } + +namespace com { namespace sun { namespace star { namespace sdbc { + class XRow; +} } } } + +namespace com { namespace sun { namespace star { namespace ucb { + struct TransferInfo; +} } } } + +namespace gvfs +{ + +class ContentProvider; +class ContentProperties; + +// Random made up names - AFAICS +#define GVFS_FILE_TYPE "application/vnd.sun.staroffice.gvfs-file" +#define GVFS_FOLDER_TYPE "application/vnd.sun.staroffice.gvfs-folder" + +class Authentication +{ +public: + // Helper class to make exceptions pleasant + Authentication( const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv ); + ~Authentication(); +}; + +class Content : public ::ucbhelper::ContentImplHelper, + public com::sun::star::ucb::XContentCreator +{ +//========================================================================= +// Internals +//========================================================================= +private: + typedef rtl::Reference< Content > ContentRef; + typedef std::list< ContentRef > ContentRefList; + + // Instance data + ContentProvider *m_pProvider; // No need for a ref, base class holds object + sal_Bool m_bTransient; // A non-existant (as yet) item + GnomeVFSFileInfo m_info; // cached status information + + // Internal helpers + void queryChildren ( ContentRefList& rChildren ); + ::com::sun::star::uno::Any getBadArgExcept (); + GnomeVFSResult getInfo ( const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment >& xEnv ); + sal_Bool isFolder ( const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment >& xEnv ); + sal_Bool exchangeIdentity( const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XContentIdentifier >& xNewId); + GnomeVFSResult doSetFileInfo ( const GnomeVFSFileInfo *newInfo, + GnomeVFSSetFileInfoMask setMask, + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment >& xEnv ); + ::rtl::OUString makeNewURL ( const char *newName ); + // End Internal helpers + + // For ucbhelper + virtual ::rtl::OUString getParentURL(); + // For ucbhelper + virtual com::sun::star::uno::Sequence< com::sun::star::beans::Property > + getProperties( const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv ); + // For ucbhelper + virtual com::sun::star::uno::Sequence< com::sun::star::ucb::CommandInfo > + getCommands( const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv ); + +public: + // Command "getPropertyValues" + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRow > + getPropertyValues( const ::com::sun::star::uno::Sequence< + ::com::sun::star::beans::Property >& rProperties, + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment >& xEnv ); + +private: + // Command "setPropertyValues" + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > + setPropertyValues( const ::com::sun::star::uno::Sequence< + ::com::sun::star::beans::PropertyValue >& rValues, + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment >& xEnv ); + + // Command "insert" + void insert( const ::com::sun::star::uno::Reference< + ::com::sun::star::io::XInputStream > & xInputStream, + sal_Bool bReplaceExisting, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment >& xEnv ) + throw( ::com::sun::star::uno::Exception ); + + // Command "transfer" + void transfer( const ::com::sun::star::ucb::TransferInfo & rArgs, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment >& xEnv ) + throw( ::com::sun::star::uno::Exception ); + + // Command "delete" + void destroy( sal_Bool bDeletePhysical ) + throw( ::com::sun::star::uno::Exception ); + + // "open" helpers + void copyData( ::com::sun::star::uno::Reference< + ::com::sun::star::io::XInputStream > xIn, + ::com::sun::star::uno::Reference< + ::com::sun::star::io::XOutputStream > xOut ); + + ::com::sun::star::uno::Reference< + ::com::sun::star::io::XInputStream > + createTempStream( const ::com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment >& xEnv ) + throw( ::com::sun::star::uno::Exception ); + ::com::sun::star::uno::Reference< + ::com::sun::star::io::XInputStream > + createInputStream( const ::com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment >& xEnv ) + throw( ::com::sun::star::uno::Exception ); + sal_Bool feedSink( ::com::sun::star::uno::Reference< + ::com::sun::star::uno::XInterface> aSink, + const ::com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment >& xEnv ); + + ::com::sun::star::uno::Any mapVFSException( const GnomeVFSResult result, + sal_Bool bWrite ); + + void cancelCommandExecution(const GnomeVFSResult result, + const ::com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv, + sal_Bool bWrite = sal_False ) + throw( ::com::sun::star::uno::Exception ); + + +public: + // Non-interface bits + char *getURI (); + rtl::OString getOURI (); + rtl::OUString getOUURI (); + +//========================================================================= +// Externals +//========================================================================= +public: + + Content( const ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + ContentProvider *pProvider, + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XContentIdentifier >& Identifier) + throw ( ::com::sun::star::ucb::ContentCreationException ); + Content( const ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + ContentProvider *pProvider, + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XContentIdentifier >& Identifier, + sal_Bool isFolder) + throw ( ::com::sun::star::ucb::ContentCreationException ); + virtual ~Content(); + + // XInterface + XINTERFACE_DECL() + + // XTypeProvider + XTYPEPROVIDER_DECL() + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName() + throw( ::com::sun::star::uno::RuntimeException ); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL + getSupportedServiceNames() + throw( ::com::sun::star::uno::RuntimeException ); + + // XContent + virtual rtl::OUString SAL_CALL + getContentType() + throw( com::sun::star::uno::RuntimeException ); + + // XCommandProcessor + virtual com::sun::star::uno::Any SAL_CALL + execute( const com::sun::star::ucb::Command& aCommand, + sal_Int32 CommandId, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment >& xEnv ) + throw( com::sun::star::uno::Exception, + com::sun::star::ucb::CommandAbortedException, + com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + abort( sal_Int32 CommandId ) + throw( com::sun::star::uno::RuntimeException ); + + ////////////////////////////////////////////////////////////////////// + // Additional interfaces + ////////////////////////////////////////////////////////////////////// + + // XContentCreator + virtual com::sun::star::uno::Sequence< + com::sun::star::ucb::ContentInfo > SAL_CALL + queryCreatableContentsInfo() + throw( com::sun::star::uno::RuntimeException ); + virtual com::sun::star::uno::Reference< + com::sun::star::ucb::XContent > SAL_CALL + createNewContent( const com::sun::star::ucb::ContentInfo& Info ) + throw( com::sun::star::uno::RuntimeException ); + + + com::sun::star::uno::Sequence< com::sun::star::ucb::ContentInfo > + queryCreatableContentsInfo( + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment >& xEnv) + throw( com::sun::star::uno::RuntimeException ); +}; + +} + +extern "C" { + extern GPrivate *auth_queue; + extern void auth_queue_destroy( gpointer data ); +} + +#endif diff --git a/ucb/source/ucp/gvfs/gvfs_directory.cxx b/ucb/source/ucp/gvfs/gvfs_directory.cxx new file mode 100644 index 000000000000..b93f34d9003f --- /dev/null +++ b/ucb/source/ucp/gvfs/gvfs_directory.cxx @@ -0,0 +1,423 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" +/* + * This file pinched from webdavdatasupplier (etc.) + * cut & paste + new getData impl. & collate ResultSet code. + */ +#include <vector> +#include <osl/diagnose.h> +#include <com/sun/star/ucb/OpenMode.hpp> +#include <ucbhelper/contentidentifier.hxx> +#include <ucbhelper/providerhelper.hxx> + +#include "gvfs_directory.hxx" + +#include <libgnomevfs/gnome-vfs-utils.h> +#include <libgnomevfs/gnome-vfs-directory.h> + +using namespace com::sun::star; +using namespace gvfs; + +// DynamicResultSet Implementation. + +DynamicResultSet::DynamicResultSet( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + const rtl::Reference< Content >& rxContent, + const ucb::OpenCommandArgument2& rCommand, + const uno::Reference< ucb::XCommandEnvironment >& rxEnv ) + : ResultSetImplHelper( rxSMgr, rCommand ), + m_xContent( rxContent ), + m_xEnv( rxEnv ) +{ +} +void DynamicResultSet::initStatic() +{ + m_xResultSet1 + = new ::ucbhelper::ResultSet( m_xSMgr, + m_aCommand.Properties, + new DataSupplier( m_xSMgr, + m_xContent, + m_aCommand.Mode ), + m_xEnv ); +} +void DynamicResultSet::initDynamic() +{ + initStatic(); + m_xResultSet2 = m_xResultSet1; +} + +//========================================================================= + + +// DataSupplier Implementation. + + + +struct ResultListEntry +{ + rtl::OUString aId; + uno::Reference< ucb::XContentIdentifier > xId; + uno::Reference< ucb::XContent > xContent; + uno::Reference< sdbc::XRow > xRow; + GnomeVFSFileInfo aInfo; + + ResultListEntry( const GnomeVFSFileInfo *fileInfo) + { + gnome_vfs_file_info_copy (&aInfo, fileInfo); + } + + ~ResultListEntry() + { + gnome_vfs_file_info_clear (&aInfo); + } +}; + +//========================================================================= +// +// ResultList. +// +//========================================================================= + +typedef std::vector< ResultListEntry* > ResultList; + +//========================================================================= +// +// struct DataSupplier_Impl. +// +//========================================================================= + +struct gvfs::DataSupplier_Impl +{ + osl::Mutex m_aMutex; + ResultList m_aResults; + rtl::Reference< Content > m_xContent; + uno::Reference< lang::XMultiServiceFactory > m_xSMgr; + sal_Int32 m_nOpenMode; + sal_Bool m_bCountFinal; + + DataSupplier_Impl( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + const rtl::Reference< Content >& rContent, + sal_Int32 nOpenMode ) + : m_xContent( rContent ), m_xSMgr( rxSMgr ), + m_nOpenMode( nOpenMode ), m_bCountFinal( sal_False ) {} + ~DataSupplier_Impl() + { + ResultList::const_iterator it = m_aResults.begin(); + ResultList::const_iterator end = m_aResults.end(); + + while ( it != end ) + { + delete (*it); + it++; + } + } +}; + +DataSupplier::DataSupplier( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + const rtl::Reference< Content >& rContent, + sal_Int32 nOpenMode ) +: m_pImpl( new DataSupplier_Impl( rxSMgr, rContent, nOpenMode ) ) +{ +} + +//========================================================================= +// virtual +DataSupplier::~DataSupplier() +{ + delete m_pImpl; +} + +// virtual +rtl::OUString DataSupplier::queryContentIdentifierString( sal_uInt32 nIndex ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( nIndex < m_pImpl->m_aResults.size() ) { + rtl::OUString aId = m_pImpl->m_aResults[ nIndex ]->aId; + if ( aId.getLength() ) // cached + return aId; + } + + if ( getResult( nIndex ) ) { + rtl::OUString aId = m_pImpl->m_xContent->getOUURI(); + + char *escaped_name; + escaped_name = gnome_vfs_escape_string( m_pImpl->m_aResults[ nIndex ]->aInfo.name ); + + if ( ( aId.lastIndexOf( '/' ) + 1 ) != aId.getLength() ) + aId += rtl::OUString::createFromAscii( "/" ); + + aId += rtl::OUString::createFromAscii( escaped_name ); + + g_free( escaped_name ); + + m_pImpl->m_aResults[ nIndex ]->aId = aId; + return aId; + } + + return rtl::OUString(); +} + +// virtual +uno::Reference< ucb::XContentIdentifier > +DataSupplier::queryContentIdentifier( sal_uInt32 nIndex ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( nIndex < m_pImpl->m_aResults.size() ) { + uno::Reference< ucb::XContentIdentifier > xId + = m_pImpl->m_aResults[ nIndex ]->xId; + if ( xId.is() ) // Already cached. + return xId; + } + + rtl::OUString aId = queryContentIdentifierString( nIndex ); + if ( aId.getLength() ) { + uno::Reference< ucb::XContentIdentifier > xId + = new ::ucbhelper::ContentIdentifier( aId ); + m_pImpl->m_aResults[ nIndex ]->xId = xId; + return xId; + } + + return uno::Reference< ucb::XContentIdentifier >(); +} + +// virtual +uno::Reference< ucb::XContent > +DataSupplier::queryContent( sal_uInt32 nIndex ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( nIndex < m_pImpl->m_aResults.size() ) { + uno::Reference< ucb::XContent > xContent + = m_pImpl->m_aResults[ nIndex ]->xContent; + if ( xContent.is() ) // Already cached. + return xContent; + } + + uno::Reference< ucb::XContentIdentifier > xId + = queryContentIdentifier( nIndex ); + if ( xId.is() ) { + try + { + // FIXME: + // It would be really nice to propagate this information + // to the Content, but we can't then register it with the + // ContentProvider, and the ucbhelper hinders here. + uno::Reference< ucb::XContent > xContent + = m_pImpl->m_xContent->getProvider()->queryContent( xId ); + m_pImpl->m_aResults[ nIndex ]->xContent = xContent; + return xContent; + + } + catch ( ucb::IllegalIdentifierException& ) { + } + } + return uno::Reference< ucb::XContent >(); +} + +// virtual +sal_Bool DataSupplier::getResult( sal_uInt32 nIndex ) +{ + osl::ClearableGuard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( m_pImpl->m_aResults.size() > nIndex ) // Result already present. + return sal_True; + + if ( getData() && m_pImpl->m_aResults.size() > nIndex ) + return sal_True; + + return sal_False; +} + +// virtual +sal_uInt32 DataSupplier::totalCount() +{ + getData(); + + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + return m_pImpl->m_aResults.size(); +} + +// virtual +sal_uInt32 DataSupplier::currentCount() +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + return m_pImpl->m_aResults.size(); +} + +// virtual +sal_Bool DataSupplier::isCountFinal() +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + return m_pImpl->m_bCountFinal; +} + +// virtual +uno::Reference< sdbc::XRow > DataSupplier::queryPropertyValues( sal_uInt32 nIndex ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( nIndex < m_pImpl->m_aResults.size() ) { + uno::Reference< sdbc::XRow > xRow = m_pImpl->m_aResults[ nIndex ]->xRow; + if ( xRow.is() ) // Already cached. + return xRow; + } + + if ( getResult( nIndex ) ) { + // Inefficient - but we can't create xContent's sensibly + // nor can we do the property code sensibly cleanly staticaly. + Content *pContent = static_cast< ::gvfs::Content * >(queryContent( nIndex ).get()); + + uno::Reference< sdbc::XRow > xRow = + pContent->getPropertyValues( getResultSet()->getProperties(), + getResultSet()->getEnvironment() ); + + m_pImpl->m_aResults[ nIndex ]->xRow = xRow; + + return xRow; + } + + return uno::Reference< sdbc::XRow >(); +} + +// virtual +void DataSupplier::releasePropertyValues( sal_uInt32 nIndex ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( nIndex < m_pImpl->m_aResults.size() ) + m_pImpl->m_aResults[ nIndex ]->xRow = uno::Reference< sdbc::XRow >(); +} + +// virtual +void DataSupplier::close() +{ +} + +// virtual +void DataSupplier::validate() + throw( ucb::ResultSetException ) +{ +} + +sal_Bool DataSupplier::getData() +{ + osl::ClearableGuard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( !m_pImpl->m_bCountFinal ) { + GnomeVFSResult result; + GnomeVFSDirectoryHandle *dirHandle = NULL; + + { + Authentication aAuth( getResultSet()->getEnvironment() ); + char *uri = m_pImpl->m_xContent->getURI(); + result = gnome_vfs_directory_open + ( &dirHandle, uri, GNOME_VFS_FILE_INFO_DEFAULT ); + + if (result != GNOME_VFS_OK) { +#ifdef DEBUG + g_warning ("Failed open of '%s' with '%s'", + uri, gnome_vfs_result_to_string( result )); +#endif + g_free( uri ); + return sal_False; + } + + g_free( uri ); + } + + GnomeVFSFileInfo* fileInfo = gnome_vfs_file_info_new (); + + while ((result = gnome_vfs_directory_read_next (dirHandle, fileInfo)) == GNOME_VFS_OK) { + if( fileInfo->name && fileInfo->name[0] == '.' && + ( fileInfo->name[1] == '\0' || + ( fileInfo->name[1] == '.' && fileInfo->name[2] == '\0' ) ) ) + continue; + + switch ( m_pImpl->m_nOpenMode ) { + case ucb::OpenMode::FOLDERS: + if ( !(fileInfo->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_TYPE) || + fileInfo->type != GNOME_VFS_FILE_TYPE_DIRECTORY ) + continue; + break; + + case ucb::OpenMode::DOCUMENTS: + if ( !(fileInfo->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_TYPE) || + fileInfo->type != GNOME_VFS_FILE_TYPE_REGULAR ) + continue; + break; + + case ucb::OpenMode::ALL: + default: + break; + } + + m_pImpl->m_aResults.push_back( new ResultListEntry( fileInfo ) ); + } + + gnome_vfs_file_info_unref (fileInfo); + +#ifdef DEBUG + g_warning ("Got %d directory entries", result); +#endif + + m_pImpl->m_bCountFinal = sal_True; + + // Callback possible, because listeners may be informed! + aGuard.clear(); + getResultSet()->rowCountFinal(); + + if (result != GNOME_VFS_ERROR_EOF) { +#ifdef DEBUG + g_warning( "Failed read_next '%s'", + gnome_vfs_result_to_string( result ) ); +#endif + return sal_False; + } + + result = gnome_vfs_directory_close (dirHandle); + if (result != GNOME_VFS_OK) { +#ifdef DEBUG + g_warning( "Failed close '%s'", + gnome_vfs_result_to_string( result ) ); +#endif + return sal_False; + } + } + + return sal_True; +} + + + diff --git a/ucb/source/ucp/gvfs/gvfs_directory.hxx b/ucb/source/ucp/gvfs/gvfs_directory.hxx new file mode 100644 index 000000000000..f914554f7736 --- /dev/null +++ b/ucb/source/ucp/gvfs/gvfs_directory.hxx @@ -0,0 +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 _GVFS_UCP_RESULTSET_HXX +#define _GVFS_UCP_RESULTSET_HXX + +#include <rtl/ref.hxx> +#include <ucbhelper/resultset.hxx> +#include <ucbhelper/resultsethelper.hxx> +#include "gvfs_content.hxx" + +namespace gvfs { + +class DynamicResultSet : public ::ucbhelper::ResultSetImplHelper +{ + rtl::Reference< Content > m_xContent; + com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > m_xEnv; + +private: + virtual void initStatic(); + virtual void initDynamic(); + +public: + DynamicResultSet( const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + const rtl::Reference< Content >& rxContent, + const com::sun::star::ucb::OpenCommandArgument2& rCommand, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment >& rxEnv ); +}; + + +struct DataSupplier_Impl; +class DataSupplier : public ucbhelper::ResultSetDataSupplier +{ +private: + gvfs::DataSupplier_Impl *m_pImpl; + sal_Bool getData(); + +public: + DataSupplier( const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + const rtl::Reference< Content >& rContent, + sal_Int32 nOpenMode); + + virtual ~DataSupplier(); + + virtual rtl::OUString queryContentIdentifierString( sal_uInt32 nIndex ); + virtual com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier > + queryContentIdentifier( sal_uInt32 nIndex ); + virtual com::sun::star::uno::Reference< com::sun::star::ucb::XContent > + queryContent( sal_uInt32 nIndex ); + + virtual sal_Bool getResult( sal_uInt32 nIndex ); + + virtual sal_uInt32 totalCount(); + virtual sal_uInt32 currentCount(); + virtual sal_Bool isCountFinal(); + + virtual com::sun::star::uno::Reference< com::sun::star::sdbc::XRow > + queryPropertyValues( sal_uInt32 nIndex ); + virtual void releasePropertyValues( sal_uInt32 nIndex ); + virtual void close(); + virtual void validate() + throw( com::sun::star::ucb::ResultSetException ); +}; + +} + +#endif diff --git a/ucb/source/ucp/gvfs/gvfs_provider.cxx b/ucb/source/ucp/gvfs/gvfs_provider.cxx new file mode 100644 index 000000000000..77415982c63d --- /dev/null +++ b/ucb/source/ucp/gvfs/gvfs_provider.cxx @@ -0,0 +1,183 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +#include <ucbhelper/contentidentifier.hxx> +#include <libgnomevfs/gnome-vfs-init.h> +#include "gvfs_provider.hxx" +#include "gvfs_content.hxx" + +using namespace com::sun::star; +using namespace gvfs; + +//========================================================================= +//========================================================================= +// +// ContentProvider Implementation. +// +//========================================================================= +//========================================================================= + +ContentProvider::ContentProvider( + const uno::Reference< lang::XMultiServiceFactory >& rSMgr ) +: ::ucbhelper::ContentProviderImplHelper( rSMgr ) +{ +} +// sdafas +//========================================================================= +// virtual +ContentProvider::~ContentProvider() +{ +} + +//========================================================================= +// +// XInterface methods. +// +//========================================================================= + +XINTERFACE_IMPL_3( ContentProvider, + lang::XTypeProvider, + lang::XServiceInfo, + com::sun::star::ucb::XContentProvider ); + +//========================================================================= +// +// XTypeProvider methods. +// +//========================================================================= + +XTYPEPROVIDER_IMPL_3( ContentProvider, + lang::XTypeProvider, + lang::XServiceInfo, + com::sun::star::ucb::XContentProvider ); + +//========================================================================= +// +// XServiceInfo methods. +// +//========================================================================= + +XSERVICEINFO_IMPL_1( ContentProvider, + rtl::OUString::createFromAscii( + "com.sun.star.comp.GnomeVFSContentProvider" ), + rtl::OUString::createFromAscii( + "com.sun.star.ucb.GnomeVFSContentProvider" ) ); +//========================================================================= +// +// Service factory implementation. +// +//========================================================================= + +ONE_INSTANCE_SERVICE_FACTORY_IMPL( ContentProvider ); + +//========================================================================= +// +// XContentProvider methods. +// +//========================================================================= + +uno::Reference< com::sun::star::ucb::XContent > SAL_CALL +ContentProvider::queryContent( + const uno::Reference< + com::sun::star::ucb::XContentIdentifier >& Identifier ) + throw( com::sun::star::ucb::IllegalIdentifierException, + uno::RuntimeException ) +{ +#ifdef DEBUG + g_warning ("QueryContent: '%s'", + (const sal_Char *)rtl::OUStringToOString + (Identifier->getContentIdentifier(), RTL_TEXTENCODING_UTF8)); +#endif + + osl::MutexGuard aGuard( m_aMutex ); + + // Check, if a content with given id already exists... + uno::Reference< com::sun::star::ucb::XContent > xContent + = queryExistingContent( Identifier ).get(); + if ( xContent.is() ) + return xContent; + + try + { + xContent = new ::gvfs::Content(m_xSMgr, this, Identifier ); + registerNewContent( xContent ); + } + catch ( com::sun::star::ucb::ContentCreationException const & ) + { + throw com::sun::star::ucb::IllegalIdentifierException(); + } + + if ( !xContent->getIdentifier().is() ) + throw com::sun::star::ucb::IllegalIdentifierException(); + + return xContent; +} + + +//============================ shlib entry points ============================================= + +extern "C" void SAL_CALL +component_getImplementationEnvironment( const sal_Char **ppEnvTypeName, + uno_Environment **/*ppEnv*/ ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + +extern "C" void * SAL_CALL +component_getFactory( const sal_Char *pImplName, + void *pServiceManager, + void */*pRegistryKey*/ ) +{ + void * pRet = 0; + + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + if (!gnome_vfs_initialized ()) + gnome_vfs_init (); + if (!auth_queue) + auth_queue = g_private_new( auth_queue_destroy ); + } + + uno::Reference< lang::XMultiServiceFactory > xSMgr + (reinterpret_cast< lang::XMultiServiceFactory * >( pServiceManager ) ); + uno::Reference< lang::XSingleServiceFactory > xFactory; + + if ( !::gvfs::ContentProvider::getImplementationName_Static().compareToAscii( pImplName ) ) + xFactory = ::gvfs::ContentProvider::createServiceFactory( xSMgr ); + + if ( xFactory.is() ) { + xFactory->acquire(); + pRet = xFactory.get(); + } + + return pRet; +} + + diff --git a/ucb/source/ucp/gvfs/gvfs_provider.hxx b/ucb/source/ucp/gvfs/gvfs_provider.hxx new file mode 100644 index 000000000000..fd9e7dfd7876 --- /dev/null +++ b/ucb/source/ucp/gvfs/gvfs_provider.hxx @@ -0,0 +1,65 @@ +/************************************************************************* + * + * 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 _PROVIDER_HXX_ +#define _PROVIDER_HXX_ + +#include <rtl/ref.hxx> +#include <com/sun/star/beans/Property.hpp> +#include <ucbhelper/providerhelper.hxx> + +namespace gvfs { + +class ContentProvider : public ::ucbhelper::ContentProviderImplHelper +{ +public: + ContentProvider( const ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XMultiServiceFactory >& rSMgr ); + virtual ~ContentProvider(); + + // XInterface + XINTERFACE_DECL() + + // XTypeProvider + XTYPEPROVIDER_DECL() + + // XServiceInfo + XSERVICEINFO_DECL() + + // XContentProvider + virtual ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XContent > SAL_CALL + queryContent( const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XContentIdentifier >& Identifier ) + throw( ::com::sun::star::ucb::IllegalIdentifierException, + ::com::sun::star::uno::RuntimeException ); + +}; + +} /* namespace gvfs */ + +#endif /* _PROVIDER_HXX_ */ + diff --git a/ucb/source/ucp/gvfs/gvfs_stream.cxx b/ucb/source/ucp/gvfs/gvfs_stream.cxx new file mode 100644 index 000000000000..ab0c6ed90fc0 --- /dev/null +++ b/ucb/source/ucp/gvfs/gvfs_stream.cxx @@ -0,0 +1,343 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" +#include "gvfs_stream.hxx" +#include <rtl/memory.h> +#include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp> + +#include <libgnomevfs/gnome-vfs-ops.h> + +using namespace cppu; +using namespace rtl; +using namespace com::sun::star::io; +using namespace com::sun::star::uno; +using namespace com::sun::star::ucb; +using namespace gvfs; + +Stream::Stream( GnomeVFSHandle *handle, + const GnomeVFSFileInfo *aInfo ) : + m_eof (sal_False), + m_bInputStreamCalled( sal_False ), + m_bOutputStreamCalled( sal_False ) +{ + m_handle = handle; + gnome_vfs_file_info_copy (&m_info, aInfo); +} + +Stream::~Stream( void ) +{ + if (m_handle) { + gnome_vfs_close (m_handle); + m_handle = NULL; + } +} + +Any Stream::queryInterface( const Type &type ) + throw( RuntimeException ) +{ + Any aRet = ::cppu::queryInterface + ( type, + static_cast< XStream * >( this ), + static_cast< XInputStream * >( this ), + static_cast< XOutputStream * >( this ), + static_cast< XSeekable * >( this ), + static_cast< XTruncate * >( this ) ); + + return aRet.hasValue() ? aRet : OWeakObject::queryInterface( type ); +} + +// ------------------------------------------------------------------- +// XStream +// ------------------------------------------------------------------- + +com::sun::star::uno::Reference< com::sun::star::io::XInputStream > SAL_CALL +Stream::getInputStream( ) + throw( com::sun::star::uno::RuntimeException ) +{ + { + osl::MutexGuard aGuard( m_aMutex ); + m_bInputStreamCalled = true; + } + return Reference< XInputStream >( this ); +} + +com::sun::star::uno::Reference< com::sun::star::io::XOutputStream > SAL_CALL +Stream::getOutputStream( ) + throw( com::sun::star::uno::RuntimeException ) +{ + { + osl::MutexGuard aGuard( m_aMutex ); + m_bOutputStreamCalled = true; + } + return Reference< XOutputStream >( this ); +} + +// ------------------------------------------------------------------- +// XInputStream +// ------------------------------------------------------------------- + +sal_Int32 SAL_CALL Stream::readBytes( + Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead ) + throw( NotConnectedException, + BufferSizeExceededException, + IOException, + RuntimeException ) +{ + GnomeVFSResult result; + GnomeVFSFileSize nBytesRead = 0; + + if( ! m_handle ) + throw IOException(); + + if( m_eof ) { + aData.realloc( 0 ); + return 0; + } + + try { + aData.realloc( nBytesToRead ); + } catch ( const Exception &e ) { + throw BufferSizeExceededException(); + } + + do { + result = gnome_vfs_read( m_handle, aData.getArray(), + nBytesToRead, &nBytesRead ); + } while( result == GNOME_VFS_ERROR_INTERRUPTED ); + + if (result != GNOME_VFS_OK && + result != GNOME_VFS_ERROR_EOF) + throwOnError( result ); + + if (result == GNOME_VFS_ERROR_EOF) + m_eof = sal_True; + + aData.realloc( sal::static_int_cast<sal_uInt32>(nBytesRead) ); + + return sal::static_int_cast<sal_Int32>(nBytesRead); +} + +sal_Int32 SAL_CALL Stream::readSomeBytes( + Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead ) + throw( NotConnectedException, + BufferSizeExceededException, + IOException, + RuntimeException ) +{ + // Again - having 2 methods here just sucks; cf. filinpstr.cxx + // This can never be an effective non-blocking API - so why bother ? + return readBytes( aData, nMaxBytesToRead ); +} + +void SAL_CALL Stream::skipBytes( sal_Int32 nBytesToSkip ) + throw( NotConnectedException, + BufferSizeExceededException, + IOException, + RuntimeException ) +{ + GnomeVFSResult result; + + if( ! m_handle ) + throw IOException(); + + result = gnome_vfs_seek( m_handle, GNOME_VFS_SEEK_CURRENT, nBytesToSkip ); + + if ( result == GNOME_VFS_ERROR_BAD_PARAMETERS || + result == GNOME_VFS_ERROR_NOT_SUPPORTED ) + g_warning ("FIXME: just read them in ..."); + + throwOnError( result ); +} + +sal_Int32 SAL_CALL Stream::available( ) + throw( NotConnectedException, + IOException, + RuntimeException ) +{ + return 0; // cf. filinpstr.cxx +} + +void SAL_CALL Stream::closeInput( void ) + throw( NotConnectedException, + IOException, + RuntimeException ) +{ + osl::MutexGuard aGuard( m_aMutex ); + m_bInputStreamCalled = false; + + if( ! m_bOutputStreamCalled ) + closeStream(); +} + +// ------------------------------------------------------------------- +// XSeekable +// ------------------------------------------------------------------- + +void SAL_CALL Stream::seek( sal_Int64 location ) + throw( ::com::sun::star::lang::IllegalArgumentException, + IOException, + RuntimeException ) +{ + GnomeVFSResult result; + + if( ! m_handle ) + throw IOException(); + + if ( location < 0 ) + throw ::com::sun::star::lang::IllegalArgumentException(); + + m_eof = sal_False; + result = gnome_vfs_seek( m_handle, GNOME_VFS_SEEK_START, location ); + + if (result == GNOME_VFS_ERROR_EOF) + throw ::com::sun::star::lang::IllegalArgumentException(); + + throwOnError( result ); +} + +sal_Int64 SAL_CALL Stream::getPosition() + throw( IOException, + RuntimeException ) +{ + GnomeVFSFileSize nBytesIn = 0; + + if( ! m_handle ) + throw IOException(); + + throwOnError( gnome_vfs_tell( m_handle, &nBytesIn ) ); + + return nBytesIn; +} + +sal_Int64 SAL_CALL Stream::getLength() + throw( IOException, RuntimeException ) +{ + // FIXME: so this sucks; it may be stale but ... + if (m_info.valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) + return m_info.size; + else { + g_warning ("FIXME: No valid length"); + return 0; + } +} + +// ------------------------------------------------------------------- +// XTruncate +// ------------------------------------------------------------------- + +void SAL_CALL Stream::truncate( void ) + throw( com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException ) +{ + if( ! m_handle ) + throw IOException(); + + throwOnError( gnome_vfs_truncate_handle( m_handle, 0 ) ); +} + +// ------------------------------------------------------------------- +// XOutputStream +// ------------------------------------------------------------------- + +void SAL_CALL Stream::writeBytes( const com::sun::star::uno::Sequence< sal_Int8 >& aData ) + throw( com::sun::star::io::NotConnectedException, + com::sun::star::io::BufferSizeExceededException, + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException) +{ + GnomeVFSResult result = GNOME_VFS_OK; + GnomeVFSFileSize toWrite = aData.getLength(); + const sal_Int8 *p = aData.getConstArray(); + + if( ! m_handle ) + throw IOException(); + + while( toWrite > 0) { + GnomeVFSFileSize bytesWritten = 0; + + result = gnome_vfs_write( m_handle, p, toWrite, &bytesWritten ); + if( result == GNOME_VFS_ERROR_INTERRUPTED ) + continue; + throwOnError( result ); + g_assert( bytesWritten <= toWrite ); + toWrite -= bytesWritten; + p += bytesWritten; + } +} + +void SAL_CALL Stream::flush( void ) + throw( NotConnectedException, BufferSizeExceededException, + IOException, RuntimeException ) +{ +} + +void SAL_CALL Stream::closeOutput( void ) + throw( com::sun::star::io::NotConnectedException, + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException ) +{ + osl::MutexGuard aGuard( m_aMutex ); + m_bOutputStreamCalled = false; + + if( ! m_bInputStreamCalled ) + closeStream(); +} + +// ------------------------------------------------------------------- +// Misc. +// ------------------------------------------------------------------- + +void Stream::closeStream( void ) + throw( ::com::sun::star::io::NotConnectedException, + ::com::sun::star::io::IOException, + ::com::sun::star::uno::RuntimeException ) +{ + if (m_handle) { + gnome_vfs_close (m_handle); + m_handle = NULL; + } else + throw IOException(); +} + +void Stream::throwOnError( GnomeVFSResult result ) + throw( NotConnectedException, + BufferSizeExceededException, + IOException, + RuntimeException ) +{ + if( result != GNOME_VFS_OK ) { + ::rtl::OUString aMsg = ::rtl::OUString::createFromAscii + ( gnome_vfs_result_to_string( result ) ); + + g_warning( "Input Stream exceptional result '%s' (%d)", + gnome_vfs_result_to_string( result ), result ); + + throw IOException( aMsg, static_cast< cppu::OWeakObject * >( this ) ); + } +} diff --git a/ucb/source/ucp/gvfs/gvfs_stream.hxx b/ucb/source/ucp/gvfs/gvfs_stream.hxx new file mode 100644 index 000000000000..93815f6b2321 --- /dev/null +++ b/ucb/source/ucp/gvfs/gvfs_stream.hxx @@ -0,0 +1,165 @@ +/************************************************************************* + * + * 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 _GVFSSTREAM_HXX_ +#define _GVFSSTREAM_HXX_ + +#include <sal/types.h> +#include <rtl/ustring.hxx> +#include <cppuhelper/weak.hxx> +#include <com/sun/star/io/XStream.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/io/XTruncate.hpp> +#include <com/sun/star/io/XSeekable.hpp> + +#include <libgnomevfs/gnome-vfs-handle.h> + +namespace gvfs +{ + +class Stream : public ::com::sun::star::io::XStream, + public ::com::sun::star::io::XInputStream, + public ::com::sun::star::io::XOutputStream, + public ::com::sun::star::io::XTruncate, + public ::com::sun::star::io::XSeekable, + public ::cppu::OWeakObject +{ +private: + GnomeVFSHandle *m_handle; + GnomeVFSFileInfo m_info; + osl::Mutex m_aMutex; + sal_Bool m_eof; + sal_Bool m_bInputStreamCalled; + sal_Bool m_bOutputStreamCalled; + + void throwOnError( GnomeVFSResult result ) + throw( ::com::sun::star::io::NotConnectedException, + ::com::sun::star::io::BufferSizeExceededException, + ::com::sun::star::io::IOException, + ::com::sun::star::uno::RuntimeException ); + + void closeStream( void ) + throw( ::com::sun::star::io::NotConnectedException, + ::com::sun::star::io::IOException, + ::com::sun::star::uno::RuntimeException ); + +public: + Stream ( GnomeVFSHandle *handle, + const GnomeVFSFileInfo *aInfo ); + virtual ~Stream(); + + // XInterface + virtual com::sun::star::uno::Any SAL_CALL queryInterface(const ::com::sun::star::uno::Type & type ) + throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL acquire( void ) + throw () + { OWeakObject::acquire(); } + virtual void SAL_CALL release( void ) + throw() + { OWeakObject::release(); } + + // XStream + virtual com::sun::star::uno::Reference< com::sun::star::io::XInputStream > SAL_CALL getInputStream( ) + throw( com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::uno::Reference< com::sun::star::io::XOutputStream > SAL_CALL getOutputStream( ) + throw( com::sun::star::uno::RuntimeException ); + + // XInputStream + virtual sal_Int32 SAL_CALL readBytes( + ::com::sun::star::uno::Sequence< sal_Int8 > & aData, + sal_Int32 nBytesToRead ) + throw( ::com::sun::star::io::NotConnectedException, + ::com::sun::star::io::BufferSizeExceededException, + ::com::sun::star::io::IOException, + ::com::sun::star::uno::RuntimeException ); + + virtual sal_Int32 SAL_CALL readSomeBytes( + ::com::sun::star::uno::Sequence< sal_Int8 > & aData, + sal_Int32 nMaxBytesToRead ) + throw( ::com::sun::star::io::NotConnectedException, + ::com::sun::star::io::BufferSizeExceededException, + ::com::sun::star::io::IOException, + ::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip ) + throw( ::com::sun::star::io::NotConnectedException, + ::com::sun::star::io::BufferSizeExceededException, + ::com::sun::star::io::IOException, + ::com::sun::star::uno::RuntimeException ); + + virtual sal_Int32 SAL_CALL available( void ) + throw( ::com::sun::star::io::NotConnectedException, + ::com::sun::star::io::IOException, + ::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL closeInput( void ) + throw( ::com::sun::star::io::NotConnectedException, + ::com::sun::star::io::IOException, + ::com::sun::star::uno::RuntimeException ); + + // XSeekable + virtual void SAL_CALL seek( sal_Int64 location ) + throw( ::com::sun::star::lang::IllegalArgumentException, + ::com::sun::star::io::IOException, + ::com::sun::star::uno::RuntimeException ); + + virtual sal_Int64 SAL_CALL getPosition() + throw( ::com::sun::star::io::IOException, + ::com::sun::star::uno::RuntimeException ); + + virtual sal_Int64 SAL_CALL getLength() + throw( ::com::sun::star::io::IOException, + ::com::sun::star::uno::RuntimeException ); + + // XOutputStream + virtual void SAL_CALL writeBytes( const com::sun::star::uno::Sequence< sal_Int8 >& aData ) + throw( com::sun::star::io::NotConnectedException, + com::sun::star::io::BufferSizeExceededException, + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL flush( void ) + throw( com::sun::star::io::NotConnectedException, + com::sun::star::io::BufferSizeExceededException, + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException); + + + virtual void SAL_CALL closeOutput( void ) + throw( com::sun::star::io::NotConnectedException, + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException ); + + // XTruncate + virtual void SAL_CALL truncate( void ) + throw( com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException ); +}; + +} // namespace gvfs +#endif // _GVFSSTREAM_HXX_ diff --git a/ucb/source/ucp/gvfs/makefile.mk b/ucb/source/ucp/gvfs/makefile.mk new file mode 100644 index 000000000000..87fcca87cf70 --- /dev/null +++ b/ucb/source/ucp/gvfs/makefile.mk @@ -0,0 +1,91 @@ +#************************************************************************* +# +# 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=ucb +# Version +UCPGVFS_MAJOR=1 +TARGET=ucpgvfs +ENABLE_EXCEPTIONS=TRUE +USE_DEFFILE=TRUE +NO_BSYMBOLIC=TRUE + +.INCLUDE: settings.mk +.IF "$(L10N_framework)"=="" + +.IF "$(ENABLE_GNOMEVFS)"!="" +COMPILER_WARN_ALL=TRUE +PKGCONFIG_MODULES=gnome-vfs-2.0 +.INCLUDE: pkg_config.mk + +.IF "$(OS)" == "SOLARIS" +LINKFLAGS+=-z nodefs +.ENDIF # "$(OS)" == "SOLARIS" + +.IF "$(OS)" == "LINUX" +# hack for faked SO environment +CFLAGS+=-gdwarf-2 +PKGCONFIG_LIBS!:=-Wl,--export-dynamic $(PKGCONFIG_LIBS:s/ -llinc//:s/ -lbonobo-activation//:s/ -lgconf-2//:s/ -lORBit-2//:s/ -lIDL-2//:s/ -lgmodule-2.0//:s/ -lgobject-2.0//:s/ -lgthread-2.0//) +.ENDIF # "$(OS)" == "LINUX" + +# no "lib" prefix +DLLPRE = + +SLOFILES=\ + $(SLO)$/gvfs_content.obj \ + $(SLO)$/gvfs_directory.obj \ + $(SLO)$/gvfs_stream.obj \ + $(SLO)$/gvfs_provider.obj + +SHL1NOCHECK=TRUE +SHL1TARGET=$(TARGET)$(UCPGVFS_MAJOR).uno +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +SHL1LIBS=$(SLB)$/$(TARGET).lib +SHL1IMPLIB=i$(TARGET) +SHL1STDLIBS=\ + $(CPPUHELPERLIB) \ + $(CPPULIB) \ + $(SALLIB) \ + $(SALHELPERLIB) \ + $(UCBHELPERLIB) + +SHL1STDLIBS+=$(PKGCONFIG_LIBS) + +SHL1VERSIONMAP=$(SOLARENV)/src/component.map + +.ENDIF # "$(ENABLE_GNOMEVFS)"!="" +.ENDIF # L10N_framework + +.INCLUDE: target.mk + +ALLTAR : $(MISC)/ucpgvfs.component + +$(MISC)/ucpgvfs.component .ERRREMOVE : $(SOLARENV)/bin/createcomponent.xslt \ + ucpgvfs.component + $(XSLTPROC) --nonet --stringparam uri \ + '$(COMPONENTPREFIX_BASIS_NATIVE)$(SHL1TARGETN:f)' -o $@ \ + $(SOLARENV)/bin/createcomponent.xslt ucpgvfs.component diff --git a/ucb/source/ucp/gvfs/ucpgvfs.component b/ucb/source/ucp/gvfs/ucpgvfs.component new file mode 100644 index 000000000000..cec3e4d1e2b1 --- /dev/null +++ b/ucb/source/ucp/gvfs/ucpgvfs.component @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* 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. +* +**********************************************************************--> + +<component loader="com.sun.star.loader.SharedLibrary" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.GnomeVFSContentProvider"> + <service name="com.sun.star.ucb.GnomeVFSContentProvider"/> + </implementation> +</component> diff --git a/ucb/source/ucp/gvfs/ucpgvfs.xml b/ucb/source/ucp/gvfs/ucpgvfs.xml new file mode 100644 index 000000000000..e1f33708f525 --- /dev/null +++ b/ucb/source/ucp/gvfs/ucpgvfs.xml @@ -0,0 +1,113 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE module-description PUBLIC "-//StarOffice//DTD ComponentDescription 1.0//EN" "module-description.dtd"> +<module-description xmlns:xlink="http://www.w3.org/1999/xlink"> + + <module-name> + ucpgvfs + </module-name> + + <component-description> + <author> + Michael Meeks + </author> + <name> + com.sun.star.comp.ucb.GnomeVFSProvider + </name> + <description> + This component implements a Content Provider for the Universal + Content Broker. It provides access to the Gnome Virtual file system + </description> + <loader-name> + com.sun.star.loader.SharedLibrary + </loader-name> + <language> + c++ + </language> + <status value="final"/> + <supported-service> + com.sun.star.ucb.GnomeVFSContentProvider + </supported-service> + + <service-dependency> + com.sun.star.config.SpecialConfigManager + </service-dependency> + <service-dependency> + com.sun.star.configuration.ConfigurationAccess + </service-dependency> + <service-dependency> + com.sun.star.configuration.ConfigurationProvider + </service-dependency> + <service-dependency> + com.sun.star.script.Converter + </service-dependency> + <service-dependency> + com.sun.star.ucb.CachedDynamicResultSetStubFactory + </service-dependency> + <service-dependency> + com.sun.star.ucb.Store + </service-dependency> + </component-description> + + <project-build-dependency> sal </project-build-dependency> + <project-build-dependency> cppu </project-build-dependency> + <project-build-dependency> cppuhelper </project-build-dependency> + <project-build-dependency> ucbhelper </project-build-dependency> + + <runtime-module-dependency> sal3 </runtime-module-dependency> + <runtime-module-dependency> cppu3 </runtime-module-dependency> + <runtime-module-dependency> cppuhelper3$(COM) </runtime-module-dependency> + <runtime-module-dependency> ucbhelper4$(COM) </runtime-module-dependency> + + <type> com.sun.star.beans.Property </type> + <type> com.sun.star.beans.PropertyAttribute </type> + <type> com.sun.star.beans.PropertySetInfoChange </type> + <type> com.sun.star.beans.PropertyState </type> + <type> com.sun.star.beans.PropertyValue </type> + <type> com.sun.star.beans.XPropertiesChangeNotifier </type> + <type> com.sun.star.beans.XPropertyAccess </type> + <type> com.sun.star.beans.XPropertyContainer </type> + <type> com.sun.star.beans.XPropertySetInfo </type> + <type> com.sun.star.beans.XPropertySetInfoChangeNotifier </type> + <type> com.sun.star.container.XChild </type> + <type> com.sun.star.container.XHierarchicalNameAccess </type> + <type> com.sun.star.frame.ConfigManager </type> + <type> com.sun.star.io.XActiveDataSink </type> + <type> com.sun.star.io.XActiveDataStreamer </type> + <type> com.sun.star.io.XSeekable </type> + <type> com.sun.star.io.XStream </type> + <type> com.sun.star.lang.XMultiServiceFactory </type> + <type> com.sun.star.lang.XServiceInfo </type> + <type> com.sun.star.lang.XSingleServiceFactory </type> + <type> com.sun.star.lang.XTypeProvider </type> + <type> com.sun.star.registry.XRegistryKey </type> + <type> com.sun.star.script.XTypeConverter </type> + <type> com/sun/star/sdbc/ColumnValue </type> + <type> com.sun.star.sdbc.XCloseable </type> + <type> com.sun.star.sdbc.XResultSetMetaDataSupplier </type> + <type> com.sun.star.sdbc.XRow </type> + <type> com.sun.star.ucb.ContentAction </type> + <type> com.sun.star.ucb.ContentInfoAttribute </type> + <type> com.sun.star.ucb.FileSystemNotation </type> + <type> com.sun.star.ucb.InsertCommandArgument </type> + <type> com.sun.star.ucb.InteractiveBadTransferURLException </type> + <type> com.sun.star.ucb.ListAction </type> + <type> com.sun.star.ucb.NameClash </type> + <type> com.sun.star.ucb.NumberedSortingInfo </type> + <type> com.sun.star.ucb.OpenCommandArgument2 </type> + <type> com.sun.star.ucb.OpenMode </type> + <type> com.sun.star.ucb.TransferInfo </type> + <type> com.sun.star.ucb.WelcomeDynamicResultSetStruct </type> + <type> com.sun.star.ucb.XCachedDynamicResultSetStubFactory </type> + <type> com.sun.star.ucb.XCommandInfo </type> + <type> com.sun.star.ucb.XCommandProcessor </type> + <type> com.sun.star.ucb.XContentAccess </type> + <type> com.sun.star.ucb.XContentCreator </type> + <type> com.sun.star.ucb.XContentIdentifier </type> + <type> com.sun.star.ucb.XContentIdentifierFactory </type> + <type> com.sun.star.ucb.XContentProvider </type> + <type> com.sun.star.ucb.XDynamicResultSet </type> + <type> com.sun.star.ucb.XFileIdentifierConverter </type> + <type> com.sun.star.ucb.XPropertySetRegistryFactory </type> + <type> com.sun.star.ucb.XSourceInitialization </type> + <type> com.sun.star.uno.XWeak </type> +</module-description> diff --git a/ucb/source/ucp/hierarchy/dynamicresultset.cxx b/ucb/source/ucp/hierarchy/dynamicresultset.cxx new file mode 100644 index 000000000000..0cb8fec28e17 --- /dev/null +++ b/ucb/source/ucp/hierarchy/dynamicresultset.cxx @@ -0,0 +1,91 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + - This implementation is not a dynamic result set!!! It only implements + the necessary interfaces, but never recognizes/notifies changes!!! + + *************************************************************************/ +#include "hierarchydatasupplier.hxx" +#include "dynamicresultset.hxx" + +using namespace com::sun::star; +using namespace hierarchy_ucp; + +//========================================================================= +//========================================================================= +// +// DynamicResultSet Implementation. +// +//========================================================================= +//========================================================================= + +DynamicResultSet::DynamicResultSet( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + const rtl::Reference< HierarchyContent >& rxContent, + const ucb::OpenCommandArgument2& rCommand ) +: ResultSetImplHelper( rxSMgr, rCommand ), + m_xContent( rxContent ) +{ +} + +//========================================================================= +// +// Non-interface methods. +// +//========================================================================= + +void DynamicResultSet::initStatic() +{ + m_xResultSet1 + = new ::ucbhelper::ResultSet( + m_xSMgr, + m_aCommand.Properties, + new HierarchyResultSetDataSupplier( m_xSMgr, + m_xContent, + m_aCommand.Mode ) ); +} + +//========================================================================= +void DynamicResultSet::initDynamic() +{ + m_xResultSet1 + = new ::ucbhelper::ResultSet( + m_xSMgr, + m_aCommand.Properties, + new HierarchyResultSetDataSupplier( m_xSMgr, + m_xContent, + m_aCommand.Mode ) ); + m_xResultSet2 = m_xResultSet1; +} + diff --git a/ucb/source/ucp/hierarchy/dynamicresultset.hxx b/ucb/source/ucp/hierarchy/dynamicresultset.hxx new file mode 100644 index 000000000000..9553b299b0ad --- /dev/null +++ b/ucb/source/ucp/hierarchy/dynamicresultset.hxx @@ -0,0 +1,55 @@ +/************************************************************************* + * + * 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 _DYNAMICRESULTSET_HXX +#define _DYNAMICRESULTSET_HXX + +#include <rtl/ref.hxx> +#include <ucbhelper/resultsethelper.hxx> +#include "hierarchycontent.hxx" + +namespace hierarchy_ucp { + +class DynamicResultSet : public ::ucbhelper::ResultSetImplHelper +{ + rtl::Reference< HierarchyContent > m_xContent; + +private: + virtual void initStatic(); + virtual void initDynamic(); + +public: + DynamicResultSet( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + const rtl::Reference< HierarchyContent >& rxContent, + const com::sun::star::ucb::OpenCommandArgument2& rCommand ); +}; + +} + +#endif /* !_DYNAMICRESULTSET_HXX */ diff --git a/ucb/source/ucp/hierarchy/hierarchycontent.cxx b/ucb/source/ucp/hierarchy/hierarchycontent.cxx new file mode 100644 index 000000000000..2243692549e6 --- /dev/null +++ b/ucb/source/ucp/hierarchy/hierarchycontent.cxx @@ -0,0 +1,2009 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + - optimize transfer command. "Move" should be implementable much more + efficient! + + ************************************************************************** + + - Root Folder vs. 'normal' Folder + - root doesn't support command 'delete' + - root doesn't support command 'insert' + - root needs not created via XContentCreator - queryContent with root + folder id ( HIERARCHY_ROOT_FOLDER_URL ) always returns a value != 0 + - root has no parent. + + *************************************************************************/ +#include <osl/diagnose.h> + +#include "osl/doublecheckedlocking.h" +#include <rtl/ustring.h> +#include <rtl/ustring.hxx> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/beans/PropertyState.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/beans/XPropertyAccess.hpp> +#include <com/sun/star/lang/IllegalAccessException.hpp> +#include <com/sun/star/sdbc/XRow.hpp> +#include <com/sun/star/ucb/ContentInfoAttribute.hpp> +#include <com/sun/star/ucb/InsertCommandArgument.hpp> +#include <com/sun/star/ucb/InteractiveBadTransferURLException.hpp> +#include <com/sun/star/ucb/MissingPropertiesException.hpp> +#include <com/sun/star/ucb/NameClash.hpp> +#include <com/sun/star/ucb/NameClashException.hpp> +#include <com/sun/star/ucb/OpenCommandArgument2.hpp> +#include <com/sun/star/ucb/TransferInfo.hpp> +#include <com/sun/star/ucb/UnsupportedNameClashException.hpp> +#include <com/sun/star/ucb/XCommandInfo.hpp> +#include <com/sun/star/ucb/XPersistentPropertySet.hpp> +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/uno/Sequence.hxx> +#include <ucbhelper/contentidentifier.hxx> +#include <ucbhelper/propertyvalueset.hxx> +#include <ucbhelper/cancelcommandexecution.hxx> +#include "hierarchycontent.hxx" +#include "hierarchyprovider.hxx" +#include "dynamicresultset.hxx" +#include "hierarchyuri.hxx" + +#include "../inc/urihelper.hxx" + +using namespace com::sun::star; +using namespace hierarchy_ucp; + +//========================================================================= +//========================================================================= +// +// HierarchyContent Implementation. +// +//========================================================================= +//========================================================================= + +// static ( "virtual" ctor ) +HierarchyContent* HierarchyContent::create( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + HierarchyContentProvider* pProvider, + const uno::Reference< ucb::XContentIdentifier >& Identifier ) +{ + // Fail, if content does not exist. + HierarchyContentProperties aProps; + if ( !loadData( rxSMgr, pProvider, Identifier, aProps ) ) + return 0; + + return new HierarchyContent( rxSMgr, pProvider, Identifier, aProps ); +} + +//========================================================================= +// static ( "virtual" ctor ) +HierarchyContent* HierarchyContent::create( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + HierarchyContentProvider* pProvider, + const uno::Reference< ucb::XContentIdentifier >& Identifier, + const ucb::ContentInfo& Info ) +{ + if ( !Info.Type.getLength() ) + return 0; + + if ( !Info.Type.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( HIERARCHY_FOLDER_CONTENT_TYPE ) ) && + !Info.Type.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( HIERARCHY_LINK_CONTENT_TYPE ) ) ) + return 0; + +#if 0 + // Fail, if content does exist. + if ( hasData( rxSMgr, pProvider, Identifier ) ) + return 0; +#endif + + return new HierarchyContent( rxSMgr, pProvider, Identifier, Info ); +} + +//========================================================================= +HierarchyContent::HierarchyContent( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + HierarchyContentProvider* pProvider, + const uno::Reference< ucb::XContentIdentifier >& Identifier, + const HierarchyContentProperties& rProps ) +: ContentImplHelper( rxSMgr, pProvider, Identifier ), + m_aProps( rProps ), + m_eState( PERSISTENT ), + m_pProvider( pProvider ), + m_bCheckedReadOnly( false ), + m_bIsReadOnly( true ) +{ + setKind( Identifier ); +} + +//========================================================================= +HierarchyContent::HierarchyContent( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + HierarchyContentProvider* pProvider, + const uno::Reference< ucb::XContentIdentifier >& Identifier, + const ucb::ContentInfo& Info ) + : ContentImplHelper( rxSMgr, pProvider, Identifier ), + m_aProps( Info.Type.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( HIERARCHY_FOLDER_CONTENT_TYPE ) ) + ? HierarchyEntryData::FOLDER + : HierarchyEntryData::LINK ), + m_eState( TRANSIENT ), + m_pProvider( pProvider ), + m_bCheckedReadOnly( false ), + m_bIsReadOnly( true ) +{ + setKind( Identifier ); +} + +//========================================================================= +// virtual +HierarchyContent::~HierarchyContent() +{ +} + +//========================================================================= +// +// XInterface methods. +// +//========================================================================= + +// virtual +void SAL_CALL HierarchyContent::acquire() + throw( ) +{ + ContentImplHelper::acquire(); +} + +//========================================================================= +// virtual +void SAL_CALL HierarchyContent::release() + throw( ) +{ + ContentImplHelper::release(); +} + +//========================================================================= +// virtual +uno::Any SAL_CALL HierarchyContent::queryInterface( const uno::Type & rType ) + throw ( uno::RuntimeException ) +{ + uno::Any aRet = ContentImplHelper::queryInterface( rType ); + + if ( !aRet.hasValue() ) + { + // Note: isReadOnly may be relative expensive. So avoid calling it + // unless it is really necessary. + aRet = cppu::queryInterface( + rType, static_cast< ucb::XContentCreator * >( this ) ); + if ( aRet.hasValue() ) + { + if ( !isFolder() || isReadOnly() ) + return uno::Any(); + } + } + + return aRet; +} + +//========================================================================= +// +// XTypeProvider methods. +// +//========================================================================= + +XTYPEPROVIDER_COMMON_IMPL( HierarchyContent ); + +//========================================================================= +// virtual +uno::Sequence< uno::Type > SAL_CALL HierarchyContent::getTypes() + throw( uno::RuntimeException ) +{ + cppu::OTypeCollection * pCollection = 0; + + if ( isFolder() && !isReadOnly() ) + { + static cppu::OTypeCollection* pFolderTypes = 0; + + pCollection = pFolderTypes; + if ( !pCollection ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + + pCollection = pFolderTypes; + if ( !pCollection ) + { + static cppu::OTypeCollection aCollection( + CPPU_TYPE_REF( lang::XTypeProvider ), + CPPU_TYPE_REF( lang::XServiceInfo ), + CPPU_TYPE_REF( lang::XComponent ), + CPPU_TYPE_REF( ucb::XContent ), + CPPU_TYPE_REF( ucb::XCommandProcessor ), + CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ), + CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ), + CPPU_TYPE_REF( beans::XPropertyContainer ), + CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ), + CPPU_TYPE_REF( container::XChild ), + CPPU_TYPE_REF( ucb::XContentCreator ) ); // !! + pCollection = &aCollection; + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + pFolderTypes = pCollection; + } + } + else { + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + } + } + else + { + static cppu::OTypeCollection* pDocumentTypes = 0; + + pCollection = pDocumentTypes; + if ( !pCollection ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + + pCollection = pDocumentTypes; + if ( !pCollection ) + { + static cppu::OTypeCollection aCollection( + CPPU_TYPE_REF( lang::XTypeProvider ), + CPPU_TYPE_REF( lang::XServiceInfo ), + CPPU_TYPE_REF( lang::XComponent ), + CPPU_TYPE_REF( ucb::XContent ), + CPPU_TYPE_REF( ucb::XCommandProcessor ), + CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ), + CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ), + CPPU_TYPE_REF( beans::XPropertyContainer ), + CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ), + CPPU_TYPE_REF( container::XChild ) ); + pCollection = &aCollection; + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + pDocumentTypes = pCollection; + } + } + else { + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + } + } + + return (*pCollection).getTypes(); +} + +//========================================================================= +// +// XServiceInfo methods. +// +//========================================================================= + +// virtual +rtl::OUString SAL_CALL HierarchyContent::getImplementationName() + throw( uno::RuntimeException ) +{ + return rtl::OUString::createFromAscii( + "com.sun.star.comp.ucb.HierarchyContent" ); +} + +//========================================================================= +// virtual +uno::Sequence< rtl::OUString > SAL_CALL +HierarchyContent::getSupportedServiceNames() + throw( uno::RuntimeException ) +{ + uno::Sequence< rtl::OUString > aSNS( 1 ); + + if ( m_eKind == LINK ) + aSNS.getArray()[ 0 ] = rtl::OUString::createFromAscii( + HIERARCHY_LINK_CONTENT_SERVICE_NAME ); + else if ( m_eKind == FOLDER ) + aSNS.getArray()[ 0 ] = rtl::OUString::createFromAscii( + HIERARCHY_FOLDER_CONTENT_SERVICE_NAME ); + else + aSNS.getArray()[ 0 ] = rtl::OUString::createFromAscii( + HIERARCHY_ROOT_FOLDER_CONTENT_SERVICE_NAME ); + + return aSNS; +} + +//========================================================================= +// +// XContent methods. +// +//========================================================================= + +// virtual +rtl::OUString SAL_CALL HierarchyContent::getContentType() + throw( uno::RuntimeException ) +{ + return m_aProps.getContentType(); +} + +//========================================================================= +// virtual +uno::Reference< ucb::XContentIdentifier > SAL_CALL +HierarchyContent::getIdentifier() + throw( uno::RuntimeException ) +{ + // Transient? + if ( m_eState == TRANSIENT ) + { + // Transient contents have no identifier. + return uno::Reference< ucb::XContentIdentifier >(); + } + + return ContentImplHelper::getIdentifier(); +} + +//========================================================================= +// +// XCommandProcessor methods. +// +//========================================================================= + +// virtual +uno::Any SAL_CALL HierarchyContent::execute( + const ucb::Command& aCommand, + sal_Int32 /*CommandId*/, + const uno::Reference< ucb::XCommandEnvironment >& Environment ) + throw( uno::Exception, + ucb::CommandAbortedException, + uno::RuntimeException ) +{ + uno::Any aRet; + + if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "getPropertyValues" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // getPropertyValues + ////////////////////////////////////////////////////////////////// + + uno::Sequence< beans::Property > Properties; + if ( !( aCommand.Argument >>= Properties ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Wrong argument type!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + aRet <<= getPropertyValues( Properties ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "setPropertyValues" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // setPropertyValues + ////////////////////////////////////////////////////////////////// + + uno::Sequence< beans::PropertyValue > aProperties; + if ( !( aCommand.Argument >>= aProperties ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Wrong argument type!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + if ( !aProperties.getLength() ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "No properties!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + aRet <<= setPropertyValues( aProperties, Environment ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "getPropertySetInfo" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // getPropertySetInfo + ////////////////////////////////////////////////////////////////// + + aRet <<= getPropertySetInfo( Environment ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "getCommandInfo" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // getCommandInfo + ////////////////////////////////////////////////////////////////// + + aRet <<= getCommandInfo( Environment ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "open" ) ) && isFolder() ) + { + ////////////////////////////////////////////////////////////////// + // open command for a folder content + ////////////////////////////////////////////////////////////////// + + ucb::OpenCommandArgument2 aOpenCommand; + if ( !( aCommand.Argument >>= aOpenCommand ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Wrong argument type!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + uno::Reference< ucb::XDynamicResultSet > xSet + = new DynamicResultSet( m_xSMgr, this, aOpenCommand ); + aRet <<= xSet; + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "insert" ) ) && + ( m_eKind != ROOT ) && !isReadOnly() ) + { + ////////////////////////////////////////////////////////////////// + // insert + // ( Not available at root folder ) + ////////////////////////////////////////////////////////////////// + + ucb::InsertCommandArgument aArg; + if ( !( aCommand.Argument >>= aArg ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Wrong argument type!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + sal_Int32 nNameClash = aArg.ReplaceExisting + ? ucb::NameClash::OVERWRITE + : ucb::NameClash::ERROR; + insert( nNameClash, Environment ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "delete" ) ) && + ( m_eKind != ROOT ) && !isReadOnly() ) + { + ////////////////////////////////////////////////////////////////// + // delete + // ( Not available at root folder ) + ////////////////////////////////////////////////////////////////// + + sal_Bool bDeletePhysical = sal_False; + aCommand.Argument >>= bDeletePhysical; + destroy( bDeletePhysical, Environment ); + + // Remove own and all children's persistent data. + if ( !removeData() ) + { + uno::Any aProps + = uno::makeAny( + beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Uri")), + -1, + uno::makeAny(m_xIdentifier-> + getContentIdentifier()), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_WRITE, + uno::Sequence< uno::Any >(&aProps, 1), + Environment, + rtl::OUString::createFromAscii( + "Cannot remove persistent data!" ), + this ); + // Unreachable + } + + // Remove own and all children's Additional Core Properties. + removeAdditionalPropertySet( sal_True ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "transfer" ) ) && + isFolder() && !isReadOnly() ) + { + ////////////////////////////////////////////////////////////////// + // transfer + // ( Not available at link objects ) + ////////////////////////////////////////////////////////////////// + + ucb::TransferInfo aInfo; + if ( !( aCommand.Argument >>= aInfo ) ) + { + OSL_ENSURE( sal_False, "Wrong argument type!" ); + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Wrong argument type!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + transfer( aInfo, Environment ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "createNewContent" ) ) && + isFolder() && !isReadOnly() ) + { + ////////////////////////////////////////////////////////////////// + // createNewContent + // ( Not available at link objects ) + ////////////////////////////////////////////////////////////////// + + ucb::ContentInfo aInfo; + if ( !( aCommand.Argument >>= aInfo ) ) + { + OSL_ENSURE( sal_False, "Wrong argument type!" ); + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Wrong argument type!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + aRet <<= createNewContent( aInfo ); + } + else + { + ////////////////////////////////////////////////////////////////// + // Unsupported command + ////////////////////////////////////////////////////////////////// + + ucbhelper::cancelCommandExecution( + uno::makeAny( ucb::UnsupportedCommandException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ) ) ), + Environment ); + // Unreachable + } + + return aRet; +} + +//========================================================================= +// virtual +void SAL_CALL HierarchyContent::abort( sal_Int32 /*CommandId*/ ) + throw( uno::RuntimeException ) +{ + // @@@ Generally, no action takes much time... +} + +//========================================================================= +// +// XContentCreator methods. +// +//========================================================================= + +// virtual +uno::Sequence< ucb::ContentInfo > SAL_CALL +HierarchyContent::queryCreatableContentsInfo() + throw( uno::RuntimeException ) +{ + return m_aProps.getCreatableContentsInfo(); +} + +//========================================================================= +// virtual +uno::Reference< ucb::XContent > SAL_CALL +HierarchyContent::createNewContent( const ucb::ContentInfo& Info ) + throw( uno::RuntimeException ) +{ + if ( isFolder() ) + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + if ( !Info.Type.getLength() ) + return uno::Reference< ucb::XContent >(); + + sal_Bool bCreateFolder = + Info.Type.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( HIERARCHY_FOLDER_CONTENT_TYPE ) ); + + if ( !bCreateFolder && + !Info.Type.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( HIERARCHY_LINK_CONTENT_TYPE ) ) ) + return uno::Reference< ucb::XContent >(); + + rtl::OUString aURL = m_xIdentifier->getContentIdentifier(); + + OSL_ENSURE( aURL.getLength() > 0, + "HierarchyContent::createNewContent - empty identifier!" ); + + if ( ( aURL.lastIndexOf( '/' ) + 1 ) != aURL.getLength() ) + aURL += rtl::OUString::createFromAscii( "/" ); + + if ( bCreateFolder ) + aURL += rtl::OUString::createFromAscii( "New_Folder" ); + else + aURL += rtl::OUString::createFromAscii( "New_Link" ); + + uno::Reference< ucb::XContentIdentifier > xId + = new ::ucbhelper::ContentIdentifier( m_xSMgr, aURL ); + + return create( m_xSMgr, m_pProvider, xId, Info ); + } + else + { + OSL_ENSURE( sal_False, + "createNewContent called on non-folder object!" ); + return uno::Reference< ucb::XContent >(); + } +} + +//========================================================================= +// virtual +rtl::OUString HierarchyContent::getParentURL() +{ + HierarchyUri aUri( m_xIdentifier->getContentIdentifier() ); + return aUri.getParentUri(); +} + +//========================================================================= +//static +sal_Bool HierarchyContent::hasData( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + HierarchyContentProvider* pProvider, + const uno::Reference< ucb::XContentIdentifier >& Identifier ) +{ + rtl::OUString aURL = Identifier->getContentIdentifier(); + + // Am I a root folder? + HierarchyUri aUri( aURL ); + if ( aUri.isRootFolder() ) + { + // hasData must always return 'true' for root folder + // even if no persistent data exist!!! + return sal_True; + } + + return HierarchyEntry( rxSMgr, pProvider, aURL ).hasData(); +} + +//========================================================================= +//static +sal_Bool HierarchyContent::loadData( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + HierarchyContentProvider* pProvider, + const uno::Reference< ucb::XContentIdentifier >& Identifier, + HierarchyContentProperties& rProps ) +{ + rtl::OUString aURL = Identifier->getContentIdentifier(); + + // Am I a root folder? + HierarchyUri aUri( aURL ); + if ( aUri.isRootFolder() ) + { + rProps = HierarchyContentProperties( HierarchyEntryData::FOLDER ); + } + else + { + HierarchyEntry aEntry( rxSMgr, pProvider, aURL ); + HierarchyEntryData aData; + if ( !aEntry.getData( aData ) ) + return sal_False; + + rProps = HierarchyContentProperties( aData ); + } + return sal_True; +} + +//========================================================================= +sal_Bool HierarchyContent::storeData() +{ + HierarchyEntry aEntry( + m_xSMgr, m_pProvider, m_xIdentifier->getContentIdentifier() ); + return aEntry.setData( m_aProps.getHierarchyEntryData(), sal_True ); +} + +//========================================================================= +sal_Bool HierarchyContent::renameData( + const uno::Reference< ucb::XContentIdentifier >& xOldId, + const uno::Reference< ucb::XContentIdentifier >& xNewId ) +{ + HierarchyEntry aEntry( + m_xSMgr, m_pProvider, xOldId->getContentIdentifier() ); + return aEntry.move( xNewId->getContentIdentifier(), + m_aProps.getHierarchyEntryData() ); +} + +//========================================================================= +sal_Bool HierarchyContent::removeData() +{ + HierarchyEntry aEntry( + m_xSMgr, m_pProvider, m_xIdentifier->getContentIdentifier() ); + return aEntry.remove(); +} + +//========================================================================= +void HierarchyContent::setKind( + const uno::Reference< ucb::XContentIdentifier >& Identifier ) +{ + if ( m_aProps.getIsFolder() ) + { + // Am I a root folder? + HierarchyUri aUri( Identifier->getContentIdentifier() ); + if ( aUri.isRootFolder() ) + m_eKind = ROOT; + else + m_eKind = FOLDER; + } + else + m_eKind = LINK; +} + +//========================================================================= +bool HierarchyContent::isReadOnly() +{ + if ( !m_bCheckedReadOnly ) + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + if ( !m_bCheckedReadOnly ) + { + m_bCheckedReadOnly = true; + m_bIsReadOnly = true; + + HierarchyUri aUri( m_xIdentifier->getContentIdentifier() ); + uno::Reference< lang::XMultiServiceFactory > xConfigProv + = m_pProvider->getConfigProvider( aUri.getService() ); + if ( xConfigProv.is() ) + { + uno::Sequence< rtl::OUString > aNames + = xConfigProv->getAvailableServiceNames(); + sal_Int32 nCount = aNames.getLength(); + for ( sal_Int32 n = 0; n < nCount; ++n ) + { + if ( aNames[ n ].equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( + "com.sun.star.ucb.HierarchyDataReadWriteAccess" + ) ) ) + { + m_bIsReadOnly = false; + break; + } + } + } + } + } + + return m_bIsReadOnly; +} + +//========================================================================= +uno::Reference< ucb::XContentIdentifier > +HierarchyContent::makeNewIdentifier( const rtl::OUString& rTitle ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + // Assemble new content identifier... + HierarchyUri aUri( m_xIdentifier->getContentIdentifier() ); + rtl::OUString aNewURL = aUri.getParentUri(); + aNewURL += rtl::OUString::createFromAscii( "/" ); + aNewURL += ::ucb_impl::urihelper::encodeSegment( rTitle ); + + return uno::Reference< ucb::XContentIdentifier >( + new ::ucbhelper::ContentIdentifier( m_xSMgr, aNewURL ) ); +} + +//========================================================================= +void HierarchyContent::queryChildren( HierarchyContentRefList& rChildren ) +{ + if ( ( m_eKind != FOLDER ) && ( m_eKind != ROOT ) ) + return; + + // Obtain a list with a snapshot of all currently instanciated contents + // from provider and extract the contents which are direct children + // of this content. + + ::ucbhelper::ContentRefList aAllContents; + m_xProvider->queryExistingContents( aAllContents ); + + rtl::OUString aURL = m_xIdentifier->getContentIdentifier(); + sal_Int32 nURLPos = aURL.lastIndexOf( '/' ); + + if ( nURLPos != ( aURL.getLength() - 1 ) ) + { + // No trailing slash found. Append. + aURL += rtl::OUString::createFromAscii( "/" ); + } + + sal_Int32 nLen = aURL.getLength(); + + ::ucbhelper::ContentRefList::const_iterator it = aAllContents.begin(); + ::ucbhelper::ContentRefList::const_iterator end = aAllContents.end(); + + while ( it != end ) + { + ::ucbhelper::ContentImplHelperRef xChild = (*it); + rtl::OUString aChildURL + = xChild->getIdentifier()->getContentIdentifier(); + + // Is aURL a prefix of aChildURL? + if ( ( aChildURL.getLength() > nLen ) && + ( aChildURL.compareTo( aURL, nLen ) == 0 ) ) + { + sal_Int32 nPos = nLen; + nPos = aChildURL.indexOf( '/', nPos ); + + if ( ( nPos == -1 ) || + ( nPos == ( aChildURL.getLength() - 1 ) ) ) + { + // No further slashes/ only a final slash. It's a child! + rChildren.push_back( + HierarchyContentRef( + static_cast< HierarchyContent * >( xChild.get() ) ) ); + } + } + ++it; + } +} + +//========================================================================= +sal_Bool HierarchyContent::exchangeIdentity( + const uno::Reference< ucb::XContentIdentifier >& xNewId ) +{ + if ( !xNewId.is() ) + return sal_False; + + osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); + + uno::Reference< ucb::XContent > xThis = this; + + // Already persistent? + if ( m_eState != PERSISTENT ) + { + OSL_ENSURE( sal_False, + "HierarchyContent::exchangeIdentity - Not persistent!" ); + return sal_False; + } + + // Am I the root folder? + if ( m_eKind == ROOT ) + { + OSL_ENSURE( sal_False, "HierarchyContent::exchangeIdentity - " + "Not supported by root folder!" ); + return sal_False; + } + + // Exchange own identitity. + + // Fail, if a content with given id already exists. + if ( !hasData( xNewId ) ) + { + rtl::OUString aOldURL = m_xIdentifier->getContentIdentifier(); + + aGuard.clear(); + if ( exchange( xNewId ) ) + { + if ( m_eKind == FOLDER ) + { + // Process instanciated children... + + HierarchyContentRefList aChildren; + queryChildren( aChildren ); + + HierarchyContentRefList::const_iterator it = aChildren.begin(); + HierarchyContentRefList::const_iterator end = aChildren.end(); + + while ( it != end ) + { + HierarchyContentRef xChild = (*it); + + // Create new content identifier for the child... + uno::Reference< ucb::XContentIdentifier > xOldChildId + = xChild->getIdentifier(); + rtl::OUString aOldChildURL + = xOldChildId->getContentIdentifier(); + rtl::OUString aNewChildURL + = aOldChildURL.replaceAt( + 0, + aOldURL.getLength(), + xNewId->getContentIdentifier() ); + uno::Reference< ucb::XContentIdentifier > xNewChildId + = new ::ucbhelper::ContentIdentifier( + m_xSMgr, aNewChildURL ); + + if ( !xChild->exchangeIdentity( xNewChildId ) ) + return sal_False; + + ++it; + } + } + return sal_True; + } + } + + OSL_ENSURE( sal_False, + "HierarchyContent::exchangeIdentity - " + "Panic! Cannot exchange identity!" ); + return sal_False; +} + +//========================================================================= +// static +uno::Reference< sdbc::XRow > HierarchyContent::getPropertyValues( + const uno::Reference< lang::XMultiServiceFactory >& rSMgr, + const uno::Sequence< beans::Property >& rProperties, + const HierarchyContentProperties& rData, + HierarchyContentProvider* pProvider, + const rtl::OUString& rContentId ) +{ + // Note: Empty sequence means "get values of all supported properties". + + rtl::Reference< ::ucbhelper::PropertyValueSet > xRow + = new ::ucbhelper::PropertyValueSet( rSMgr ); + + sal_Int32 nCount = rProperties.getLength(); + if ( nCount ) + { + uno::Reference< beans::XPropertySet > xAdditionalPropSet; + sal_Bool bTriedToGetAdditonalPropSet = sal_False; + + const beans::Property* pProps = rProperties.getConstArray(); + for ( sal_Int32 n = 0; n < nCount; ++n ) + { + const beans::Property& rProp = pProps[ n ]; + + // Process Core properties. + + if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) ) + { + xRow->appendString ( rProp, rData.getContentType() ); + } + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "Title" ) ) ) + { + xRow->appendString ( rProp, rData.getTitle() ); + } + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) ) + { + xRow->appendBoolean( rProp, rData.getIsDocument() ); + } + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) ) + { + xRow->appendBoolean( rProp, rData.getIsFolder() ); + } + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "CreatableContentsInfo" ) ) ) + { + xRow->appendObject( + rProp, uno::makeAny( rData.getCreatableContentsInfo() ) ); + } + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "TargetURL" ) ) ) + { + // TargetURL is only supported by links. + + if ( rData.getIsDocument() ) + xRow->appendString( rProp, rData.getTargetURL() ); + else + xRow->appendVoid( rProp ); + } + else + { + // Not a Core Property! Maybe it's an Additional Core Property?! + + if ( !bTriedToGetAdditonalPropSet && !xAdditionalPropSet.is() ) + { + xAdditionalPropSet + = uno::Reference< beans::XPropertySet >( + pProvider->getAdditionalPropertySet( rContentId, + sal_False ), + uno::UNO_QUERY ); + bTriedToGetAdditonalPropSet = sal_True; + } + + if ( xAdditionalPropSet.is() ) + { + if ( !xRow->appendPropertySetValue( + xAdditionalPropSet, + rProp ) ) + { + // Append empty entry. + xRow->appendVoid( rProp ); + } + } + else + { + // Append empty entry. + xRow->appendVoid( rProp ); + } + } + } + } + else + { + // Append all Core Properties. + xRow->appendString ( + beans::Property( rtl::OUString::createFromAscii( "ContentType" ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ), + rData.getContentType() ); + xRow->appendString ( + beans::Property( rtl::OUString::createFromAscii( "Title" ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + // @@@ Might actually be read-only! + beans::PropertyAttribute::BOUND ), + rData.getTitle() ); + xRow->appendBoolean( + beans::Property( rtl::OUString::createFromAscii( "IsDocument" ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ), + rData.getIsDocument() ); + xRow->appendBoolean( + beans::Property( rtl::OUString::createFromAscii( "IsFolder" ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ), + rData.getIsFolder() ); + + if ( rData.getIsDocument() ) + xRow->appendString( + beans::Property( rtl::OUString::createFromAscii( "TargetURL" ), + -1, + getCppuType( + static_cast< const rtl::OUString * >( 0 ) ), + // @@@ Might actually be read-only! + beans::PropertyAttribute::BOUND ), + rData.getTargetURL() ); + xRow->appendObject( + beans::Property( + rtl::OUString::createFromAscii( "CreatableContentsInfo" ), + -1, + getCppuType( static_cast< + const uno::Sequence< ucb::ContentInfo > * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ), + uno::makeAny( rData.getCreatableContentsInfo() ) ); + + // Append all Additional Core Properties. + + uno::Reference< beans::XPropertySet > xSet( + pProvider->getAdditionalPropertySet( rContentId, sal_False ), + uno::UNO_QUERY ); + xRow->appendPropertySet( xSet ); + } + + return uno::Reference< sdbc::XRow >( xRow.get() ); +} + +//========================================================================= +uno::Reference< sdbc::XRow > HierarchyContent::getPropertyValues( + const uno::Sequence< beans::Property >& rProperties ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + return getPropertyValues( m_xSMgr, + rProperties, + m_aProps, + m_pProvider, + m_xIdentifier->getContentIdentifier() ); +} + +//========================================================================= +uno::Sequence< uno::Any > HierarchyContent::setPropertyValues( + const uno::Sequence< beans::PropertyValue >& rValues, + const uno::Reference< ucb::XCommandEnvironment > & xEnv ) + throw( uno::Exception ) +{ + osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); + + uno::Sequence< uno::Any > aRet( rValues.getLength() ); + uno::Sequence< beans::PropertyChangeEvent > aChanges( rValues.getLength() ); + sal_Int32 nChanged = 0; + + beans::PropertyChangeEvent aEvent; + aEvent.Source = static_cast< cppu::OWeakObject * >( this ); + aEvent.Further = sal_False; +// aEvent.PropertyName = + aEvent.PropertyHandle = -1; +// aEvent.OldValue = +// aEvent.NewValue = + + const beans::PropertyValue* pValues = rValues.getConstArray(); + sal_Int32 nCount = rValues.getLength(); + + uno::Reference< ucb::XPersistentPropertySet > xAdditionalPropSet; + sal_Bool bTriedToGetAdditonalPropSet = sal_False; + + sal_Bool bExchange = sal_False; + rtl::OUString aOldTitle; + rtl::OUString aOldName; + sal_Int32 nTitlePos = -1; + + for ( sal_Int32 n = 0; n < nCount; ++n ) + { + const beans::PropertyValue& rValue = pValues[ n ]; + + if ( rValue.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) ) + { + // Read-only property! + aRet[ n ] <<= lang::IllegalAccessException( + rtl::OUString::createFromAscii( + "Property is read-only!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + else if ( rValue.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) ) + { + // Read-only property! + aRet[ n ] <<= lang::IllegalAccessException( + rtl::OUString::createFromAscii( + "Property is read-only!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + else if ( rValue.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) ) + { + // Read-only property! + aRet[ n ] <<= lang::IllegalAccessException( + rtl::OUString::createFromAscii( + "Property is read-only!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + else if ( rValue.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "CreatableContentsInfo" ) ) ) + { + // Read-only property! + aRet[ n ] <<= lang::IllegalAccessException( + rtl::OUString::createFromAscii( + "Property is read-only!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + else if ( rValue.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "Title" ) ) ) + { + if ( isReadOnly() ) + { + aRet[ n ] <<= lang::IllegalAccessException( + rtl::OUString::createFromAscii( + "Property is read-only!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + else + { + rtl::OUString aNewValue; + if ( rValue.Value >>= aNewValue ) + { + // No empty titles! + if ( aNewValue.getLength() > 0 ) + { + if ( aNewValue != m_aProps.getTitle() ) + { + // modified title -> modified URL -> exchange ! + if ( m_eState == PERSISTENT ) + bExchange = sal_True; + + aOldTitle = m_aProps.getTitle(); + aOldName = m_aProps.getName(); + + m_aProps.setTitle( aNewValue ); + m_aProps.setName( + ::ucb_impl::urihelper::encodeSegment( + aNewValue ) ); + + // property change event will be set later... + + // remember position within sequence of values + // (for error handling). + nTitlePos = n; + } + } + else + { + aRet[ n ] <<= lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Empty title not allowed!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ); + } + } + else + { + aRet[ n ] <<= beans::IllegalTypeException( + rtl::OUString::createFromAscii( + "Property value has wrong type!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + } + } + else if ( rValue.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "TargetURL" ) ) ) + { + if ( isReadOnly() ) + { + aRet[ n ] <<= lang::IllegalAccessException( + rtl::OUString::createFromAscii( + "Property is read-only!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + else + { + // TargetURL is only supported by links. + + if ( m_eKind == LINK ) + { + rtl::OUString aNewValue; + if ( rValue.Value >>= aNewValue ) + { + // No empty target URL's! + if ( aNewValue.getLength() > 0 ) + { + if ( aNewValue != m_aProps.getTargetURL() ) + { + aEvent.PropertyName = rValue.Name; + aEvent.OldValue + = uno::makeAny( m_aProps.getTargetURL() ); + aEvent.NewValue + = uno::makeAny( aNewValue ); + + aChanges.getArray()[ nChanged ] = aEvent; + + m_aProps.setTargetURL( aNewValue ); + nChanged++; + } + } + else + { + aRet[ n ] <<= lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Empty target URL not allowed!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ); + } + } + else + { + aRet[ n ] <<= beans::IllegalTypeException( + rtl::OUString::createFromAscii( + "Property value has wrong type!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + } + else + { + aRet[ n ] <<= beans::UnknownPropertyException( + rtl::OUString::createFromAscii( + "TargetURL only supported by links!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + } + } + else + { + // Not a Core Property! Maybe it's an Additional Core Property?! + + if ( !bTriedToGetAdditonalPropSet && !xAdditionalPropSet.is() ) + { + xAdditionalPropSet = getAdditionalPropertySet( sal_False ); + bTriedToGetAdditonalPropSet = sal_True; + } + + if ( xAdditionalPropSet.is() ) + { + try + { + uno::Any aOldValue = xAdditionalPropSet->getPropertyValue( + rValue.Name ); + if ( aOldValue != rValue.Value ) + { + xAdditionalPropSet->setPropertyValue( + rValue.Name, rValue.Value ); + + aEvent.PropertyName = rValue.Name; + aEvent.OldValue = aOldValue; + aEvent.NewValue = rValue.Value; + + aChanges.getArray()[ nChanged ] = aEvent; + nChanged++; + } + } + catch ( beans::UnknownPropertyException const & e ) + { + aRet[ n ] <<= e; + } + catch ( lang::WrappedTargetException const & e ) + { + aRet[ n ] <<= e; + } + catch ( beans::PropertyVetoException const & e ) + { + aRet[ n ] <<= e; + } + catch ( lang::IllegalArgumentException const & e ) + { + aRet[ n ] <<= e; + } + } + else + { + aRet[ n ] <<= uno::Exception( + rtl::OUString::createFromAscii( + "No property set for storing the value!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + } + } + + if ( bExchange ) + { + uno::Reference< ucb::XContentIdentifier > xOldId + = m_xIdentifier; + uno::Reference< ucb::XContentIdentifier > xNewId + = makeNewIdentifier( m_aProps.getTitle() ); + + aGuard.clear(); + if ( exchangeIdentity( xNewId ) ) + { + // Adapt persistent data. + renameData( xOldId, xNewId ); + + // Adapt Additional Core Properties. + renameAdditionalPropertySet( xOldId->getContentIdentifier(), + xNewId->getContentIdentifier(), + sal_True ); + } + else + { + // Roll-back. + m_aProps.setTitle( aOldTitle ); + m_aProps.setName ( aOldName ); + + aOldTitle = aOldName = rtl::OUString(); + + // Set error . + aRet[ nTitlePos ] <<= uno::Exception( + rtl::OUString::createFromAscii( "Exchange failed!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + } + + if ( aOldTitle.getLength() ) + { + aEvent.PropertyName = rtl::OUString::createFromAscii( "Title" ); + aEvent.OldValue = uno::makeAny( aOldTitle ); + aEvent.NewValue = uno::makeAny( m_aProps.getTitle() ); + + aChanges.getArray()[ nChanged ] = aEvent; + nChanged++; + } + + if ( nChanged > 0 ) + { + // Save changes, if content was already made persistent. + if ( !bExchange && ( m_eState == PERSISTENT ) ) + { + if ( !storeData() ) + { + uno::Any aProps + = uno::makeAny( + beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Uri")), + -1, + uno::makeAny(m_xIdentifier-> + getContentIdentifier()), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_WRITE, + uno::Sequence< uno::Any >(&aProps, 1), + xEnv, + rtl::OUString::createFromAscii( + "Cannot store persistent data!" ), + this ); + // Unreachable + } + } + + aChanges.realloc( nChanged ); + + aGuard.clear(); + notifyPropertiesChange( aChanges ); + } + + return aRet; +} + +//========================================================================= +void HierarchyContent::insert( sal_Int32 nNameClashResolve, + const uno::Reference< + ucb::XCommandEnvironment > & xEnv ) + throw( uno::Exception ) +{ + osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); + + // Am I the root folder? + if ( m_eKind == ROOT ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( ucb::UnsupportedCommandException( + rtl::OUString::createFromAscii( + "Not supported by root folder!" ), + static_cast< cppu::OWeakObject * >( this ) ) ), + xEnv ); + // Unreachable + } + + // Check, if all required properties were set. + if ( m_aProps.getTitle().getLength() == 0 ) + { + uno::Sequence< rtl::OUString > aProps( 1 ); + aProps[ 0 ] = rtl::OUString::createFromAscii( "Title" ); + ucbhelper::cancelCommandExecution( + uno::makeAny( ucb::MissingPropertiesException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + aProps ) ), + xEnv ); + // Unreachable + } + + // Assemble new content identifier... + + uno::Reference< ucb::XContentIdentifier > xId + = makeNewIdentifier( m_aProps.getTitle() ); + + // Handle possible name clash... + + switch ( nNameClashResolve ) + { + // fail. + case ucb::NameClash::ERROR: + if ( hasData( xId ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( + ucb::NameClashException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + task::InteractionClassification_ERROR, + m_aProps.getTitle() ) ), + xEnv ); + // Unreachable + } + break; + + // replace existing object. + case ucb::NameClash::OVERWRITE: + break; + + // "invent" a new valid title. + case ucb::NameClash::RENAME: + if ( hasData( xId ) ) + { + sal_Int32 nTry = 0; + + do + { + rtl::OUString aNewId = xId->getContentIdentifier(); + aNewId += rtl::OUString::createFromAscii( "_" ); + aNewId += rtl::OUString::valueOf( ++nTry ); + xId = new ::ucbhelper::ContentIdentifier( m_xSMgr, aNewId ); + } + while ( hasData( xId ) && ( nTry < 1000 ) ); + + if ( nTry == 1000 ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( + ucb::UnsupportedNameClashException( + rtl::OUString::createFromAscii( + "Unable to resolve name clash!" ), + static_cast< cppu::OWeakObject * >( this ), + nNameClashResolve ) ), + xEnv ); + // Unreachable + } + else + { + rtl::OUString aNewTitle( m_aProps.getTitle() ); + aNewTitle += rtl::OUString::createFromAscii( "_" ); + aNewTitle += rtl::OUString::valueOf( nTry ); + m_aProps.setTitle( aNewTitle ); + } + } + break; + + case ucb::NameClash::KEEP: // deprecated + case ucb::NameClash::ASK: + default: + if ( hasData( xId ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( + ucb::UnsupportedNameClashException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + nNameClashResolve ) ), + xEnv ); + // Unreachable + } + break; + } + + // Identifier changed? + sal_Bool bNewId = ( xId->getContentIdentifier() + != m_xIdentifier->getContentIdentifier() ); + m_xIdentifier = xId; + + if ( !storeData() ) + { + uno::Any aProps + = uno::makeAny(beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Uri")), + -1, + uno::makeAny(m_xIdentifier-> + getContentIdentifier()), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_WRITE, + uno::Sequence< uno::Any >(&aProps, 1), + xEnv, + rtl::OUString::createFromAscii( "Cannot store persistent data!" ), + this ); + // Unreachable + } + + m_eState = PERSISTENT; + + if ( bNewId ) + { + aGuard.clear(); + inserted(); + } +} + +//========================================================================= +void HierarchyContent::destroy( sal_Bool bDeletePhysical, + const uno::Reference< + ucb::XCommandEnvironment > & xEnv ) + throw( uno::Exception ) +{ + // @@@ take care about bDeletePhysical -> trashcan support + + osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); + + uno::Reference< ucb::XContent > xThis = this; + + // Persistent? + if ( m_eState != PERSISTENT ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( ucb::UnsupportedCommandException( + rtl::OUString::createFromAscii( + "Not persistent!" ), + static_cast< cppu::OWeakObject * >( this ) ) ), + xEnv ); + // Unreachable + } + + // Am I the root folder? + if ( m_eKind == ROOT ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( ucb::UnsupportedCommandException( + rtl::OUString::createFromAscii( + "Not supported by root folder!" ), + static_cast< cppu::OWeakObject * >( this ) ) ), + xEnv ); + // Unreachable + } + + m_eState = DEAD; + + aGuard.clear(); + deleted(); + + if ( m_eKind == FOLDER ) + { + // Process instanciated children... + + HierarchyContentRefList aChildren; + queryChildren( aChildren ); + + HierarchyContentRefList::const_iterator it = aChildren.begin(); + HierarchyContentRefList::const_iterator end = aChildren.end(); + + while ( it != end ) + { + (*it)->destroy( bDeletePhysical, xEnv ); + ++it; + } + } +} + +//========================================================================= +void HierarchyContent::transfer( + const ucb::TransferInfo& rInfo, + const uno::Reference< ucb::XCommandEnvironment > & xEnv ) + throw( uno::Exception ) +{ + osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); + + // Persistent? + if ( m_eState != PERSISTENT ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( ucb::UnsupportedCommandException( + rtl::OUString::createFromAscii( + "Not persistent!" ), + static_cast< cppu::OWeakObject * >( this ) ) ), + xEnv ); + // Unreachable + } + + // Is source a hierarchy content? + if ( ( rInfo.SourceURL.getLength() < HIERARCHY_URL_SCHEME_LENGTH + 2 ) || + ( rInfo.SourceURL.compareToAscii( HIERARCHY_URL_SCHEME ":/", + HIERARCHY_URL_SCHEME_LENGTH + 2 ) + != 0 ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( ucb::InteractiveBadTransferURLException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ) ) ), + xEnv ); + // Unreachable + } + + // Is source not a parent of me / not me? + rtl::OUString aId = m_xIdentifier->getContentIdentifier(); + sal_Int32 nPos = aId.lastIndexOf( '/' ); + if ( nPos != ( aId.getLength() - 1 ) ) + { + // No trailing slash found. Append. + aId += rtl::OUString::createFromAscii( "/" ); + } + + if ( rInfo.SourceURL.getLength() <= aId.getLength() ) + { + if ( aId.compareTo( + rInfo.SourceURL, rInfo.SourceURL.getLength() ) == 0 ) + { + uno::Any aProps + = uno::makeAny(beans::PropertyValue( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("Uri")), + -1, + uno::makeAny(rInfo.SourceURL), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_RECURSIVE, + uno::Sequence< uno::Any >(&aProps, 1), + xEnv, + rtl::OUString::createFromAscii( + "Target is equal to or is a child of source!" ), + this ); + // Unreachable + } + } + + ////////////////////////////////////////////////////////////////////// + // 0) Obtain content object for source. + ////////////////////////////////////////////////////////////////////// + + uno::Reference< ucb::XContentIdentifier > xId + = new ::ucbhelper::ContentIdentifier( m_xSMgr, rInfo.SourceURL ); + + // Note: The static cast is okay here, because its sure that + // m_xProvider is always the HierarchyContentProvider. + rtl::Reference< HierarchyContent > xSource; + + try + { + xSource = static_cast< HierarchyContent * >( + m_xProvider->queryContent( xId ).get() ); + } + catch ( ucb::IllegalIdentifierException const & ) + { + // queryContent + } + + if ( !xSource.is() ) + { + uno::Any aProps + = uno::makeAny(beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Uri")), + -1, + uno::makeAny(xId->getContentIdentifier()), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_READ, + uno::Sequence< uno::Any >(&aProps, 1), + xEnv, + rtl::OUString::createFromAscii( + "Cannot instanciate source object!" ), + this ); + // Unreachable + } + + ////////////////////////////////////////////////////////////////////// + // 1) Create new child content. + ////////////////////////////////////////////////////////////////////// + + rtl::OUString aType = xSource->isFolder() + ? rtl::OUString::createFromAscii( HIERARCHY_FOLDER_CONTENT_TYPE ) + : rtl::OUString::createFromAscii( HIERARCHY_LINK_CONTENT_TYPE ); + ucb::ContentInfo aContentInfo; + aContentInfo.Type = aType; + aContentInfo.Attributes = 0; + + // Note: The static cast is okay here, because its sure that + // createNewContent always creates a HierarchyContent. + rtl::Reference< HierarchyContent > xTarget + = static_cast< HierarchyContent * >( + createNewContent( aContentInfo ).get() ); + if ( !xTarget.is() ) + { + uno::Any aProps + = uno::makeAny(beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Folder")), + -1, + uno::makeAny(aId), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_CREATE, + uno::Sequence< uno::Any >(&aProps, 1), + xEnv, + rtl::OUString::createFromAscii( + "XContentCreator::createNewContent failed!" ), + this ); + // Unreachable + } + + ////////////////////////////////////////////////////////////////////// + // 2) Copy data from source content to child content. + ////////////////////////////////////////////////////////////////////// + + uno::Sequence< beans::Property > aSourceProps + = xSource->getPropertySetInfo( xEnv )->getProperties(); + sal_Int32 nCount = aSourceProps.getLength(); + + if ( nCount ) + { + sal_Bool bHadTitle = ( rInfo.NewTitle.getLength() == 0 ); + + // Get all source values. + uno::Reference< sdbc::XRow > xRow + = xSource->getPropertyValues( aSourceProps ); + + uno::Sequence< beans::PropertyValue > aValues( nCount ); + beans::PropertyValue* pValues = aValues.getArray(); + + const beans::Property* pProps = aSourceProps.getConstArray(); + for ( sal_Int32 n = 0; n < nCount; ++n ) + { + const beans::Property& rProp = pProps[ n ]; + beans::PropertyValue& rValue = pValues[ n ]; + + rValue.Name = rProp.Name; + rValue.Handle = rProp.Handle; + + if ( !bHadTitle && rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "Title" ) ) ) + { + // Set new title instead of original. + bHadTitle = sal_True; + rValue.Value <<= rInfo.NewTitle; + } + else + rValue.Value = xRow->getObject( + n + 1, + uno::Reference< container::XNameAccess >() ); + + rValue.State = beans::PropertyState_DIRECT_VALUE; + + if ( rProp.Attributes & beans::PropertyAttribute::REMOVABLE ) + { + // Add Additional Core Property. + try + { + xTarget->addProperty( rProp.Name, + rProp.Attributes, + rValue.Value ); + } + catch ( beans::PropertyExistException const & ) + { + } + catch ( beans::IllegalTypeException const & ) + { + } + catch ( lang::IllegalArgumentException const & ) + { + } + } + } + + // Set target values. + xTarget->setPropertyValues( aValues, xEnv ); + } + + ////////////////////////////////////////////////////////////////////// + // 3) Commit (insert) child. + ////////////////////////////////////////////////////////////////////// + + xTarget->insert( rInfo.NameClash, xEnv ); + + ////////////////////////////////////////////////////////////////////// + // 4) Transfer (copy) children of source. + ////////////////////////////////////////////////////////////////////// + + if ( xSource->isFolder() ) + { + HierarchyEntry aFolder( + m_xSMgr, m_pProvider, xId->getContentIdentifier() ); + HierarchyEntry::iterator it; + + while ( aFolder.next( it ) ) + { + const HierarchyEntryData& rResult = *it; + + rtl::OUString aChildId = xId->getContentIdentifier(); + if ( ( aChildId.lastIndexOf( '/' ) + 1 ) != aChildId.getLength() ) + aChildId += rtl::OUString::createFromAscii( "/" ); + + aChildId += rResult.getName(); + + ucb::TransferInfo aInfo; + aInfo.MoveData = sal_False; + aInfo.NewTitle = rtl::OUString(); + aInfo.SourceURL = aChildId; + aInfo.NameClash = rInfo.NameClash; + + // Transfer child to target. + xTarget->transfer( aInfo, xEnv ); + } + } + + ////////////////////////////////////////////////////////////////////// + // 5) Destroy source ( when moving only ) . + ////////////////////////////////////////////////////////////////////// + + if ( rInfo.MoveData ) + { + xSource->destroy( sal_True, xEnv ); + + // Remove all persistent data of source and its children. + if ( !xSource->removeData() ) + { + uno::Any aProps + = uno::makeAny( + beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Uri")), + -1, + uno::makeAny( + xSource->m_xIdentifier-> + getContentIdentifier()), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_WRITE, + uno::Sequence< uno::Any >(&aProps, 1), + xEnv, + rtl::OUString::createFromAscii( + "Cannot remove persistent data of source object!" ), + this ); + // Unreachable + } + + // Remove own and all children's Additional Core Properties. + xSource->removeAdditionalPropertySet( sal_True ); + } +} + +//========================================================================= +//========================================================================= +// +// HierarchyContentProperties Implementation. +// +//========================================================================= +//========================================================================= + +uno::Sequence< ucb::ContentInfo > +HierarchyContentProperties::getCreatableContentsInfo() const +{ + if ( getIsFolder() ) + { + uno::Sequence< ucb::ContentInfo > aSeq( 2 ); + + // Folder. + aSeq.getArray()[ 0 ].Type + = rtl::OUString::createFromAscii( HIERARCHY_FOLDER_CONTENT_TYPE ); + aSeq.getArray()[ 0 ].Attributes + = ucb::ContentInfoAttribute::KIND_FOLDER; + + uno::Sequence< beans::Property > aFolderProps( 1 ); + aFolderProps.getArray()[ 0 ] = beans::Property( + rtl::OUString::createFromAscii( "Title" ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND ); + aSeq.getArray()[ 0 ].Properties = aFolderProps; + + // Link. + aSeq.getArray()[ 1 ].Type + = rtl::OUString::createFromAscii( HIERARCHY_LINK_CONTENT_TYPE ); + aSeq.getArray()[ 1 ].Attributes + = ucb::ContentInfoAttribute::KIND_LINK; + + uno::Sequence< beans::Property > aLinkProps( 2 ); + aLinkProps.getArray()[ 0 ] = beans::Property( + rtl::OUString::createFromAscii( "Title" ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND ); + aLinkProps.getArray()[ 1 ] = beans::Property( + rtl::OUString::createFromAscii( "TargetURL" ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND ); + aSeq.getArray()[ 1 ].Properties = aLinkProps; + + return aSeq; + } + else + { + return uno::Sequence< ucb::ContentInfo >( 0 ); + } +} diff --git a/ucb/source/ucp/hierarchy/hierarchycontent.hxx b/ucb/source/ucp/hierarchy/hierarchycontent.hxx new file mode 100644 index 000000000000..5b7360a87719 --- /dev/null +++ b/ucb/source/ucp/hierarchy/hierarchycontent.hxx @@ -0,0 +1,311 @@ +/************************************************************************* + * + * 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 _HIERARCHYCONTENT_HXX +#define _HIERARCHYCONTENT_HXX + +#include <list> +#include <rtl/ref.hxx> +#include <com/sun/star/ucb/XContentCreator.hpp> +#include <ucbhelper/contenthelper.hxx> +#include "hierarchydata.hxx" +#include "hierarchyprovider.hxx" + +namespace com { namespace sun { namespace star { namespace beans { + struct Property; + struct PropertyValue; +} } } } + +namespace com { namespace sun { namespace star { namespace sdbc { + class XRow; +} } } } + +namespace com { namespace sun { namespace star { namespace ucb { + struct TransferInfo; +} } } } + +namespace hierarchy_ucp +{ + +//========================================================================= + +#define HIERARCHY_ROOT_FOLDER_CONTENT_SERVICE_NAME \ + "com.sun.star.ucb.HierarchyRootFolderContent" +#define HIERARCHY_FOLDER_CONTENT_SERVICE_NAME \ + "com.sun.star.ucb.HierarchyFolderContent" +#define HIERARCHY_LINK_CONTENT_SERVICE_NAME \ + "com.sun.star.ucb.HierarchyLinkContent" + +//========================================================================= + +class HierarchyContentProperties +{ +public: + HierarchyContentProperties() {}; + + HierarchyContentProperties( const HierarchyEntryData::Type & rType ) + : m_aData( rType ), + m_aContentType( rType == HierarchyEntryData::FOLDER + ? rtl::OUString::createFromAscii( HIERARCHY_FOLDER_CONTENT_TYPE ) + : rtl::OUString::createFromAscii( HIERARCHY_LINK_CONTENT_TYPE ) ) {} + + HierarchyContentProperties( const HierarchyEntryData & rData ) + : m_aData( rData ), + m_aContentType( rData.getType() == HierarchyEntryData::FOLDER + ? rtl::OUString::createFromAscii( HIERARCHY_FOLDER_CONTENT_TYPE ) + : rtl::OUString::createFromAscii( HIERARCHY_LINK_CONTENT_TYPE ) ) {} + + const rtl::OUString & getName() const { return m_aData.getName(); } + void setName( const rtl::OUString & rName ) { m_aData.setName( rName ); }; + + const rtl::OUString & getTitle() const { return m_aData.getTitle(); } + void setTitle( const rtl::OUString & rTitle ) + { m_aData.setTitle( rTitle ); }; + + const rtl::OUString & getTargetURL() const + { return m_aData.getTargetURL(); } + void setTargetURL( const rtl::OUString & rURL ) + { m_aData.setTargetURL( rURL ); }; + + const rtl::OUString & getContentType() const { return m_aContentType; } + + sal_Bool getIsFolder() const + { return m_aData.getType() == HierarchyEntryData::FOLDER; } + + sal_Bool getIsDocument() const { return !getIsFolder(); } + + com::sun::star::uno::Sequence< com::sun::star::ucb::ContentInfo > + getCreatableContentsInfo() const; + + const HierarchyEntryData & getHierarchyEntryData() const { return m_aData; } + +private: + HierarchyEntryData m_aData; + rtl::OUString m_aContentType; +}; + +//========================================================================= + +class HierarchyContentProvider; + +class HierarchyContent : public ::ucbhelper::ContentImplHelper, + public com::sun::star::ucb::XContentCreator +{ + enum ContentKind { LINK, FOLDER, ROOT }; + enum ContentState { TRANSIENT, // created via CreateNewContent, + // but did not process "insert" yet + PERSISTENT, // processed "insert" + DEAD // processed "delete" + }; + + HierarchyContentProperties m_aProps; + ContentKind m_eKind; + ContentState m_eState; + HierarchyContentProvider* m_pProvider; + bool m_bCheckedReadOnly; + bool m_bIsReadOnly; + +private: + HierarchyContent( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + HierarchyContentProvider* pProvider, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& Identifier, + const HierarchyContentProperties& rProps ); + HierarchyContent( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + HierarchyContentProvider* pProvider, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& Identifier, + const com::sun::star::ucb::ContentInfo& Info ); + + virtual com::sun::star::uno::Sequence< com::sun::star::beans::Property > + getProperties( const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv ); + virtual com::sun::star::uno::Sequence< com::sun::star::ucb::CommandInfo > + getCommands( const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv ); + virtual ::rtl::OUString getParentURL(); + + static sal_Bool hasData( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + HierarchyContentProvider* pProvider, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& Identifier ); + sal_Bool hasData( + const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& Identifier ) + { return hasData( m_xSMgr, m_pProvider, Identifier ); } + static sal_Bool loadData( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + HierarchyContentProvider* pProvider, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& Identifier, + HierarchyContentProperties& rProps ); + sal_Bool storeData(); + sal_Bool renameData( const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& xOldId, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& xNewId ); + sal_Bool removeData(); + + void setKind( const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& Identifier ); + + bool isReadOnly(); + + sal_Bool isFolder() const { return ( m_eKind > LINK ); } + + ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XContentIdentifier > + makeNewIdentifier( const rtl::OUString& rTitle ); + + typedef rtl::Reference< HierarchyContent > HierarchyContentRef; + typedef std::list< HierarchyContentRef > HierarchyContentRefList; + void queryChildren( HierarchyContentRefList& rChildren ); + + sal_Bool exchangeIdentity( + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XContentIdentifier >& xNewId ); + + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRow > + getPropertyValues( const ::com::sun::star::uno::Sequence< + ::com::sun::star::beans::Property >& rProperties ); + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > + setPropertyValues( + const ::com::sun::star::uno::Sequence< + ::com::sun::star::beans::PropertyValue >& rValues, + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw( ::com::sun::star::uno::Exception ); + + void insert( sal_Int32 nNameClashResolve, + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw( ::com::sun::star::uno::Exception ); + + void destroy( sal_Bool bDeletePhysical, + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw( ::com::sun::star::uno::Exception ); + + void transfer( const ::com::sun::star::ucb::TransferInfo& rInfo, + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw( ::com::sun::star::uno::Exception ); + +public: + // Create existing content. Fail, if not already exists. + static HierarchyContent* create( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + HierarchyContentProvider* pProvider, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& Identifier ); + + // Create new content. Fail, if already exists. + static HierarchyContent* create( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + HierarchyContentProvider* pProvider, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& Identifier, + const com::sun::star::ucb::ContentInfo& Info ); + + virtual ~HierarchyContent(); + + // XInterface + XINTERFACE_DECL() + + // XTypeProvider + XTYPEPROVIDER_DECL() + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL + getImplementationName() + throw( ::com::sun::star::uno::RuntimeException ); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL + getSupportedServiceNames() + throw( ::com::sun::star::uno::RuntimeException ); + + // XContent + virtual rtl::OUString SAL_CALL + getContentType() + throw( com::sun::star::uno::RuntimeException ); + virtual com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier > SAL_CALL + getIdentifier() + throw( com::sun::star::uno::RuntimeException ); + + // XCommandProcessor + virtual com::sun::star::uno::Any SAL_CALL + execute( const com::sun::star::ucb::Command& aCommand, + sal_Int32 CommandId, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment >& Environment ) + throw( com::sun::star::uno::Exception, + com::sun::star::ucb::CommandAbortedException, + com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + abort( sal_Int32 CommandId ) + throw( com::sun::star::uno::RuntimeException ); + + ////////////////////////////////////////////////////////////////////// + // Additional interfaces + ////////////////////////////////////////////////////////////////////// + + // XContentCreator + virtual com::sun::star::uno::Sequence< + com::sun::star::ucb::ContentInfo > SAL_CALL + queryCreatableContentsInfo() + throw( com::sun::star::uno::RuntimeException ); + virtual com::sun::star::uno::Reference< + com::sun::star::ucb::XContent > SAL_CALL + createNewContent( const com::sun::star::ucb::ContentInfo& Info ) + throw( com::sun::star::uno::RuntimeException ); + + ////////////////////////////////////////////////////////////////////// + // Non-interface methods. + ////////////////////////////////////////////////////////////////////// + + static ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRow > + getPropertyValues( const ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XMultiServiceFactory >& rSMgr, + const ::com::sun::star::uno::Sequence< + ::com::sun::star::beans::Property >& rProperties, + const HierarchyContentProperties& rData, + HierarchyContentProvider* pProvider, + const ::rtl::OUString& rContentId ); +}; + +} // namespace hierarchy_ucp + +#endif /* !_HIERARCHYCONTENT_HXX */ diff --git a/ucb/source/ucp/hierarchy/hierarchycontentcaps.cxx b/ucb/source/ucp/hierarchy/hierarchycontentcaps.cxx new file mode 100644 index 000000000000..a5371c213f1c --- /dev/null +++ b/ucb/source/ucp/hierarchy/hierarchycontentcaps.cxx @@ -0,0 +1,765 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + ************************************************************************** + + Props/Commands: + + root folder folder link link + (new) (new) + ---------------------------------------------------------------- + ContentType x x x x x + IsDocument x x x x x + IsFolder x x x x x + Title x x x x x + TargetURL x x + CreatableContentsInfo x x x x x + + getCommandInfo x x x x x + getPropertySetInfo x x x x x + getPropertyValues x x x x x + setPropertyValues x x x x x + createNewContent x x + insert x x + delete x x + open x x + transfer x x + + *************************************************************************/ + +#include <com/sun/star/beans/Property.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/ucb/CommandInfo.hpp> +#include <com/sun/star/ucb/OpenCommandArgument2.hpp> +#include <com/sun/star/ucb/TransferInfo.hpp> +#include <com/sun/star/uno/Sequence.hxx> +#include "hierarchycontent.hxx" + +using namespace com::sun::star; +using namespace hierarchy_ucp; + +//========================================================================= +// +// HierarchyContent implementation. +// +//========================================================================= + +#define MAKEPROPSEQUENCE( a ) \ + uno::Sequence< beans::Property >( a, sizeof( a ) / sizeof( a[ 0 ] ) ) + +#define MAKECMDSEQUENCE( a ) \ + uno::Sequence< ucb::CommandInfo >( a, sizeof( a ) / sizeof( a[ 0 ] ) ) + +//========================================================================= +// +// IMPORTENT: If any property data ( name / type / ... ) are changed, then +// HierarchyContent::getPropertyValues(...) must be adapted too! +// +//========================================================================= + +// virtual +uno::Sequence< beans::Property > HierarchyContent::getProperties( + const uno::Reference< ucb::XCommandEnvironment > & /*xEnv*/ ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + if ( m_eKind == LINK ) + { + //================================================================= + // + // Link: Supported properties + // + //================================================================= + + if ( isReadOnly() ) + { + static beans::Property aLinkPropertyInfoTable[] = + { + /////////////////////////////////////////////////////////// + // Required properties + /////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "ContentType" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "IsDocument" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + /////////////////////////////////////////////////////////// + // Optional standard properties + /////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TargetURL" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "CreatableContentsInfo" ) ), + -1, + getCppuType( static_cast< + const uno::Sequence< ucb::ContentInfo > * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ) + /////////////////////////////////////////////////////////// + // New properties + /////////////////////////////////////////////////////////// + }; + return MAKEPROPSEQUENCE( aLinkPropertyInfoTable ); + } + else + { + static beans::Property aLinkPropertyInfoTable[] = + { + /////////////////////////////////////////////////////////// + // Required properties + /////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "ContentType" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "IsDocument" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + ), + /////////////////////////////////////////////////////////// + // Optional standard properties + /////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TargetURL" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "CreatableContentsInfo" ) ), + -1, + getCppuType( static_cast< + const uno::Sequence< ucb::ContentInfo > * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ) + /////////////////////////////////////////////////////////// + // New properties + /////////////////////////////////////////////////////////// + }; + return MAKEPROPSEQUENCE( aLinkPropertyInfoTable ); + } + } + else if ( m_eKind == FOLDER ) + { + //================================================================= + // + // Folder: Supported properties + // + //================================================================= + + if ( isReadOnly() ) + { + static beans::Property aFolderPropertyInfoTable[] = + { + /////////////////////////////////////////////////////////// + // Required properties + /////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "ContentType" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "IsDocument" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + /////////////////////////////////////////////////////////// + // Optional standard properties + /////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "CreatableContentsInfo" ) ), + -1, + getCppuType( static_cast< + const uno::Sequence< ucb::ContentInfo > * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ) + /////////////////////////////////////////////////////////// + // New properties + /////////////////////////////////////////////////////////// + }; + return MAKEPROPSEQUENCE( aFolderPropertyInfoTable ); + } + else + { + static beans::Property aFolderPropertyInfoTable[] = + { + /////////////////////////////////////////////////////////// + // Required properties + /////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "ContentType" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "IsDocument" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + ), + /////////////////////////////////////////////////////////// + // Optional standard properties + /////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "CreatableContentsInfo" ) ), + -1, + getCppuType( static_cast< + const uno::Sequence< ucb::ContentInfo > * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ) + /////////////////////////////////////////////////////////// + // New properties + /////////////////////////////////////////////////////////// + }; + return MAKEPROPSEQUENCE( aFolderPropertyInfoTable ); + } + } + else + { + //================================================================= + // + // Root Folder: Supported properties + // + //================================================================= + + // Currently no difference between reonly /read-write + // -> all props ar read-only + + static beans::Property aRootFolderPropertyInfoTable[] = + { + /////////////////////////////////////////////////////////////// + // Required properties + /////////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ContentType" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsDocument" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + /////////////////////////////////////////////////////////////// + // Optional standard properties + /////////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "CreatableContentsInfo" ) ), + -1, + getCppuType( static_cast< + const uno::Sequence< ucb::ContentInfo > * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ) + /////////////////////////////////////////////////////////////// + // New properties + /////////////////////////////////////////////////////////////// + }; + return MAKEPROPSEQUENCE( aRootFolderPropertyInfoTable ); + } +} + +//========================================================================= +// virtual +uno::Sequence< ucb::CommandInfo > HierarchyContent::getCommands( + const uno::Reference< ucb::XCommandEnvironment > & /*xEnv*/ ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + if ( m_eKind == LINK ) + { + //================================================================= + // + // Link: Supported commands + // + //================================================================= + + if ( isReadOnly() ) + { + static const ucb::CommandInfo aLinkCommandInfoTable[] = + { + /////////////////////////////////////////////////////////// + // Required commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getCommandInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertySetInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertyValues" ) ), + -1, + getCppuType( + static_cast< uno::Sequence< beans::Property > * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ), + -1, + getCppuType( + static_cast< + uno::Sequence< beans::PropertyValue > * >( 0 ) ) + ) + /////////////////////////////////////////////////////////// + // Optional standard commands + /////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////// + // New commands + /////////////////////////////////////////////////////////// + }; + return MAKECMDSEQUENCE( aLinkCommandInfoTable ); + } + else + { + static const ucb::CommandInfo aLinkCommandInfoTable[] = + { + /////////////////////////////////////////////////////////// + // Required commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getCommandInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertySetInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertyValues" ) ), + -1, + getCppuType( + static_cast< uno::Sequence< beans::Property > * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ), + -1, + getCppuType( + static_cast< + uno::Sequence< beans::PropertyValue > * >( 0 ) ) + ), + /////////////////////////////////////////////////////////// + // Optional standard commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "delete" ) ), + -1, + getCppuBooleanType() + ), + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "insert" ) ), + -1, + getCppuVoidType() + ) + /////////////////////////////////////////////////////////// + // New commands + /////////////////////////////////////////////////////////// + }; + return MAKECMDSEQUENCE( aLinkCommandInfoTable ); + } + } + else if ( m_eKind == FOLDER ) + { + //================================================================= + // + // Folder: Supported commands + // + //================================================================= + + if ( isReadOnly() ) + { + static const ucb::CommandInfo aFolderCommandInfoTable[] = + { + /////////////////////////////////////////////////////////// + // Required commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getCommandInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertySetInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertyValues" ) ), + -1, + getCppuType( + static_cast< uno::Sequence< beans::Property > * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ), + -1, + getCppuType( + static_cast< + uno::Sequence< beans::PropertyValue > * >( 0 ) ) + ), + /////////////////////////////////////////////////////////// + // Optional standard commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "open" ) ), + -1, + getCppuType( + static_cast< ucb::OpenCommandArgument2 * >( 0 ) ) + ) + /////////////////////////////////////////////////////////// + // New commands + /////////////////////////////////////////////////////////// + }; + return MAKECMDSEQUENCE( aFolderCommandInfoTable ); + } + else + { + static const ucb::CommandInfo aFolderCommandInfoTable[] = + { + /////////////////////////////////////////////////////////// + // Required commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getCommandInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertySetInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertyValues" ) ), + -1, + getCppuType( + static_cast< uno::Sequence< beans::Property > * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ), + -1, + getCppuType( + static_cast< + uno::Sequence< beans::PropertyValue > * >( 0 ) ) + ), + /////////////////////////////////////////////////////////// + // Optional standard commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "delete" ) ), + -1, + getCppuBooleanType() + ), + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "insert" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "open" ) ), + -1, + getCppuType( + static_cast< ucb::OpenCommandArgument2 * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "transfer" ) ), + -1, + getCppuType( static_cast< ucb::TransferInfo * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "createNewContent" ) ), + -1, + getCppuType( static_cast< ucb::ContentInfo * >( 0 ) ) + ) + /////////////////////////////////////////////////////////// + // New commands + /////////////////////////////////////////////////////////// + }; + return MAKECMDSEQUENCE( aFolderCommandInfoTable ); + } + } + else + { + //================================================================= + // + // Root Folder: Supported commands + // + //================================================================= + + if ( isReadOnly() ) + { + static const ucb::CommandInfo aRootFolderCommandInfoTable[] = + { + /////////////////////////////////////////////////////////// + // Required commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getCommandInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertySetInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertyValues" ) ), + -1, + getCppuType( + static_cast< uno::Sequence< beans::Property > * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ), + -1, + getCppuType( + static_cast< + uno::Sequence< beans::PropertyValue > * >( 0 ) ) + ), + /////////////////////////////////////////////////////////// + // Optional standard commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "open" ) ), + -1, + getCppuType( + static_cast< ucb::OpenCommandArgument2 * >( 0 ) ) + ) + /////////////////////////////////////////////////////////// + // New commands + /////////////////////////////////////////////////////////// + }; + return MAKECMDSEQUENCE( aRootFolderCommandInfoTable ); + } + else + { + static const ucb::CommandInfo aRootFolderCommandInfoTable[] = + { + /////////////////////////////////////////////////////////// + // Required commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getCommandInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertySetInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertyValues" ) ), + -1, + getCppuType( + static_cast< uno::Sequence< beans::Property > * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ), + -1, + getCppuType( + static_cast< + uno::Sequence< beans::PropertyValue > * >( 0 ) ) + ), + /////////////////////////////////////////////////////////// + // Optional standard commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "open" ) ), + -1, + getCppuType( + static_cast< ucb::OpenCommandArgument2 * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "transfer" ) ), + -1, + getCppuType( static_cast< ucb::TransferInfo * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "createNewContent" ) ), + -1, + getCppuType( static_cast< ucb::ContentInfo * >( 0 ) ) + ) + /////////////////////////////////////////////////////////// + // New commands + /////////////////////////////////////////////////////////// + }; + return MAKECMDSEQUENCE( aRootFolderCommandInfoTable ); + } + } +} diff --git a/ucb/source/ucp/hierarchy/hierarchydata.cxx b/ucb/source/ucp/hierarchy/hierarchydata.cxx new file mode 100644 index 000000000000..d2e8f5031527 --- /dev/null +++ b/ucb/source/ucp/hierarchy/hierarchydata.cxx @@ -0,0 +1,1266 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + - HierarchyEntry::move + --> Rewrite to use XNamed ( once this is supported by config db api ). + + *************************************************************************/ +#include "hierarchydata.hxx" + +#include <vector> +#include <osl/diagnose.h> +#include <rtl/ustrbuf.hxx> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/container/XHierarchicalNameAccess.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/container/XNameReplace.hpp> +#include <com/sun/star/util/XChangesBatch.hpp> +#ifndef _COM_SUN_STAR_UTIL_XOFFICEINSTALLTIONDIRECTORIES_HPP_ +#include <com/sun/star/util/XOfficeInstallationDirectories.hpp> +#endif +#include "hierarchyprovider.hxx" +#include "hierarchyuri.hxx" + +using namespace com::sun::star; + +namespace hierarchy_ucp +{ + +//========================================================================= +struct HierarchyEntry::iterator_Impl +{ + HierarchyEntryData entry; + uno::Reference< container::XHierarchicalNameAccess > dir; + uno::Reference< util::XOfficeInstallationDirectories > officeDirs; + uno::Sequence< rtl::OUString> names; + sal_Int32 pos; + iterator_Impl() + : officeDirs( 0 ), pos( -1 /* before first */ ) {}; +}; + +//========================================================================= +void makeXMLName( const rtl::OUString & rIn, rtl::OUStringBuffer & rBuffer ) +{ + sal_Int32 nCount = rIn.getLength(); + for ( sal_Int32 n = 0; n < nCount; ++n ) + { + const sal_Unicode c = rIn.getStr()[ n ]; + switch ( c ) + { + case '&': + rBuffer.appendAscii( "&" ); + break; + + case '"': + rBuffer.appendAscii( """ ); + break; + + case '\'': + rBuffer.appendAscii( "'" ); + break; + + case '<': + rBuffer.appendAscii( "<" ); + break; + + case '>': + rBuffer.appendAscii( ">" ); + break; + + default: + rBuffer.append( c ); + break; + } + } +} + +//========================================================================= +//========================================================================= +// +// HierarchyEntry Implementation. +// +//========================================================================= +//========================================================================= + +#define READ_SERVICE_NAME "com.sun.star.ucb.HierarchyDataReadAccess" +#define READWRITE_SERVICE_NAME "com.sun.star.ucb.HierarchyDataReadWriteAccess" + +// describe path of cfg entry +#define CFGPROPERTY_NODEPATH "nodepath" + +//========================================================================= +HierarchyEntry::HierarchyEntry( + const uno::Reference< lang::XMultiServiceFactory >& rSMgr, + HierarchyContentProvider* pProvider, + const rtl::OUString& rURL ) +: m_xSMgr( rSMgr ), + m_xOfficeInstDirs( pProvider->getOfficeInstallationDirectories() ), + m_bTriedToGetRootReadAccess( sal_False ) +{ + HierarchyUri aUri( rURL ); + m_aServiceSpecifier = aUri.getService(); + + if ( pProvider ) + { + m_xConfigProvider + = pProvider->getConfigProvider( m_aServiceSpecifier ); + m_xRootReadAccess + = pProvider->getRootConfigReadNameAccess( m_aServiceSpecifier ); + } + + // Note: do not init m_aPath in init list. createPathFromHierarchyURL + // needs m_xSMgr and m_aMutex. + m_aPath = createPathFromHierarchyURL( aUri ); + + // Extract language independent name from URL. + sal_Int32 nPos = rURL.lastIndexOf( '/' ); + if ( nPos > HIERARCHY_URL_SCHEME_LENGTH ) + m_aName = rURL.copy( nPos + 1 ); + else + OSL_ENSURE( sal_False, "HierarchyEntry - Invalid URL!" ); +} + +//========================================================================= +sal_Bool HierarchyEntry::hasData() +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + uno::Reference< container::XHierarchicalNameAccess > xRootReadAccess + = getRootReadAccess(); + + OSL_ENSURE( xRootReadAccess.is(), "HierarchyEntry::hasData - No root!" ); + + if ( xRootReadAccess.is() ) + return xRootReadAccess->hasByHierarchicalName( m_aPath ); + + return sal_False; +} + +//========================================================================= +sal_Bool HierarchyEntry::getData( HierarchyEntryData& rData ) +{ + try + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + uno::Reference< container::XHierarchicalNameAccess > xRootReadAccess + = getRootReadAccess(); + + OSL_ENSURE( xRootReadAccess.is(), + "HierarchyEntry::getData - No root!" ); + + if ( xRootReadAccess.is() ) + { + rtl::OUString aTitlePath = m_aPath; + aTitlePath += rtl::OUString::createFromAscii( "/Title" ); + + // Note: Avoid NoSuchElementExceptions, because exceptions are + // relatively 'expensive'. Checking for availability of + // title value is sufficient here, because if it is + // there, the other values will be available too. + if ( !xRootReadAccess->hasByHierarchicalName( aTitlePath ) ) + return sal_False; + + rtl::OUString aValue; + + // Get Title value. + if ( !( xRootReadAccess->getByHierarchicalName( aTitlePath ) + >>= aValue ) ) + { + OSL_ENSURE( sal_False, + "HierarchyEntry::getData - " + "Got no Title value!" ); + return sal_False; + } + + rData.setTitle( aValue ); + + // Get TargetURL value. + rtl::OUString aTargetURLPath = m_aPath; + aTargetURLPath += rtl::OUString::createFromAscii( "/TargetURL" ); + if ( !( xRootReadAccess->getByHierarchicalName( aTargetURLPath ) + >>= aValue ) ) + { + OSL_ENSURE( sal_False, + "HierarchyEntry::getData - " + "Got no TargetURL value!" ); + return sal_False; + } + + // TargetURL property may contain a reference to the Office + // installation directory. To ensure a reloctable office + // installation, the path to the office installtion directory must + // never be stored directly. A placeholder is used instead. Replace + // it by actual installation directory. + if ( m_xOfficeInstDirs.is() && ( aValue.getLength() > 0 ) ) + aValue = m_xOfficeInstDirs->makeAbsoluteURL( aValue ); + rData.setTargetURL( aValue ); + + rtl::OUString aTypePath = m_aPath; + aTypePath += rtl::OUString::createFromAscii( "/Type" ); + if ( xRootReadAccess->hasByHierarchicalName( aTypePath ) ) + { + // Might not be present since it was introduced long after + // Title and TargetURL (#82433#)... So not getting it is + // not an error. + + // Get Type value. + sal_Int32 nType = 0; + if ( xRootReadAccess->getByHierarchicalName( aTypePath ) + >>= nType ) + { + if ( nType == 0 ) + { + rData.setType( HierarchyEntryData::LINK ); + } + else if ( nType == 1 ) + { + rData.setType( HierarchyEntryData::FOLDER ); + } + else + { + OSL_ENSURE( sal_False, + "HierarchyEntry::getData - " + "Unknown Type value!" ); + return sal_False; + } + } + } + + rData.setName( m_aName ); + return sal_True; + } + } + catch ( uno::RuntimeException const & ) + { + throw; + } + catch ( container::NoSuchElementException const & ) + { + // getByHierarchicalName + + OSL_ENSURE( sal_False, + "HierarchyEntry::getData - caught NoSuchElementException!" ); + } + return sal_False; +} + +//========================================================================= +sal_Bool HierarchyEntry::setData( + const HierarchyEntryData& rData, sal_Bool bCreate ) +{ + try + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + if ( !m_xConfigProvider.is() ) + m_xConfigProvider = uno::Reference< lang::XMultiServiceFactory >( + m_xSMgr->createInstance( m_aServiceSpecifier ), + uno::UNO_QUERY ); + + if ( m_xConfigProvider.is() ) + { + // Create parent's key. It must exist! + + rtl::OUString aParentPath; + sal_Bool bRoot = sal_True; + + sal_Int32 nPos = m_aPath.lastIndexOf( '/' ); + if ( nPos != -1 ) + { + // Skip "/Children" segment of the path, too. + nPos = m_aPath.lastIndexOf( '/', nPos - 1 ); + + OSL_ENSURE( nPos != -1, + "HierarchyEntry::setData - Wrong path!" ); + + aParentPath += m_aPath.copy( 0, nPos ); + bRoot = sal_False; + } + + uno::Sequence< uno::Any > aArguments( 1 ); + beans::PropertyValue aProperty; + + aProperty.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + CFGPROPERTY_NODEPATH ) ); + aProperty.Value <<= aParentPath; + aArguments[ 0 ] <<= aProperty; + + uno::Reference< util::XChangesBatch > xBatch( + m_xConfigProvider->createInstanceWithArguments( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + READWRITE_SERVICE_NAME ) ), + aArguments ), + uno::UNO_QUERY ); + + OSL_ENSURE( xBatch.is(), + "HierarchyEntry::setData - No batch!" ); + + uno::Reference< container::XNameAccess > xParentNameAccess( + xBatch, uno::UNO_QUERY ); + + OSL_ENSURE( xParentNameAccess.is(), + "HierarchyEntry::setData - No name access!" ); + + if ( xBatch.is() && xParentNameAccess.is() ) + { + // Try to create own key. It must not exist! + + sal_Bool bExists = sal_True; + uno::Any aMyKey; + + try + { + uno::Reference< container::XNameAccess > xNameAccess; + + if ( bRoot ) + { + xNameAccess = xParentNameAccess; + } + else + { + xParentNameAccess->getByName( + rtl::OUString::createFromAscii( "Children" ) ) + >>= xNameAccess; + } + + if ( xNameAccess->hasByName( m_aName ) ) + aMyKey = xNameAccess->getByName( m_aName ); + else + bExists = sal_False; + } + catch ( container::NoSuchElementException const & ) + { + bExists = sal_False; + } + + uno::Reference< container::XNameReplace > xNameReplace; + uno::Reference< container::XNameContainer > xContainer; + + if ( bExists ) + { + // Key exists. Replace values. + + aMyKey >>= xNameReplace; + + OSL_ENSURE( xNameReplace.is(), + "HierarchyEntry::setData - No name replace!" ); + } + else + { + if ( !bCreate ) + return sal_True; + + // Key does not exist. Create / fill / insert it. + + uno::Reference< lang::XSingleServiceFactory > xFac; + + if ( bRoot ) + { + // Special handling for children of root, + // which is not an entry. It's only a set + // of entries. + xFac = uno::Reference< lang::XSingleServiceFactory >( + xParentNameAccess, uno::UNO_QUERY ); + } + else + { + // Append new entry to parents child list, + // which is a set of entries. + xParentNameAccess->getByName( + rtl::OUString::createFromAscii( + "Children" ) ) >>= xFac; + } + + OSL_ENSURE( xFac.is(), + "HierarchyEntry::setData - No factory!" ); + + if ( xFac.is() ) + { + xNameReplace + = uno::Reference< container::XNameReplace >( + xFac->createInstance(), uno::UNO_QUERY ); + + OSL_ENSURE( xNameReplace.is(), + "HierarchyEntry::setData - No name replace!" ); + + if ( xNameReplace.is() ) + { + xContainer + = uno::Reference< container::XNameContainer >( + xFac, uno::UNO_QUERY ); + + OSL_ENSURE( xContainer.is(), + "HierarchyEntry::setData - No container!" ); + } + } + } + + if ( xNameReplace.is() ) + { + // Set Title value. + xNameReplace->replaceByName( + rtl::OUString::createFromAscii( "Title" ), + uno::makeAny( rData.getTitle() ) ); + + // Set TargetURL value. + + // TargetURL property may contain a reference to the Office + // installation directory. To ensure a reloctable office + // installation, the path to the office installtion + // directory must never be stored directly. Use a + // placeholder instead. + rtl::OUString aValue( rData.getTargetURL() ); + if ( m_xOfficeInstDirs.is() && ( aValue.getLength() > 0 ) ) + aValue + = m_xOfficeInstDirs->makeRelocatableURL( aValue ); + + xNameReplace->replaceByName( + rtl::OUString::createFromAscii( "TargetURL" ), + uno::makeAny( aValue ) ); + + // Set Type value. + sal_Int32 nType + = rData.getType() == HierarchyEntryData::LINK ? 0 : 1; + xNameReplace->replaceByName( + rtl::OUString::createFromAscii( "Type" ), + uno::makeAny( nType ) ); + + if ( xContainer.is() ) + xContainer->insertByName( + m_aName, uno::makeAny( xNameReplace ) ); + + // Commit changes. + xBatch->commitChanges(); + return sal_True; + } + } + } + } + catch ( uno::RuntimeException const & ) + { + throw; + } + catch ( lang::IllegalArgumentException const & ) + { + // replaceByName, insertByName + + OSL_ENSURE( + sal_False, + "HierarchyEntry::setData - caught IllegalArgumentException!" ); + } + catch ( container::NoSuchElementException const & ) + { + // replaceByName, getByName + + OSL_ENSURE( + sal_False, + "HierarchyEntry::setData - caught NoSuchElementException!" ); + } + catch ( container::ElementExistException const & ) + { + // insertByName + + OSL_ENSURE( + sal_False, + "HierarchyEntry::setData - caught ElementExistException!" ); + } + catch ( lang::WrappedTargetException const & ) + { + // replaceByName, insertByName, getByName, commitChanges + + OSL_ENSURE( + sal_False, + "HierarchyEntry::setData - caught WrappedTargetException!" ); + } + catch ( uno::Exception const & ) + { + // createInstance, createInstanceWithArguments + + OSL_ENSURE( + sal_False, + "HierarchyEntry::setData - caught Exception!" ); + } + + return sal_False; +} + +//========================================================================= +sal_Bool HierarchyEntry::move( + const rtl::OUString& rNewURL, const HierarchyEntryData& rData ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + rtl::OUString aNewPath = createPathFromHierarchyURL( rNewURL ); + + if ( aNewPath == m_aPath ) + return sal_True; + +#if 0 + // In the "near future"... ( not yet implemented in config db ) + + - get update access for m_aPath + - update access -> XNamed + - xNamed::setName( newName ) + - updateaccess commit +#else + + sal_Bool bOldRoot = sal_True; + uno::Reference< util::XChangesBatch > xOldParentBatch; + + rtl::OUString aNewKey; + sal_Int32 nURLPos = rNewURL.lastIndexOf( '/' ); + if ( nURLPos > HIERARCHY_URL_SCHEME_LENGTH ) + aNewKey = rNewURL.copy( nURLPos + 1 ); + else + { + OSL_ENSURE( sal_False, "HierarchyEntry::move - Invalid URL!" ); + return sal_False; + } + + sal_Bool bNewRoot = sal_True; + uno::Reference< util::XChangesBatch > xNewParentBatch; + + sal_Bool bDifferentParents = sal_True; + + try + { + if ( !m_xConfigProvider.is() ) + m_xConfigProvider = uno::Reference< lang::XMultiServiceFactory >( + m_xSMgr->createInstance( m_aServiceSpecifier ), + uno::UNO_QUERY ); + + if ( !m_xConfigProvider.is() ) + return sal_False; + + rtl::OUString aOldParentPath; + sal_Int32 nPos = m_aPath.lastIndexOf( '/' ); + if ( nPos != -1 ) + { + // Skip "/Children" segment of the path, too. + nPos = m_aPath.lastIndexOf( '/', nPos - 1 ); + + OSL_ENSURE( nPos != -1, "HierarchyEntry::move - Wrong path!" ); + + aOldParentPath += m_aPath.copy( 0, nPos ); + bOldRoot = sal_False; + } + + rtl::OUString aNewParentPath; + nPos = aNewPath.lastIndexOf( '/' ); + if ( nPos != -1 ) + { + // Skip "/Children" segment of the path, too. + nPos = aNewPath.lastIndexOf( '/', nPos - 1 ); + + OSL_ENSURE( nPos != -1, "HierarchyEntry::move - Wrong path!" ); + + aNewParentPath += aNewPath.copy( 0, nPos ); + bNewRoot = sal_False; + } + + uno::Sequence< uno::Any > aArguments( 1 ); + beans::PropertyValue aProperty; + + aProperty.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + CFGPROPERTY_NODEPATH ) ); + aProperty.Value <<= aOldParentPath; + aArguments[ 0 ] <<= aProperty; + + xOldParentBatch = uno::Reference< util::XChangesBatch >( + m_xConfigProvider->createInstanceWithArguments( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + READWRITE_SERVICE_NAME ) ), + aArguments ), + uno::UNO_QUERY ); + + OSL_ENSURE( xOldParentBatch.is(), "HierarchyEntry::move - No batch!" ); + + if ( !xOldParentBatch.is() ) + return sal_False; + + if ( aOldParentPath == aNewParentPath ) + { + bDifferentParents = sal_False; + xNewParentBatch = xOldParentBatch; + } + else + { + bDifferentParents = sal_True; + + aProperty.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + CFGPROPERTY_NODEPATH ) ); + aProperty.Value <<= aNewParentPath; + aArguments[ 0 ] <<= aProperty; + + xNewParentBatch = uno::Reference< util::XChangesBatch >( + m_xConfigProvider->createInstanceWithArguments( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + READWRITE_SERVICE_NAME ) ), + aArguments ), + uno::UNO_QUERY ); + + OSL_ENSURE( + xNewParentBatch.is(), "HierarchyEntry::move - No batch!" ); + + if ( !xNewParentBatch.is() ) + return sal_False; + } + } + catch ( uno::RuntimeException const & ) + { + throw; + } + catch ( uno::Exception const & ) + { + // createInstance, createInstanceWithArguments + + OSL_ENSURE( sal_False, "HierarchyEntry::move - caught Exception!" ); + return sal_False; + } + + ////////////////////////////////////////////////////////////////////// + // (1) Get entry... + ////////////////////////////////////////////////////////////////////// + + uno::Any aEntry; + uno::Reference< container::XNameAccess > xOldParentNameAccess; + uno::Reference< container::XNameContainer > xOldNameContainer; + + try + { + xOldParentNameAccess + = uno::Reference< container::XNameAccess >( + xOldParentBatch, uno::UNO_QUERY ); + + OSL_ENSURE( xOldParentNameAccess.is(), + "HierarchyEntry::move - No name access!" ); + + if ( !xOldParentNameAccess.is() ) + return sal_False; + + if ( bOldRoot ) + { + xOldNameContainer = uno::Reference< container::XNameContainer >( + xOldParentNameAccess, uno::UNO_QUERY ); + } + else + { + xOldParentNameAccess->getByName( + rtl::OUString::createFromAscii( "Children" ) ) + >>= xOldNameContainer; + } + + aEntry = xOldNameContainer->getByName( m_aName ); + } + catch ( container::NoSuchElementException const & ) + { + // getByName + + OSL_ENSURE( sal_False, + "HierarchyEntry::move - caught NoSuchElementException!" ); + return sal_False; + } + catch ( lang::WrappedTargetException const & ) + { + // getByName + + OSL_ENSURE( sal_False, + "HierarchyEntry::move - caught WrappedTargetException!" ); + return sal_False; + } + + ////////////////////////////////////////////////////////////////////// + // (2) Remove entry... Note: Insert BEFORE remove does not work! + ////////////////////////////////////////////////////////////////////// + + try + { + xOldNameContainer->removeByName( m_aName ); + xOldParentBatch->commitChanges(); + } + catch ( container::NoSuchElementException const & ) + { + // getByName, removeByName + + OSL_ENSURE( sal_False, + "HierarchyEntry::move - caught NoSuchElementException!" ); + return sal_False; + } + + ////////////////////////////////////////////////////////////////////// + // (3) Insert entry at new parent... + ////////////////////////////////////////////////////////////////////// + + try + { + uno::Reference< container::XNameReplace > xNewNameReplace; + aEntry >>= xNewNameReplace; + + OSL_ENSURE( xNewNameReplace.is(), + "HierarchyEntry::move - No name replace!" ); + + if ( !xNewNameReplace.is() ) + return sal_False; + + uno::Reference< container::XNameAccess > xNewParentNameAccess; + if ( bDifferentParents ) + xNewParentNameAccess + = uno::Reference< container::XNameAccess >( + xNewParentBatch, uno::UNO_QUERY ); + else + xNewParentNameAccess = xOldParentNameAccess; + + OSL_ENSURE( xNewParentNameAccess.is(), + "HierarchyEntry::move - No name access!" ); + + if ( !xNewParentNameAccess.is() ) + return sal_False; + + uno::Reference< container::XNameContainer > xNewNameContainer; + if ( bDifferentParents ) + { + if ( bNewRoot ) + { + xNewNameContainer + = uno::Reference< container::XNameContainer >( + xNewParentNameAccess, uno::UNO_QUERY ); + } + else + { + xNewParentNameAccess->getByName( + rtl::OUString::createFromAscii( "Children" ) ) + >>= xNewNameContainer; + } + } + else + xNewNameContainer = xOldNameContainer; + + if ( !xNewNameContainer.is() ) + return sal_False; + + xNewNameReplace->replaceByName( + rtl::OUString::createFromAscii( "Title" ), + uno::makeAny( rData.getTitle() ) ); + + // TargetURL property may contain a reference to the Office + // installation directory. To ensure a reloctable office + // installation, the path to the office installtion + // directory must never be stored directly. Use a placeholder + // instead. + rtl::OUString aValue( rData.getTargetURL() ); + if ( m_xOfficeInstDirs.is() && ( aValue.getLength() > 0 ) ) + aValue = m_xOfficeInstDirs->makeRelocatableURL( aValue ); + xNewNameReplace->replaceByName( + rtl::OUString::createFromAscii( "TargetURL" ), + uno::makeAny( aValue ) ); + sal_Int32 nType = rData.getType() == HierarchyEntryData::LINK ? 0 : 1; + xNewNameReplace->replaceByName( + rtl::OUString::createFromAscii( "Type" ), + uno::makeAny( nType ) ); + + xNewNameContainer->insertByName( aNewKey, aEntry ); + xNewParentBatch->commitChanges(); + } + catch ( container::NoSuchElementException const & ) + { + // replaceByName, insertByName, getByName + + OSL_ENSURE( sal_False, + "HierarchyEntry::move - caught NoSuchElementException!" ); + return sal_False; + } + catch ( lang::IllegalArgumentException const & ) + { + // replaceByName, insertByName + + OSL_ENSURE( + sal_False, + "HierarchyEntry::move - caught IllegalArgumentException!" ); + return sal_False; + } + catch ( container::ElementExistException const & ) + { + // insertByName + + OSL_ENSURE( sal_False, + "HierarchyEntry::move - caught ElementExistException!" ); + return sal_False; + } + catch ( lang::WrappedTargetException const & ) + { + // replaceByName, insertByName, getByName + + OSL_ENSURE( sal_False, + "HierarchyEntry::move - caught WrappedTargetException!" ); + return sal_False; + } + +#if 0 + ////////////////////////////////////////////////////////////////////// + // (4) Commit changes... + ////////////////////////////////////////////////////////////////////// + + try + { + xNewParentBatch->commitChanges(); + + if ( bDifferentParents ) + xOldParentBatch->commitChanges(); + } + catch ( lang::WrappedTargetException const & ) + { + // commitChanges + + OSL_ENSURE( sal_False, + "HierarchyEntry::move - caught WrappedTargetException!" ); + return sal_False; + } +#endif + + return sal_True; +#endif +} + +//========================================================================= +sal_Bool HierarchyEntry::remove() +{ + try + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + if ( !m_xConfigProvider.is() ) + m_xConfigProvider = uno::Reference< lang::XMultiServiceFactory >( + m_xSMgr->createInstance( m_aServiceSpecifier ), + uno::UNO_QUERY ); + + if ( m_xConfigProvider.is() ) + { + // Create parent's key. It must exist! + + rtl::OUString aParentPath; + sal_Bool bRoot = sal_True; + + sal_Int32 nPos = m_aPath.lastIndexOf( '/' ); + if ( nPos != -1 ) + { + // Skip "/Children" segment of the path, too. + nPos = m_aPath.lastIndexOf( '/', nPos - 1 ); + + OSL_ENSURE( nPos != -1, + "HierarchyEntry::remove - Wrong path!" ); + + aParentPath += m_aPath.copy( 0, nPos ); + bRoot = sal_False; + } + + uno::Sequence< uno::Any > aArguments( 1 ); + beans::PropertyValue aProperty; + + aProperty.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + CFGPROPERTY_NODEPATH ) ); + aProperty.Value <<= aParentPath; + aArguments[ 0 ] <<= aProperty; + + uno::Reference< util::XChangesBatch > xBatch( + m_xConfigProvider->createInstanceWithArguments( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + READWRITE_SERVICE_NAME ) ), + aArguments ), + uno::UNO_QUERY ); + + OSL_ENSURE( xBatch.is(), + "HierarchyEntry::remove - No batch!" ); + + uno::Reference< container::XNameAccess > xParentNameAccess( + xBatch, uno::UNO_QUERY ); + + OSL_ENSURE( xParentNameAccess.is(), + "HierarchyEntry::remove - No name access!" ); + + if ( xBatch.is() && xParentNameAccess.is() ) + { + uno::Reference< container::XNameContainer > xContainer; + + if ( bRoot ) + { + // Special handling for children of root, + // which is not an entry. It's only a set + // of entries. + xContainer = uno::Reference< container::XNameContainer >( + xParentNameAccess, uno::UNO_QUERY ); + } + else + { + // Append new entry to parents child list, + // which is a set of entries. + xParentNameAccess->getByName( + rtl::OUString::createFromAscii( "Children" ) ) + >>= xContainer; + } + + OSL_ENSURE( xContainer.is(), + "HierarchyEntry::remove - No container!" ); + + if ( xContainer.is() ) + { + xContainer->removeByName( m_aName ); + xBatch->commitChanges(); + return sal_True; + } + } + } + } + catch ( uno::RuntimeException const & ) + { + throw; + } + catch ( container::NoSuchElementException const & ) + { + // getByName, removeByName + + OSL_ENSURE( + sal_False, + "HierarchyEntry::remove - caught NoSuchElementException!" ); + } + catch ( lang::WrappedTargetException const & ) + { + // getByName, commitChanges + + OSL_ENSURE( + sal_False, + "HierarchyEntry::remove - caught WrappedTargetException!" ); + } + catch ( uno::Exception const & ) + { + // createInstance, createInstanceWithArguments + + OSL_ENSURE( sal_False, + "HierarchyEntry::remove - caught Exception!" ); + } + + return sal_False; +} + +//========================================================================= +sal_Bool HierarchyEntry::first( iterator& it ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + if ( it.m_pImpl->pos == -1 ) + { + // Init... + + try + { + uno::Reference< container::XHierarchicalNameAccess > + xRootHierNameAccess = getRootReadAccess(); + + if ( xRootHierNameAccess.is() ) + { + uno::Reference< container::XNameAccess > xNameAccess; + + if ( m_aPath.getLength() > 0 ) + { + rtl::OUString aPath = m_aPath; + aPath += rtl::OUString::createFromAscii( "/Children" ); + + xRootHierNameAccess->getByHierarchicalName( aPath ) + >>= xNameAccess; + } + else + xNameAccess + = uno::Reference< container::XNameAccess >( + xRootHierNameAccess, uno::UNO_QUERY ); + + OSL_ENSURE( xNameAccess.is(), + "HierarchyEntry::first - No name access!" ); + + if ( xNameAccess.is() ) + it.m_pImpl->names = xNameAccess->getElementNames(); + + uno::Reference< container::XHierarchicalNameAccess > + xHierNameAccess( xNameAccess, uno::UNO_QUERY ); + + OSL_ENSURE( xHierNameAccess.is(), + "HierarchyEntry::first - No hier. name access!" ); + + it.m_pImpl->dir = xHierNameAccess; + + it.m_pImpl->officeDirs = m_xOfficeInstDirs; + } + } + catch ( uno::RuntimeException const & ) + { + throw; + } + catch ( container::NoSuchElementException const& ) + { + // getByHierarchicalName + + OSL_ENSURE( + sal_False, + "HierarchyEntry::first - caught NoSuchElementException!" ); + } + catch ( uno::Exception const & ) + { + OSL_ENSURE( sal_False, + "HierarchyEntry::first - caught Exception!" ); + } + } + + if ( it.m_pImpl->names.getLength() == 0 ) + return sal_False; + + it.m_pImpl->pos = 0; + return sal_True; +} + +//========================================================================= +sal_Bool HierarchyEntry::next( iterator& it ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + if ( it.m_pImpl->pos == -1 ) + return first( it ); + + ++(it.m_pImpl->pos); + + return ( it.m_pImpl->pos < it.m_pImpl->names.getLength() ); +} + +//========================================================================= +rtl::OUString HierarchyEntry::createPathFromHierarchyURL( + const HierarchyUri& rURI ) +{ + // Transform path.... + // folder/subfolder/subsubfolder + // --> ['folder']/Children/['subfolder']/Children/['subsubfolder'] + + const rtl::OUString aPath = rURI.getPath().copy( 1 ); // skip leading slash. + sal_Int32 nLen = aPath.getLength(); + + if ( nLen ) + { + rtl::OUStringBuffer aNewPath; + aNewPath.appendAscii( "['" ); + + sal_Int32 nStart = 0; + sal_Int32 nEnd = aPath.indexOf( '/' ); + + do + { + if ( nEnd == -1 ) + nEnd = nLen; + + rtl::OUString aToken = aPath.copy( nStart, nEnd - nStart ); + makeXMLName( aToken, aNewPath ); + + if ( nEnd != nLen ) + { + aNewPath.appendAscii( "']/Children/['" ); + nStart = nEnd + 1; + nEnd = aPath.indexOf( '/', nStart ); + } + else + aNewPath.appendAscii( "']" ); + } + while ( nEnd != nLen ); + + return aNewPath.makeStringAndClear(); + } + + return aPath; +} + +//========================================================================= +uno::Reference< container::XHierarchicalNameAccess > +HierarchyEntry::getRootReadAccess() +{ + if ( !m_xRootReadAccess.is() ) + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + if ( !m_xRootReadAccess.is() ) + { + if ( m_bTriedToGetRootReadAccess ) // #82494# + { + OSL_ENSURE( sal_False, + "HierarchyEntry::getRootReadAccess - " + "Unable to read any config data! -> #82494#" ); + return uno::Reference< container::XHierarchicalNameAccess >(); + } + + try + { + if ( !m_xConfigProvider.is() ) + m_xConfigProvider + = uno::Reference< lang::XMultiServiceFactory >( + m_xSMgr->createInstance( m_aServiceSpecifier ), + uno::UNO_QUERY ); + + if ( m_xConfigProvider.is() ) + { + // Create Root object. + + uno::Sequence< uno::Any > aArguments( 1 ); + beans::PropertyValue aProperty; + aProperty.Name = rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( CFGPROPERTY_NODEPATH ) ); + aProperty.Value <<= rtl::OUString(); // root path + aArguments[ 0 ] <<= aProperty; + + m_bTriedToGetRootReadAccess = sal_True; + + m_xRootReadAccess + = uno::Reference< container::XHierarchicalNameAccess >( + m_xConfigProvider->createInstanceWithArguments( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + READ_SERVICE_NAME ) ), + aArguments ), + uno::UNO_QUERY ); + } + } + catch ( uno::RuntimeException const & ) + { + throw; + } + catch ( uno::Exception const & ) + { + // createInstance, createInstanceWithArguments + + OSL_ENSURE( sal_False, + "HierarchyEntry::getRootReadAccess - " + "caught Exception!" ); + } + } + } + return m_xRootReadAccess; +} + +//========================================================================= +//========================================================================= +// +// HierarchyEntry::iterator Implementation. +// +//========================================================================= +//========================================================================= + +HierarchyEntry::iterator::iterator() +{ + m_pImpl = new iterator_Impl; +} + +//========================================================================= +HierarchyEntry::iterator::~iterator() +{ + delete m_pImpl; +} + +//========================================================================= +const HierarchyEntryData& HierarchyEntry::iterator::operator*() const +{ + if ( ( m_pImpl->pos != -1 ) + && ( m_pImpl->dir.is() ) + && ( m_pImpl->pos < m_pImpl->names.getLength() ) ) + { + try + { + rtl::OUStringBuffer aKey; + aKey.appendAscii( "['" ); + makeXMLName( m_pImpl->names.getConstArray()[ m_pImpl->pos ], aKey ); + aKey.appendAscii( "']" ); + + rtl::OUString aTitle = aKey.makeStringAndClear(); + rtl::OUString aTargetURL = aTitle; + rtl::OUString aType = aTitle; + + aTitle += rtl::OUString::createFromAscii( "/Title" ); + aTargetURL += rtl::OUString::createFromAscii( "/TargetURL" ); + aType += rtl::OUString::createFromAscii( "/Type" ); + + rtl::OUString aValue; + m_pImpl->dir->getByHierarchicalName( aTitle ) >>= aValue; + m_pImpl->entry.setTitle( aValue ); + + m_pImpl->dir->getByHierarchicalName( aTargetURL ) >>= aValue; + + // TargetURL property may contain a reference to the Office + // installation directory. To ensure a reloctable office + // installation, the path to the office installtion directory must + // never be stored directly. A placeholder is used instead. Replace + // it by actual installation directory. + if ( m_pImpl->officeDirs.is() && ( aValue.getLength() > 0 ) ) + aValue = m_pImpl->officeDirs->makeAbsoluteURL( aValue ); + m_pImpl->entry.setTargetURL( aValue ); + + if ( m_pImpl->dir->hasByHierarchicalName( aType ) ) + { + // Might not be present since it was introduced long + // after Title and TargetURL (#82433#)... So not getting + // it is not an error. + + // Get Type value. + sal_Int32 nType = 0; + if ( m_pImpl->dir->getByHierarchicalName( aType ) >>= nType ) + { + if ( nType == 0 ) + { + m_pImpl->entry.setType( HierarchyEntryData::LINK ); + } + else if ( nType == 1 ) + { + m_pImpl->entry.setType( HierarchyEntryData::FOLDER ); + } + else + { + OSL_ENSURE( sal_False, + "HierarchyEntry::getData - " + "Unknown Type value!" ); + } + } + } + + m_pImpl->entry.setName( + m_pImpl->names.getConstArray()[ m_pImpl->pos ] ); + } + catch ( container::NoSuchElementException const & ) + { + m_pImpl->entry = HierarchyEntryData(); + } + } + + return m_pImpl->entry; +} + +} // namespace hierarchy_ucp diff --git a/ucb/source/ucp/hierarchy/hierarchydata.hxx b/ucb/source/ucp/hierarchy/hierarchydata.hxx new file mode 100644 index 000000000000..769611342baf --- /dev/null +++ b/ucb/source/ucp/hierarchy/hierarchydata.hxx @@ -0,0 +1,149 @@ +/************************************************************************* + * + * 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 _HIERARCHYDATA_HXX +#define _HIERARCHYDATA_HXX + +#include <rtl/ustring.hxx> +#include <osl/mutex.hxx> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> + +namespace com { namespace sun { namespace star { + namespace container { + class XHierarchicalNameAccess; + } + namespace util { + class XOfficeInstallationDirectories; + } +} } } + +namespace hierarchy_ucp +{ + +//========================================================================= + +class HierarchyEntryData +{ +public: + enum Type { NONE, LINK, FOLDER }; + + HierarchyEntryData() : m_aType( NONE ) {} + HierarchyEntryData( const Type & rType ) : m_aType( rType ) {} + + const rtl::OUString & getName() const { return m_aName; } + void setName( const rtl::OUString & rName ) { m_aName = rName; } + + const rtl::OUString & getTitle() const { return m_aTitle; } + void setTitle( const rtl::OUString & rTitle ) { m_aTitle = rTitle; } + + const rtl::OUString & getTargetURL() const { return m_aTargetURL; } + void setTargetURL( const rtl::OUString & rURL ) { m_aTargetURL = rURL; } + + Type getType() const + { return ( m_aType != NONE ) ? m_aType + : m_aTargetURL.getLength() + ? LINK + : FOLDER; } + void setType( const Type & rType ) { m_aType = rType; } + +private: + rtl::OUString m_aName; // Name (language independent) + rtl::OUString m_aTitle; // Title (language dependent) + rtl::OUString m_aTargetURL; // Target URL ( links only ) + Type m_aType; // Type +}; + +//========================================================================= + +class HierarchyContentProvider; +class HierarchyUri; + +class HierarchyEntry +{ + ::rtl::OUString m_aServiceSpecifier; + ::rtl::OUString m_aName; + ::rtl::OUString m_aPath; + ::osl::Mutex m_aMutex; + ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XMultiServiceFactory > m_xSMgr; + ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XMultiServiceFactory > m_xConfigProvider; + ::com::sun::star::uno::Reference< + ::com::sun::star::container::XHierarchicalNameAccess > + m_xRootReadAccess; + ::com::sun::star::uno::Reference< + ::com::sun::star::util::XOfficeInstallationDirectories > + m_xOfficeInstDirs; + sal_Bool m_bTriedToGetRootReadAccess; // #82494# + +private: + ::rtl::OUString createPathFromHierarchyURL( const HierarchyUri & rURI ); + ::com::sun::star::uno::Reference< + ::com::sun::star::container::XHierarchicalNameAccess > + getRootReadAccess(); + +public: + HierarchyEntry( const ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XMultiServiceFactory >& rSMgr, + HierarchyContentProvider* pProvider, + const ::rtl::OUString& rURL ); + + sal_Bool hasData(); + + sal_Bool getData( HierarchyEntryData& rData ); + + sal_Bool setData( const HierarchyEntryData& rData, sal_Bool bCreate ); + + sal_Bool move( const ::rtl::OUString& rNewURL, + const HierarchyEntryData& rData ); + + sal_Bool remove(); + + // Iteration. + + struct iterator_Impl; + + class iterator + { + friend class HierarchyEntry; + + iterator_Impl* m_pImpl; + + public: + iterator(); + ~iterator(); + + const HierarchyEntryData& operator*() const; + }; + + sal_Bool first( iterator& it ); + sal_Bool next ( iterator& it ); +}; + +} // namespace hierarchy_ucp + +#endif /* !_HIERARCHYDATA_HXX */ diff --git a/ucb/source/ucp/hierarchy/hierarchydatasource.cxx b/ucb/source/ucp/hierarchy/hierarchydatasource.cxx new file mode 100644 index 000000000000..467259caf0eb --- /dev/null +++ b/ucb/source/ucp/hierarchy/hierarchydatasource.cxx @@ -0,0 +1,1116 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + Note: Configuration Management classes do not support XAggregation. + So I have to wrap the interesting interfaces manually. + + *************************************************************************/ +#include "hierarchydatasource.hxx" +#include <osl/diagnose.h> + +#include "osl/doublecheckedlocking.h" +#include <cppuhelper/interfacecontainer.hxx> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/container/XHierarchicalNameAccess.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/util/XChangesBatch.hpp> +#include <com/sun/star/util/XChangesNotifier.hpp> + +using namespace com::sun::star; +using namespace hierarchy_ucp; + +//========================================================================= + +// describe path of cfg entry +#define CFGPROPERTY_NODEPATH "nodepath" +// true->async. update; false->sync. update +#define CFGPROPERTY_LAZYWRITE "lazywrite" + +#define READ_SERVICE_NAME "com.sun.star.ucb.HierarchyDataReadAccess" +#define READWRITE_SERVICE_NAME "com.sun.star.ucb.HierarchyDataReadWriteAccess" + +#define CONFIG_PROVIDER_SERVICE_NAME \ + "com.sun.star.configuration.ConfigurationProvider" +#define CONFIG_READ_SERVICE_NAME \ + "com.sun.star.configuration.ConfigurationAccess" +#define CONFIG_READWRITE_SERVICE_NAME \ + "com.sun.star.configuration.ConfigurationUpdateAccess" +#define CONFIG_DATA_ROOT_KEY \ + "/org.openoffice.ucb.Hierarchy/Root" + +//========================================================================= + +namespace hcp_impl +{ + +//========================================================================= +// +// HierarchyDataReadAccess Implementation. +// +//========================================================================= + +class HierarchyDataAccess : public cppu::OWeakObject, + public lang::XServiceInfo, + public lang::XTypeProvider, + public lang::XComponent, + public lang::XSingleServiceFactory, + public container::XHierarchicalNameAccess, + public container::XNameContainer, + public util::XChangesNotifier, + public util::XChangesBatch +{ + osl::Mutex m_aMutex; + uno::Reference< uno::XInterface > m_xConfigAccess; + uno::Reference< lang::XComponent > m_xCfgC; + uno::Reference< lang::XSingleServiceFactory > m_xCfgSSF; + uno::Reference< container::XHierarchicalNameAccess > m_xCfgHNA; + uno::Reference< container::XNameContainer > m_xCfgNC; + uno::Reference< container::XNameReplace > m_xCfgNR; + uno::Reference< container::XNameAccess > m_xCfgNA; + uno::Reference< container::XElementAccess > m_xCfgEA; + uno::Reference< util::XChangesNotifier > m_xCfgCN; + uno::Reference< util::XChangesBatch > m_xCfgCB; + bool m_bReadOnly; + +public: + HierarchyDataAccess( const uno::Reference< + uno::XInterface > & xConfigAccess, + bool bReadOnly ); + virtual ~HierarchyDataAccess(); + + // XInterface + XINTERFACE_DECL() + + // XServiceInfo + XSERVICEINFO_DECL() + + // XTypeProvider + XTYPEPROVIDER_DECL() + + // XComponent + virtual void SAL_CALL + dispose() + throw ( uno::RuntimeException ); + virtual void SAL_CALL + addEventListener( const uno::Reference< lang::XEventListener > & xListener ) + throw ( uno::RuntimeException ); + virtual void SAL_CALL + removeEventListener( const uno::Reference< + lang::XEventListener > & aListener ) + throw ( uno::RuntimeException ); + + // XSingleServiceFactory + virtual uno::Reference< uno::XInterface > SAL_CALL + createInstance() + throw ( uno::Exception, uno::RuntimeException ); + virtual uno::Reference< uno::XInterface > SAL_CALL + createInstanceWithArguments( const uno::Sequence< uno::Any > & aArguments ) + throw ( uno::Exception, uno::RuntimeException ); + + // XHierarchicalNameAccess + virtual uno::Any SAL_CALL + getByHierarchicalName( const rtl::OUString & aName ) + throw ( container::NoSuchElementException, uno::RuntimeException ); + virtual sal_Bool SAL_CALL + hasByHierarchicalName( const rtl::OUString & aName ) + throw ( uno::RuntimeException ); + + // XNameContainer + virtual void SAL_CALL + insertByName( const rtl::OUString & aName, const uno::Any & aElement ) + throw ( lang::IllegalArgumentException, + container::ElementExistException, + lang::WrappedTargetException, + uno::RuntimeException ); + virtual void SAL_CALL + removeByName( const rtl::OUString & Name ) + throw ( container::NoSuchElementException, + lang::WrappedTargetException, + uno::RuntimeException ); + + // XNameReplace ( base of XNameContainer ) + virtual void SAL_CALL + replaceByName( const rtl::OUString & aName, const uno::Any & aElement ) + throw ( lang::IllegalArgumentException, + container::NoSuchElementException, + lang::WrappedTargetException, + uno::RuntimeException ); + + // XNameAccess ( base of XNameReplace ) + virtual uno::Any SAL_CALL + getByName( const rtl::OUString & aName ) + throw ( container::NoSuchElementException, + lang::WrappedTargetException, + uno::RuntimeException ); + virtual uno::Sequence< rtl::OUString > SAL_CALL + getElementNames() + throw ( uno::RuntimeException ); + virtual sal_Bool SAL_CALL + hasByName( const rtl::OUString & aName ) + throw ( uno::RuntimeException ); + + // XElementAccess ( base of XNameAccess ) + virtual uno::Type SAL_CALL + getElementType() + throw ( uno::RuntimeException ); + virtual sal_Bool SAL_CALL + hasElements() + throw ( uno::RuntimeException ); + + // XChangesNotifier + virtual void SAL_CALL + addChangesListener( const uno::Reference< + util::XChangesListener > & aListener ) + throw ( uno::RuntimeException ); + virtual void SAL_CALL + removeChangesListener( const uno::Reference< + util::XChangesListener > & aListener ) + throw ( uno::RuntimeException ); + + // XChangesBatch + virtual void SAL_CALL + commitChanges() + throw ( lang::WrappedTargetException, uno::RuntimeException ); + virtual sal_Bool SAL_CALL + hasPendingChanges() + throw ( uno::RuntimeException ); + virtual uno::Sequence< util::ElementChange > SAL_CALL + getPendingChanges() + throw ( uno::RuntimeException ); +}; + +} // namespace hcp_impl + +using namespace hcp_impl; + +//========================================================================= +//========================================================================= +// +// HierarchyDataSource Implementation. +// +//========================================================================= +//========================================================================= + +HierarchyDataSource::HierarchyDataSource( + const uno::Reference< lang::XMultiServiceFactory > & rxServiceMgr ) +: m_xSMgr( rxServiceMgr ), + m_pDisposeEventListeners( 0 ) +{ +} + +//========================================================================= +// virtual +HierarchyDataSource::~HierarchyDataSource() +{ + delete m_pDisposeEventListeners; +} + +//========================================================================= +// +// XInterface methods. +// +//========================================================================= + +XINTERFACE_IMPL_4( HierarchyDataSource, + lang::XTypeProvider, + lang::XServiceInfo, + lang::XComponent, + lang::XMultiServiceFactory ); + +//========================================================================= +// +// XTypeProvider methods. +// +//========================================================================= + +XTYPEPROVIDER_IMPL_4( HierarchyDataSource, + lang::XTypeProvider, + lang::XServiceInfo, + lang::XComponent, + lang::XMultiServiceFactory ); + +//========================================================================= +// +// XServiceInfo methods. +// +//========================================================================= + +XSERVICEINFO_IMPL_0( HierarchyDataSource, + rtl::OUString::createFromAscii( + "com.sun.star.comp.ucb.HierarchyDataSource" ) ) +{ + uno::Sequence< rtl::OUString > aSNS( 2 ); + aSNS[ 0 ] = rtl::OUString::createFromAscii( + "com.sun.star.ucb.DefaultHierarchyDataSource" ); + aSNS[ 1 ] = rtl::OUString::createFromAscii( + "com.sun.star.ucb.HierarchyDataSource" ); + return aSNS; +} + +ONE_INSTANCE_SERVICE_FACTORY_IMPL( HierarchyDataSource ); + +//========================================================================= +// +// XComponent methods. +// +//========================================================================= + +// virtual +void SAL_CALL HierarchyDataSource::dispose() + throw( uno::RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + if ( m_pDisposeEventListeners && m_pDisposeEventListeners->getLength() ) + { + lang::EventObject aEvt; + aEvt.Source = static_cast< lang::XComponent * >( this ); + m_pDisposeEventListeners->disposeAndClear( aEvt ); + } +} + +//========================================================================= +// virtual +void SAL_CALL HierarchyDataSource::addEventListener( + const uno::Reference< lang::XEventListener > & Listener ) + throw( uno::RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + if ( !m_pDisposeEventListeners ) + m_pDisposeEventListeners + = new cppu::OInterfaceContainerHelper( m_aMutex ); + + m_pDisposeEventListeners->addInterface( Listener ); +} + +//========================================================================= +// virtual +void SAL_CALL HierarchyDataSource::removeEventListener( + const uno::Reference< lang::XEventListener > & Listener ) + throw( uno::RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + if ( m_pDisposeEventListeners ) + m_pDisposeEventListeners->removeInterface( Listener ); +} + +//========================================================================= +// +// XMultiServiceFactory methods. +// +//========================================================================= + +// virtual +uno::Reference< uno::XInterface > SAL_CALL +HierarchyDataSource::createInstance( const rtl::OUString & aServiceSpecifier ) + throw ( uno::Exception, uno::RuntimeException ) +{ + // Create view to root node. + + beans::PropertyValue aProp; + aProp.Name = rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( CFGPROPERTY_NODEPATH ) ); + aProp.Value <<= + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( CONFIG_DATA_ROOT_KEY ) ); + + uno::Sequence< uno::Any > aArguments( 1 ); + aArguments[ 0 ] <<= aProp; + + return createInstanceWithArguments( aServiceSpecifier, aArguments, false ); +} + +//========================================================================= +// virtual +uno::Reference< uno::XInterface > SAL_CALL +HierarchyDataSource::createInstanceWithArguments( + const rtl::OUString & ServiceSpecifier, + const uno::Sequence< uno::Any > & Arguments ) + throw ( uno::Exception, uno::RuntimeException ) +{ + return createInstanceWithArguments( ServiceSpecifier, Arguments, true ); +} + +//========================================================================= +// virtual +uno::Sequence< rtl::OUString > SAL_CALL +HierarchyDataSource::getAvailableServiceNames() + throw ( uno::RuntimeException ) +{ + uno::Sequence< rtl::OUString > aNames( 2 ); + aNames[ 0 ] = rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( READ_SERVICE_NAME ) ); + aNames[ 1 ] = rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( READWRITE_SERVICE_NAME ) ); + return aNames; +} + +//========================================================================= +// +// Non-interface methods +// +//========================================================================= + +uno::Reference< uno::XInterface > SAL_CALL +HierarchyDataSource::createInstanceWithArguments( + const rtl::OUString & ServiceSpecifier, + const uno::Sequence< uno::Any > & Arguments, + bool bCheckArgs ) + throw ( uno::Exception, uno::RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + // Check service specifier. + bool bReadOnly = !!ServiceSpecifier.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( READ_SERVICE_NAME ) ); + bool bReadWrite = !bReadOnly && + ServiceSpecifier.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( READWRITE_SERVICE_NAME ) ); + + if ( !bReadOnly && !bReadWrite ) + { + OSL_ENSURE( false, + "HierarchyDataSource::createInstanceWithArguments - " + "Unsupported service specifier!" ); + return uno::Reference< uno::XInterface >(); + } + + uno::Sequence< uno::Any > aNewArgs( Arguments ); + + bool bHasLazyWriteProp = bReadOnly; // property must be added only if + // a writable view is requested. + if ( bCheckArgs ) + { + // Check arguments. + bool bHasNodePath = false; + sal_Int32 nCount = Arguments.getLength(); + for ( sal_Int32 n = 0; n < nCount; ++n ) + { + beans::PropertyValue aProp; + if ( Arguments[ n ] >>= aProp ) + { + if ( aProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( CFGPROPERTY_NODEPATH ) ) ) + { + rtl::OUString aPath; + if ( aProp.Value >>= aPath ) + { + bHasNodePath = true; + + // Create path to data inside the configuration. + rtl::OUString aConfigPath; + if ( !createConfigPath( aPath, aConfigPath ) ) + { + OSL_ENSURE( false, + "HierarchyDataSource::" + "createInstanceWithArguments - " + "Invalid node path!" ); + return uno::Reference< uno::XInterface >(); + } + + aProp.Value <<= aConfigPath; + + // Set new path in arguments. + aNewArgs[ n ] <<= aProp; + + if ( bHasLazyWriteProp ) + break; + } + else + { + OSL_ENSURE( false, + "HierarchyDataSource::createInstanceWithArguments - " + "Invalid type for property 'nodepath'!" ); + return uno::Reference< uno::XInterface >(); + } + } + else if ( aProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( + CFGPROPERTY_LAZYWRITE ) ) ) + { + if ( aProp.Value.getValueType() == getCppuBooleanType() ) + { + bHasLazyWriteProp = true; + + if ( bHasNodePath ) + break; + } + else + { + OSL_ENSURE( false, + "HierarchyDataSource::createInstanceWithArguments - " + "Invalid type for property 'lazywrite'!" ); + return uno::Reference< uno::XInterface >(); + } + } + } + } + + if ( !bHasNodePath ) + { + OSL_ENSURE( false, + "HierarchyDataSource::createInstanceWithArguments - " + "No 'nodepath' property!" ); + return uno::Reference< uno::XInterface >(); + } + } + + // Create Configuration Provider. + uno::Reference< lang::XMultiServiceFactory > xProv = getConfigProvider(); + if ( !xProv.is() ) + return uno::Reference< uno::XInterface >(); + + uno::Reference< uno::XInterface > xConfigAccess; + try + { + if ( bReadOnly ) + { + // Create configuration read-only access object. + xConfigAccess = xProv->createInstanceWithArguments( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + CONFIG_READ_SERVICE_NAME ) ), + aNewArgs ); + } + else + { + // Append 'lazywrite' property value, if not already present. + if ( !bHasLazyWriteProp ) + { + sal_Int32 nLen = aNewArgs.getLength(); + aNewArgs.realloc( nLen + 1 ); + + beans::PropertyValue aProp; + aProp.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + CFGPROPERTY_LAZYWRITE ) ); + aProp.Value <<= sal_True; + aNewArgs[ nLen ] <<= aProp; + } + + // Create configuration read-write access object. + xConfigAccess = xProv->createInstanceWithArguments( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + CONFIG_READWRITE_SERVICE_NAME ) ), + aNewArgs ); + } + } + catch ( uno::Exception const & ) + { + OSL_ENSURE( false, + "HierarchyDataSource::createInstanceWithArguments - " + "Cannot instanciate configuration access!" ); + throw; + } + + if ( !xConfigAccess.is() ) + { + OSL_ENSURE( false, + "HierarchyDataSource::createInstanceWithArguments - " + "Cannot instanciate configuration access!" ); + return xConfigAccess; + } + + return uno::Reference< uno::XInterface >( + static_cast< cppu::OWeakObject * >( + new HierarchyDataAccess( xConfigAccess, bReadOnly ) ) ); +} + +//========================================================================= +uno::Reference< lang::XMultiServiceFactory > +HierarchyDataSource::getConfigProvider() +{ + if ( !m_xConfigProvider.is() ) + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + if ( !m_xConfigProvider.is() ) + { + try + { + m_xConfigProvider + = uno::Reference< lang::XMultiServiceFactory >( + m_xSMgr->createInstance( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + CONFIG_PROVIDER_SERVICE_NAME ) ) ), + uno::UNO_QUERY ); + + OSL_ENSURE( m_xConfigProvider.is(), + "HierarchyDataSource::getConfigProvider - " + "No configuration provider!" ); + } + catch ( uno::Exception const & ) + { + OSL_ENSURE( false, + "HierarchyDataSource::getConfigProvider - " + "caught exception!" ); + } + } + } + + return m_xConfigProvider; +} + +//========================================================================= +bool HierarchyDataSource::createConfigPath( + const rtl::OUString & rInPath, rtl::OUString & rOutPath ) +{ + if ( rInPath.getLength() ) + { + if ( rInPath.indexOf( '/' ) == 0 ) + { + OSL_ENSURE( false, + "HierarchyDataSource::createConfigPath - " + "Leading slash in node path!" ); + return false; + } + + if ( rInPath.lastIndexOf( '/' ) == rInPath.getLength() - 1 ) + { + OSL_ENSURE( false, + "HierarchyDataSource::createConfigPath - " + "Trailing slash in node path!" ); + return false; + } + + rtl::OUString aOutPath( + RTL_CONSTASCII_USTRINGPARAM( CONFIG_DATA_ROOT_KEY "/" ) ); + aOutPath += rInPath; + rOutPath = aOutPath; + } + else + { + rOutPath = rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( CONFIG_DATA_ROOT_KEY ) ); + } + + return true; +} + +//========================================================================= +//========================================================================= +// +// HierarchyDataAccess Implementation. +// +//========================================================================= +//========================================================================= + +#define ENSURE_ORIG_INTERFACE( interface_name, member_name ) \ + m_xCfg##member_name; \ + if ( !m_xCfg##member_name.is() ) \ + { \ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); \ + if ( !m_xCfg##member_name.is() ) \ + m_xCfg##member_name \ + = uno::Reference< interface_name >( \ + m_xConfigAccess, uno::UNO_QUERY ); \ + xOrig = m_xCfg##member_name; \ + } + +//========================================================================= +HierarchyDataAccess::HierarchyDataAccess( const uno::Reference< + uno::XInterface > & xConfigAccess, + bool bReadOnly ) +: m_xConfigAccess( xConfigAccess ), + m_bReadOnly( bReadOnly ) +{ +} + +//========================================================================= +// virtual +HierarchyDataAccess::~HierarchyDataAccess() +{ +} + +//========================================================================= +// +// XInterface methods. +// +//========================================================================= + +XINTERFACE_COMMON_IMPL( HierarchyDataAccess ); + +//========================================================================= +// virtual +uno::Any SAL_CALL HierarchyDataAccess::queryInterface( const uno::Type & aType ) + throw ( uno::RuntimeException ) +{ + // Interfaces supported in read-only and read-write mode. + uno::Any aRet = cppu::queryInterface( aType, + static_cast< lang::XTypeProvider * >( this ), + static_cast< lang::XServiceInfo * >( this ), + static_cast< lang::XComponent * >( this ), + static_cast< container::XHierarchicalNameAccess * >( this ), + static_cast< container::XNameAccess * >( this ), + static_cast< container::XElementAccess * >( this ), + static_cast< util::XChangesNotifier * >( this ) ); + + // Interfaces supported only in read-write mode. + if ( !aRet.hasValue() && !m_bReadOnly ) + { + aRet = cppu::queryInterface( aType, + static_cast< lang::XSingleServiceFactory * >( this ), + static_cast< container::XNameContainer * >( this ), + static_cast< container::XNameReplace * >( this ), + static_cast< util::XChangesBatch * >( this ) ); + } + + return aRet.hasValue() ? aRet : OWeakObject::queryInterface( aType ); +} + +//========================================================================= +// +// XTypeProvider methods. +// +//========================================================================= + +XTYPEPROVIDER_COMMON_IMPL( HierarchyDataAccess ); + +//========================================================================= +// virtual +uno::Sequence< uno::Type > SAL_CALL HierarchyDataAccess::getTypes() + throw( uno::RuntimeException ) +{ + cppu::OTypeCollection * pCollection = 0; + + if ( m_bReadOnly ) + { + static cppu::OTypeCollection* pReadOnlyTypes = 0; + + pCollection = pReadOnlyTypes; + if ( !pCollection ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + + pCollection = pReadOnlyTypes; + if ( !pCollection ) + { + static cppu::OTypeCollection aCollection( + CPPU_TYPE_REF( lang::XTypeProvider ), + CPPU_TYPE_REF( lang::XServiceInfo ), + CPPU_TYPE_REF( lang::XComponent ), + CPPU_TYPE_REF( container::XHierarchicalNameAccess ), + CPPU_TYPE_REF( container::XNameAccess ), + CPPU_TYPE_REF( util::XChangesNotifier ) ); + pCollection = &aCollection; + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + pReadOnlyTypes = pCollection; + } + } + else { + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + } + } + else + { + static cppu::OTypeCollection* pReadWriteTypes = 0; + + pCollection = pReadWriteTypes; + if ( !pCollection ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + + pCollection = pReadWriteTypes; + if ( !pCollection ) + { + static cppu::OTypeCollection aCollection( + CPPU_TYPE_REF( lang::XTypeProvider ), + CPPU_TYPE_REF( lang::XServiceInfo ), + CPPU_TYPE_REF( lang::XComponent ), + CPPU_TYPE_REF( lang::XSingleServiceFactory ), + CPPU_TYPE_REF( container::XHierarchicalNameAccess ), + CPPU_TYPE_REF( container::XNameContainer ), + CPPU_TYPE_REF( util::XChangesBatch ), + CPPU_TYPE_REF( util::XChangesNotifier ) ); + pCollection = &aCollection; + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + pReadWriteTypes = pCollection; + } + } + else { + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + } + } + + return (*pCollection).getTypes(); +} + +//========================================================================= +// +// XServiceInfo methods. +// +//========================================================================= + +XSERVICEINFO_NOFACTORY_IMPL_0( + HierarchyDataAccess, + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.comp.ucb.HierarchyDataAccess" ) ) ) +{ + uno::Sequence< rtl::OUString > aSNS( 2 ); + aSNS[ 0 ] = rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( READ_SERVICE_NAME ) ); + aSNS[ 1 ] = rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( READWRITE_SERVICE_NAME ) ); + return aSNS; +} + +//========================================================================= +// +// XComponent methods. +// +//========================================================================= + +// virtual +void SAL_CALL HierarchyDataAccess::dispose() + throw ( uno::RuntimeException ) +{ + uno::Reference< lang::XComponent > xOrig + = ENSURE_ORIG_INTERFACE( lang::XComponent, C ); + + OSL_ENSURE( xOrig.is(), + "HierarchyDataAccess : Data source is not an XComponent!" ); + xOrig->dispose(); +} + +//========================================================================= +// virtual +void SAL_CALL HierarchyDataAccess::addEventListener( + const uno::Reference< lang::XEventListener > & xListener ) + throw ( uno::RuntimeException ) +{ + uno::Reference< lang::XComponent > xOrig + = ENSURE_ORIG_INTERFACE( lang::XComponent, C ); + + OSL_ENSURE( xOrig.is(), + "HierarchyDataAccess : Data source is not an XComponent!" ); + xOrig->addEventListener( xListener ); +} + +//========================================================================= +// virtual +void SAL_CALL HierarchyDataAccess::removeEventListener( + const uno::Reference< lang::XEventListener > & aListener ) + throw ( uno::RuntimeException ) +{ + uno::Reference< lang::XComponent > xOrig + = ENSURE_ORIG_INTERFACE( lang::XComponent, C ); + + OSL_ENSURE( xOrig.is(), + "HierarchyDataAccess : Data source is not an XComponent!" ); + xOrig->removeEventListener( aListener ); +} + +//========================================================================= +// +// XHierarchicalNameAccess methods. +// +//========================================================================= + +// virtual +uno::Any SAL_CALL HierarchyDataAccess::getByHierarchicalName( + const rtl::OUString & aName ) + throw ( container::NoSuchElementException, uno::RuntimeException ) +{ + uno::Reference< container::XHierarchicalNameAccess > xOrig + = ENSURE_ORIG_INTERFACE( container::XHierarchicalNameAccess, HNA ); + + OSL_ENSURE( xOrig.is(), + "HierarchyDataAccess : " + "Data source is not an XHierarchicalNameAccess!" ); + return xOrig->getByHierarchicalName( aName ); +} + +//========================================================================= +// virtual +sal_Bool SAL_CALL HierarchyDataAccess::hasByHierarchicalName( + const rtl::OUString & aName ) + throw ( uno::RuntimeException ) +{ + uno::Reference< container::XHierarchicalNameAccess > xOrig + = ENSURE_ORIG_INTERFACE( container::XHierarchicalNameAccess, HNA ); + + OSL_ENSURE( xOrig.is(), + "HierarchyDataAccess : " + "Data source is not an XHierarchicalNameAccess!" ); + return xOrig->hasByHierarchicalName( aName ); +} + +//========================================================================= +// +// XNameAccess methods. +// +//========================================================================= + +// virtual +uno::Any SAL_CALL HierarchyDataAccess::getByName( const rtl::OUString & aName ) + throw ( container::NoSuchElementException, + lang::WrappedTargetException, + uno::RuntimeException ) +{ + uno::Reference< container::XNameAccess > xOrig + = ENSURE_ORIG_INTERFACE( container::XNameAccess, NA ); + + OSL_ENSURE( xOrig.is(), + "HierarchyDataAccess : Data source is not an XNameAccess!" ); + return xOrig->getByName( aName ); +} + +//========================================================================= +// virtual +uno::Sequence< rtl::OUString > SAL_CALL HierarchyDataAccess::getElementNames() + throw ( uno::RuntimeException ) +{ + uno::Reference< container::XNameAccess > xOrig + = ENSURE_ORIG_INTERFACE( container::XNameAccess, NA ); + + OSL_ENSURE( xOrig.is(), + "HierarchyDataAccess : Data source is not an XNameAccess!" ); + return xOrig->getElementNames(); +} + +//========================================================================= +// virtual +sal_Bool SAL_CALL HierarchyDataAccess::hasByName( const rtl::OUString & aName ) + throw ( uno::RuntimeException ) +{ + uno::Reference< container::XNameAccess > xOrig + = ENSURE_ORIG_INTERFACE( container::XNameAccess, NA ); + + OSL_ENSURE( xOrig.is(), + "HierarchyDataAccess : Data source is not an XNameAccess!" ); + return xOrig->hasByName( aName ); +} + +//========================================================================= +// +// XElementAccess methods. +// +//========================================================================= + +// virtual +uno::Type SAL_CALL HierarchyDataAccess::getElementType() + throw ( uno::RuntimeException ) +{ + uno::Reference< container::XElementAccess > xOrig + = ENSURE_ORIG_INTERFACE( container::XElementAccess, EA ); + + OSL_ENSURE( xOrig.is(), + "HierarchyDataAccess : Data source is not an XElementAccess!" ); + return xOrig->getElementType(); +} + +//========================================================================= +// virtual +sal_Bool SAL_CALL HierarchyDataAccess::hasElements() + throw ( uno::RuntimeException ) +{ + uno::Reference< container::XElementAccess > xOrig + = ENSURE_ORIG_INTERFACE( container::XElementAccess, EA ); + + OSL_ENSURE( xOrig.is(), + "HierarchyDataAccess : Data source is not an XElementAccess!" ); + return xOrig->hasElements(); +} + +//========================================================================= +// +// XChangesNotifier methods. +// +//========================================================================= + +// virtual +void SAL_CALL HierarchyDataAccess::addChangesListener( + const uno::Reference< util::XChangesListener > & aListener ) + throw ( uno::RuntimeException ) +{ + uno::Reference< util::XChangesNotifier > xOrig + = ENSURE_ORIG_INTERFACE( util::XChangesNotifier, CN ); + + OSL_ENSURE( xOrig.is(), + "HierarchyDataAccess : Data source is not an XChangesNotifier!" ); + xOrig->addChangesListener( aListener ); +} + +//========================================================================= +// virtual +void SAL_CALL HierarchyDataAccess::removeChangesListener( + const uno::Reference< util::XChangesListener > & aListener ) + throw ( uno::RuntimeException ) +{ + uno::Reference< util::XChangesNotifier > xOrig + = ENSURE_ORIG_INTERFACE( util::XChangesNotifier, CN ); + + OSL_ENSURE( xOrig.is(), + "HierarchyDataAccess : Data source is not an XChangesNotifier!" ); + xOrig->removeChangesListener( aListener ); +} + +//========================================================================= +// +// XSingleServiceFactory methods. +// +//========================================================================= + +// virtual +uno::Reference< uno::XInterface > SAL_CALL HierarchyDataAccess::createInstance() + throw ( uno::Exception, uno::RuntimeException ) +{ + uno::Reference< lang::XSingleServiceFactory > xOrig + = ENSURE_ORIG_INTERFACE( lang::XSingleServiceFactory, SSF ); + + OSL_ENSURE( xOrig.is(), + "HierarchyDataAccess : Data source is not an XSingleServiceFactory!" ); + return xOrig->createInstance(); +} + +//========================================================================= +// virtual +uno::Reference< uno::XInterface > SAL_CALL +HierarchyDataAccess::createInstanceWithArguments( + const uno::Sequence< uno::Any > & aArguments ) + throw ( uno::Exception, uno::RuntimeException ) +{ + uno::Reference< lang::XSingleServiceFactory > xOrig + = ENSURE_ORIG_INTERFACE( lang::XSingleServiceFactory, SSF ); + + OSL_ENSURE( xOrig.is(), + "HierarchyDataAccess : Data source is not an XSingleServiceFactory!" ); + return xOrig->createInstanceWithArguments( aArguments ); +} + +//========================================================================= +// +// XNameContainer methods. +// +//========================================================================= + +// virtual +void SAL_CALL +HierarchyDataAccess::insertByName( const rtl::OUString & aName, + const uno::Any & aElement ) + throw ( lang::IllegalArgumentException, + container::ElementExistException, + lang::WrappedTargetException, + uno::RuntimeException ) +{ + uno::Reference< container::XNameContainer > xOrig + = ENSURE_ORIG_INTERFACE( container::XNameContainer, NC ); + + OSL_ENSURE( xOrig.is(), + "HierarchyDataAccess : Data source is not an XNameContainer!" ); + xOrig->insertByName( aName, aElement ); +} + +//========================================================================= +// virtual +void SAL_CALL +HierarchyDataAccess::removeByName( const rtl::OUString & Name ) + throw ( container::NoSuchElementException, + lang::WrappedTargetException, + uno::RuntimeException ) +{ + uno::Reference< container::XNameContainer > xOrig + = ENSURE_ORIG_INTERFACE( container::XNameContainer, NC ); + + OSL_ENSURE( xOrig.is(), + "HierarchyDataAccess : Data source is not an XNameContainer!" ); + xOrig->removeByName( Name ); +} + +//========================================================================= +// +// XNameReplace methods. +// +//========================================================================= + +// virtual +void SAL_CALL HierarchyDataAccess::replaceByName( const rtl::OUString & aName, + const uno::Any & aElement ) + throw ( lang::IllegalArgumentException, + container::NoSuchElementException, + lang::WrappedTargetException, + uno::RuntimeException ) +{ + uno::Reference< container::XNameReplace > xOrig + = ENSURE_ORIG_INTERFACE( container::XNameReplace, NR ); + + OSL_ENSURE( xOrig.is(), + "HierarchyDataAccess : Data source is not an XNameReplace!" ); + xOrig->replaceByName( aName, aElement ); +} + +//========================================================================= +// +// XChangesBatch methods. +// +//========================================================================= + +// virtual +void SAL_CALL HierarchyDataAccess::commitChanges() + throw ( lang::WrappedTargetException, uno::RuntimeException ) +{ + uno::Reference< util::XChangesBatch > xOrig + = ENSURE_ORIG_INTERFACE( util::XChangesBatch, CB ); + + OSL_ENSURE( xOrig.is(), + "HierarchyDataAccess : Data source is not an XChangesBatch!" ); + xOrig->commitChanges(); +} + +//========================================================================= +// virtual +sal_Bool SAL_CALL HierarchyDataAccess::hasPendingChanges() + throw ( uno::RuntimeException ) +{ + uno::Reference< util::XChangesBatch > xOrig + = ENSURE_ORIG_INTERFACE( util::XChangesBatch, CB ); + + OSL_ENSURE( xOrig.is(), + "HierarchyDataAccess : Data source is not an XChangesBatch!" ); + return xOrig->hasPendingChanges(); +} + +//========================================================================= +// virtual +uno::Sequence< util::ElementChange > SAL_CALL +HierarchyDataAccess::getPendingChanges() + throw ( uno::RuntimeException ) +{ + uno::Reference< util::XChangesBatch > xOrig + = ENSURE_ORIG_INTERFACE( util::XChangesBatch, CB ); + + OSL_ENSURE( xOrig.is(), + "HierarchyDataAccess : Data source is not an XChangesBatch!" ); + return xOrig->getPendingChanges(); +} + diff --git a/ucb/source/ucp/hierarchy/hierarchydatasource.hxx b/ucb/source/ucp/hierarchy/hierarchydatasource.hxx new file mode 100644 index 000000000000..329011e142db --- /dev/null +++ b/ucb/source/ucp/hierarchy/hierarchydatasource.hxx @@ -0,0 +1,125 @@ +/************************************************************************* + * + * 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 _HIERARCHYDATASOURCE_HXX +#define _HIERARCHYDATASOURCE_HXX + +#include <osl/mutex.hxx> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XTypeProvider.hpp> +#include <cppuhelper/weak.hxx> +#include <ucbhelper/macros.hxx> + +namespace cppu { class OInterfaceContainerHelper; } + +namespace hierarchy_ucp { + +//========================================================================= + +class HierarchyDataSource : public cppu::OWeakObject, + public com::sun::star::lang::XServiceInfo, + public com::sun::star::lang::XTypeProvider, + public com::sun::star::lang::XComponent, + public com::sun::star::lang::XMultiServiceFactory +{ + osl::Mutex m_aMutex; + com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory > m_xSMgr; + com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory > m_xConfigProvider; + cppu::OInterfaceContainerHelper * m_pDisposeEventListeners; + +public: + HierarchyDataSource( const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory > & + rxServiceMgr ); + virtual ~HierarchyDataSource(); + + // XInterface + XINTERFACE_DECL() + + // XServiceInfo + XSERVICEINFO_DECL() + + // XTypeProvider + XTYPEPROVIDER_DECL() + + // XComponent + virtual void SAL_CALL + dispose() + throw ( com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + addEventListener( const com::sun::star::uno::Reference< + com::sun::star::lang::XEventListener > & xListener ) + throw ( com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + removeEventListener( const com::sun::star::uno::Reference< + com::sun::star::lang::XEventListener > & aListener ) + throw ( com::sun::star::uno::RuntimeException ); + + // XMultiServiceFactory + virtual com::sun::star::uno::Reference< + com::sun::star::uno::XInterface > SAL_CALL + createInstance( const rtl::OUString & aServiceSpecifier ) + throw ( com::sun::star::uno::Exception, + com::sun::star::uno::RuntimeException ); + virtual com::sun::star::uno::Reference< + com::sun::star::uno::XInterface > SAL_CALL + createInstanceWithArguments( const rtl::OUString & ServiceSpecifier, + const com::sun::star::uno::Sequence< + com::sun::star::uno::Any > & Arguments ) + throw ( com::sun::star::uno::Exception, + com::sun::star::uno::RuntimeException ); + virtual com::sun::star::uno::Sequence< rtl::OUString > SAL_CALL + getAvailableServiceNames() + throw ( com::sun::star::uno::RuntimeException ); + + // Non-Interface methods + +private: + com::sun::star::uno::Reference< + com::sun::star::uno::XInterface > SAL_CALL + createInstanceWithArguments( const rtl::OUString & ServiceSpecifier, + const com::sun::star::uno::Sequence< + com::sun::star::uno::Any > & Arguments, + bool bCheckArgs ) + throw ( com::sun::star::uno::Exception, + com::sun::star::uno::RuntimeException ); + + com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory > + getConfigProvider(); + + bool + createConfigPath( const rtl::OUString & rInPath, rtl::OUString & rOutPath ); +}; + +} // namespace hierarchy_ucp + +#endif /* !_HIERARCHYDATASOURCE_HXX */ diff --git a/ucb/source/ucp/hierarchy/hierarchydatasupplier.cxx b/ucb/source/ucp/hierarchy/hierarchydatasupplier.cxx new file mode 100644 index 000000000000..8cd53a4a6201 --- /dev/null +++ b/ucb/source/ucp/hierarchy/hierarchydatasupplier.cxx @@ -0,0 +1,446 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ + +#include <vector> +#include <ucbhelper/contentidentifier.hxx> +#include "hierarchydatasupplier.hxx" +#include "hierarchyprovider.hxx" +#include "hierarchycontent.hxx" + +using namespace com::sun::star; +using namespace hierarchy_ucp; + +namespace hierarchy_ucp +{ + +//========================================================================= +// +// struct ResultListEntry. +// +//========================================================================= + +struct ResultListEntry +{ + rtl::OUString aId; + uno::Reference< ucb::XContentIdentifier > xId; + uno::Reference< ucb::XContent > xContent; + uno::Reference< sdbc::XRow > xRow; + HierarchyEntryData aData; + + ResultListEntry( const HierarchyEntryData& rEntry ) : aData( rEntry ) {} +}; + +//========================================================================= +// +// ResultList. +// +//========================================================================= + +typedef std::vector< ResultListEntry* > ResultList; + +//========================================================================= +// +// struct DataSupplier_Impl. +// +//========================================================================= + +struct DataSupplier_Impl +{ + osl::Mutex m_aMutex; + ResultList m_aResults; + rtl::Reference< HierarchyContent > m_xContent; + uno::Reference< lang::XMultiServiceFactory > m_xSMgr; + HierarchyEntry m_aFolder; + HierarchyEntry::iterator m_aIterator; + sal_Int32 m_nOpenMode; + sal_Bool m_bCountFinal; + + DataSupplier_Impl( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + const rtl::Reference< HierarchyContent >& rContent, + sal_Int32 nOpenMode ) + : m_xContent( rContent ), m_xSMgr( rxSMgr ), + m_aFolder( rxSMgr, + static_cast< HierarchyContentProvider * >( + rContent->getProvider().get() ), + rContent->getIdentifier()->getContentIdentifier() ), + m_nOpenMode( nOpenMode ), m_bCountFinal( sal_False ) {} + ~DataSupplier_Impl(); +}; + +//========================================================================= +DataSupplier_Impl::~DataSupplier_Impl() +{ + ResultList::const_iterator it = m_aResults.begin(); + ResultList::const_iterator end = m_aResults.end(); + + while ( it != end ) + { + delete (*it); + it++; + } +} + +} + +//========================================================================= +//========================================================================= +// +// HierarchyResultSetDataSupplier Implementation. +// +//========================================================================= +//========================================================================= + +HierarchyResultSetDataSupplier::HierarchyResultSetDataSupplier( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + const rtl::Reference< HierarchyContent >& rContent, + sal_Int32 nOpenMode ) +: m_pImpl( new DataSupplier_Impl( rxSMgr, rContent, nOpenMode ) ) +{ +} + +//========================================================================= +// virtual +HierarchyResultSetDataSupplier::~HierarchyResultSetDataSupplier() +{ + delete m_pImpl; +} + +//========================================================================= +// virtual +rtl::OUString HierarchyResultSetDataSupplier::queryContentIdentifierString( + sal_uInt32 nIndex ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( nIndex < m_pImpl->m_aResults.size() ) + { + rtl::OUString aId = m_pImpl->m_aResults[ nIndex ]->aId; + if ( aId.getLength() ) + { + // Already cached. + return aId; + } + } + + if ( getResult( nIndex ) ) + { + rtl::OUString aId + = m_pImpl->m_xContent->getIdentifier()->getContentIdentifier(); + + if ( ( aId.lastIndexOf( '/' ) + 1 ) != aId.getLength() ) + aId += rtl::OUString::createFromAscii( "/" ); + + aId += m_pImpl->m_aResults[ nIndex ]->aData.getName(); + + m_pImpl->m_aResults[ nIndex ]->aId = aId; + return aId; + } + return rtl::OUString(); +} + +//========================================================================= +// virtual +uno::Reference< ucb::XContentIdentifier > +HierarchyResultSetDataSupplier::queryContentIdentifier( sal_uInt32 nIndex ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( nIndex < m_pImpl->m_aResults.size() ) + { + uno::Reference< ucb::XContentIdentifier > xId + = m_pImpl->m_aResults[ nIndex ]->xId; + if ( xId.is() ) + { + // Already cached. + return xId; + } + } + + rtl::OUString aId = queryContentIdentifierString( nIndex ); + if ( aId.getLength() ) + { + uno::Reference< ucb::XContentIdentifier > xId + = new ::ucbhelper::ContentIdentifier( aId ); + m_pImpl->m_aResults[ nIndex ]->xId = xId; + return xId; + } + return uno::Reference< ucb::XContentIdentifier >(); +} + +//========================================================================= +// virtual +uno::Reference< ucb::XContent > +HierarchyResultSetDataSupplier::queryContent( sal_uInt32 nIndex ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( nIndex < m_pImpl->m_aResults.size() ) + { + uno::Reference< ucb::XContent > xContent + = m_pImpl->m_aResults[ nIndex ]->xContent; + if ( xContent.is() ) + { + // Already cached. + return xContent; + } + } + + uno::Reference< ucb::XContentIdentifier > xId + = queryContentIdentifier( nIndex ); + if ( xId.is() ) + { + try + { + uno::Reference< ucb::XContent > xContent + = m_pImpl->m_xContent->getProvider()->queryContent( xId ); + m_pImpl->m_aResults[ nIndex ]->xContent = xContent; + return xContent; + + } + catch ( ucb::IllegalIdentifierException const & ) + { + } + } + return uno::Reference< ucb::XContent >(); +} + +//========================================================================= +// virtual +sal_Bool HierarchyResultSetDataSupplier::getResult( sal_uInt32 nIndex ) +{ + osl::ClearableGuard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( m_pImpl->m_aResults.size() > nIndex ) + { + // Result already present. + return sal_True; + } + + // Result not (yet) present. + + if ( m_pImpl->m_bCountFinal ) + return sal_False; + + // Try to obtain result... + + sal_uInt32 nOldCount = m_pImpl->m_aResults.size(); + sal_Bool bFound = sal_False; + sal_uInt32 nPos = nOldCount; + + while ( m_pImpl->m_aFolder.next( m_pImpl->m_aIterator ) ) + { + const HierarchyEntryData& rResult = *m_pImpl->m_aIterator; + if ( checkResult( rResult ) ) + { + m_pImpl->m_aResults.push_back( new ResultListEntry( rResult ) ); + + if ( nPos == nIndex ) + { + // Result obtained. + bFound = sal_True; + break; + } + } + nPos++; + } + + if ( !bFound ) + m_pImpl->m_bCountFinal = sal_True; + + rtl::Reference< ::ucbhelper::ResultSet > xResultSet = getResultSet().get(); + if ( xResultSet.is() ) + { + // Callbacks follow! + aGuard.clear(); + + if ( nOldCount < m_pImpl->m_aResults.size() ) + xResultSet->rowCountChanged( + nOldCount, m_pImpl->m_aResults.size() ); + + if ( m_pImpl->m_bCountFinal ) + xResultSet->rowCountFinal(); + } + + return bFound; +} + +//========================================================================= +// virtual +sal_uInt32 HierarchyResultSetDataSupplier::totalCount() +{ + osl::ClearableGuard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( m_pImpl->m_bCountFinal ) + return m_pImpl->m_aResults.size(); + + sal_uInt32 nOldCount = m_pImpl->m_aResults.size(); + + while ( m_pImpl->m_aFolder.next( m_pImpl->m_aIterator ) ) + { + const HierarchyEntryData& rResult = *m_pImpl->m_aIterator; + if ( checkResult( rResult ) ) + m_pImpl->m_aResults.push_back( new ResultListEntry( rResult ) ); + } + + m_pImpl->m_bCountFinal = sal_True; + + rtl::Reference< ::ucbhelper::ResultSet > xResultSet = getResultSet().get(); + if ( xResultSet.is() ) + { + // Callbacks follow! + aGuard.clear(); + + if ( nOldCount < m_pImpl->m_aResults.size() ) + xResultSet->rowCountChanged( + nOldCount, m_pImpl->m_aResults.size() ); + + xResultSet->rowCountFinal(); + } + + return m_pImpl->m_aResults.size(); +} + +//========================================================================= +// virtual +sal_uInt32 HierarchyResultSetDataSupplier::currentCount() +{ + return m_pImpl->m_aResults.size(); +} + +//========================================================================= +// virtual +sal_Bool HierarchyResultSetDataSupplier::isCountFinal() +{ + return m_pImpl->m_bCountFinal; +} + +//========================================================================= +// virtual +uno::Reference< sdbc::XRow > +HierarchyResultSetDataSupplier::queryPropertyValues( sal_uInt32 nIndex ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( nIndex < m_pImpl->m_aResults.size() ) + { + uno::Reference< sdbc::XRow > xRow + = m_pImpl->m_aResults[ nIndex ]->xRow; + if ( xRow.is() ) + { + // Already cached. + return xRow; + } + } + + if ( getResult( nIndex ) ) + { + static rtl::OUString aFolderType( + rtl::OUString::createFromAscii( HIERARCHY_FOLDER_CONTENT_TYPE ) ); + static rtl::OUString aLinkType( + rtl::OUString::createFromAscii( HIERARCHY_LINK_CONTENT_TYPE ) ); + + HierarchyContentProperties aData( + m_pImpl->m_aResults[ nIndex ]->aData ); + + uno::Reference< sdbc::XRow > xRow + = HierarchyContent::getPropertyValues( + m_pImpl->m_xSMgr, + getResultSet()->getProperties(), + aData, + static_cast< HierarchyContentProvider * >( + m_pImpl->m_xContent->getProvider().get() ), + queryContentIdentifierString( nIndex ) ); + m_pImpl->m_aResults[ nIndex ]->xRow = xRow; + return xRow; + } + + return uno::Reference< sdbc::XRow >(); +} + +//========================================================================= +// virtual +void HierarchyResultSetDataSupplier::releasePropertyValues( sal_uInt32 nIndex ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( nIndex < m_pImpl->m_aResults.size() ) + m_pImpl->m_aResults[ nIndex ]->xRow = uno::Reference< sdbc::XRow >(); +} + +//========================================================================= +// virtual +void HierarchyResultSetDataSupplier::close() +{ +} + +//========================================================================= +// virtual +void HierarchyResultSetDataSupplier::validate() + throw( ucb::ResultSetException ) +{ +} + +//========================================================================= +sal_Bool HierarchyResultSetDataSupplier::checkResult( + const HierarchyEntryData& rResult ) +{ + switch ( m_pImpl->m_nOpenMode ) + { + case ucb::OpenMode::FOLDERS: + if ( rResult.getType() == HierarchyEntryData::LINK ) + { + // Entry is a link. + return sal_False; + } + break; + + case ucb::OpenMode::DOCUMENTS: + if ( rResult.getType() == HierarchyEntryData::FOLDER ) + { + // Entry is a folder. + return sal_False; + } + break; + + case ucb::OpenMode::ALL: + default: + break; + } + + return sal_True; +} + diff --git a/ucb/source/ucp/hierarchy/hierarchydatasupplier.hxx b/ucb/source/ucp/hierarchy/hierarchydatasupplier.hxx new file mode 100644 index 000000000000..87218e0729d0 --- /dev/null +++ b/ucb/source/ucp/hierarchy/hierarchydatasupplier.hxx @@ -0,0 +1,82 @@ +/************************************************************************* + * + * 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 _HIERARCHYDATASUPPLIER_HXX +#define _HIERARCHYDATASUPPLIER_HXX + +#include <rtl/ref.hxx> +#include <com/sun/star/ucb/OpenMode.hpp> +#include <ucbhelper/resultset.hxx> + +namespace hierarchy_ucp { + +class HierarchyEntryData; +struct DataSupplier_Impl; +class HierarchyContent; + +class HierarchyResultSetDataSupplier : + public ::ucbhelper::ResultSetDataSupplier +{ + DataSupplier_Impl* m_pImpl; + +private: + sal_Bool checkResult( const HierarchyEntryData& rResult ); + +public: + HierarchyResultSetDataSupplier( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + const rtl::Reference< HierarchyContent >& rContent, + sal_Int32 nOpenMode = com::sun::star::ucb::OpenMode::ALL ); + virtual ~HierarchyResultSetDataSupplier(); + + virtual rtl::OUString queryContentIdentifierString( sal_uInt32 nIndex ); + virtual com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier > + queryContentIdentifier( sal_uInt32 nIndex ); + virtual com::sun::star::uno::Reference< com::sun::star::ucb::XContent > + queryContent( sal_uInt32 nIndex ); + + virtual sal_Bool getResult( sal_uInt32 nIndex ); + + virtual sal_uInt32 totalCount(); + virtual sal_uInt32 currentCount(); + virtual sal_Bool isCountFinal(); + + virtual com::sun::star::uno::Reference< com::sun::star::sdbc::XRow > + queryPropertyValues( sal_uInt32 nIndex ); + virtual void releasePropertyValues( sal_uInt32 nIndex ); + + virtual void close(); + + virtual void validate() + throw( com::sun::star::ucb::ResultSetException ); +}; + +} // namespace hierarchy_ucp + +#endif /* !_HIERARCHYDATASUPPLIER_HXX */ diff --git a/ucb/source/ucp/hierarchy/hierarchyprovider.cxx b/ucb/source/ucp/hierarchy/hierarchyprovider.cxx new file mode 100644 index 000000000000..5ce8ea891f51 --- /dev/null +++ b/ucb/source/ucp/hierarchy/hierarchyprovider.cxx @@ -0,0 +1,338 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + - XInitialization::initialize does not work any longer! + + *************************************************************************/ +#include <osl/diagnose.h> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/container/XHierarchicalNameAccess.hpp> +#include <com/sun/star/util/XOfficeInstallationDirectories.hpp> +#include <ucbhelper/contentidentifier.hxx> +#include "hierarchyprovider.hxx" +#include "hierarchycontent.hxx" +#include "hierarchyuri.hxx" + +#include "../inc/urihelper.hxx" + +using namespace com::sun::star; +using namespace hierarchy_ucp; + +//========================================================================= +//========================================================================= +// +// HierarchyContentProvider Implementation. +// +//========================================================================= +//========================================================================= + +HierarchyContentProvider::HierarchyContentProvider( + const uno::Reference< lang::XMultiServiceFactory >& rXSMgr ) +: ::ucbhelper::ContentProviderImplHelper( rXSMgr ) +{ +} + +//========================================================================= +// virtual +HierarchyContentProvider::~HierarchyContentProvider() +{ +} + +//========================================================================= +// +// XInterface methods. +// +//========================================================================= + +XINTERFACE_IMPL_4( HierarchyContentProvider, + lang::XTypeProvider, + lang::XServiceInfo, + ucb::XContentProvider, + lang::XInitialization ); + +//========================================================================= +// +// XTypeProvider methods. +// +//========================================================================= + +XTYPEPROVIDER_IMPL_4( HierarchyContentProvider, + lang::XTypeProvider, + lang::XServiceInfo, + ucb::XContentProvider, + lang::XInitialization ); + +//========================================================================= +// +// XServiceInfo methods. +// +//========================================================================= + +XSERVICEINFO_IMPL_1( HierarchyContentProvider, + rtl::OUString::createFromAscii( + "com.sun.star.comp.ucb.HierarchyContentProvider" ), + rtl::OUString::createFromAscii( + HIERARCHY_CONTENT_PROVIDER_SERVICE_NAME ) ); + +//========================================================================= +// +// Service factory implementation. +// +//========================================================================= + +ONE_INSTANCE_SERVICE_FACTORY_IMPL( HierarchyContentProvider ); + +//========================================================================= +// +// XContentProvider methods. +// +//========================================================================= + +// virtual +uno::Reference< ucb::XContent > SAL_CALL +HierarchyContentProvider::queryContent( + const uno::Reference< ucb::XContentIdentifier >& Identifier ) + throw( ucb::IllegalIdentifierException, uno::RuntimeException ) +{ + HierarchyUri aUri( Identifier->getContentIdentifier() ); + if ( !aUri.isValid() ) + throw ucb::IllegalIdentifierException(); + + // Encode URL and create new Id. This may "correct" user-typed-in URL's. + uno::Reference< ucb::XContentIdentifier > xCanonicId + = new ::ucbhelper::ContentIdentifier( m_xSMgr, + ::ucb_impl::urihelper::encodeURI( + aUri.getUri() ) ); + osl::MutexGuard aGuard( m_aMutex ); + + // Check, if a content with given id already exists... + uno::Reference< ucb::XContent > xContent + = queryExistingContent( xCanonicId ).get(); + if ( xContent.is() ) + return xContent; + + // Create a new content. + xContent = HierarchyContent::create( m_xSMgr, this, xCanonicId ); + registerNewContent( xContent ); + + if ( xContent.is() && !xContent->getIdentifier().is() ) + throw ucb::IllegalIdentifierException(); + + return xContent; +} + +//========================================================================= +// +// XInitialization methods. +// +//========================================================================= + +// virtual +void SAL_CALL HierarchyContentProvider::initialize( + const uno::Sequence< uno::Any >& aArguments ) + throw( uno::Exception, uno::RuntimeException ) +{ +#if 0 + if ( aArguments.getLength() > 0 ) + { + // Extract config provider from service init args. + aArguments[ 0 ] >>= m_xConfigProvider; + + OSL_ENSURE( m_xConfigProvider.is(), + "HierarchyContentProvider::initialize - " + "No config provider!" ); + } +#else + if ( aArguments.getLength() > 0 ) + OSL_ENSURE( false, + "HierarchyContentProvider::initialize : not supported!" ); +#endif +} + +//========================================================================= +// +// Non-interface methods. +// +//========================================================================= + +uno::Reference< lang::XMultiServiceFactory > +HierarchyContentProvider::getConfigProvider( + const rtl::OUString & rServiceSpecifier ) +{ + osl::MutexGuard aGuard( m_aMutex ); + ConfigProviderMap::iterator it = m_aConfigProviderMap.find( + rServiceSpecifier ); + if ( it == m_aConfigProviderMap.end() ) + { + try + { + ConfigProviderMapEntry aEntry; + aEntry.xConfigProvider + = uno::Reference< lang::XMultiServiceFactory >( + m_xSMgr->createInstance( rServiceSpecifier ), + uno::UNO_QUERY ); + + if ( aEntry.xConfigProvider.is() ) + { + m_aConfigProviderMap[ rServiceSpecifier ] = aEntry; + return aEntry.xConfigProvider; + } + } + catch ( uno::Exception const & ) + { +// OSL_ENSURE( sal_False, +// "HierarchyContentProvider::getConfigProvider - " +// "caught exception!" ); + } + + OSL_ENSURE( sal_False, + "HierarchyContentProvider::getConfigProvider - " + "No config provider!" ); + + return uno::Reference< lang::XMultiServiceFactory >(); + } + + return (*it).second.xConfigProvider; +} + +//========================================================================= +uno::Reference< container::XHierarchicalNameAccess > +HierarchyContentProvider::getRootConfigReadNameAccess( + const rtl::OUString & rServiceSpecifier ) +{ + osl::MutexGuard aGuard( m_aMutex ); + ConfigProviderMap::iterator it = m_aConfigProviderMap.find( + rServiceSpecifier ); + if ( it != m_aConfigProviderMap.end() ) + { + if ( !( (*it).second.xRootReadAccess.is() ) ) + { + if ( (*it).second.bTriedToGetRootReadAccess ) // #82494# + { + OSL_ENSURE( sal_False, + "HierarchyContentProvider::getRootConfigReadNameAccess - " + "Unable to read any config data! -> #82494#" ); + return uno::Reference< container::XHierarchicalNameAccess >(); + } + + try + { + uno::Reference< lang::XMultiServiceFactory > xConfigProv + = getConfigProvider( rServiceSpecifier ); + + if ( xConfigProv.is() ) + { + uno::Sequence< uno::Any > aArguments( 1 ); + beans::PropertyValue aProperty; + aProperty.Name + = rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "nodepath" ) ); + aProperty.Value <<= rtl::OUString(); // root path + aArguments[ 0 ] <<= aProperty; + + (*it).second.bTriedToGetRootReadAccess = true; + + (*it).second.xRootReadAccess + = uno::Reference< container::XHierarchicalNameAccess >( + xConfigProv->createInstanceWithArguments( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.ucb." + "HierarchyDataReadAccess" ) ), + aArguments ), + uno::UNO_QUERY ); + } + } + catch ( uno::RuntimeException const & ) + { + throw; + } + catch ( uno::Exception const & ) + { + // createInstance, createInstanceWithArguments + + OSL_ENSURE( sal_False, + "HierarchyContentProvider::getRootConfigReadNameAccess - " + "caught Exception!" ); + } + } + } + + return (*it).second.xRootReadAccess; +} + +//========================================================================= +uno::Reference< util::XOfficeInstallationDirectories > +HierarchyContentProvider::getOfficeInstallationDirectories() +{ + if ( !m_xOfficeInstDirs.is() ) + { + osl::MutexGuard aGuard( m_aMutex ); + if ( !m_xOfficeInstDirs.is() ) + { + OSL_ENSURE( m_xSMgr.is(), "No service manager!" ); + + uno::Reference< uno::XComponentContext > xCtx; + uno::Reference< beans::XPropertySet > xPropSet( + m_xSMgr, uno::UNO_QUERY ); + if ( xPropSet.is() ) + { + xPropSet->getPropertyValue( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ) ) ) + >>= xCtx; + } + + OSL_ENSURE( xCtx.is(), + "Unable to obtain component context from " + "service manager!" ); + + if ( xCtx.is() ) + { + xCtx->getValueByName( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "/singletons/" + "com.sun.star.util.theOfficeInstallationDirectories" ) ) ) + >>= m_xOfficeInstDirs; + +// Be silent. singleton only available in an Office environment. +// OSL_ENSURE( m_xOfficeInstDirs.is(), +// "Unable to obtain office directories singleton!" ); + } + } + } + return m_xOfficeInstDirs; +} + diff --git a/ucb/source/ucp/hierarchy/hierarchyprovider.hxx b/ucb/source/ucp/hierarchy/hierarchyprovider.hxx new file mode 100644 index 000000000000..9212aadf417e --- /dev/null +++ b/ucb/source/ucp/hierarchy/hierarchyprovider.hxx @@ -0,0 +1,155 @@ +/************************************************************************* + * + * 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 _HIERARCHYPROVIDER_HXX +#define _HIERARCHYPROVIDER_HXX + +#include <hash_map> +#include <ucbhelper/providerhelper.hxx> +#include <com/sun/star/lang/XInitialization.hpp> + +namespace com { namespace sun { namespace star { + namespace container { + class XHierarchicalNameAccess; + } + namespace util { + class XOfficeInstallationDirectories; + } +} } } + +namespace hierarchy_ucp { + +//========================================================================= + +#define HIERARCHY_CONTENT_PROVIDER_SERVICE_NAME \ + "com.sun.star.ucb.HierarchyContentProvider" +#define HIERARCHY_CONTENT_PROVIDER_SERVICE_NAME_LENGTH 41 + +#define HIERARCHY_URL_SCHEME \ + "vnd.sun.star.hier" +#define HIERARCHY_URL_SCHEME_LENGTH 17 + +#define HIERARCHY_FOLDER_CONTENT_TYPE \ + "application/" HIERARCHY_URL_SCHEME "-folder" +#define HIERARCHY_LINK_CONTENT_TYPE \ + "application/" HIERARCHY_URL_SCHEME "-link" + +//========================================================================= + +struct ConfigProviderMapEntry +{ + com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory > xConfigProvider; + com::sun::star::uno::Reference< + com::sun::star::container::XHierarchicalNameAccess > xRootReadAccess; + bool bTriedToGetRootReadAccess; // #82494# + + ConfigProviderMapEntry() : bTriedToGetRootReadAccess( false ) {} +}; + +struct equalString +{ + bool operator()( + const rtl::OUString& rKey1, const rtl::OUString& rKey2 ) const + { + return !!( rKey1 == rKey2 ); + } +}; + +struct hashString +{ + size_t operator()( const rtl::OUString & rName ) const + { + return rName.hashCode(); + } +}; + +typedef std::hash_map +< + rtl::OUString, // servcie specifier + ConfigProviderMapEntry, + hashString, + equalString +> +ConfigProviderMap; + +//========================================================================= + +class HierarchyContentProvider : public ::ucbhelper::ContentProviderImplHelper, + public com::sun::star::lang::XInitialization +{ + ConfigProviderMap m_aConfigProviderMap; + com::sun::star::uno::Reference< + com::sun::star::util::XOfficeInstallationDirectories > m_xOfficeInstDirs; + +public: + HierarchyContentProvider( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rXSMgr ); + virtual ~HierarchyContentProvider(); + + // XInterface + XINTERFACE_DECL() + + // XTypeProvider + XTYPEPROVIDER_DECL() + + // XServiceInfo + XSERVICEINFO_DECL() + + // XContentProvider + virtual com::sun::star::uno::Reference< + com::sun::star::ucb::XContent > SAL_CALL + queryContent( const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& Identifier ) + throw( com::sun::star::ucb::IllegalIdentifierException, + com::sun::star::uno::RuntimeException ); + + // XInitialization + virtual void SAL_CALL + initialize( const ::com::sun::star::uno::Sequence< + ::com::sun::star::uno::Any >& aArguments ) + throw( ::com::sun::star::uno::Exception, + ::com::sun::star::uno::RuntimeException ); + + // Non-Interface methods + com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory > + getConfigProvider( const rtl::OUString & rServiceSpecifier ); + com::sun::star::uno::Reference< + com::sun::star::container::XHierarchicalNameAccess > + getRootConfigReadNameAccess( const rtl::OUString & rServiceSpecifier ); + + // Note: may retrun an empty reference. + com::sun::star::uno::Reference< + com::sun::star::util::XOfficeInstallationDirectories > + getOfficeInstallationDirectories(); +}; + +} // namespace hierarchy_ucp + +#endif /* !_HIERARCHYPROVIDER_HXX */ diff --git a/ucb/source/ucp/hierarchy/hierarchyservices.cxx b/ucb/source/ucp/hierarchy/hierarchyservices.cxx new file mode 100644 index 000000000000..1830ecc35625 --- /dev/null +++ b/ucb/source/ucp/hierarchy/hierarchyservices.cxx @@ -0,0 +1,86 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include "hierarchyprovider.hxx" +#include "hierarchydatasource.hxx" + +using namespace com::sun::star; +using namespace hierarchy_ucp; + +//========================================================================= +extern "C" void SAL_CALL component_getImplementationEnvironment( + const sal_Char ** ppEnvTypeName, uno_Environment ** /*ppEnv*/ ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + +//========================================================================= +extern "C" void * SAL_CALL component_getFactory( + const sal_Char * pImplName, void * pServiceManager, void * /*pRegistryKey*/ ) +{ + void * pRet = 0; + + uno::Reference< lang::XMultiServiceFactory > xSMgr( + reinterpret_cast< lang::XMultiServiceFactory * >( + pServiceManager ) ); + uno::Reference< lang::XSingleServiceFactory > xFactory; + + ////////////////////////////////////////////////////////////////////// + // Hierarchy Content Provider. + ////////////////////////////////////////////////////////////////////// + + if ( HierarchyContentProvider::getImplementationName_Static(). + compareToAscii( pImplName ) == 0 ) + { + xFactory = HierarchyContentProvider::createServiceFactory( xSMgr ); + } + + ////////////////////////////////////////////////////////////////////// + // Hierarchy Data Source. + ////////////////////////////////////////////////////////////////////// + + else if ( HierarchyDataSource::getImplementationName_Static(). + compareToAscii( pImplName ) == 0 ) + { + xFactory = HierarchyDataSource::createServiceFactory( xSMgr ); + } + + ////////////////////////////////////////////////////////////////////// + + if ( xFactory.is() ) + { + xFactory->acquire(); + pRet = xFactory.get(); + } + + return pRet; +} + diff --git a/ucb/source/ucp/hierarchy/hierarchyuri.cxx b/ucb/source/ucp/hierarchy/hierarchyuri.cxx new file mode 100644 index 000000000000..0621db72d5bb --- /dev/null +++ b/ucb/source/ucp/hierarchy/hierarchyuri.cxx @@ -0,0 +1,209 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ + +#include "rtl/ustrbuf.hxx" +#include "osl/diagnose.h" + +#include "hierarchyuri.hxx" + +using namespace hierarchy_ucp; + +//========================================================================= + +#define DEFAULT_DATA_SOURCE_SERVICE \ + "com.sun.star.ucb.DefaultHierarchyDataSource" + +//========================================================================= +//========================================================================= +// +// HierarchyUri Implementation. +// +//========================================================================= +//========================================================================= + +void HierarchyUri::init() const +{ + // Already inited? + if ( m_aUri.getLength() && !m_aPath.getLength() ) + { + // Note: Maybe it's a re-init, setUri only resets m_aPath! + m_aService = m_aParentUri = m_aName = rtl::OUString(); + + // URI must match at least: <sheme>: + if ( ( m_aUri.getLength() < HIERARCHY_URL_SCHEME_LENGTH + 1 ) ) + { + // error, but remember that we did a init(). + m_aPath = rtl::OUString::createFromAscii( "/" ); + return; + } + + // Scheme is case insensitive. + rtl::OUString aScheme + = m_aUri.copy( 0, HIERARCHY_URL_SCHEME_LENGTH ).toAsciiLowerCase(); + if ( aScheme.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( HIERARCHY_URL_SCHEME ) ) ) + { + m_aUri = m_aUri.replaceAt( 0, aScheme.getLength(), aScheme ); + + sal_Int32 nPos = 0; + + // If the URI has no service specifier, insert default service. + // This is for backward compatibility and for convenience. + + if ( m_aUri.getLength() == HIERARCHY_URL_SCHEME_LENGTH + 1 ) + { + // root folder URI without path and service specifier. + m_aUri += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "//" DEFAULT_DATA_SOURCE_SERVICE "/" ) ); + m_aService + = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + DEFAULT_DATA_SOURCE_SERVICE ) ); + + nPos = m_aUri.getLength() - 1; + } + else if ( ( m_aUri.getLength() == HIERARCHY_URL_SCHEME_LENGTH + 2 ) + && + ( m_aUri.getStr()[ HIERARCHY_URL_SCHEME_LENGTH + 1 ] + == sal_Unicode( '/' ) ) ) + { + // root folder URI without service specifier. + m_aUri += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "/" DEFAULT_DATA_SOURCE_SERVICE "/" ) ); + m_aService + = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + DEFAULT_DATA_SOURCE_SERVICE ) ); + + nPos = m_aUri.getLength() - 1; + } + else if ( ( m_aUri.getLength() > HIERARCHY_URL_SCHEME_LENGTH + 2 ) + && + ( m_aUri.getStr()[ HIERARCHY_URL_SCHEME_LENGTH + 2 ] + != sal_Unicode( '/' ) ) ) + { + // other (no root folder) URI without service specifier. + m_aUri = m_aUri.replaceAt( + HIERARCHY_URL_SCHEME_LENGTH + 2, + 0, + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "/" DEFAULT_DATA_SOURCE_SERVICE "/" ) ) ); + m_aService + = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + DEFAULT_DATA_SOURCE_SERVICE ) ); + + nPos + = HIERARCHY_URL_SCHEME_LENGTH + 3 + m_aService.getLength(); + } + else + { + // URI with service specifier. + sal_Int32 nStart = HIERARCHY_URL_SCHEME_LENGTH + 3; + + // Here: - m_aUri has at least the form "<scheme>://" + // - nStart points to char after <scheme>:// + + // Only <scheme>:// ? + if ( nStart == m_aUri.getLength() ) + { + // error, but remember that we did a init(). + m_aPath = rtl::OUString::createFromAscii( "/" ); + return; + } + + // Empty path segments? + if ( m_aUri.indexOf( + rtl::OUString::createFromAscii( "//" ), + nStart ) != -1 ) + { + // error, but remember that we did a init(). + m_aPath = rtl::OUString::createFromAscii( "/" ); + return; + } + + sal_Int32 nEnd = m_aUri.indexOf( '/', nStart ); + + // Only <scheme>:/// ? + if ( nEnd == nStart ) + { + // error, but remember that we did a init(). + m_aPath = rtl::OUString::createFromAscii( "/" ); + return; + } + + if ( nEnd == -1 ) + { + // Trailing slash missing. + nEnd = m_aUri.getLength(); + m_aUri += rtl::OUString::createFromAscii( "/" ); + } + + m_aService = m_aUri.copy( nStart, nEnd - nStart ); + + nPos = nEnd; + } + + // Here: - m_aUri has at least the form "<scheme>://<service>/" + // - m_aService was set + // - m_aPath, m_aParentPath, m_aName not yet set + // - nPos points to slash after service specifier + + // Remove trailing slash, if not a root folder URI. + sal_Int32 nEnd = m_aUri.lastIndexOf( '/' ); + if ( ( nEnd > nPos ) && ( nEnd == ( m_aUri.getLength() - 1 ) ) ) + m_aUri = m_aUri.copy( 0, nEnd ); + + // Path (includes leading slash) + m_aPath = m_aUri.copy( nPos ); + + // parent URI + name + sal_Int32 nLastSlash = m_aUri.lastIndexOf( '/' ); + if ( ( nLastSlash != -1 ) && + ( nLastSlash != m_aUri.getLength() - 1 ) ) // root + { + m_aParentUri = m_aUri.copy( 0, nLastSlash ); + m_aName = m_aUri.copy( nLastSlash + 1 ); + } + + // success + m_bValid = true; + } + else + { + // error, but remember that we did a init(). + m_aPath = rtl::OUString::createFromAscii( "/" ); + } + } +} + diff --git a/ucb/source/ucp/hierarchy/hierarchyuri.hxx b/ucb/source/ucp/hierarchy/hierarchyuri.hxx new file mode 100644 index 000000000000..012d59bb4cf2 --- /dev/null +++ b/ucb/source/ucp/hierarchy/hierarchyuri.hxx @@ -0,0 +1,91 @@ +/************************************************************************* + * + * 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 _HIERARCHYURI_HXX +#define _HIERARCHYURI_HXX + +#include <rtl/ustring.hxx> + +namespace hierarchy_ucp { + +//========================================================================= + +#define HIERARCHY_URL_SCHEME "vnd.sun.star.hier" +#define HIERARCHY_URL_SCHEME_LENGTH 17 + +//========================================================================= + +class HierarchyUri +{ + mutable ::rtl::OUString m_aUri; + mutable ::rtl::OUString m_aParentUri; + mutable ::rtl::OUString m_aService; + mutable ::rtl::OUString m_aPath; + mutable ::rtl::OUString m_aName; + mutable bool m_bValid; + +private: + void init() const; + +public: + HierarchyUri() : m_bValid( false ) {} + HierarchyUri( const ::rtl::OUString & rUri ) + : m_aUri( rUri ), m_bValid( false ) {} + + sal_Bool isValid() const + { init(); return m_bValid; } + + const ::rtl::OUString & getUri() const + { init(); return m_aUri; } + + void setUri( const ::rtl::OUString & rUri ) + { m_aPath = ::rtl::OUString(); m_aUri = rUri; m_bValid = false; } + + const ::rtl::OUString & getParentUri() const + { init(); return m_aParentUri; } + + const ::rtl::OUString & getService() const + { init(); return m_aService; } + + const ::rtl::OUString & getPath() const + { init(); return m_aPath; } + + const ::rtl::OUString & getName() const + { init(); return m_aName; } + + inline sal_Bool isRootFolder() const; +}; + +inline sal_Bool HierarchyUri::isRootFolder() const +{ + init(); + return ( ( m_aPath.getLength() == 1 ) && + ( m_aPath.getStr()[ 0 ] == sal_Unicode( '/' ) ) ); +} +} + +#endif diff --git a/ucb/source/ucp/hierarchy/makefile.mk b/ucb/source/ucp/hierarchy/makefile.mk new file mode 100644 index 000000000000..9263faa24b08 --- /dev/null +++ b/ucb/source/ucp/hierarchy/makefile.mk @@ -0,0 +1,92 @@ +#************************************************************************* +# +# 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=ucb +TARGET=ucphier +ENABLE_EXCEPTIONS=TRUE +USE_DEFFILE=TRUE +NO_BSYMBOLIC=TRUE + +# Version +UCPHIER_MAJOR=1 + +# --- Settings --------------------------------------------------------- + +.INCLUDE: settings.mk + +# --- General ----------------------------------------------------- +.IF "$(L10N_framework)"=="" + +SLOFILES=\ + $(SLO)$/hierarchyservices.obj \ + $(SLO)$/hierarchydata.obj \ + $(SLO)$/hierarchyprovider.obj \ + $(SLO)$/hierarchycontent.obj \ + $(SLO)$/hierarchycontentcaps.obj \ + $(SLO)$/hierarchydatasupplier.obj \ + $(SLO)$/dynamicresultset.obj \ + $(SLO)$/hierarchydatasource.obj \ + $(SLO)$/hierarchyuri.obj + +LIB1TARGET=$(SLB)$/_$(TARGET).lib +LIB1OBJFILES=$(SLOFILES) + +# --- Shared-Library --------------------------------------------------- + +SHL1TARGET=$(TARGET)$(UCPHIER_MAJOR) +SHL1IMPLIB=i$(TARGET) + +SHL1VERSIONMAP=$(SOLARENV)/src/component.map + +SHL1STDLIBS=\ + $(CPPUHELPERLIB) \ + $(CPPULIB) \ + $(SALLIB) \ + $(SALHELPERLIB) \ + $(UCBHELPERLIB) + +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +SHL1LIBS=$(LIB1TARGET) + +# --- Def-File --------------------------------------------------------- + +DEF1NAME=$(SHL1TARGET) + +# --- Targets ---------------------------------------------------------- + +.ENDIF # L10N_framework +.INCLUDE: target.mk + + +ALLTAR : $(MISC)/ucphier1.component + +$(MISC)/ucphier1.component .ERRREMOVE : $(SOLARENV)/bin/createcomponent.xslt \ + ucphier1.component + $(XSLTPROC) --nonet --stringparam uri \ + '$(COMPONENTPREFIX_BASIS_NATIVE)$(SHL1TARGETN:f)' -o $@ \ + $(SOLARENV)/bin/createcomponent.xslt ucphier1.component diff --git a/ucb/source/ucp/hierarchy/ucphier.xml b/ucb/source/ucp/hierarchy/ucphier.xml new file mode 100644 index 000000000000..1c63cbcbd7ee --- /dev/null +++ b/ucb/source/ucp/hierarchy/ucphier.xml @@ -0,0 +1,121 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE module-description PUBLIC "-//StarOffice//DTD ComponentDescription 1.0//EN" "module-description.dtd"> +<module-description xmlns:xlink="http://www.w3.org/1999/xlink"> + + <module-name> + ucphier + </module-name> + + <component-description> + <author> + Kai Sommerfeld + </author> + <name> + com.sun.star.comp.ucb.HierarchyContentProvider + </name> + <description> + This component implements a Content Provider for the Universal + Content Broker. It provides access to a persistent hierarchy of + folders and links. + </description> + <loader-name> + com.sun.star.loader.SharedLibrary + </loader-name> + <language> + c++ + </language> + <status value="final"/> + <supported-service> + com.sun.star.ucb.HierarchyContentProvider + </supported-service> + + <service-dependency> + com.sun.star.ucb.DefaultHierarchyDataSource + </service-dependency> + <service-dependency> + com.sun.star.util.OfficeeInstallationDirectories + </service-dependency> + </component-description> + + <component-description> + <author> + Kai Sommerfeld + </author> + <name> + com.sun.star.comp.ucb.HierarchyDataSource + </name> + <description> + This component implements a default data source for the Hierarchy + Content Provider. The data are accessed using the service + com.sun.star.configuration.ConfigurationProvider. + </description> + <loader-name> + com.sun.star.loader.SharedLibrary + </loader-name> + <language> + c++ + </language> + <status value="final"/> + <supported-service> + com.sun.star.ucb.DefaultHierarchyDataSource + </supported-service> + + <service-dependency> + com.sun.star.configuration.ConfigurationProvider + </service-dependency> + </component-description> + + <project-build-dependency> sal </project-build-dependency> + <project-build-dependency> cppu </project-build-dependency> + <project-build-dependency> cppuhelper </project-build-dependency> + <project-build-dependency> ucbhelper </project-build-dependency> + + <runtime-module-dependency> sal3 </runtime-module-dependency> + <runtime-module-dependency> cppu3 </runtime-module-dependency> + <runtime-module-dependency> cppuhelper3$(COM) </runtime-module-dependency> + <runtime-module-dependency> ucbhelper4$(COM) </runtime-module-dependency> + + <type> com.sun.star.beans.PropertyAttribute </type> + <type> com.sun.star.beans.XPropertiesChangeNotifier </type> + <type> com.sun.star.beans.XPropertyAccess </type> + <type> com.sun.star.beans.XPropertyContainer </type> + <type> com.sun.star.beans.XPropertySetInfoChangeNotifier </type> + <type> com.sun.star.container.XChild </type> + <type> com.sun.star.container.XHierarchicalNameAccess </type> + <type> com.sun.star.container.XNameContainer </type> + <type> com.sun.star.lang.IllegalAccessException </type> + <type> com.sun.star.lang.XComponent </type> + <type> com.sun.star.lang.XInitialization </type> + <type> com.sun.star.lang.XMultiServiceFactory </type> + <type> com.sun.star.lang.XServiceInfo </type> + <type> com.sun.star.lang.XSingleServiceFactory </type> + <type> com.sun.star.lang.XTypeProvider </type> + <type> com.sun.star.registry.XRegistryKey </type> + <type> com.sun.star.sdbc.XCloseable </type> + <type> com.sun.star.sdbc.XColumnLocate </type> + <type> com.sun.star.sdbc.XResultSetMetaDataSupplier </type> + <type> com.sun.star.sdbc.XRow </type> + <type> com.sun.star.ucb.ContentInfoAttribute </type> + <type> com.sun.star.ucb.InsertCommandArgument </type> + <type> com.sun.star.ucb.InteractiveBadTransferURLException </type> + <type> com.sun.star.ucb.MissingPropertiesException </type> + <type> com.sun.star.ucb.NameClash </type> + <type> com.sun.star.ucb.NameClashException </type> + <type> com.sun.star.ucb.OpenCommandArgument2 </type> + <type> com.sun.star.ucb.OpenMode </type> + <type> com.sun.star.ucb.ResultSetException </type> + <type> com.sun.star.ucb.TransferInfo </type> + <type> com.sun.star.ucb.UnsuppertedNameClashException </type> + <type> com.sun.star.ucb.XCommandInfo </type> + <type> com.sun.star.ucb.XCommandInfoChangeNotifier </type> + <type> com.sun.star.ucb.XCommandProcessor </type> + <type> com.sun.star.ucb.XContentAccess </type> + <type> com.sun.star.ucb.XContentCreator </type> + <type> com.sun.star.ucb.XContentProvider </type> + <type> com.sun.star.ucb.XDynamicResultSet </type> + <type> com.sun.star.ucb.XPersistentPropertySet </type> + <type> com.sun.star.uno.XWeak </type> + <type> com.sun.star.util.XChangesBatch </type> + <type> com.sun.star.util.XChangesNotifier </type> + <type> com.sun.star.util.XOfficeInstallationDirectories </type> +</module-description> diff --git a/ucb/source/ucp/hierarchy/ucphier1.component b/ucb/source/ucp/hierarchy/ucphier1.component new file mode 100644 index 000000000000..5483187d8674 --- /dev/null +++ b/ucb/source/ucp/hierarchy/ucphier1.component @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* 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. +* +**********************************************************************--> + +<component loader="com.sun.star.loader.SharedLibrary" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.ucb.HierarchyContentProvider"> + <service name="com.sun.star.ucb.HierarchyContentProvider"/> + </implementation> + <implementation name="com.sun.star.comp.ucb.HierarchyDataSource"> + <service name="com.sun.star.ucb.DefaultHierarchyDataSource"/> + <service name="com.sun.star.ucb.HierarchyDataSource"/> + </implementation> +</component> diff --git a/ucb/source/ucp/inc/urihelper.hxx b/ucb/source/ucp/inc/urihelper.hxx new file mode 100644 index 000000000000..a67fbe0564c1 --- /dev/null +++ b/ucb/source/ucp/inc/urihelper.hxx @@ -0,0 +1,123 @@ +/************************************************************************* + * + * 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 INCLUDED_URIHELPER_HXX +#define INCLUDED_URIHELPER_HXX + +#include "rtl/ustring.hxx" +#include "rtl/ustrbuf.hxx" +#include "rtl/uri.hxx" + +//========================================================================= + +namespace ucb_impl { namespace urihelper { + + inline ::rtl::OUString encodeSegment( const ::rtl::OUString & rSegment ) + { + return rtl::Uri::encode( rSegment, + rtl_UriCharClassPchar, + rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8 ); + } + + inline ::rtl::OUString decodeSegment( const rtl::OUString& rSegment ) + { + return rtl::Uri::decode( rSegment, + rtl_UriDecodeWithCharset, + RTL_TEXTENCODING_UTF8 ); + } + + inline ::rtl::OUString encodeURI( const ::rtl::OUString & rURI ) + { + rtl::OUString aFragment; + rtl::OUString aParams; + rtl::OUString aURI; + + sal_Int32 nFragment = rURI.lastIndexOf( sal_Unicode( '#' ) ); + if ( nFragment != -1 ) + aFragment = rURI.copy( nFragment + 1 ); + + sal_Int32 nParams = ( nFragment == -1 ) + ? rURI.lastIndexOf( sal_Unicode( '?' ) ) + : rURI.lastIndexOf( sal_Unicode( '?' ), nFragment ); + if ( nParams != -1 ) + aParams = ( nFragment == -1 ) + ? rURI.copy( nParams + 1 ) + : rURI.copy( nParams + 1, nFragment - nParams - 1 ); + + aURI = ( nParams != -1 ) + ? rURI.copy( 0, nParams ) + : ( nFragment != -1 ) + ? rURI.copy( 0, nFragment ) + : rURI; + + if ( aFragment.getLength() > 1 ) + aFragment = + rtl::Uri::encode( aFragment, + rtl_UriCharClassUric, + rtl_UriEncodeKeepEscapes, /* #i81690# */ + RTL_TEXTENCODING_UTF8 ); + + if ( aParams.getLength() > 1 ) + aParams = + rtl::Uri::encode( aParams, + rtl_UriCharClassUric, + rtl_UriEncodeKeepEscapes, /* #i81690# */ + RTL_TEXTENCODING_UTF8 ); + + rtl::OUStringBuffer aResult; + sal_Int32 nIndex = 0; + do + { + aResult.append( + rtl::Uri::encode( aURI.getToken( 0, '/', nIndex ), + rtl_UriCharClassPchar, + rtl_UriEncodeKeepEscapes, /* #i81690# */ + RTL_TEXTENCODING_UTF8 ) ); + if ( nIndex >= 0 ) + aResult.append( sal_Unicode( '/' ) ); + } + while ( nIndex >= 0 ); + + if ( aParams.getLength() > 0 ) + { + aResult.append( sal_Unicode( '?' ) ); + aResult.append( aParams ); + } + + if ( aFragment.getLength() > 0 ) + { + aResult.append( sal_Unicode( '#' ) ); + aResult.append( aFragment ); + } + + return aResult.makeStringAndClear(); + } + +} } // namespace + +#endif /* !INCLUDED_URIHELPER_HXX */ diff --git a/ucb/source/ucp/odma/makefile.mk b/ucb/source/ucp/odma/makefile.mk new file mode 100644 index 000000000000..14a7d3d45c3d --- /dev/null +++ b/ucb/source/ucp/odma/makefile.mk @@ -0,0 +1,97 @@ +#************************************************************************* +# +# 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. +# +#************************************************************************* + +UCP_VERSION=1 +UCP_NAME=odma + + +PRJ=..$/..$/.. +PRJNAME=ucb + +TARGET=ucp$(UCP_NAME) +TARGET2=s$(UCP_NAME) + +ENABLE_EXCEPTIONS=TRUE +USE_DEFFILE=TRUE + +TARGET2TYPE=CUI +LIBTARGET=NO + +# --- Settings --------------------------------------------------------- + +.INCLUDE: settings.mk + +# --- General ----------------------------------------------------- + +SLOFILES=\ + $(SLO)$/odma_lib.obj \ + $(SLO)$/odma_services.obj \ + $(SLO)$/odma_provider.obj \ + $(SLO)$/odma_content.obj \ + $(SLO)$/odma_resultset.obj \ + $(SLO)$/odma_datasupplier.obj \ + $(SLO)$/odma_inputstream.obj \ + $(SLO)$/odma_contentcaps.obj + +LIB1TARGET=$(SLB)$/_$(TARGET).lib +LIB1OBJFILES=$(SLOFILES) + +# --- Shared-Library --------------------------------------------------- + +SHL1TARGET=$(TARGET)$(UCP_VERSION) +SHL1IMPLIB=i$(TARGET) +SHL1VERSIONMAP=$(SOLARENV)/src/component.map + +SHL1STDLIBS=\ + $(CPPUHELPERLIB) \ + $(CPPULIB) \ + $(SALLIB) \ + $(SALHELPERLIB) \ + $(UCBHELPERLIB) + +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +SHL1LIBS=$(LIB1TARGET) + +# --- Def-File --------------------------------------------------------- + +DEF1NAME=$(SHL1TARGET) + +# --- SODMA executable ------------------------------------------------- +OBJFILES= $(OBJ)$/odma_main.obj + +APP2TARGET= $(TARGET2) +APP2OBJS= $(OBJFILES) +APP2STDLIBS=$(SALLIB) \ + $(CPPULIB) \ + $(CPPUHELPERLIB) + +DEF2DES=UCB ODMA URL converter + +# --- Targets ---------------------------------------------------------- + +.INCLUDE: target.mk + diff --git a/ucb/source/ucp/odma/odma.h b/ucb/source/ucp/odma/odma.h new file mode 100644 index 000000000000..8a5ed94b4f65 --- /dev/null +++ b/ucb/source/ucp/odma/odma.h @@ -0,0 +1,315 @@ +/* odma.h - Definitions, prototypes, etc. for Open Document Managment API + (ODMA) version 2.0. + + COPYRIGHT (C) 1994, 1995 + AIIM International + All Right Reserved +*/ + +#ifndef ODMA_H +#define ODMA_H + +/* Type definitions */ +typedef LPVOID ODMHANDLE; +typedef LPSTR (*ODMSAVEASCALLBACK)(DWORD dwEnvData, LPSTR lpszFormat, LPVOID pInstanceData); +typedef int ODMSTATUS; + +/* Constants */ +#define ODM_API_VERSION 200 /* Version of the API */ + +#ifdef WIN32 + #define ODM_DOCID_MAX 255 /* Win32 */ + +#elif defined( _WINDOWS_ ) || defined( _MSDOS ) + #define ODM_DOCID_MAX 80 /* Windows 3.x */ + +#else + #define ODM_DOCID_MAX 255 /* Other platforms */ +#endif + +#define ODM_DMSID_MAX 9 /* Max length of a DMS ID including the + /* terminating NULL character. */ + +#define ODM_APPID_MAX 16 /* Max length of a application ID including + /* the terminating NULL character. */ + +// ODMA 2.0 +#define ODM_QUERYID_MAX 255 // Max length of a query ID including + // the terminating NULL character. + +#define ODM_FORMAT_MAX 81 // Max length of a format including + // the terminating NULL character. + +// Maximum length of a filename returned by ODMA including the terminating +// NULL character. Platform dependent. + +#ifdef WIN32 + #define ODM_FILENAME_MAX 255 /* Win32 */ + +#elif defined( _WINDOWS_ ) || defined( _MSDOS ) + #define ODM_FILENAME_MAX 128 /* Windows 3.x */ + +#elif defined( unix ) || defined( _UNIX ) + #define ODM_FILENAME_MAX 1024 /* Unix */ + +#else + #define ODM_FILENAME_MAX 255 /* Other platforms */ +#endif + + +/* Common format type names */ +#define ODM_FORMAT_TEXT "Text" +#define ODM_FORMAT_RTF "Rich text format" +#define ODM_FORMAT_DCA "DCA RFT" /* IBM DCA Rich Format Text */ +#define ODM_FORMAT_TIFF "Tiff" +#define ODM_FORMAT_GIF "Gif" /* Compuserve Graphics Interchange Format */ +#define ODM_FORMAT_BMP "Windows bitmap" +#define ODM_FORMAT_PCX "PCX" +#define ODM_FORMAT_CGM "CGM" /* Computer Graphics Metafile */ +#define ODM_FORMAT_EXE "Executable file" +#define ODM_FORMAT_PCL "PCL" /* HP Printer Control Language */ +#define ODM_FORMAT_PS "PostScript" + + +/* Error returns */ +#define ODM_SUCCESS 0 // Success! +#define ODM_E_FAIL 1 /* Unspecified failure */ +#define ODM_E_CANCEL 2 /* Action was cancelled at user's request */ +#define ODM_E_NODMS 3 /* DMS not registered */ +#define ODM_E_CANTINIT 4 /* DMS failed to initalize */ +#define ODM_E_VERSION 5 /* DMS doesn't support the requested + version of ODMA */ +#define ODM_E_APPSELECT 6 /* User has indicated that he wants to use + the application's file selection + capabilities rather than those of the + DMS. */ +#define ODM_E_USERINT 7 /* Requested action cannot be performed + without user interaction, but silent + mode was specified. */ +#define ODM_E_HANDLE 8 /* The DMHANDLE argument was invalid. */ +#define ODM_E_ACCESS 9 /* User does not have requested access + rights to specified document. */ +#define ODM_E_INUSE 10 /* Document is currently in use and cannot + be accessed in specified mode. */ +#define ODM_E_DOCID 11 /* Invalid document ID */ +#define ODM_E_OPENMODE 12 /* The specified action is incompatible + with the mode in which the document was + opened. */ +#define ODM_E_NOOPEN 13 /* The specified document is not open. */ +#define ODM_E_ITEM 14 /* Invalid item specifier. */ +#define ODM_E_OTHERAPP 15 /* Selected document was for another app. */ +#define ODM_E_NOMOREDATA 16 /* No more data is available */ +#define ODM_E_PARTIALSUCCESS 17 /* */ +// Additional Error code from ODMA 2.0 +#define ODM_E_REQARG 18 /* */ +#define ODM_E_NOSUPPORT 19 /* */ +#define ODM_E_TRUNCATED 20 /* */ +#define ODM_E_INVARG 21 +#define ODM_E_OFFLINE 22 /* */ + + +// ODMOpenDoc modes +#define ODM_MODIFYMODE 1 /* Open document in a modifiable mode. */ +#define ODM_VIEWMODE 2 /* Open document in non-modifiable mode. */ +// ODMA 2.0 +#define ODM_REFCOPY 3 + + +// Actions for ODMActivate +#define ODM_NONE 0 /* No specific action is requested. */ +#define ODM_DELETE 1 /* Delete the specified document. */ +#define ODM_SHOWATTRIBUTES 2 /* Display the specified document's profile + or attributes. */ +#define ODM_EDITATTRIBUTES 3 /* Edit the specified document's profile or + attributes. */ +#define ODM_VIEWDOC 4 /* Display the specified document in a + viewer window. */ +#define ODM_OPENDOC 5 /* Open the specified document in its + native application. */ +// ODMA 2.0 +#define ODM_NEWDOC 6 +#define ODM_CHECKOUT 7 +#define ODM_CANCELCHECKOUT 8 +#define ODM_CHECKIN 9 +#define ODM_SHOWHISTORY 10 + + +// Item selectors for ODMGetDocInfo and ODMSetDocInfo +#define ODM_AUTHOR 1 /* Author of the document. */ +#define ODM_NAME 2 /* Descriptive name of the document. */ +#define ODM_TYPE 3 /* Type of the document. */ +#define ODM_TITLETEXT 4 /* Suggested text to display in the + document window's title bar. */ +#define ODM_DMS_DEFINED 5 /* DMS defined data. */ +#define ODM_CONTENTFORMAT 6 /* String describing document's format */ +// ODMA 2.0 +#define ODM_ALTERNATE_RENDERINGS 7 +#define ODM_CHECKEDOUTBY 8 +#define ODM_CHECKOUTCOMMENT 9 +#define ODM_CHECKOUTDATE 10 +#define ODM_CREATEDBY 11 +#define ODM_CREATEDDATE 12 +#define ODM_DOCID_LATEST 13 +#define ODM_DOCID_RELEASED 14 +#define ODM_DOCVERSION 15 +#define ODM_DOCVERSION_LATEST 16 +#define ODM_DOCVERSION_RELEASED 17 +#define ODM_LOCATION 18 +#define ODM_KEYWORDS 19 +#define ODM_LASTCHECKINBY 20 +#define ODM_LASTCHECKINDATE 21 +#define ODM_MODIFYDATE 22 +#define ODM_MODIFYDATE_LATEST 23 +#define ODM_MODIFYDATE_RELEASED 24 +#define ODM_OWNER 25 +#define ODM_SUBJECT 26 +#define ODM_TITLETEXT_RO 27 +#define ODM_URL 28 + + +// Item selectors for ODMQueryCapability ODMA 2.0 +#define ODM_QC_ACTIVATE 1 +#define ODM_QC_CLOSEDOC 2 +#define ODM_QC_CLOSEDOCEX 3 +#define ODM_QC_GETALTERNATECONTENT 4 +#define ODM_QC_GETDMSINFO 5 +#define ODM_QC_GETDOCINFO 6 +#define ODM_QC_GETDOCRELATION 7 +#define ODM_QC_GETLEADMONIKER 8 +#define ODM_QC_NEWDOC 9 +#define ODM_QC_OPENDOC 10 +#define ODM_QC_QUERYCLOSE 11 +#define ODM_QC_QUERYEXECUTE 12 +#define ODM_QC_QUERYGETRESULTS 13 +#define ODM_QC_SAVEAS 14 +#define ODM_QC_SAVEASEX 15 +#define ODM_QC_SAVEDOC 16 +#define ODM_QC_SAVEDOCEX 17 +#define ODM_QC_SELECTDOC 18 +#define ODM_QC_SELECTDOCEX 19 +#define ODM_QC_SETALTERNATECONTENT 20 +#define ODM_QC_SETDOCEVENT 21 +#define ODM_QC_SETDOCRELATION 22 +#define ODM_QC_SETDOCINFO 23 + + +// Misc. modes, flags +#define ODM_SILENT 16 /* Don't interact with the user while + fulfilling this request. */ +//ODMA 2.0 +#define ODM_VERSION_SAME 1 +#define ODM_VERSION_MAJOR 2 +#define ODM_VERSION_MINOR 4 +#define ODM_VERSION_CHANGED 8 +#define ODM_ALT_DELETE 32 + +//ODMA 2.0 DMS Info Flags +#define ODM_EXT_QUERY 1 +#define ODM_EXT_WORKFLOW 2 + +// Flags for Query Interface +#define ODM_ALL 1 // All DMS's should be searched +#define ODM_SPECIFIC 2 // Only specific DMS's should be searched + + +// Function prototypes +#ifdef __cplusplus +extern "C" { +#endif + +ODMSTATUS WINAPI ODMRegisterApp(ODMHANDLE FAR *pOdmHandle, WORD version, + LPSTR lpszAppId, DWORD dwEnvData, LPVOID pReserved); + +void WINAPI ODMUnRegisterApp(ODMHANDLE odmHandle); + +ODMSTATUS WINAPI ODMSelectDoc(ODMHANDLE odmHandle, LPSTR lpszDocId, + LPDWORD pdwFlags); + +ODMSTATUS WINAPI ODMOpenDoc(ODMHANDLE odmHandle, DWORD flags, + LPSTR lpszDocId, LPSTR lpszDocLocation); + +ODMSTATUS WINAPI ODMSaveDoc(ODMHANDLE odmHandle, LPSTR lpszDocId, + LPSTR lpszNewDocId); + +ODMSTATUS WINAPI ODMCloseDoc(ODMHANDLE odmHandle, LPSTR lpszDocId, + DWORD activeTime, DWORD pagesPrinted, LPVOID sessionData, WORD dataLen); + +ODMSTATUS WINAPI ODMNewDoc(ODMHANDLE odmHandle, LPSTR lpszDocId, + DWORD dwFlags, LPSTR lpszFormat, LPSTR lpszDocLocation); + +ODMSTATUS WINAPI ODMSaveAs(ODMHANDLE odmHandle, LPSTR lpszDocId, + LPSTR lpszNewDocId, LPSTR lpszFormat, ODMSAVEASCALLBACK pcbCallBack, + LPVOID pInstanceData); + +ODMSTATUS WINAPI ODMActivate(ODMHANDLE odmHandle, WORD action, + LPSTR lpszDocId); + +ODMSTATUS WINAPI ODMGetDocInfo(ODMHANDLE odmHandle, LPSTR lpszDocId, + WORD item, LPSTR lpszData, WORD dataLen); + +ODMSTATUS WINAPI ODMSetDocInfo(ODMHANDLE odmHandle, LPSTR lpszDocId, + WORD item, LPSTR lpszData); + +ODMSTATUS WINAPI ODMGetDMSInfo(ODMHANDLE odmHandle, LPSTR lpszDmsId, + LPWORD pwVerNo, LPDWORD pdwExtensions); + +/* Query Enhancements */ +WORD WINAPI ODMGetDMSCount(); + +WORD WINAPI ODMGetDMSList( LPSTR buffer, WORD buffer_size ); + +ODMSTATUS WINAPI ODMGetDMS( LPCSTR lpszAppId, LPSTR lpszDMSId ); + +ODMSTATUS WINAPI ODMSetDMS( LPCSTR lpszAppId, LPCSTR lpszDMSId ); + +ODMSTATUS WINAPI ODMQueryExecute(ODMHANDLE odmHandle, LPCSTR lpszQuery, + DWORD flags, LPCSTR lpszDMSList, LPSTR queryId ); + +ODMSTATUS WINAPI ODMQueryGetResults(ODMHANDLE odmHandle, LPCSTR queryId, + LPSTR lpszDocId, LPSTR lpszDocName, WORD docNameLen, + WORD *docCount ); + +ODMSTATUS WINAPI ODMQueryClose(ODMHANDLE odmHandle, LPCSTR queryId ); + +/* ODMA 2.0 Enhancements */ +ODMSTATUS WINAPI ODMCloseDocEx(ODMHANDLE odmHandle, LPSTR lpszDocId, + LPDWORD pdwFlags, DWORD activeTime, DWORD pagesPrinted, + LPVOID sessionData, WORD dataLen); + +ODMSTATUS WINAPI ODMSaveAsEx(ODMHANDLE odmHandle, LPSTR lpszDocId, + LPSTR lpszNewDocId, LPSTR lpszFormat, ODMSAVEASCALLBACK pcbCallBack, + LPVOID pInstanceData, LPDWORD pdwFlags); + +ODMSTATUS WINAPI ODMSaveDocEx(ODMHANDLE odmHandle, LPSTR lpszDocId, + LPSTR lpszNewDocId, LPDWORD pdwFlags); + +ODMSTATUS WINAPI ODMSelectDocEx(ODMHANDLE odmHandle, LPSTR lpszDocIds, + LPWORD pwDocIdsLen, LPWORD pwDocCount, LPDWORD pdwFlags, + LPSTR lpszFormatFilter); + +ODMSTATUS WINAPI ODMQueryCapability(ODMHANDLE odmHandle, LPCSTR lpszDmsId, + DWORD function, DWORD item, DWORD flags); + +ODMSTATUS WINAPI ODMSetDocEvent(ODMHANDLE odmHandle, LPSTR lpszDocId, + DWORD flags, DWORD event, LPVOID lpData, DWORD dwDataLen, + LPSTR lpszComment); + +ODMSTATUS WINAPI ODMGetAlternateContent(ODMHANDLE odmHandle, LPSTR lpszDocId, + LPDWORD pdwFlags, LPSTR lpszFormat, LPSTR lpszDocLocation); + +ODMSTATUS WINAPI ODMSetAlternateContent(ODMHANDLE odmHandle, LPSTR lpszDocId, + LPDWORD pdwFlags, LPSTR lpszFormat, LPSTR lpszDocLocation); + +ODMSTATUS WINAPI ODMGetDocRelation(ODMHANDLE odmHandle, LPSTR lpszDocId, + LPDWORD pdwFlags, LPSTR lpszLinkedId, LPSTR lpszFormat, + LPSTR lpszPreviousId); + +ODMSTATUS WINAPI ODMSetDocRelation(ODMHANDLE odmHandle, LPSTR lpszDocId, + LPDWORD pdwFlags, LPSTR lpszLinkedId, LPSTR lpszFormat, + LPSTR lpszPreviousId); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ucb/source/ucp/odma/odma_content.cxx b/ucb/source/ucp/odma/odma_content.cxx new file mode 100644 index 000000000000..ae3c3ede60e7 --- /dev/null +++ b/ucb/source/ucp/odma/odma_content.cxx @@ -0,0 +1,1215 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ +#include <osl/diagnose.h> +#include "odma_contentprops.hxx" +#include <com/sun/star/ucb/XDynamicResultSet.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/beans/XPropertyAccess.hpp> +#include <com/sun/star/lang/IllegalAccessException.hpp> +#include <com/sun/star/ucb/UnsupportedDataSinkException.hpp> +#include <com/sun/star/sdbc/XRow.hpp> +#include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/io/XActiveDataSink.hpp> +#include <com/sun/star/ucb/OpenCommandArgument2.hpp> +#include <com/sun/star/ucb/OpenMode.hpp> +#include <com/sun/star/ucb/XCommandInfo.hpp> +#include <com/sun/star/ucb/XPersistentPropertySet.hpp> +#include <ucbhelper/contentidentifier.hxx> +#include <ucbhelper/propertyvalueset.hxx> +#include <ucbhelper/cancelcommandexecution.hxx> +#include <com/sun/star/ucb/UnsupportedOpenModeException.hpp> +#include <com/sun/star/ucb/MissingInputStreamException.hpp> +#include <com/sun/star/ucb/InsertCommandArgument.hpp> +#include <com/sun/star/ucb/MissingPropertiesException.hpp> +#include <com/sun/star/io/XActiveDataStreamer.hpp> +#include <com/sun/star/ucb/TransferInfo.hpp> +#include <com/sun/star/ucb/NameClash.hpp> +#include "odma_content.hxx" +#include "odma_provider.hxx" +#include "odma_resultset.hxx" +#include "odma_inputstream.hxx" +#include <ucbhelper/content.hxx> +#include <com/sun/star/uno/Exception.hpp> +#include <rtl/ref.hxx> +#include <osl/file.hxx> + +using namespace com::sun::star; +using namespace odma; + +//========================================================================= +//========================================================================= +// +// Content Implementation. +// +//========================================================================= +//========================================================================= + +Content::Content( const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + ContentProvider* pProvider, + const uno::Reference< ucb::XContentIdentifier >& Identifier, + const ::rtl::Reference<ContentProperties>& _rProps) + : ContentImplHelper( rxSMgr, pProvider, Identifier ) + ,m_aProps(_rProps) + ,m_pProvider(pProvider) + ,m_pContent(NULL) +{ + OSL_ENSURE(m_aProps.is(),"No valid ContentPropeties!"); +} + +//========================================================================= +// virtual +Content::~Content() +{ + delete m_pContent; +} + +//========================================================================= +// +// XInterface methods. +// +//========================================================================= + +// virtual +void SAL_CALL Content::acquire() throw() +{ + ContentImplHelper::acquire(); +} + +//========================================================================= +// virtual +void SAL_CALL Content::release() throw() +{ + ContentImplHelper::release(); +} + +//========================================================================= +// virtual +uno::Any SAL_CALL Content::queryInterface( const uno::Type & rType ) + throw ( uno::RuntimeException ) +{ + uno::Any aRet; + + // @@@ Add support for additional interfaces. +#if 0 + aRet = cppu::queryInterface( rType, + static_cast< yyy::Xxxxxxxxx * >( this ) ); +#endif + + return aRet.hasValue() ? aRet : ContentImplHelper::queryInterface( rType ); +} + +//========================================================================= +// +// XTypeProvider methods. +// +//========================================================================= + +XTYPEPROVIDER_COMMON_IMPL( Content ); + +//========================================================================= +// virtual +uno::Sequence< uno::Type > SAL_CALL Content::getTypes() + throw( uno::RuntimeException ) +{ + // @@@ Add own interfaces. + + static cppu::OTypeCollection* pCollection = 0; + + if ( !pCollection ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + if ( !pCollection ) + { + static cppu::OTypeCollection aCollection( + CPPU_TYPE_REF( lang::XTypeProvider ), + CPPU_TYPE_REF( lang::XServiceInfo ), + CPPU_TYPE_REF( lang::XComponent ), + CPPU_TYPE_REF( ucb::XContent ), + CPPU_TYPE_REF( ucb::XCommandProcessor ), + CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ), + CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ), + CPPU_TYPE_REF( beans::XPropertyContainer ), + CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ), + CPPU_TYPE_REF( container::XChild ) ); + pCollection = &aCollection; + } + } + + return (*pCollection).getTypes(); +} + +//========================================================================= +// +// XServiceInfo methods. +// +//========================================================================= + +// virtual +rtl::OUString SAL_CALL Content::getImplementationName() + throw( uno::RuntimeException ) +{ + // @@@ Adjust implementation name. Keep the prefix "com.sun.star.comp."! + return rtl::OUString::createFromAscii( "com.sun.star.comp.odma.Content" ); +} + +//========================================================================= +// virtual +uno::Sequence< rtl::OUString > SAL_CALL Content::getSupportedServiceNames() + throw( uno::RuntimeException ) +{ + // @@@ Adjust macro name. + uno::Sequence< rtl::OUString > aSNS( 1 ); + aSNS.getArray()[ 0 ] + = rtl::OUString::createFromAscii( ODMA_CONTENT_SERVICE_NAME ); + return aSNS; +} + +//========================================================================= +// +// XContent methods. +// +//========================================================================= + +// virtual +rtl::OUString SAL_CALL Content::getContentType() + throw( uno::RuntimeException ) +{ + // @@@ Adjust macro name ( def in odma_provider.hxx ). + return rtl::OUString::createFromAscii( ODMA_CONTENT_TYPE ); +} + +//========================================================================= +// +// XCommandProcessor methods. +// +//========================================================================= + +// virtual +uno::Any SAL_CALL Content::execute( + const ucb::Command& aCommand, + sal_Int32 /*CommandId*/, + const uno::Reference< ucb::XCommandEnvironment >& Environment ) + throw( uno::Exception, + ucb::CommandAbortedException, + uno::RuntimeException ) +{ + uno::Any aRet; + + if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "getPropertyValues" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // getPropertyValues + ////////////////////////////////////////////////////////////////// + + uno::Sequence< beans::Property > Properties; + if ( !( aCommand.Argument >>= Properties ) ) + { + OSL_ENSURE( sal_False, "Wrong argument type!" ); + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + aRet <<= getPropertyValues( Properties, Environment ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "setPropertyValues" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // setPropertyValues + ////////////////////////////////////////////////////////////////// + + uno::Sequence< beans::PropertyValue > aProperties; + if ( !( aCommand.Argument >>= aProperties ) ) + { + OSL_ENSURE( sal_False, "Wrong argument type!" ); + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + if ( !aProperties.getLength() ) + { + OSL_ENSURE( sal_False, "No properties!" ); + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + aRet <<= setPropertyValues( aProperties, Environment ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "getPropertySetInfo" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // getPropertySetInfo + ////////////////////////////////////////////////////////////////// + + // Note: Implemented by base class. + aRet <<= getPropertySetInfo( Environment ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "getCommandInfo" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // getCommandInfo + ////////////////////////////////////////////////////////////////// + + // Note: Implemented by base class. + aRet <<= getCommandInfo( Environment ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "open" ) ) ) + { + ucb::OpenCommandArgument2 aOpenCommand; + if ( !( aCommand.Argument >>= aOpenCommand ) ) + { + OSL_ENSURE( sal_False, "Wrong argument type!" ); + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + sal_Bool bOpenFolder = + ( ( aOpenCommand.Mode == ucb::OpenMode::ALL ) || + ( aOpenCommand.Mode == ucb::OpenMode::FOLDERS ) || + ( aOpenCommand.Mode == ucb::OpenMode::DOCUMENTS ) ); + + if ( bOpenFolder) + { + // open as folder - return result set + + uno::Reference< ucb::XDynamicResultSet > xSet + = new DynamicResultSet( m_xSMgr, + this, + aOpenCommand, + Environment ); + aRet <<= xSet; + } + + if ( aOpenCommand.Sink.is() ) + { + // Open document - supply document data stream. + + // Check open mode + if ( ( aOpenCommand.Mode + == ucb::OpenMode::DOCUMENT_SHARE_DENY_NONE ) || + ( aOpenCommand.Mode + == ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE ) ) + { + // Unsupported. + ucbhelper::cancelCommandExecution( + uno::makeAny( ucb::UnsupportedOpenModeException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + sal_Int16( aOpenCommand.Mode ) ) ), + Environment ); + // Unreachable + } + + + rtl::OUString aURL = m_xIdentifier->getContentIdentifier(); + rtl::OUString sFileURL = openDoc(); + delete m_pContent; + m_pContent = new ::ucbhelper::Content(sFileURL,NULL); + if(!m_pContent->isDocument()) + { + rtl::OUString sErrorMsg(RTL_CONSTASCII_USTRINGPARAM("File: ")); + sErrorMsg += sFileURL; + sErrorMsg += rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" could not be found.")); + ucbhelper::cancelCommandExecution( + uno::makeAny( io::IOException( + sErrorMsg, + static_cast< cppu::OWeakObject * >( this )) ), + Environment ); + } + + uno::Reference< io::XOutputStream > xOut + = uno::Reference< io::XOutputStream >( + aOpenCommand.Sink, uno::UNO_QUERY ); + if ( xOut.is() ) + { + // @@@ PUSH: write data into xOut + m_pContent->openStream(xOut); + } + else + { + uno::Reference< io::XActiveDataSink > xDataSink + = uno::Reference< io::XActiveDataSink >( + aOpenCommand.Sink, uno::UNO_QUERY ); + if ( xDataSink.is() ) + { + // @@@ PULL: wait for client read + uno::Reference< io::XInputStream > xIn; + try + { + xIn = m_pContent->openStream(); + } + catch(uno::Exception&) + { + OSL_ENSURE(0,"Exception occured while creating the file content!"); + } + xDataSink->setInputStream( xIn ); + } + else + { + uno::Reference< io::XActiveDataStreamer > activeDataStreamer( aOpenCommand.Sink,uno::UNO_QUERY ); + if(activeDataStreamer.is()) + { + activeDataStreamer->setStream(new OOdmaStream(m_pContent,getContentProvider(),m_aProps)); + m_pContent = NULL; // don't delete here because the stream is now the owner + } + else + { + // Note: aOpenCommand.Sink may contain an XStream + // implementation. Support for this type of + // sink is optional... + ucbhelper::cancelCommandExecution( + uno::makeAny( ucb::UnsupportedDataSinkException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + aOpenCommand.Sink ) ), + Environment ); + // Unreachable + } + } + } + } + } + else if ( aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "close" ) ) ) + { + getContentProvider()->closeDocument(m_aProps->m_sDocumentId); + } + else if ( aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "delete" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // delete + ////////////////////////////////////////////////////////////////// + + // Remove own and all children's Additional Core Properties. + removeAdditionalPropertySet( sal_True ); + // Remove own and all childrens(!) persistent data. + if(!getContentProvider()->deleteDocument(m_aProps)) + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "insert" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // insert + ////////////////////////////////////////////////////////////////// + + ucb::InsertCommandArgument arg; + if ( !( aCommand.Argument >>= arg ) ) + { + OSL_ENSURE( sal_False, "Wrong argument type!" ); + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + insert( arg.Data, arg.ReplaceExisting, Environment ); + } + else if( ! aCommand.Name.compareToAscii( "transfer" ) ) + { + ucb::TransferInfo aTransferInfo; + if( ! ( aCommand.Argument >>= aTransferInfo ) ) + { + OSL_ENSURE( sal_False, "Wrong argument type!" ); + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + ::rtl::Reference<ContentProperties> aProp = m_aProps; + if(aProp->m_bIsFolder) + { + aProp = getContentProvider()->getContentPropertyWithTitle(aTransferInfo.NewTitle); + if(!aProp.is()) + aProp = getContentProvider()->getContentPropertyWithSavedAsName(aTransferInfo.NewTitle); + sal_Bool bError = !aProp.is(); + if(bError) + { + sal_Char* pExtension = NULL; + ::rtl::OString sExt; + sal_Int32 nPos = aTransferInfo.NewTitle.lastIndexOf('.'); + if(nPos != -1) + { + sExt = ::rtl::OUStringToOString(aTransferInfo.NewTitle.copy(nPos+1),RTL_TEXTENCODING_ASCII_US); + if(sExt.equalsIgnoreAsciiCase("txt")) + pExtension = ODM_FORMAT_TEXT; + else if(sExt.equalsIgnoreAsciiCase("rtf")) + pExtension = ODM_FORMAT_RTF; + else if(sExt.equalsIgnoreAsciiCase("ps")) + pExtension = ODM_FORMAT_PS; + else + pExtension = const_cast<sal_Char*>(sExt.getStr()); + } + else + pExtension = ODM_FORMAT_TEXT; + + sal_Char* lpszNewDocId = new sal_Char[ODM_DOCID_MAX]; + void *pData = NULL; + DWORD dwFlags = ODM_SILENT; + ODMSTATUS odm = NODMSaveAsEx(ContentProvider::getHandle(), + NULL, // means it is saved the first time + lpszNewDocId, + pExtension, + NULL, // no callback function here + pData, + &dwFlags); + + // check if we have to call the DMS dialog + if(odm == ODM_E_USERINT) + { + dwFlags = 0; + odm = NODMSaveAsEx(ContentProvider::getHandle(), + NULL, // means it is saved the first time + lpszNewDocId, + pExtension, + NULL, // no callback function here + pData, + &dwFlags); + } + bError = odm != ODM_SUCCESS; + if(!bError) + { + aProp = new ContentProperties(); + aProp->m_sDocumentId = ::rtl::OString(lpszNewDocId); + aProp->m_sContentType = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ODMA_CONTENT_TYPE)); + aProp->m_sSavedAsName = aTransferInfo.NewTitle; + getContentProvider()->append(aProp); + + // now set the title + WORD nDocInfo = ODM_NAME; + ::rtl::OUString sFileName = aTransferInfo.NewTitle; + sal_Int32 nIndex = aTransferInfo.NewTitle.lastIndexOf( sal_Unicode('.') ); + if(nIndex != -1) + sFileName = aTransferInfo.NewTitle.copy(0,nIndex); + + ::rtl::OString sDocInfoValue = ::rtl::OUStringToOString(sFileName,RTL_TEXTENCODING_ASCII_US); + odm = NODMSetDocInfo( ContentProvider::getHandle(), + lpszNewDocId, + nDocInfo, + const_cast<sal_Char*>(sDocInfoValue.getStr()) + ); + + } + else if ( odm == ODM_E_CANCEL) + NODMActivate(ContentProvider::getHandle(), + ODM_DELETE, + lpszNewDocId); + + delete [] lpszNewDocId; + } + if(bError) + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + } + rtl::OUString sFileURL = ContentProvider::openDoc(aProp); + + sal_Int32 nLastIndex = sFileURL.lastIndexOf( sal_Unicode('/') ); + ::ucbhelper::Content aContent(sFileURL.copy(0,nLastIndex),NULL); + // aTransferInfo.NameClash = ucb::NameClash::OVERWRITE; + aTransferInfo.NewTitle = sFileURL.copy( 1 + nLastIndex ); + aContent.executeCommand(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("transfer")),uno::makeAny(aTransferInfo)); + getContentProvider()->saveDocument(aProp->m_sDocumentId); + } + else + { + ////////////////////////////////////////////////////////////////// + // Unsupported command + ////////////////////////////////////////////////////////////////// + + OSL_ENSURE( sal_False, "Content::execute - unsupported command!" ); + + ucbhelper::cancelCommandExecution( + uno::makeAny( ucb::UnsupportedCommandException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ) ) ), + Environment ); + // Unreachable + } + + return aRet; +} + +//========================================================================= +// virtual +void SAL_CALL Content::abort( sal_Int32 /*CommandId*/ ) + throw( uno::RuntimeException ) +{ + // @@@ Implement logic to abort running commands, if this makes + // sense for your content. +} + +//========================================================================= +// +// Non-interface methods. +// +//========================================================================= + +// virtual +::rtl::OUString Content::getParentURL() +{ + ::rtl::OUString sURL = m_xIdentifier->getContentIdentifier(); + + // @@@ Extract URL of parent from aURL and return it... + static ::rtl::OUString sScheme1(RTL_CONSTASCII_USTRINGPARAM(ODMA_URL_SCHEME ODMA_URL_SHORT "/")); + static ::rtl::OUString sScheme2(RTL_CONSTASCII_USTRINGPARAM(ODMA_URL_SCHEME ODMA_URL_SHORT)); + if(sURL == sScheme1 || sURL == sScheme2) + sURL = ::rtl::OUString(); + else + sURL = sScheme1; + + return sURL; +} + +//========================================================================= +// static +uno::Reference< sdbc::XRow > Content::getPropertyValues( + const uno::Reference< lang::XMultiServiceFactory >& rSMgr, + const uno::Sequence< beans::Property >& rProperties, + const rtl::Reference<ContentProperties>& rData, + const rtl::Reference< ::ucbhelper::ContentProviderImplHelper >& rProvider, + const rtl::OUString& rContentId ) +{ + // Note: Empty sequence means "get values of all supported properties". + + rtl::Reference< ::ucbhelper::PropertyValueSet > xRow + = new ::ucbhelper::PropertyValueSet( rSMgr ); + + sal_Int32 nCount = rProperties.getLength(); + if ( nCount ) + { + uno::Reference< beans::XPropertySet > xAdditionalPropSet; + sal_Bool bTriedToGetAdditonalPropSet = sal_False; + + const beans::Property* pProps = rProperties.getConstArray(); + for ( sal_Int32 n = 0; n < nCount; ++n ) + { + const beans::Property& rProp = pProps[ n ]; + + // Process Core properties. + + if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) ) + { + xRow->appendString ( rProp, rData->m_sContentType ); + } + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "Title" ) ) ) + { + xRow->appendString ( rProp, rData->m_sTitle ); + } + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) ) + { + xRow->appendBoolean( rProp, rData->m_bIsDocument ); + } + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) ) + { + xRow->appendBoolean( rProp, rData->m_bIsFolder ); + } + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "DateCreated" ) ) ) + { + xRow->appendTimestamp( rProp, rData->m_aDateCreated ); + } + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "DateModified" ) ) ) + { + xRow->appendTimestamp( rProp, rData->m_aDateModified ); + } + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "IsReadOnly" ) ) ) + { + xRow->appendBoolean( rProp, rData->m_bIsReadOnly ); + } + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "Author" ) ) ) + { + xRow->appendString ( rProp, rData->m_sAuthor ); + } + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "Subject" ) ) ) + { + xRow->appendString ( rProp, rData->m_sSubject ); + } + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "Keywords" ) ) ) + { + xRow->appendString ( rProp, rData->m_sKeywords ); + } + else + { + // @@@ Note: If your data source supports adding/removing + // properties, you should implement the interface + // XPropertyContainer by yourself and supply your own + // logic here. The base class uses the service + // "com.sun.star.ucb.Store" to maintain Additional Core + // properties. But using server functionality is preferred! + + // Not a Core Property! Maybe it's an Additional Core Property?! + + if ( !bTriedToGetAdditonalPropSet && !xAdditionalPropSet.is() ) + { + xAdditionalPropSet + = uno::Reference< beans::XPropertySet >( + rProvider->getAdditionalPropertySet( rContentId, + sal_False ), + uno::UNO_QUERY ); + bTriedToGetAdditonalPropSet = sal_True; + } + + if ( xAdditionalPropSet.is() ) + { + if ( !xRow->appendPropertySetValue( + xAdditionalPropSet, + rProp ) ) + { + // Append empty entry. + xRow->appendVoid( rProp ); + } + } + else + { + // Append empty entry. + xRow->appendVoid( rProp ); + } + } + } + } + else + { + // Append all Core Properties. + xRow->appendString ( + beans::Property( rtl::OUString::createFromAscii( "ContentType" ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ), + rData->m_sContentType ); + xRow->appendString ( + beans::Property( rtl::OUString::createFromAscii( "Title" ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND ), + rData->m_sTitle ); + xRow->appendBoolean( + beans::Property( rtl::OUString::createFromAscii( "IsDocument" ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ), + rData->m_bIsDocument ); + xRow->appendBoolean( + beans::Property( rtl::OUString::createFromAscii( "IsFolder" ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ), + rData->m_bIsFolder ); + + // @@@ Append other properties supported directly. + xRow->appendTimestamp( + beans::Property( rtl::OUString::createFromAscii( "DateCreated" ), + -1, + getCppuType(static_cast< const util::DateTime * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ), + rData->m_aDateCreated ); + xRow->appendTimestamp( + beans::Property( rtl::OUString::createFromAscii( "DateModified" ), + -1, + getCppuType(static_cast< const util::DateTime * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ), + rData->m_aDateModified ); + xRow->appendBoolean( + beans::Property( rtl::OUString::createFromAscii( "IsReadOnly" ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ), + rData->m_bIsReadOnly ); + xRow->appendString ( + beans::Property( rtl::OUString::createFromAscii( "Author" ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND ), + rData->m_sAuthor ); + xRow->appendString ( + beans::Property( rtl::OUString::createFromAscii( "Subject" ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND ), + rData->m_sSubject ); + xRow->appendString ( + beans::Property( rtl::OUString::createFromAscii( "Keywords" ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND ), + rData->m_sKeywords ); + + // @@@ Note: If your data source supports adding/removing + // properties, you should implement the interface + // XPropertyContainer by yourself and supply your own + // logic here. The base class uses the service + // "com.sun.star.ucb.Store" to maintain Additional Core + // properties. But using server functionality is preferred! + + // Append all Additional Core Properties. + + uno::Reference< beans::XPropertySet > xSet( + rProvider->getAdditionalPropertySet( rContentId, sal_False ), + uno::UNO_QUERY ); + xRow->appendPropertySet( xSet ); + } + + return uno::Reference< sdbc::XRow >( xRow.get() ); +} + +//========================================================================= +uno::Reference< sdbc::XRow > Content::getPropertyValues( + const uno::Sequence< beans::Property >& rProperties, + const uno::Reference< ucb::XCommandEnvironment >& /*xEnv*/ ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + return getPropertyValues( m_xSMgr, + rProperties, + m_aProps, + rtl::Reference< + ::ucbhelper::ContentProviderImplHelper >( + m_xProvider.get() ), + m_xIdentifier->getContentIdentifier() ); +} + +//========================================================================= +uno::Sequence< uno::Any > Content::setPropertyValues( + const uno::Sequence< beans::PropertyValue >& rValues, + const uno::Reference< ucb::XCommandEnvironment >& /*xEnv*/ ) +{ + osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); + + uno::Sequence< uno::Any > aRet( rValues.getLength() ); + uno::Sequence< beans::PropertyChangeEvent > aChanges( rValues.getLength() ); + sal_Int32 nChanged = 0; + + beans::PropertyChangeEvent aEvent; + aEvent.Source = static_cast< cppu::OWeakObject * >( this ); + aEvent.Further = sal_False; +// aEvent.PropertyName = + aEvent.PropertyHandle = -1; +// aEvent.OldValue = +// aEvent.NewValue = + + const beans::PropertyValue* pValues = rValues.getConstArray(); + sal_Int32 nCount = rValues.getLength(); + + uno::Reference< ucb::XPersistentPropertySet > xAdditionalPropSet; + sal_Bool bTriedToGetAdditonalPropSet = sal_False; + + for ( sal_Int32 n = 0; n < nCount; ++n ) + { + const beans::PropertyValue& rValue = pValues[ n ]; + + if ( rValue.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "Title" ) ) ) + { + changePropertyValue(rValue,n,m_aProps->m_sTitle,nChanged,aRet,aChanges); + } + else if ( rValue.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "Author") ) ) + { + changePropertyValue(rValue,n,m_aProps->m_sAuthor,nChanged,aRet,aChanges); + } + else if ( rValue.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "Keywords") ) ) + { + changePropertyValue(rValue,n,m_aProps->m_sKeywords,nChanged,aRet,aChanges); + } + else if ( rValue.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "Subject") ) ) + { + changePropertyValue(rValue,n,m_aProps->m_sSubject,nChanged,aRet,aChanges); + } + else if ( rValue.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) || + rValue.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) || + rValue.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) || + rValue.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "DateCreated" ) ) || + rValue.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "DateModified" ) ) || + rValue.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "IsReadOnly" ) ) ) + { + // Read-only property! + aRet[ n ] <<= lang::IllegalAccessException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Property is read-only!") ), + static_cast< cppu::OWeakObject * >( this ) ); + } + else + { + // @@@ Note: If your data source supports adding/removing + // properties, you should implement the interface + // XPropertyContainer by yourself and supply your own + // logic here. The base class uses the service + // "com.sun.star.ucb.Store" to maintain Additional Core + // properties. But using server functionality is preferred! + + // Not a Core Property! Maybe it's an Additional Core Property?! + + if ( !bTriedToGetAdditonalPropSet && !xAdditionalPropSet.is() ) + { + xAdditionalPropSet = getAdditionalPropertySet( sal_False ); + bTriedToGetAdditonalPropSet = sal_True; + } + + if ( xAdditionalPropSet.is() ) + { + try + { + uno::Any aOldValue + = xAdditionalPropSet->getPropertyValue( rValue.Name ); + if ( aOldValue != rValue.Value ) + { + xAdditionalPropSet->setPropertyValue( + rValue.Name, rValue.Value ); + + aEvent.PropertyName = rValue.Name; + aEvent.OldValue = aOldValue; + aEvent.NewValue = rValue.Value; + + aChanges.getArray()[ nChanged ] = aEvent; + nChanged++; + } + else + { + // Old value equals new value. No error! + } + } + catch ( beans::UnknownPropertyException const & e ) + { + aRet[ n ] <<= e; + } + catch ( lang::WrappedTargetException const & e ) + { + aRet[ n ] <<= e; + } + catch ( beans::PropertyVetoException const & e ) + { + aRet[ n ] <<= e; + } + catch ( lang::IllegalArgumentException const & e ) + { + aRet[ n ] <<= e; + } + } + else + { + aRet[ n ] <<= uno::Exception( + rtl::OUString::createFromAscii( + "No property set for storing the value!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + } + } + + if ( nChanged > 0 ) + { + // @@@ Save changes. +// storeData(); + + aGuard.clear(); + aChanges.realloc( nChanged ); + notifyPropertiesChange( aChanges ); + } + + return aRet; +} + +#if 0 +//========================================================================= +void Content::queryChildren( ContentRefList& rChildren ) +{ + // @@@ Adapt method to your URL scheme... + + // Obtain a list with a snapshot of all currently instanciated contents + // from provider and extract the contents which are direct children + // of this content. + + ::ucbhelper::ContentRefList aAllContents; + m_xProvider->queryExistingContents( aAllContents ); + + OUString aURL = m_xIdentifier->getContentIdentifier(); + sal_Int32 nPos = aURL.lastIndexOf( '/' ); + + if ( nPos != ( aURL.getLength() - 1 ) ) + { + // No trailing slash found. Append. + aURL += OUString::createFromAscii( "/" ); + } + + sal_Int32 nLen = aURL.getLength(); + + ::ucbhelper::ContentRefList::const_iterator it = aAllContents.begin(); + ::ucbhelper::ContentRefList::const_iterator end = aAllContents.end(); + + while ( it != end ) + { + ::ucbhelper::ContentImplHelperRef xChild = (*it); + OUString aChildURL = xChild->getIdentifier()->getContentIdentifier(); + + // Is aURL a prefix of aChildURL? + if ( ( aChildURL.getLength() > nLen ) && + ( aChildURL.compareTo( aURL, nLen ) == 0 ) ) + { + sal_Int32 nPos = nLen; + nPos = aChildURL.indexOf( '/', nPos ); + + if ( ( nPos == -1 ) || + ( nPos == ( aChildURL.getLength() - 1 ) ) ) + { + // No further slashes / only a final slash. It's a child! + rChildren.push_back( + ContentRef( + static_cast< Content * >( xChild.get() ) ) ); + } + } + ++it; + } +} +#endif +//========================================================================= +void Content::insert( + const uno::Reference< io::XInputStream > & xInputStream, + sal_Bool bReplaceExisting, + const uno::Reference< ucb::XCommandEnvironment >& Environment ) + throw( uno::Exception ) +{ + osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); + + // Check, if all required properties were set. + if ( !m_aProps->m_sTitle.getLength()) + { + OSL_ENSURE( sal_False, "Content::insert - property value missing!" ); + + uno::Sequence< rtl::OUString > aProps( 1 ); + aProps[ 0 ] = rtl::OUString::createFromAscii( "zzzz" ); + ucbhelper::cancelCommandExecution( + uno::makeAny( ucb::MissingPropertiesException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + aProps ) ), + Environment ); + // Unreachable + } + + if ( !xInputStream.is() ) + { + OSL_ENSURE( sal_False, "Content::insert - No data stream!" ); + + ucbhelper::cancelCommandExecution( + uno::makeAny( ucb::MissingInputStreamException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ) ) ), + Environment ); + // Unreachable + } + + // Assemble new content identifier... + + // uno::Reference< ucb::XContentIdentifier > xId = ...; + + // Fail, if a resource with given id already exists. + if ( !bReplaceExisting ) // && hasData( m_xIdentifier ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( ucb::UnsupportedCommandException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ) ) ), + Environment ); +// ucbhelper::cancelCommandExecution( +// ucb::IOErrorCode_ALREADY_EXISTING, +// Environment, +// uno::makeAny(static_cast< cppu::OWeakObject * >( this )) +// ); + // Unreachable + } + + // m_xIdentifier = xId; + +// @@@ +// storeData(); + + aGuard.clear(); + inserted(); +} +#if 0 +//========================================================================= +void Content::destroy( sal_Bool bDeletePhysical ) + throw( uno::Exception ) +{ + // @@@ take care about bDeletePhysical -> trashcan support + + uno::Reference< ucb::XContent > xThis = this; + + deleted(); + + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + // Process instanciated children... + + ContentRefList aChildren; + queryChildren( aChildren ); + + ContentRefList::const_iterator it = aChildren.begin(); + ContentRefList::const_iterator end = aChildren.end(); + + while ( it != end ) + { + (*it)->destroy( bDeletePhysical ); + ++it; + } +} +#endif + +// ----------------------------------------------------------------------------- +::rtl::OUString Content::openDoc() +{ + OSL_ENSURE(m_aProps.is(),"No valid content properties!"); + return ContentProvider::openDoc(m_aProps); +} +// ----------------------------------------------------------------------------- +void Content::changePropertyValue(const beans::PropertyValue& _rValue, + sal_Int32 _rnCurrentPos, + ::rtl::OUString& _rsMemberValue, + sal_Int32& _rnChanged, + uno::Sequence< uno::Any >& _rRet, + uno::Sequence< beans::PropertyChangeEvent >& _rChanges) throw (beans::IllegalTypeException) +{ + rtl::OUString sNewValue; + sal_Bool bError = sal_False; + if ( _rValue.Value >>= sNewValue ) + { + if ( sNewValue != _rsMemberValue ) + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + // first we have to check if we could change the property inside the DMS + ::rtl::OString sDocInfoValue = ::rtl::OUStringToOString(sNewValue,RTL_TEXTENCODING_ASCII_US); + WORD nDocInfo = 0; + if(&_rsMemberValue == &m_aProps->m_sTitle) + nDocInfo = ODM_TITLETEXT; + else if(&_rsMemberValue == &m_aProps->m_sAuthor) + nDocInfo = ODM_AUTHOR; + else if(&_rsMemberValue == &m_aProps->m_sSubject) + nDocInfo = ODM_SUBJECT; + else if(&_rsMemberValue == &m_aProps->m_sKeywords) + nDocInfo = ODM_KEYWORDS; + else + bError = sal_True; + + if(!bError) + { + ODMSTATUS odm = NODMSetDocInfo( ContentProvider::getHandle(), + const_cast<sal_Char*>(m_aProps->m_sDocumentId.getStr()), + nDocInfo, + const_cast<sal_Char*>(sDocInfoValue.getStr()) + ); + if(odm == ODM_SUCCESS) + { + beans::PropertyChangeEvent aEvent; + aEvent.Source = static_cast< cppu::OWeakObject * >( this ); + aEvent.Further = sal_False; + aEvent.PropertyHandle = -1; + aEvent.PropertyName = _rValue.Name; + aEvent.OldValue = uno::makeAny( _rsMemberValue ); + aEvent.NewValue = uno::makeAny( sNewValue ); + + _rChanges.getArray()[ _rnChanged ] = aEvent; + + _rsMemberValue = sNewValue; + ++_rnChanged; + } + } + } + else + { + // Old value equals new value. No error! + } + } + else + bError = sal_True; + + if(bError) + { + _rRet[ _rnCurrentPos ] <<= beans::IllegalTypeException( + rtl::OUString::createFromAscii( + "Property value has wrong type!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } +} +// ----------------------------------------------------------------------------- + diff --git a/ucb/source/ucp/odma/odma_content.hxx b/ucb/source/ucp/odma/odma_content.hxx new file mode 100644 index 000000000000..30422a82e284 --- /dev/null +++ b/ucb/source/ucp/odma/odma_content.hxx @@ -0,0 +1,196 @@ +/************************************************************************* + * + * 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 ODMA_CONTENT_HXX +#define ODMA_CONTENT_HXX + +#include <list> +#include <ucbhelper/contenthelper.hxx> + +namespace com { namespace sun { namespace star { + namespace beans { + struct Property; + struct PropertyValue; + } + namespace sdbc { + class XRow; + } + namespace io { + class XInputStream; + } +}}} +namespace ucbhelper +{ + class Content; +} + + +// @@@ Adjust namespace name. +namespace odma +{ + +//========================================================================= + +// @@@ Adjust service name. + +// UNO service name for the content. +#define ODMA_CONTENT_SERVICE_NAME \ + "com.sun.star.ucb.OdmaContent" + +//========================================================================= +class ContentProvider; +class ContentProperties; +class Content : public ::ucbhelper::ContentImplHelper +{ + ::rtl::Reference<ContentProperties> m_aProps; + ContentProvider* m_pProvider; + ::ucbhelper::Content* m_pContent; + +private: + virtual com::sun::star::uno::Sequence< com::sun::star::beans::Property > + getProperties( const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv ); + virtual com::sun::star::uno::Sequence< com::sun::star::ucb::CommandInfo > + getCommands( const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv ); + virtual ::rtl::OUString getParentURL(); + + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRow > + getPropertyValues( const ::com::sun::star::uno::Sequence< + ::com::sun::star::beans::Property >& rProperties, + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment >& xEnv ); + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > + setPropertyValues( const ::com::sun::star::uno::Sequence< + ::com::sun::star::beans::PropertyValue >& rValues, + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment >& xEnv ); + + /** openDoc returns the file URL for the DOC ID + @return the url of the temporary file + */ + ::rtl::OUString openDoc(); + + /** changePropertyValue sets the property referenced by _sMemberValue to the new value + @param _rValue the new value to set + @param _rnCurrentPos the current position inside the Any sequence _rRet + @param _sMemberValue the place where to set the property + @param _rnChanged will be incremented when property changed + @param _rRet collect the exceptions + @param _rChanges contains the changes done + */ + void changePropertyValue(const ::com::sun::star::beans::PropertyValue& _rValue, + sal_Int32 _rnCurrentPos, + ::rtl::OUString& _rsMemberValue, + sal_Int32& _rnChanged, + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& _rRet, + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyChangeEvent >& _rChanges) throw (::com::sun::star::beans::IllegalTypeException); + +// typedef rtl::Reference< Content > ContentRef; +// typedef std::list< ContentRef > ContentRefList; +// void queryChildren( ContentRefList& rChildren ); + + // Command "insert" + void insert( const ::com::sun::star::uno::Reference< + ::com::sun::star::io::XInputStream > & xInputStream, + sal_Bool bReplaceExisting, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment >& Environment ) + throw( ::com::sun::star::uno::Exception ); + +// // Command "delete" +// void destroy( sal_Bool bDeletePhysical ) +// throw( ::com::sun::star::uno::Exception ); + +public: + Content( const ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + ContentProvider* pProvider, + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XContentIdentifier >& Identifier, + const ::rtl::Reference<ContentProperties>& _rProps); + virtual ~Content(); + + // XInterface + XINTERFACE_DECL() + + // XTypeProvider + XTYPEPROVIDER_DECL() + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL + getImplementationName() + throw( ::com::sun::star::uno::RuntimeException ); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL + getSupportedServiceNames() + throw( ::com::sun::star::uno::RuntimeException ); + + // XContent + virtual rtl::OUString SAL_CALL + getContentType() + throw( com::sun::star::uno::RuntimeException ); + + // XCommandProcessor + virtual com::sun::star::uno::Any SAL_CALL + execute( const com::sun::star::ucb::Command& aCommand, + sal_Int32 CommandId, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment >& Environment ) + throw( com::sun::star::uno::Exception, + com::sun::star::ucb::CommandAbortedException, + com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + abort( sal_Int32 CommandId ) + throw( com::sun::star::uno::RuntimeException ); + + ////////////////////////////////////////////////////////////////////// + // Additional interfaces + ////////////////////////////////////////////////////////////////////// + + // @@@ Add additional interfaces ( like com::sun:.star::ucb::XContentCreator ). + + ////////////////////////////////////////////////////////////////////// + // Non-interface methods. + ////////////////////////////////////////////////////////////////////// + + // Called from resultset data supplier. + static ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRow > + getPropertyValues( const ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XMultiServiceFactory >& rSMgr, + const ::com::sun::star::uno::Sequence< + ::com::sun::star::beans::Property >& rProperties, + const ::rtl::Reference<ContentProperties>& rData, + const ::rtl::Reference< + ::ucbhelper::ContentProviderImplHelper >& rProvider, + const ::rtl::OUString& rContentId ); + + ContentProvider* getContentProvider() const { return m_pProvider; } +}; + +} + +#endif diff --git a/ucb/source/ucp/odma/odma_contentcaps.cxx b/ucb/source/ucp/odma/odma_contentcaps.cxx new file mode 100644 index 000000000000..8bc0b5cd51dc --- /dev/null +++ b/ucb/source/ucp/odma/odma_contentcaps.cxx @@ -0,0 +1,247 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ +#include <com/sun/star/beans/Property.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/ucb/CommandInfo.hpp> +#include <com/sun/star/ucb/InsertCommandArgument.hpp> +#include <com/sun/star/ucb/OpenCommandArgument2.hpp> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/util/DateTime.hpp> +#include <com/sun/star/ucb/TransferInfo.hpp> +#include "odma_content.hxx" + +using namespace com::sun::star; +using namespace odma; + +//========================================================================= +// +// Content implementation. +// +//========================================================================= + +//========================================================================= +// +// IMPORTENT: If any property data ( name / type / ... ) are changed, then +// Content::getPropertyValues(...) must be adapted too! +// +//========================================================================= + +// virtual +uno::Sequence< beans::Property > Content::getProperties( + const uno::Reference< ucb::XCommandEnvironment > & /*xEnv*/ ) +{ + // @@@ Add additional properties... + + // @@@ Note: If your data source supports adding/removing properties, + // you should implement the interface XPropertyContainer + // by yourself and supply your own logic here. The base class + // uses the service "com.sun.star.ucb.Store" to maintain + // Additional Core properties. But using server functionality + // is preferred! In fact you should return a table conatining + // even that dynamicly added properties. + +// osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + //================================================================= + // + // Supported properties + // + //================================================================= + + #define PROPERTY_COUNT 10 + + static beans::Property aPropertyInfoTable[] = + { + /////////////////////////////////////////////////////////////// + // Required properties + /////////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ContentType" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsDocument" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + ), + /////////////////////////////////////////////////////////////// + // Optional standard properties + /////////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DateCreated" ) ), + -1, + getCppuType(static_cast< const util::DateTime * >( 0 ) ), + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DateModified" ) ), + -1, + getCppuType(static_cast< const util::DateTime * >( 0 ) ), + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsReadOnly" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY + ), + /////////////////////////////////////////////////////////////// + // New properties + /////////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Author" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Subject" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Keywords" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + ) + }; + return uno::Sequence< + beans::Property >( aPropertyInfoTable, PROPERTY_COUNT ); +} + +//========================================================================= +// virtual +uno::Sequence< ucb::CommandInfo > Content::getCommands( + const uno::Reference< ucb::XCommandEnvironment > & /*xEnv*/ ) +{ + // @@@ Add additional commands... + +// osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + //================================================================= + // + // Supported commands + // + //================================================================= + + #define COMMAND_COUNT 8 + + static ucb::CommandInfo aCommandInfoTable[] = + { + /////////////////////////////////////////////////////////////// + // Required commands + /////////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getCommandInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getPropertySetInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getPropertyValues" ) ), + -1, + getCppuType( + static_cast< uno::Sequence< beans::Property > * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ), + -1, + getCppuType( + static_cast< uno::Sequence< beans::PropertyValue > * >( 0 ) ) + ), + /////////////////////////////////////////////////////////////// + // Optional standard commands + /////////////////////////////////////////////////////////////// +/* + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "delete" ) ), + -1, + getCppuBooleanType() + ), +*/ + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "insert" ) ), + -1, + getCppuType( + static_cast< ucb::InsertCommandArgument * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "open" ) ), + -1, + getCppuType( static_cast< ucb::OpenCommandArgument2 * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "close" ) ), + -1, + getCppuVoidType( ) + ), + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "transfer" ) ), + -1, + getCppuType( static_cast< ucb::TransferInfo * >( 0 ) ) + ) + + /////////////////////////////////////////////////////////////// + // New commands + /////////////////////////////////////////////////////////////// + }; + + return uno::Sequence< + ucb::CommandInfo >( aCommandInfoTable, COMMAND_COUNT ); +} + diff --git a/ucb/source/ucp/odma/odma_contentprops.hxx b/ucb/source/ucp/odma/odma_contentprops.hxx new file mode 100644 index 000000000000..602c1d3d8354 --- /dev/null +++ b/ucb/source/ucp/odma/odma_contentprops.hxx @@ -0,0 +1,85 @@ +/************************************************************************* + * + * 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 ODMA_CONTENTPROPS_HXX +#define ODMA_CONTENTPROPS_HXX + +#include "rtl/ref.hxx" +#include "salhelper/simplereferenceobject.hxx" +#include <rtl/ustring.hxx> +#include <com/sun/star/util/DateTime.hpp> +#include <functional> + +namespace odma +{ + class ContentProperties : public salhelper::SimpleReferenceObject + { + public: + com::sun::star::util::DateTime m_aDateCreated; // when was the document created + com::sun::star::util::DateTime m_aDateModified; // when was the document last modified + ::rtl::OUString m_sTitle; // Title + ::rtl::OUString m_sContentType; // ContentType + ::rtl::OString m_sDocumentId; // the document id given from the DMS + ::rtl::OUString m_sDocumentName;// document name + ::rtl::OUString m_sFileURL; // the temporary file location + ::rtl::OUString m_sAuthor; // the Author of the document + ::rtl::OUString m_sSubject; // the subject of the document + ::rtl::OUString m_sKeywords; // the keywords of the document + ::rtl::OUString m_sSavedAsName; // the name which was used to save it + sal_Bool m_bIsDocument; // IsDocument + sal_Bool m_bIsFolder; // IsFolder + sal_Bool m_bIsOpen; // is true when OpenDoc was called + sal_Bool m_bIsReadOnly; // true when the document is read-only + + // @@@ Add other properties supported by your content. + + ContentProperties() + :m_bIsDocument( sal_True ) + ,m_bIsFolder( sal_False ) + ,m_bIsOpen( sal_False ) + ,m_bIsReadOnly( sal_False ) + {} + + inline ::rtl::OUString getTitle() const { return m_sTitle; } + inline ::rtl::OUString getSavedAsName() const { return m_sSavedAsName; } + }; + typedef ::std::binary_function< ::rtl::Reference<ContentProperties>, ::rtl::OUString,bool> TContentPropertiesFunctorBase; + /// binary_function Functor object for class ContentProperties return type is bool + class ContentPropertiesMemberFunctor : public TContentPropertiesFunctorBase + { + ::std::const_mem_fun_t< ::rtl::OUString,ContentProperties> m_aFunction; + public: + ContentPropertiesMemberFunctor(const ::std::const_mem_fun_t< ::rtl::OUString,ContentProperties>& _rFunc) + : m_aFunction(_rFunc){} + + inline bool operator()(const ::rtl::Reference<ContentProperties>& lhs,const ::rtl::OUString& rhs) const + { + return !!(m_aFunction(lhs.get()) == rhs); + } + }; +} +#endif // ODMA_CONTENTPROPS_HXX + diff --git a/ucb/source/ucp/odma/odma_datasupplier.cxx b/ucb/source/ucp/odma/odma_datasupplier.cxx new file mode 100644 index 000000000000..aab2a3d8663c --- /dev/null +++ b/ucb/source/ucp/odma/odma_datasupplier.cxx @@ -0,0 +1,455 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ + +#include <vector> +#include <ucbhelper/contentidentifier.hxx> +#include <ucbhelper/providerhelper.hxx> +#include "odma_datasupplier.hxx" +#include "odma_content.hxx" +#include "odma_contentprops.hxx" +#include "odma_provider.hxx" +#include "odma_lib.hxx" + +using namespace com::sun::star::beans; +using namespace com::sun::star::lang; +using namespace com::sun::star::ucb; +using namespace com::sun::star::uno; +using namespace com::sun::star::sdbc; + +using namespace odma; + +namespace odma +{ + +//========================================================================= +// +// struct ResultListEntry. +// +//========================================================================= + +struct ResultListEntry +{ + ::rtl::OUString aId; + Reference< XContentIdentifier > xId; + Reference< XContent > xContent; + Reference< XRow > xRow; + ::rtl::Reference<ContentProperties> rData; + + ResultListEntry( const ::rtl::Reference<ContentProperties>& rEntry ) : rData( rEntry ) {} +}; + +//========================================================================= +// +// ResultList. +// +//========================================================================= + +typedef std::vector< ResultListEntry* > ResultList; + +//========================================================================= +// +// struct DataSupplier_Impl. +// +//========================================================================= + +struct DataSupplier_Impl +{ + osl::Mutex m_aMutex; + ResultList m_aResults; + rtl::Reference< Content > m_xContent; + Reference< XMultiServiceFactory > m_xSMgr; +// @@@ The data source and an iterator for it +// Entry m_aFolder; +// Entry::iterator m_aIterator; + sal_Int32 m_nOpenMode; + sal_Bool m_bCountFinal; + + DataSupplier_Impl( const Reference< XMultiServiceFactory >& rxSMgr, + const rtl::Reference< Content >& rContent, + sal_Int32 nOpenMode ) + : m_xContent( rContent ), m_xSMgr( rxSMgr ), +// m_aFolder( rxSMgr, rContent->getIdentifier()->getContentIdentifier() ), + m_nOpenMode( nOpenMode ), m_bCountFinal( sal_False ) {} + ~DataSupplier_Impl(); +}; + +//========================================================================= +DataSupplier_Impl::~DataSupplier_Impl() +{ + ResultList::const_iterator it = m_aResults.begin(); + ResultList::const_iterator end = m_aResults.end(); + + while ( it != end ) + { + delete (*it); + it++; + } +} + +} + +//========================================================================= +//========================================================================= +// +// DataSupplier Implementation. +// +//========================================================================= +//========================================================================= + +DataSupplier::DataSupplier( const Reference<XMultiServiceFactory >& rxSMgr, + const rtl::Reference< ::odma::Content >& rContent, + sal_Int32 nOpenMode ) +: m_pImpl( new DataSupplier_Impl( rxSMgr, rContent, nOpenMode ) ) +{ +} + +//========================================================================= +// virtual +DataSupplier::~DataSupplier() +{ + delete m_pImpl; +} + +//========================================================================= +// virtual +::rtl::OUString DataSupplier::queryContentIdentifierString( sal_uInt32 nIndex ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( nIndex < m_pImpl->m_aResults.size() ) + { + ::rtl::OUString aId = m_pImpl->m_aResults[ nIndex ]->aId; + if ( aId.getLength() ) + { + // Already cached. + return aId; + } + } + + if ( getResult( nIndex ) ) + { + ::rtl::OUString aId + = m_pImpl->m_xContent->getIdentifier()->getContentIdentifier(); + + aId += m_pImpl->m_aResults[ nIndex ]->rData->m_sTitle; + + m_pImpl->m_aResults[ nIndex ]->aId = aId; + return aId; + } + return ::rtl::OUString(); +} + +//========================================================================= +// virtual +Reference< XContentIdentifier > DataSupplier::queryContentIdentifier( + sal_uInt32 nIndex ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( nIndex < m_pImpl->m_aResults.size() ) + { + Reference< XContentIdentifier > xId + = m_pImpl->m_aResults[ nIndex ]->xId; + if ( xId.is() ) + { + // Already cached. + return xId; + } + } + + ::rtl::OUString aId = queryContentIdentifierString( nIndex ); + if ( aId.getLength() ) + { + Reference< XContentIdentifier > xId + = new ucbhelper::ContentIdentifier( aId ); + m_pImpl->m_aResults[ nIndex ]->xId = xId; + return xId; + } + return Reference< XContentIdentifier >(); +} + +//========================================================================= +// virtual +Reference< XContent > DataSupplier::queryContent( sal_uInt32 nIndex ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( nIndex < m_pImpl->m_aResults.size() ) + { + Reference< XContent > xContent + = m_pImpl->m_aResults[ nIndex ]->xContent; + if ( xContent.is() ) + { + // Already cached. + return xContent; + } + } + + Reference< XContentIdentifier > xId = queryContentIdentifier( nIndex ); + if ( xId.is() ) + { + try + { + Reference< XContent > xContent + = m_pImpl->m_xContent->getProvider()->queryContent( xId ); + m_pImpl->m_aResults[ nIndex ]->xContent = xContent; + return xContent; + + } + catch ( IllegalIdentifierException& ) + { + } + } + return Reference< XContent >(); +} + +//========================================================================= +// virtual +sal_Bool DataSupplier::getResult( sal_uInt32 nIndex ) +{ + osl::ClearableGuard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( m_pImpl->m_aResults.size() > nIndex ) + { + // Result already present. + return sal_True; + } + + // Result not (yet) present. + + if ( m_pImpl->m_bCountFinal ) + return sal_False; + + // Try to obtain result... + + sal_uInt32 nOldCount = m_pImpl->m_aResults.size(); + sal_Bool bFound = sal_False; +// sal_uInt32 nPos = nOldCount; + + // @@@ Obtain data and put it into result list... +/* + while ( m_pImpl->m_aFolder.next( m_pImpl->m_aIterator ) ) + { + m_pImpl->m_aResults.push_back( + new ResultListEntry( *m_pImpl->m_aIterator ) ); + + if ( nPos == nIndex ) + { + // Result obtained. + bFound = sal_True; + break; + } + + nPos++; + } +*/ + // now query for all documents in the DMS + OSL_ENSURE(ContentProvider::getHandle(),"No Handle!"); + sal_Char* pQueryId = new sal_Char[ODM_QUERYID_MAX]; + sal_Char* lpszDMSList = new sal_Char[ODM_DMSID_MAX]; + + ODMSTATUS odm = NODMGetDMS(ODMA_ODMA_REGNAME, lpszDMSList); + lpszDMSList[strlen(lpszDMSList)+1] = '\0'; + + ::rtl::OString sQuery("SELECT ODM_DOCID, ODM_NAME"); + + DWORD dwFlags = ODM_SPECIFIC; + odm = NODMQueryExecute(ContentProvider::getHandle(), sQuery,dwFlags, lpszDMSList, pQueryId ); + if(odm != ODM_SUCCESS) + return sal_False; + + sal_uInt16 nCount = 10; + sal_uInt16 nMaxCount = 10; + sal_Char* lpszDocId = new sal_Char[ODM_DOCID_MAX * nMaxCount]; + sal_Char* lpszDocName = new sal_Char[ODM_NAME_MAX * nMaxCount]; + + + ::rtl::OUString sContentType(RTL_CONSTASCII_USTRINGPARAM(ODMA_CONTENT_TYPE)); + sal_uInt32 nCurrentCount = 0; + do + { + if(nCount >= nMaxCount) + { + nCount = nMaxCount; + odm = NODMQueryGetResults(ContentProvider::getHandle(), pQueryId,lpszDocId, lpszDocName, ODM_NAME_MAX, (WORD*)&nCount); + nCurrentCount += nCount; + } + if(odm == ODM_SUCCESS && nIndex < nCurrentCount) + { + bFound = sal_True; + for(sal_uInt16 i = 0; i < nCount; ++i) + { + ::rtl::Reference<ContentProperties> rProps = new ContentProperties(); + rProps->m_sDocumentId = ::rtl::OString(&lpszDocId[ODM_DOCID_MAX*i]); + rProps->m_sContentType = sContentType; + m_pImpl->m_xContent->getContentProvider()->append(rProps); + m_pImpl->m_aResults.push_back( new ResultListEntry(rProps)); + } + } + } + while(nCount > nMaxCount); + + + // now close the query + odm = NODMQueryClose(ContentProvider::getHandle(), pQueryId); + + delete [] lpszDMSList; + delete [] pQueryId; + delete [] lpszDocId; + delete [] lpszDocName; + + if ( !bFound ) + m_pImpl->m_bCountFinal = sal_True; + + rtl::Reference< ucbhelper::ResultSet > xResultSet = getResultSet(); + if ( xResultSet.is() ) + { + // Callbacks follow! + aGuard.clear(); + + if ( nOldCount < m_pImpl->m_aResults.size() ) + xResultSet->rowCountChanged( + nOldCount, m_pImpl->m_aResults.size() ); + + if ( m_pImpl->m_bCountFinal ) + xResultSet->rowCountFinal(); + } + + return bFound; +} + +//========================================================================= +// virtual +sal_uInt32 DataSupplier::totalCount() +{ + osl::ClearableGuard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( m_pImpl->m_bCountFinal ) + return m_pImpl->m_aResults.size(); + + sal_uInt32 nOldCount = m_pImpl->m_aResults.size(); + + // @@@ Obtain data and put it into result list... +/* + while ( m_pImpl->m_aFolder.next( m_pImpl->m_aIterator ) ) + m_pImpl->m_aResults.push_back( + new ResultListEntry( *m_pImpl->m_aIterator ) ); +*/ + m_pImpl->m_bCountFinal = sal_True; + + rtl::Reference< ucbhelper::ResultSet > xResultSet = getResultSet(); + if ( xResultSet.is() ) + { + // Callbacks follow! + aGuard.clear(); + + if ( nOldCount < m_pImpl->m_aResults.size() ) + xResultSet->rowCountChanged( + nOldCount, m_pImpl->m_aResults.size() ); + + xResultSet->rowCountFinal(); + } + + return m_pImpl->m_aResults.size(); +} + +//========================================================================= +// virtual +sal_uInt32 DataSupplier::currentCount() +{ + return m_pImpl->m_aResults.size(); +} + +//========================================================================= +// virtual +sal_Bool DataSupplier::isCountFinal() +{ + return m_pImpl->m_bCountFinal; +} + +//========================================================================= +// virtual +Reference< XRow > DataSupplier::queryPropertyValues( sal_uInt32 nIndex ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( nIndex < m_pImpl->m_aResults.size() ) + { + Reference< XRow > xRow = m_pImpl->m_aResults[ nIndex ]->xRow; + if ( xRow.is() ) + { + // Already cached. + return xRow; + } + } + + if ( getResult( nIndex ) ) + { + Reference< XRow > xRow = Content::getPropertyValues( + m_pImpl->m_xSMgr, + getResultSet()->getProperties(), + m_pImpl->m_aResults[ nIndex ]->rData, + m_pImpl->m_xContent->getProvider(), + queryContentIdentifierString( nIndex ) ); + m_pImpl->m_aResults[ nIndex ]->xRow = xRow; + return xRow; + } + + return Reference< XRow >(); +} + +//========================================================================= +// virtual +void DataSupplier::releasePropertyValues( sal_uInt32 nIndex ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( nIndex < m_pImpl->m_aResults.size() ) + m_pImpl->m_aResults[ nIndex ]->xRow = Reference< XRow >(); +} + +//========================================================================= +// virtual +void DataSupplier::close() +{ +} + +//========================================================================= +// virtual +void DataSupplier::validate() + throw( ResultSetException ) +{ +} diff --git a/ucb/source/ucp/odma/odma_datasupplier.hxx b/ucb/source/ucp/odma/odma_datasupplier.hxx new file mode 100644 index 000000000000..a37ecebf0e39 --- /dev/null +++ b/ucb/source/ucp/odma/odma_datasupplier.hxx @@ -0,0 +1,74 @@ +/************************************************************************* + * + * 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 ODMA_DATASUPPLIER_HXX +#define ODMA_DATASUPPLIER_HXX + +#include <ucbhelper/resultset.hxx> + +namespace odma { + +struct DataSupplier_Impl; +class Content; + +class DataSupplier : public ucbhelper::ResultSetDataSupplier +{ + DataSupplier_Impl* m_pImpl; + +public: + DataSupplier( const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + const rtl::Reference< Content >& rContent, + sal_Int32 nOpenMode ); + virtual ~DataSupplier(); + + virtual rtl::OUString queryContentIdentifierString( sal_uInt32 nIndex ); + virtual com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier > + queryContentIdentifier( sal_uInt32 nIndex ); + virtual com::sun::star::uno::Reference< com::sun::star::ucb::XContent > + queryContent( sal_uInt32 nIndex ); + + virtual sal_Bool getResult( sal_uInt32 nIndex ); + + virtual sal_uInt32 totalCount(); + virtual sal_uInt32 currentCount(); + virtual sal_Bool isCountFinal(); + + virtual com::sun::star::uno::Reference< com::sun::star::sdbc::XRow > + queryPropertyValues( sal_uInt32 nIndex ); + virtual void releasePropertyValues( sal_uInt32 nIndex ); + + virtual void close(); + + virtual void validate() + throw( com::sun::star::ucb::ResultSetException ); +}; + +} + +#endif diff --git a/ucb/source/ucp/odma/odma_inputstream.cxx b/ucb/source/ucp/odma/odma_inputstream.cxx new file mode 100644 index 000000000000..65491c34829b --- /dev/null +++ b/ucb/source/ucp/odma/odma_inputstream.cxx @@ -0,0 +1,286 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" +#include "odma_inputstream.hxx" +#include "com/sun/star/io/IOException.hpp" +#include <com/sun/star/ucb/OpenCommandArgument2.hpp> +#include <com/sun/star/ucb/OpenMode.hpp> +#include <ucbhelper/content.hxx> +#include <com/sun/star/io/XActiveDataStreamer.hpp> +#include <cppuhelper/implbase1.hxx> +#include "odma_contentprops.hxx" +#include "odma_provider.hxx" + +using namespace odma; +using namespace com::sun::star; + +class OActiveDataStreamer : public ::cppu::WeakImplHelper1< io::XActiveDataStreamer> +{ + uno::Reference< io::XStream > m_xStream; +public: + OActiveDataStreamer(){} + virtual void SAL_CALL setStream( const uno::Reference< io::XStream >& _rStream ) throw (uno::RuntimeException) + { + m_xStream = _rStream; + } + virtual uno::Reference< io::XStream > SAL_CALL getStream( ) throw (uno::RuntimeException) + { + return m_xStream; + } +}; +// ----------------------------------------------------------------------------- +OOdmaStream::OOdmaStream(::ucbhelper::Content* _pContent, + ContentProvider* _pProvider, + const ::rtl::Reference<ContentProperties>& _rProp) + :m_pContent(_pContent) + ,m_bInputStreamCalled(sal_False) + ,m_bOutputStreamCalled(sal_False) + ,m_bModified(sal_False) + ,m_pProvider(_pProvider) + ,m_aProp(_rProp) +{ +} +// ----------------------------------------------------------------------------- +OOdmaStream::~OOdmaStream() +{ + try + { + closeStream(); + delete m_pContent; + } + catch (io::IOException const &) + { + OSL_ENSURE(false, "unexpected situation"); + } + catch (uno::RuntimeException const &) + { + OSL_ENSURE(false, "unexpected situation"); + } +} +// ----------------------------------------------------------------------------- +uno::Reference< io::XInputStream > SAL_CALL OOdmaStream::getInputStream( ) throw( uno::RuntimeException) +{ + { + osl::MutexGuard aGuard( m_aMutex ); + m_bInputStreamCalled = sal_True; + } + return uno::Reference< io::XInputStream >( this ); +} +// ----------------------------------------------------------------------------- +uno::Reference< io::XOutputStream > SAL_CALL OOdmaStream::getOutputStream( ) throw( uno::RuntimeException ) +{ + { + osl::MutexGuard aGuard( m_aMutex ); + m_bOutputStreamCalled = sal_True; + } + return uno::Reference< io::XOutputStream >( this ); +} +// ----------------------------------------------------------------------------- +sal_Int32 SAL_CALL OOdmaStream::readBytes( uno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead ) + throw( io::NotConnectedException, + io::BufferSizeExceededException, + io::IOException, + uno::RuntimeException) +{ + ensureInputStream(); + + return m_xInput->readBytes(aData,nBytesToRead); +} +// ----------------------------------------------------------------------------- +sal_Int32 SAL_CALL OOdmaStream::readSomeBytes( uno::Sequence< sal_Int8 >& aData,sal_Int32 nMaxBytesToRead ) + throw( io::NotConnectedException, + io::BufferSizeExceededException, + io::IOException, + uno::RuntimeException) +{ + return readBytes( aData,nMaxBytesToRead ); +} +// ----------------------------------------------------------------------------- +void SAL_CALL OOdmaStream::skipBytes( sal_Int32 nBytesToSkip ) + throw( io::NotConnectedException, + io::BufferSizeExceededException, + io::IOException, + uno::RuntimeException ) +{ + ensureInputStream(); + m_xInput->skipBytes(nBytesToSkip ); +} +// ----------------------------------------------------------------------------- +sal_Int32 SAL_CALL OOdmaStream::available() + throw( io::NotConnectedException, + io::IOException, + uno::RuntimeException) +{ + ensureInputStream(); + return m_xInput->available(); +} +// ----------------------------------------------------------------------------- +void SAL_CALL OOdmaStream::writeBytes( const uno::Sequence< sal_Int8 >& aData ) + throw( io::NotConnectedException, + io::BufferSizeExceededException, + io::IOException, + uno::RuntimeException) +{ + ensureOutputStream(); + m_xOutput->writeBytes(aData); + m_bModified = sal_True; +} +// ----------------------------------------------------------------------------- +void SAL_CALL OOdmaStream::closeStream() throw( io::NotConnectedException,io::IOException,uno::RuntimeException ) +{ + if( m_xInput.is() ) + { + m_xInput->closeInput(); + m_xInput = NULL; + m_xInputSeek = NULL; + } + if(m_xOutput.is()) + { + m_xOutput->closeOutput(); + m_xOutput = NULL; + m_xTruncate = NULL; + if(m_bModified) + m_pProvider->saveDocument(m_aProp->m_sDocumentId); + } +} +// ----------------------------------------------------------------------------- +void SAL_CALL OOdmaStream::closeInput() + throw( io::NotConnectedException, + io::IOException, + uno::RuntimeException ) +{ + osl::MutexGuard aGuard( m_aMutex ); + m_bInputStreamCalled = sal_False; + + if( ! m_bOutputStreamCalled ) + closeStream(); +} +// ----------------------------------------------------------------------------- +void SAL_CALL OOdmaStream::closeOutput() + throw( io::NotConnectedException, + io::IOException, + uno::RuntimeException ) +{ + osl::MutexGuard aGuard( m_aMutex ); + m_bOutputStreamCalled = sal_False; + + if( ! m_bInputStreamCalled ) + closeStream(); +} +// ----------------------------------------------------------------------------- +void SAL_CALL OOdmaStream::flush() + throw( io::NotConnectedException, + io::BufferSizeExceededException, + io::IOException, + uno::RuntimeException ) +{ + ensureOutputStream(); + m_xOutput->flush(); +} +// ----------------------------------------------------------------------------- +void OOdmaStream::ensureInputStream() throw( io::IOException ) +{ + try + { + if(!m_xInput.is()) + { + m_xInput = m_pContent->openStream(); + m_xInputSeek = uno::Reference< io::XSeekable>(m_xInput,uno::UNO_QUERY); + } + } + catch(const uno::Exception&) + { + } + if(!m_xInput.is()) + throw io::IOException(); +} +// ----------------------------------------------------------------------------- +void OOdmaStream::ensureOutputStream() throw( io::IOException ) +{ + try + { + if(!m_xOutput.is()) + { + ucb::OpenCommandArgument2 aCommand; + aCommand.Mode = ucb::OpenMode::DOCUMENT; + uno::Reference< io::XActiveDataStreamer > xActiveStreamer = new OActiveDataStreamer(); + aCommand.Sink = xActiveStreamer; + m_pContent->executeCommand(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("open")),uno::makeAny(aCommand)); + if(xActiveStreamer.is()) + { + uno::Reference< io::XStream> xStream = xActiveStreamer->getStream(); + if(xStream.is()) + m_xOutput = xStream->getOutputStream(); + } + } + } + catch(const uno::Exception&) + { + } + if(!m_xOutput.is()) + throw io::IOException(); + m_xTruncate = uno::Reference< io::XTruncate>(m_xOutput,uno::UNO_QUERY); +} +// ----------------------------------------------------------------------------- +// XTruncate +void SAL_CALL OOdmaStream::truncate( void ) + throw( io::IOException, + uno::RuntimeException ) +{ + if(m_xTruncate.is()) + m_xTruncate->truncate(); +} +// ----------------------------------------------------------------------------- +// XSeekable +void SAL_CALL OOdmaStream::seek(sal_Int64 location ) + throw( lang::IllegalArgumentException, + io::IOException, + uno::RuntimeException ) +{ + ensureInputStream(); + if(m_xInputSeek.is()) + m_xInputSeek->seek(location); +} +// ----------------------------------------------------------------------------- +sal_Int64 SAL_CALL OOdmaStream::getPosition() + throw( io::IOException, + uno::RuntimeException ) +{ + ensureInputStream(); + return m_xInputSeek.is() ? m_xInputSeek->getPosition() : sal_Int64(0); +} +// ----------------------------------------------------------------------------- +sal_Int64 SAL_CALL OOdmaStream::getLength() + throw( io::IOException, + uno::RuntimeException ) +{ + ensureInputStream(); + return m_xInputSeek.is() ? m_xInputSeek->getLength() : sal_Int64(0); +} +// ----------------------------------------------------------------------------- diff --git a/ucb/source/ucp/odma/odma_inputstream.hxx b/ucb/source/ucp/odma/odma_inputstream.hxx new file mode 100644 index 000000000000..c751b81989b8 --- /dev/null +++ b/ucb/source/ucp/odma/odma_inputstream.hxx @@ -0,0 +1,138 @@ +/************************************************************************* + * + * 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 ODMA_INPUTSTREAM_HXX +#define ODMA_INPUTSTREAM_HXX + +#include <osl/mutex.hxx> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/io/XStream.hpp> +#include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/io/XTruncate.hpp> +#include <com/sun/star/io/XSeekable.hpp> +#include <cppuhelper/implbase5.hxx> + +#include "rtl/ref.hxx" + +namespace ucbhelper +{ + class Content; +} +namespace odma +{ + typedef ::cppu::WeakImplHelper5< ::com::sun::star::io::XInputStream, + ::com::sun::star::io::XStream, + ::com::sun::star::io::XTruncate, + ::com::sun::star::io::XSeekable, + ::com::sun::star::io::XOutputStream> OOdmaStreamBase; + + class ContentProvider; + class ContentProperties; + class OOdmaStream : public OOdmaStreamBase + { + ::osl::Mutex m_aMutex; + ::com::sun::star::uno::Reference< ::com::sun::star::io::XOutputStream> m_xOutput; + ::com::sun::star::uno::Reference< ::com::sun::star::io::XTruncate> m_xTruncate; + ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream> m_xInput; + ::com::sun::star::uno::Reference< ::com::sun::star::io::XSeekable> m_xInputSeek; + + ::rtl::Reference<ContentProperties> m_aProp; + ::ucbhelper::Content* m_pContent; + ContentProvider* m_pProvider; + sal_Bool m_bInputStreamCalled; + sal_Bool m_bOutputStreamCalled; + sal_Bool m_bModified; + + void ensureInputStream() throw( ::com::sun::star::io::IOException ); + void ensureOutputStream() throw( ::com::sun::star::io::IOException ); + void SAL_CALL closeStream() throw( ::com::sun::star::io::NotConnectedException, + ::com::sun::star::io::IOException, + ::com::sun::star::uno::RuntimeException ); + public: + OOdmaStream(::ucbhelper::Content* _pContent, + ContentProvider* _pProvider, + const ::rtl::Reference<ContentProperties>& _rProp); + virtual ~OOdmaStream(); + // com::sun::star::io::XInputStream + virtual sal_Int32 SAL_CALL readBytes( ::com::sun::star::uno::Sequence<sal_Int8>& aData, sal_Int32 nBytesToRead ) + throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, + ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + + virtual sal_Int32 SAL_CALL readSomeBytes( ::com::sun::star::uno::Sequence<sal_Int8>& aData, sal_Int32 nMaxBytesToRead ) + throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, + ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip ) + throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, + ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + + virtual sal_Int32 SAL_CALL available( ) + throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL closeInput( ) + throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + + // com::sun::star::io::XStream + virtual com::sun::star::uno::Reference< com::sun::star::io::XInputStream > SAL_CALL getInputStream( ) throw( com::sun::star::uno::RuntimeException ); + virtual com::sun::star::uno::Reference< com::sun::star::io::XOutputStream > SAL_CALL getOutputStream( ) throw( com::sun::star::uno::RuntimeException ); + + // com::sun::star::io::XOutputStream + void SAL_CALL writeBytes( const com::sun::star::uno::Sequence< sal_Int8 >& aData ) + throw( com::sun::star::io::NotConnectedException, + com::sun::star::io::BufferSizeExceededException, + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException); + + void SAL_CALL flush() + throw( com::sun::star::io::NotConnectedException, + com::sun::star::io::BufferSizeExceededException, + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException); + void SAL_CALL closeOutput() + throw( com::sun::star::io::NotConnectedException, + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException ); + // XTruncate + virtual void SAL_CALL truncate( void ) + throw( com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException ); + // XSeekable + void SAL_CALL seek(sal_Int64 location ) + throw( com::sun::star::lang::IllegalArgumentException, + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException ); + + sal_Int64 SAL_CALL getPosition() + throw( com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException ); + + sal_Int64 SAL_CALL getLength() + throw( com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException ); + }; +} +#endif // ODMA_INPUTSTREAM_HXX diff --git a/ucb/source/ucp/odma/odma_lib.cxx b/ucb/source/ucp/odma/odma_lib.cxx new file mode 100644 index 000000000000..cf9da3a2b942 --- /dev/null +++ b/ucb/source/ucp/odma/odma_lib.cxx @@ -0,0 +1,129 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" +//#ifndef _OSL_PROCESS_H_ +//#include <osl/process.h> +//#endif +#include <osl/module.h> +#include <rtl/ustring.hxx> +#include "odma_lib.hxx" + + +namespace odma +{ + + TODMRegisterApp pODMRegisterApp; + TODMUnRegisterApp pODMUnRegisterApp; + TODMSelectDoc pODMSelectDoc; + TODMOpenDoc pODMOpenDoc; + TODMSaveDoc pODMSaveDoc; + TODMCloseDoc pODMCloseDoc; + TODMNewDoc pODMNewDoc; + TODMSaveAs pODMSaveAs; + TODMActivate pODMActivate; + TODMGetDocInfo pODMGetDocInfo; + TODMSetDocInfo pODMSetDocInfo; + TODMGetDMSInfo pODMGetDMSInfo; + TODMGetDMSCount pODMGetDMSCount; + TODMGetDMSList pODMGetDMSList; + TODMGetDMS pODMGetDMS; + TODMSetDMS pODMSetDMS; + TODMQueryExecute pODMQueryExecute; + TODMQueryGetResults pODMQueryGetResults; + TODMQueryClose pODMQueryClose; + TODMCloseDocEx pODMCloseDocEx; + TODMSaveAsEx pODMSaveAsEx; + TODMSaveDocEx pODMSaveDocEx; + TODMSelectDocEx pODMSelectDocEx; + TODMQueryCapability pODMQueryCapability; + TODMSetDocEvent pODMSetDocEvent; + TODMGetAlternateContent pODMGetAlternateContent; + TODMSetAlternateContent pODMSetAlternateContent; + TODMGetDocRelation pODMGetDocRelation; + TODMSetDocRelation pODMSetDocRelation; + + sal_Bool LoadFunctions(oslModule _pODMA); + + sal_Bool LoadLibrary() + { + static sal_Bool bLoaded = sal_False; + static oslModule pODMA = NULL; + + if (bLoaded) + return sal_True; + ::rtl::OUString sPath; + #ifdef WNT + sPath = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ODMA32.DLL")); + #endif + #ifdef UNX + sPath = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("libodma.so")); + #endif + + pODMA = osl_loadModule( sPath.pData,SAL_LOADMODULE_NOW ); + if( !pODMA) + return sal_False; + + return bLoaded = LoadFunctions(pODMA); + } + // ------------------------------------------------------------------------- + + sal_Bool LoadFunctions(oslModule pODMA) + { + if ( ( pODMRegisterApp = (TODMRegisterApp)osl_getSymbol(pODMA,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ODMRegisterApp")).pData)) == NULL ) return sal_False; + if ( ( pODMUnRegisterApp = (TODMUnRegisterApp)osl_getSymbol(pODMA,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ODMUnRegisterApp")).pData)) == NULL ) return sal_False; + if ( ( pODMSelectDoc = (TODMSelectDoc)osl_getSymbol(pODMA,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ODMSelectDoc")).pData)) == NULL ) return sal_False; + if ( ( pODMOpenDoc = (TODMOpenDoc)osl_getSymbol(pODMA,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ODMOpenDoc")).pData)) == NULL ) return sal_False; + if ( ( pODMSaveDoc = (TODMSaveDoc)osl_getSymbol(pODMA,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ODMSaveDoc")).pData)) == NULL ) return sal_False; + if ( ( pODMCloseDoc = (TODMCloseDoc)osl_getSymbol(pODMA,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ODMCloseDoc")).pData)) == NULL ) return sal_False; + if ( ( pODMNewDoc = (TODMNewDoc)osl_getSymbol(pODMA,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ODMNewDoc")).pData)) == NULL ) return sal_False; + if ( ( pODMSaveAs = (TODMSaveAs)osl_getSymbol(pODMA,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ODMSaveAs")).pData)) == NULL ) return sal_False; + if ( ( pODMActivate = (TODMActivate)osl_getSymbol(pODMA,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ODMActivate")).pData)) == NULL ) return sal_False; + if ( ( pODMGetDocInfo = (TODMGetDocInfo)osl_getSymbol(pODMA,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ODMGetDocInfo")).pData)) == NULL ) return sal_False; + if ( ( pODMSetDocInfo = (TODMSetDocInfo)osl_getSymbol(pODMA,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ODMSetDocInfo")).pData)) == NULL ) return sal_False; + if ( ( pODMGetDMSInfo = (TODMGetDMSInfo)osl_getSymbol(pODMA,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ODMGetDMSInfo")).pData)) == NULL ) return sal_False; + if ( ( pODMGetDMSCount = (TODMGetDMSCount)osl_getSymbol(pODMA,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ODMGetDMSCount")).pData)) == NULL ) return sal_False; + if ( ( pODMGetDMSList = (TODMGetDMSList)osl_getSymbol(pODMA,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ODMGetDMSList")).pData)) == NULL ) return sal_False; + if ( ( pODMGetDMS = (TODMGetDMS)osl_getSymbol(pODMA,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ODMGetDMS")).pData)) == NULL ) return sal_False; + if ( ( pODMSetDMS = (TODMSetDMS)osl_getSymbol(pODMA,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ODMSetDMS")).pData)) == NULL ) return sal_False; + if ( ( pODMQueryExecute = (TODMQueryExecute)osl_getSymbol(pODMA,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ODMQueryExecute")).pData)) == NULL ) return sal_False; + if ( ( pODMQueryGetResults = (TODMQueryGetResults)osl_getSymbol(pODMA,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ODMQueryGetResults")).pData)) == NULL ) return sal_False; + if ( ( pODMQueryClose = (TODMQueryClose)osl_getSymbol(pODMA,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ODMQueryClose")).pData)) == NULL ) return sal_False; + if ( ( pODMCloseDocEx = (TODMCloseDocEx)osl_getSymbol(pODMA,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ODMCloseDocEx")).pData)) == NULL ) return sal_False; + if ( ( pODMSaveAsEx = (TODMSaveAsEx)osl_getSymbol(pODMA,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ODMSaveAsEx")).pData)) == NULL ) return sal_False; + if ( ( pODMSaveDocEx = (TODMSaveDocEx)osl_getSymbol(pODMA,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ODMSaveDocEx")).pData)) == NULL ) return sal_False; + if ( ( pODMSelectDocEx = (TODMSelectDocEx)osl_getSymbol(pODMA,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ODMSelectDocEx")).pData)) == NULL ) return sal_False; + if ( ( pODMQueryCapability = (TODMQueryCapability)osl_getSymbol(pODMA,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ODMQueryCapability")).pData)) == NULL ) return sal_False; + if ( ( pODMSetDocEvent = (TODMSetDocEvent)osl_getSymbol(pODMA,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ODMSetDocEvent")).pData)) == NULL ) return sal_False; + if ( ( pODMGetAlternateContent = (TODMGetAlternateContent)osl_getSymbol(pODMA,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ODMGetAlternateContent")).pData)) == NULL ) return sal_False; + if ( ( pODMSetAlternateContent = (TODMSetAlternateContent)osl_getSymbol(pODMA,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ODMSetAlternateContent")).pData)) == NULL ) return sal_False; + if ( ( pODMGetDocRelation = (TODMGetDocRelation)osl_getSymbol(pODMA,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ODMGetDocRelation")).pData)) == NULL ) return sal_False; + if ( ( pODMSetDocRelation = (TODMSetDocRelation)osl_getSymbol(pODMA,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ODMSetDocRelation")).pData)) == NULL ) return sal_False; + return sal_True; + } +} diff --git a/ucb/source/ucp/odma/odma_lib.hxx b/ucb/source/ucp/odma/odma_lib.hxx new file mode 100644 index 000000000000..f4229572dbab --- /dev/null +++ b/ucb/source/ucp/odma/odma_lib.hxx @@ -0,0 +1,272 @@ +/************************************************************************* + * + * 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 ODMA_LIB_HXX +#define ODMA_LIB_HXX + +typedef void *LPVOID; +typedef char *LPSTR, + *PSTR; +typedef const char *LPCSTR; +typedef unsigned long DWORD; +typedef unsigned short WORD; +typedef unsigned short *LPWORD; +typedef DWORD *LPDWORD; + +#define WINAPI __stdcall +#define FAR + +#include "odma.h" + +namespace odma +{ + typedef ODMSTATUS (WINAPI *TODMRegisterApp) ( ODMHANDLE FAR *pOdmHandle, + WORD version, + LPSTR lpszAppId, + DWORD dwEnvData, + LPVOID pReserved); + + typedef void (WINAPI *TODMUnRegisterApp)(ODMHANDLE odmHandle); + + + typedef ODMSTATUS (WINAPI *TODMSelectDoc)( ODMHANDLE odmHandle, + LPSTR lpszDocId, + LPDWORD pdwFlags); + + + typedef ODMSTATUS (WINAPI *TODMOpenDoc)( ODMHANDLE odmHandle, + DWORD flags, + LPSTR lpszDocId, + LPSTR lpszDocLocation); + + typedef ODMSTATUS (WINAPI *TODMSaveDoc)( ODMHANDLE odmHandle, + LPSTR lpszDocId, + LPSTR lpszNewDocId); + + typedef ODMSTATUS (WINAPI *TODMCloseDoc)( ODMHANDLE odmHandle, + LPSTR lpszDocId, + DWORD activeTime, + DWORD pagesPrinted, + LPVOID sessionData, + WORD dataLen); + + typedef ODMSTATUS (WINAPI *TODMNewDoc)( ODMHANDLE odmHandle, + LPSTR lpszDocId, + DWORD dwFlags, + LPSTR lpszFormat, + LPSTR lpszDocLocation); + + typedef ODMSTATUS (WINAPI *TODMSaveAs)( ODMHANDLE odmHandle, + LPSTR lpszDocId, + LPSTR lpszNewDocId, + LPSTR lpszFormat, + ODMSAVEASCALLBACK pcbCallBack, + LPVOID pInstanceData); + + typedef ODMSTATUS (WINAPI *TODMActivate)( ODMHANDLE odmHandle, + WORD action, + LPSTR lpszDocId); + + typedef ODMSTATUS (WINAPI *TODMGetDocInfo)( ODMHANDLE odmHandle, + LPSTR lpszDocId, + WORD item, + LPSTR lpszData, + WORD dataLen); + + typedef ODMSTATUS (WINAPI *TODMSetDocInfo)( ODMHANDLE odmHandle, + LPSTR lpszDocId, + WORD item, + LPSTR lpszData); + + typedef ODMSTATUS (WINAPI *TODMGetDMSInfo)( ODMHANDLE odmHandle, + LPSTR lpszDmsId, + LPWORD pwVerNo, + LPDWORD pdwExtensions); + + /* Query Enhancements */ + typedef WORD (WINAPI *TODMGetDMSCount)(); + + typedef WORD (WINAPI *TODMGetDMSList)( LPSTR buffer, + WORD buffer_size ); + + typedef ODMSTATUS (WINAPI *TODMGetDMS)( LPCSTR lpszAppId, + LPSTR lpszDMSId ); + + typedef ODMSTATUS (WINAPI *TODMSetDMS)( LPCSTR lpszAppId, + LPCSTR lpszDMSId ); + + typedef ODMSTATUS (WINAPI *TODMQueryExecute)( ODMHANDLE odmHandle, + LPCSTR lpszQuery, + DWORD flags, + LPCSTR lpszDMSList, + LPSTR queryId ); + + typedef ODMSTATUS (WINAPI *TODMQueryGetResults)(ODMHANDLE odmHandle, + LPCSTR queryId, + LPSTR lpszDocId, + LPSTR lpszDocName, + WORD docNameLen, + WORD *docCount ); + + typedef ODMSTATUS (WINAPI *TODMQueryClose)( ODMHANDLE odmHandle, + LPCSTR queryId ); + + /* ODMA 2.0 Enhancements */ + typedef ODMSTATUS (WINAPI *TODMCloseDocEx)( ODMHANDLE odmHandle, + LPSTR lpszDocId, + LPDWORD pdwFlags, + DWORD activeTime, + DWORD pagesPrinted, + LPVOID sessionData, + WORD dataLen); + + typedef ODMSTATUS (WINAPI *TODMSaveAsEx)( ODMHANDLE odmHandle, + LPSTR lpszDocId, + LPSTR lpszNewDocId, + LPSTR lpszFormat, + ODMSAVEASCALLBACK pcbCallBack, + LPVOID pInstanceData, + LPDWORD pdwFlags); + + typedef ODMSTATUS (WINAPI *TODMSaveDocEx)( ODMHANDLE odmHandle, + LPSTR lpszDocId, + LPSTR lpszNewDocId, + LPDWORD pdwFlags); + + typedef ODMSTATUS (WINAPI *TODMSelectDocEx)( ODMHANDLE odmHandle, + LPSTR lpszDocIds, + LPWORD pwDocIdsLen, + LPWORD pwDocCount, + LPDWORD pdwFlags, + LPSTR lpszFormatFilter); + + typedef ODMSTATUS (WINAPI *TODMQueryCapability)(ODMHANDLE odmHandle, + LPCSTR lpszDmsId, + DWORD function, + DWORD item, + DWORD flags); + + typedef ODMSTATUS (WINAPI *TODMSetDocEvent)( ODMHANDLE odmHandle, + LPSTR lpszDocId, + DWORD flags, + DWORD event, + LPVOID lpData, + DWORD dwDataLen, + LPSTR lpszComment); + + typedef ODMSTATUS (WINAPI *TODMGetAlternateContent)(ODMHANDLE odmHandle, + LPSTR lpszDocId, + LPDWORD pdwFlags, + LPSTR lpszFormat, + LPSTR lpszDocLocation); + + typedef ODMSTATUS (WINAPI *TODMSetAlternateContent)(ODMHANDLE odmHandle, + LPSTR lpszDocId, + LPDWORD pdwFlags, + LPSTR lpszFormat, + LPSTR lpszDocLocation); + + typedef ODMSTATUS (WINAPI *TODMGetDocRelation)( ODMHANDLE odmHandle, + LPSTR lpszDocId, + LPDWORD pdwFlags, + LPSTR lpszLinkedId, + LPSTR lpszFormat, + LPSTR lpszPreviousId); + + typedef ODMSTATUS (WINAPI *TODMSetDocRelation)( ODMHANDLE odmHandle, + LPSTR lpszDocId, + LPDWORD pdwFlags, + LPSTR lpszLinkedId, + LPSTR lpszFormat, + LPSTR lpszPreviousId); + + // now we define some macros + + #define NODMRegisterApp(a,b,c,d,e) (*(pODMRegisterApp))(a,b,c,d,e) + #define NODMUnRegisterApp(a) (*(pODMUnRegisterApp))(a) + #define NODMSelectDoc(a,b,c) (*(pODMSelectDoc))(a,b,c) + #define NODMOpenDoc(a,b,c,d) (*(pODMOpenDoc))(a,b,c,d) + #define NODMSaveDoc(a,b,c) (*(pODMSaveDoc))(a,b,c) + #define NODMCloseDoc(a,b,c,d,e,f) (*(pODMCloseDoc))(a,b,c,d,e,f) + #define NODMNewDoc(a,b,c,d,e) (*(pODMNewDoc))(a,b,c,d,e) + #define NODMSaveAs(a,b,c,d,e,f) (*(pODMSaveAs))(a,b,c,d,e,f) + #define NODMActivate(a,b,c) (*(pODMActivate))(a,b,c) + #define NODMGetDocInfo(a,b,c,d,e) (*(pODMGetDocInfo))(a,b,c,d,e) + #define NODMSetDocInfo(a,b,c,d) (*(pODMSetDocInfo))(a,b,c,d) + #define NODMGetDMSInfo(a,b,c,d) (*(pODMGetDMSInfo))(a,b,c,d) + #define NODMGetDMSCount() (*(pODMGetDMSCount))() + #define NODMGetDMSList(a,b) (*(pODMGetDMSList))(a,b) + #define NODMGetDMS(a,b) (*(pODMGetDMS))(a,b) + #define NODMSetDMS(a,b) (*(pODMSetDMS))(a,b) + #define NODMQueryExecute(a,b,c,d,e) (*(pODMQueryExecute))(a,b,c,d,e) + #define NODMQueryGetResults(a,b,c,d,e,f) (*(pODMQueryGetResults))(a,b,c,d,e,f) + #define NODMQueryClose(a,b) (*(pODMQueryClose))(a,b) + #define NODMCloseDocEx(a,b,c,d,e,f,g) (*(pODMCloseDocEx))(a,b,c,d,e,f,g) + #define NODMSaveAsEx(a,b,c,d,e,f,g) (*(pODMSaveAsEx))(a,b,c,d,e,f,g) + #define NODMSaveDocEx(a,b,c,d) (*(pODMSaveDocEx))(a,b,c,d) + #define NODMSelectDocEx(a,b,c,d,e,f) (*(pODMSelectDocEx))(a,b,c,d,e,f) + #define NODMQueryCapability(a,b,c,d,e) (*(pODMQueryCapability))(a,b,c,d,e) + #define NODMSetDocEvent(a,b,c,d,e,f,g) (*(pODMSetDocEvent))(a,b,c,d,e,f,g) + #define NODMGetAlternateContent(a,b,c,d,e) (*(pODMGetAlternateContent))(a,b,c,d,e) + #define NODMSetAlternateContent(a,b,c,d,e) (*(pODMSetAlternateContent))(a,b,c,d,e) + #define NODMGetDocRelation(a,b,c,d,e,f) (*(pODMGetDocRelation))(a,b,c,d,e,f) + #define NODMSetDocRelation(a,b,c,d,e,f) (*(pODMSetDocRelation))(a,b,c,d,e,f) + + sal_Bool LoadLibrary(); + + extern TODMRegisterApp pODMRegisterApp; + extern TODMUnRegisterApp pODMUnRegisterApp; + extern TODMSelectDoc pODMSelectDoc; + extern TODMOpenDoc pODMOpenDoc; + extern TODMSaveDoc pODMSaveDoc; + extern TODMCloseDoc pODMCloseDoc; + extern TODMNewDoc pODMNewDoc; + extern TODMSaveAs pODMSaveAs; + extern TODMActivate pODMActivate; + extern TODMGetDocInfo pODMGetDocInfo; + extern TODMSetDocInfo pODMSetDocInfo; + extern TODMGetDMSInfo pODMGetDMSInfo; + extern TODMGetDMSCount pODMGetDMSCount; + extern TODMGetDMSList pODMGetDMSList; + extern TODMGetDMS pODMGetDMS; + extern TODMSetDMS pODMSetDMS; + extern TODMQueryExecute pODMQueryExecute; + extern TODMQueryGetResults pODMQueryGetResults; + extern TODMQueryClose pODMQueryClose; + extern TODMCloseDocEx pODMCloseDocEx; + extern TODMSaveAsEx pODMSaveAsEx; + extern TODMSaveDocEx pODMSaveDocEx; + extern TODMSelectDocEx pODMSelectDocEx; + extern TODMQueryCapability pODMQueryCapability; + extern TODMSetDocEvent pODMSetDocEvent; + extern TODMGetAlternateContent pODMGetAlternateContent; + extern TODMSetAlternateContent pODMSetAlternateContent; + extern TODMGetDocRelation pODMGetDocRelation; + extern TODMSetDocRelation pODMSetDocRelation; + +} + +#endif // ODMA_LIB_HXX diff --git a/ucb/source/ucp/odma/odma_main.cxx b/ucb/source/ucp/odma/odma_main.cxx new file mode 100644 index 000000000000..3d7a22e907dd --- /dev/null +++ b/ucb/source/ucp/odma/odma_main.cxx @@ -0,0 +1,91 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" +#include <osl/process.h> +#include "odma_provider.hxx" + +#ifdef WNT +#define SOFFICE "soffice.exe" +#else +#define SOFFICE "soffice" +#endif + +/** our main program to convert ODMAIDs to ODMA URLs +*/ + +#if (defined UNX) || (defined OS2) +void main( int argc, char * argv[] ) +#else +void _cdecl main( int argc, char * argv[] ) +#endif +{ + static ::rtl::OUString sProcess(RTL_CONSTASCII_USTRINGPARAM(SOFFICE)); + if(argc > 1) + { + ::rtl::OUString* pArguments = new ::rtl::OUString[argc-1]; + for(int i = 0; i < argc-1; ++i) + { + pArguments[i] = ::rtl::OUString::createFromAscii(argv[i+1]); + if( pArguments[i].matchIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM(ODMA_URL_ODMAID))) + { + ::rtl::OUString sArgument + = ::rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + ODMA_URL_SCHEME ODMA_URL_SHORT "/")); + sArgument += pArguments[i]; + pArguments[i] = sArgument; + } + } + + rtl_uString ** ustrArgumentList = new rtl_uString * [argc-1]; + for (int i = 0; i < argc-1; i++) + ustrArgumentList[i] = pArguments[i].pData; + + oslProcess aProcess; + + if ( osl_Process_E_None == osl_executeProcess( + sProcess.pData, + ustrArgumentList, + argc-1, + osl_Process_DETACHED, + NULL, + NULL, + NULL, + 0, + &aProcess ) + ) + osl_freeProcessHandle( aProcess ); + + delete [] ustrArgumentList; + delete [] pArguments; + } +} + diff --git a/ucb/source/ucp/odma/odma_provider.cxx b/ucb/source/ucp/odma/odma_provider.cxx new file mode 100644 index 000000000000..6c4df4c40b88 --- /dev/null +++ b/ucb/source/ucp/odma/odma_provider.cxx @@ -0,0 +1,599 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ +#include <ucbhelper/contentidentifier.hxx> +#include "odma_provider.hxx" +#include "odma_content.hxx" +#include "odma_contentprops.hxx" +#include <com/sun/star/util/Date.hpp> +#include <com/sun/star/util/Time.hpp> +#include <rtl/uri.hxx> +#include <algorithm> +#include <osl/file.hxx> + +using namespace com::sun::star; +using namespace odma; + +//========================================================================= +//========================================================================= +// +// ContentProvider Implementation. +// +//========================================================================= +//========================================================================= +ODMHANDLE ContentProvider::m_aOdmHandle = NULL; + +ContentProvider::ContentProvider( + const uno::Reference< lang::XMultiServiceFactory >& rSMgr ) +: ::ucbhelper::ContentProviderImplHelper( rSMgr ) +{ + +} + +//========================================================================= +// virtual +ContentProvider::~ContentProvider() +{ + ContentsMap::iterator aIter = m_aContents.begin(); + for (;aIter != m_aContents.end() ;++aIter ) + { + if(aIter->second->m_bIsOpen) + closeDocument(aIter->first); + } + if(m_aOdmHandle) + { + NODMUnRegisterApp(m_aOdmHandle); + m_aOdmHandle = NULL; + } +} +// ----------------------------------------------------------------------------- +ODMHANDLE ContentProvider::getHandle() +{ + if(!m_aOdmHandle) + { + ODMSTATUS odm = NODMRegisterApp(&m_aOdmHandle,ODM_API_VERSION,ODMA_ODMA_REGNAME,NULL,NULL); + switch(odm) + { + case ODM_SUCCESS: + break; + case ODM_E_NODMS: + break; + case ODM_E_CANTINIT: + break; + case ODM_E_VERSION: + break; + default: + break; + } + } + return m_aOdmHandle; +} +// ----------------------------------------------------------------------------- + +//========================================================================= +// +// XInterface methods. +// +//========================================================================= + +// @@@ Add own interfaces. +XINTERFACE_IMPL_3( ContentProvider, + lang::XTypeProvider, + lang::XServiceInfo, + ucb::XContentProvider ); + +//========================================================================= +// +// XTypeProvider methods. +// +//========================================================================= + +// @@@ Add own interfaces. +XTYPEPROVIDER_IMPL_3( ContentProvider, + lang::XTypeProvider, + lang::XServiceInfo, + ucb::XContentProvider ); + +//========================================================================= +// +// XServiceInfo methods. +// +//========================================================================= + +// @@@ Adjust implementation name. Keep the prefix "com.sun.star.comp."! +// @@@ Adjust service name. +XSERVICEINFO_IMPL_1( ContentProvider, + rtl::OUString::createFromAscii( + "com.sun.star.comp.odma.ContentProvider" ), + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ODMA_CONTENT_PROVIDER_SERVICE_NAME) ) ); + +//========================================================================= +// +// Service factory implementation. +// +//========================================================================= + +ONE_INSTANCE_SERVICE_FACTORY_IMPL( ContentProvider ); + +//========================================================================= +// +// XContentProvider methods. +// +//========================================================================= + +// virtual +uno::Reference< ucb::XContent > SAL_CALL ContentProvider::queryContent( + const uno::Reference< ucb::XContentIdentifier >& Identifier ) + throw( ucb::IllegalIdentifierException, uno::RuntimeException ) +{ + // Check URL scheme... + if(!getHandle()) + throw ucb::IllegalIdentifierException(); + + rtl::OUString aScheme( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(ODMA_URL_SCHEME) ) ); + sal_Int32 nIndex = 0; + rtl::OUString sOdma = aScheme.getToken(3,'.',nIndex); + rtl::OUString sCanonicURL = Identifier->getContentIdentifier(); + // check if url starts with odma + if ( !(Identifier->getContentProviderScheme().equalsIgnoreAsciiCase( aScheme ) || + Identifier->getContentProviderScheme().equalsIgnoreAsciiCase( sOdma )) ) + throw ucb::IllegalIdentifierException(); + + if(!( sCanonicURL.matchIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM(ODMA_URL_SCHEME_SHORT ODMA_URL_SHORT)) || + sCanonicURL.matchIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM(ODMA_URL_SCHEME ODMA_URL_SHORT)))) + throw ucb::IllegalIdentifierException(); + + // @@@ Further id checks may go here... +#if 0 + if ( id-check-failes ) + throw ucb::IllegalIdentifierException(); +#endif + + // @@@ Id normalization may go here... +#if 0 + // Normalize URL and create new Id. + rtl::OUString aCanonicURL = ( Identifier->getContentIdentifier() ); + uno::Reference< ucb::XContentIdentifier > xCanonicId + = new ::ucb::ContentIdentifier( m_xSMgr, aCanonicURL ); +#else + uno::Reference< ucb::XContentIdentifier > xCanonicId = Identifier; +#endif + + osl::MutexGuard aGuard( m_aMutex ); + + // Check, if a content with given id already exists... + uno::Reference< ucb::XContent > xContent + = queryExistingContent( xCanonicId ).get(); + if ( xContent.is() ) + return xContent; + + // @@@ Decision, which content implementation to instanciate may be + // made here ( in case you have different content classes ). + + // Create a new content. + + sCanonicURL = convertURL(sCanonicURL); + + ::rtl::Reference<ContentProperties> aProp; + // first check if we got an ODMA ID from outside + if( sCanonicURL.matchIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM(ODMA_URL_ODMAID))) + {// we get an orignal ODMA id so we have to look for the name + ::rtl::OString sDocId = ::rtl::OUStringToOString(sCanonicURL,RTL_TEXTENCODING_MS_1252); + sal_Char* lpszDocName = new sal_Char[ODM_NAME_MAX]; + + ODMSTATUS odm = NODMGetDocInfo( getHandle(), + const_cast<sal_Char*>(sDocId.getStr()), + ODM_NAME, + lpszDocName, + ODM_NAME_MAX + ); + if(odm == ODM_SUCCESS) + { + aProp = new ContentProperties(); + aProp->m_sDocumentName = ::rtl::OStringToOUString(rtl::OString(lpszDocName),RTL_TEXTENCODING_ASCII_US); + aProp->m_sDocumentId = sDocId; + aProp->m_sContentType = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ODMA_CONTENT_TYPE)); + append(aProp); + } + delete [] lpszDocName; + } + else // we got an already fetched name here so look for it + { + // we have a valid document name + aProp = getContentPropertyWithTitle(sCanonicURL); + if(!aProp.is()) + aProp = getContentPropertyWithSavedAsName(sCanonicURL); + if(!aProp.is()) + { + if(sCanonicURL.equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("/"))) + { // found only the scheme + aProp = new ContentProperties(); + aProp->m_sDocumentId = "/"; + aProp->m_sTitle = sCanonicURL; + aProp->m_bIsFolder = sal_True; + aProp->m_bIsDocument = !aProp->m_bIsFolder; + m_aContents.insert(ContentsMap::value_type(aProp->m_sDocumentId,aProp)); + } + else + aProp = queryContentProperty(sCanonicURL); + } + } + if(!aProp.is()) + throw ucb::IllegalIdentifierException(); + + xContent = new Content( m_xSMgr, this, xCanonicId ,aProp); + registerNewContent( xContent ); + + if ( !xContent->getIdentifier().is() ) + throw ucb::IllegalIdentifierException(); + + return xContent; +} +// ----------------------------------------------------------------------------- +void ContentProvider::closeDocument(const ::rtl::OString& _sDocumentId) +{ + ContentsMap::iterator aIter = m_aContents.find(_sDocumentId); + if(aIter != m_aContents.end()) + { + DWORD dwFlags = ODM_SILENT; + ODMSTATUS odm = NODMCloseDocEx( ContentProvider::getHandle(), + const_cast<sal_Char*>(_sDocumentId.getStr()), + &dwFlags, + 0xFFFFFFFF, + 0xFFFFFFFF, + NULL, + 0); + OSL_ENSURE(odm == ODM_SUCCESS,"Error while closing a document!"); + if(odm == ODM_SUCCESS) + aIter->second->m_bIsOpen = sal_False; + } +} +// ----------------------------------------------------------------------------- +void ContentProvider::saveDocument(const ::rtl::OString& _sDocumentId) +{ + ContentsMap::iterator aIter = m_aContents.find(_sDocumentId); + if(aIter != m_aContents.end()) + { + sal_Char* lpszDocId = new sal_Char[ODM_DOCID_MAX]; + DWORD dwFlags = ODM_SILENT; + ODMSTATUS odm = NODMSaveDocEx(getHandle(), + const_cast<sal_Char*>(_sDocumentId.getStr()), + lpszDocId, + &dwFlags); + OSL_ENSURE(odm == ODM_SUCCESS,"Could not save document!"); + if(odm != ODM_SUCCESS) + { + delete [] lpszDocId; + throw uno::Exception(); + } + aIter->second->m_sDocumentId = rtl::OString(lpszDocId); + delete [] lpszDocId; + } +} +// ----------------------------------------------------------------------------- +util::Date toDate(const ::rtl::OString& _sSQLString) +{ + sal_uInt16 nYear = 0, + nMonth = 0, + nDay = 0; + nYear = (sal_uInt16)_sSQLString.copy(0,4).toInt32(); + nMonth = (sal_uInt16)_sSQLString.copy(4,2).toInt32(); + nDay = (sal_uInt16)_sSQLString.copy(6,2).toInt32(); + + return util::Date(nDay,nMonth,nYear); +} +//----------------------------------------------------------------------------- +util::Time toTime(const ::rtl::OString& _sSQLString) +{ + sal_uInt16 nHour = 0, + nMinute = 0, + nSecond = 0; + nHour = (sal_uInt16)_sSQLString.copy(8,2).toInt32(); + nMinute = (sal_uInt16)_sSQLString.copy(10,2).toInt32(); + nSecond = (sal_uInt16)_sSQLString.copy(12,2).toInt32(); + + return util::Time(0,nHour,nMinute,nSecond); +} +//----------------------------------------------------------------------------- +util::DateTime toDateTime(const ::rtl::OString& _sSQLString) +{ + util::Date aDate = toDate(_sSQLString); + util::Time aTime = toTime(_sSQLString); + + return util::DateTime(0,aTime.Seconds,aTime.Minutes,aTime.Hours,aDate.Day,aDate.Month,aDate.Year); +} +// ----------------------------------------------------------------------------- +void ContentProvider::fillDocumentProperties(const ::rtl::Reference<ContentProperties>& _rProp) +{ + // read some properties from the DMS + sal_Char* lpszDocInfo = new sal_Char[ODM_DOCID_MAX]; + sal_Char* pDocId = const_cast<sal_Char*>(_rProp->m_sDocumentId.getStr()); + + // read the create date of the document + ODMSTATUS odm = NODMGetDocInfo( getHandle(), + pDocId, + ODM_CREATEDDATE, + lpszDocInfo, + ODM_DOCID_MAX); + if(odm == ODM_SUCCESS) + _rProp->m_aDateCreated = toDateTime(::rtl::OString(lpszDocInfo)); + + // read the modified date of the document + odm = NODMGetDocInfo( getHandle(), + pDocId, + ODM_MODIFYDATE, + lpszDocInfo, + ODM_DOCID_MAX); + if(odm == ODM_SUCCESS) + _rProp->m_aDateModified = toDateTime(::rtl::OString(lpszDocInfo)); + + // read the title of the document + odm = NODMGetDocInfo( getHandle(), + pDocId, + ODM_TITLETEXT, + lpszDocInfo, + ODM_DOCID_MAX); + if(odm == ODM_SUCCESS) + _rProp->m_sTitle = ::rtl::OStringToOUString(rtl::OString(lpszDocInfo),RTL_TEXTENCODING_ASCII_US); + + // read the name of the document + odm = NODMGetDocInfo( getHandle(), + pDocId, + ODM_NAME, + lpszDocInfo, + ODM_DOCID_MAX); + if(odm == ODM_SUCCESS) + _rProp->m_sDocumentName = ::rtl::OStringToOUString(rtl::OString(lpszDocInfo),RTL_TEXTENCODING_ASCII_US); + + // read the author of the document + odm = NODMGetDocInfo( getHandle(), + pDocId, + ODM_AUTHOR, + lpszDocInfo, + ODM_DOCID_MAX); + if(odm == ODM_SUCCESS) + _rProp->m_sAuthor = ::rtl::OStringToOUString(rtl::OString(lpszDocInfo),RTL_TEXTENCODING_ASCII_US); + + // read the subject of the document + odm = NODMGetDocInfo( getHandle(), + pDocId, + ODM_SUBJECT, + lpszDocInfo, + ODM_DOCID_MAX); + if(odm == ODM_SUCCESS) + _rProp->m_sSubject = ::rtl::OStringToOUString(rtl::OString(lpszDocInfo),RTL_TEXTENCODING_ASCII_US); + + // read the keywords of the document + odm = NODMGetDocInfo( getHandle(), + pDocId, + ODM_KEYWORDS, + lpszDocInfo, + ODM_DOCID_MAX); + if(odm == ODM_SUCCESS) + _rProp->m_sKeywords = ::rtl::OStringToOUString(rtl::OString(lpszDocInfo),RTL_TEXTENCODING_ASCII_US); + +/* + odm = NODMGetDocInfo( getHandle(), + const_cast<sal_Char*>(_rProp->m_sDocumentId.getStr()), + ODM_URL, + lpszDocInfo, + ODM_DOCID_MAX); +*/ + delete [] lpszDocInfo; +} +// ----------------------------------------------------------------------------- +void ContentProvider::append(const ::rtl::Reference<ContentProperties>& _rProp) +{ + // now fill some more properties + fillDocumentProperties(_rProp); + // and append them + m_aContents.insert(ContentsMap::value_type(_rProp->m_sDocumentId,_rProp)); +} +// ----------------------------------------------------------------------------- +::rtl::Reference<ContentProperties> ContentProvider::queryContentProperty(const ::rtl::OUString& _sDocumentName) +{ + ::rtl::Reference<ContentProperties> aReturn; + sal_Char* lpszDMSList = new sal_Char[ODM_DMSID_MAX]; + + ODMSTATUS odm = NODMGetDMS(ODMA_ODMA_REGNAME, lpszDMSList); + if(odm == ODM_SUCCESS) + { + sal_Char* pQueryId = new sal_Char[ODM_QUERYID_MAX]; + lpszDMSList[strlen(lpszDMSList)+1] = '\0'; + + ::rtl::OString sTitleText(::rtl::OUStringToOString(_sDocumentName,RTL_TEXTENCODING_ASCII_US)); + ::rtl::OString sQuery("SELECT ODM_DOCID, ODM_NAME WHERE ODM_TITLETEXT = '"); + sQuery += sTitleText; + sQuery += "'"; + + DWORD dwFlags = ODM_SPECIFIC; + odm = NODMQueryExecute(getHandle(), sQuery,dwFlags, lpszDMSList, pQueryId ); + if(odm == ODM_SUCCESS) + { + sal_uInt16 nCount = 10; + sal_uInt16 nMaxCount = 10; + sal_Char* lpszDocId = new sal_Char[ODM_DOCID_MAX * nMaxCount]; + sal_Char* lpszDocName = new sal_Char[ODM_NAME_MAX * nMaxCount]; + sal_Char* lpszDocInfo = new sal_Char[ODM_DOCID_MAX]; + + ::rtl::OUString sContentType(RTL_CONSTASCII_USTRINGPARAM(ODMA_CONTENT_TYPE)); + do + { + if(nCount >= nMaxCount) + { + // get the result + nCount = nMaxCount; + odm = NODMQueryGetResults(getHandle(), pQueryId,lpszDocId, lpszDocName, ODM_NAME_MAX, (WORD*)&nCount); + } + if(odm == ODM_SUCCESS) + for(sal_uInt16 i = 0; i < nCount; ++i) + { + odm = NODMGetDocInfo( getHandle(), + &lpszDocId[ODM_DOCID_MAX*i], + ODM_TITLETEXT, + lpszDocInfo, + ODM_DOCID_MAX); + if( odm == ODM_SUCCESS && sTitleText == ::rtl::OString(lpszDocInfo)) + { + aReturn = new ContentProperties(); + aReturn->m_sDocumentName = ::rtl::OStringToOUString(rtl::OString(&lpszDocName[ODM_NAME_MAX*i]),RTL_TEXTENCODING_ASCII_US); + aReturn->m_sDocumentId = ::rtl::OString(&lpszDocId[ODM_DOCID_MAX*i]); + aReturn->m_sContentType = sContentType; + append(aReturn); + nCount = 0; // break condition from outer loop + break; + } + } + } + while(nCount > nMaxCount); + + delete [] lpszDocInfo; + delete [] lpszDocId; + delete [] lpszDocName; + } + + // now close the query + odm = NODMQueryClose(ContentProvider::getHandle(), pQueryId); + delete [] pQueryId; + } + delete [] lpszDMSList; + + + return aReturn; +} +// ----------------------------------------------------------------------------- +::rtl::Reference<ContentProperties> ContentProvider::getContentProperty(const ::rtl::OUString& _sName, + const ContentPropertiesMemberFunctor& _aFunctor) const +{ + ::rtl::Reference<ContentProperties> aReturn; + ContentsMap::const_iterator aFind = ::std::find_if( m_aContents.begin(), + m_aContents.end(), + ::std::compose1( + ::std::bind2nd(_aFunctor,_sName), + ::std::select2nd<ContentsMap::value_type>() + ) + ); + if(aFind != m_aContents.end()) + aReturn = aFind->second; + return aReturn; +} +// ----------------------------------------------------------------------------- +::rtl::Reference<ContentProperties> ContentProvider::getContentPropertyWithSavedAsName(const ::rtl::OUString& _sSaveAsName) const +{ + ContentPropertiesMemberFunctor aFunc(::std::mem_fun(&ContentProperties::getSavedAsName)); + return getContentProperty(_sSaveAsName,aFunc); +} +// ----------------------------------------------------------------------------- +::rtl::Reference<ContentProperties> ContentProvider::getContentPropertyWithTitle(const ::rtl::OUString& _sTitle) const +{ + ContentPropertiesMemberFunctor aFunc(::std::mem_fun(&ContentProperties::getTitle)); + return getContentProperty(_sTitle,aFunc); +} +// ----------------------------------------------------------------------------- +::rtl::OUString ContentProvider::openDoc(const ::rtl::Reference<ContentProperties>& _rProp) throw (uno::Exception) +{ + OSL_ENSURE(_rProp.is(),"No valid content properties!"); + if(!_rProp->m_bIsOpen) + { + sal_Char *pFileName = new sal_Char[ODM_FILENAME_MAX]; + + DWORD dwFlag = ODM_MODIFYMODE | ODM_SILENT; + ODMSTATUS odm = NODMOpenDoc(getHandle(), dwFlag, const_cast<sal_Char*>(_rProp->m_sDocumentId.getStr()), pFileName); + switch(odm) + { + case ODM_E_INUSE: + dwFlag = ODM_VIEWMODE; + if( NODMOpenDoc(getHandle(), dwFlag, const_cast<sal_Char*>(_rProp->m_sDocumentId.getStr()), pFileName) != ODM_SUCCESS) + break; + // else run through + case ODM_SUCCESS: + ::osl::FileBase::getFileURLFromSystemPath(::rtl::OStringToOUString(rtl::OString(pFileName),RTL_TEXTENCODING_ASCII_US) + ,_rProp->m_sFileURL); + _rProp->m_bIsOpen = sal_True; + break; + default: + delete [] pFileName; + throw uno::Exception(); // TODO give a more precise error message here + } + + delete [] pFileName; + } + return _rProp->m_sFileURL; +} +// ----------------------------------------------------------------------------- +::rtl::OUString ContentProvider::convertURL(const ::rtl::OUString& _sCanonicURL) +{ + sal_Int32 nPos = 0; + // check if url starts with odma + if(_sCanonicURL.matchIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM(ODMA_URL_SCHEME_SHORT ODMA_URL_SHORT))) + { // URL starts with odma:// so we have to remove this + nPos = ODMA_URL_SHORT_LGTH; + } + else if(_sCanonicURL.matchIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM(ODMA_URL_SCHEME ODMA_URL_SHORT))) + { // URL starts with vnd.sun.star.odma:/// so we have to remove this + nPos = ODMA_URL_LGTH; + } + + ::rtl::OUString sCanonicURL = _sCanonicURL; + // now check what formats we allow + if(nPos == _sCanonicURL.getLength()) // only ask for root entry + sCanonicURL = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/")); + + if(nPos < sCanonicURL.getLength()) + { + sCanonicURL = sCanonicURL.copy(nPos); + sCanonicURL = rtl::Uri::decode(sCanonicURL,rtl_UriDecodeWithCharset,RTL_TEXTENCODING_UTF8); + } + if(sCanonicURL.getLength() > 1 && sCanonicURL.getStr()[0] == sal_Unicode('/')) + { + sCanonicURL = sCanonicURL.copy(1); + if(sCanonicURL.getLength() == 1 && sCanonicURL.getStr()[0] == sal_Unicode('.')) + sCanonicURL = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/")); + } + return sCanonicURL; +} +// ----------------------------------------------------------------------------- +sal_Bool ContentProvider::deleteDocument(const ::rtl::Reference<ContentProperties>& _rProp) +{ + closeDocument(_rProp->m_sDocumentId); + ODMSTATUS odm = NODMActivate(ContentProvider::getHandle(), + ODM_DELETE, + const_cast< sal_Char*>(_rProp->m_sDocumentId.getStr())); + if(odm == ODM_SUCCESS) + m_aContents.erase(_rProp->m_sDocumentId); + + return odm == ODM_SUCCESS; +} +// ----------------------------------------------------------------------------- diff --git a/ucb/source/ucp/odma/odma_provider.hxx b/ucb/source/ucp/odma/odma_provider.hxx new file mode 100644 index 000000000000..0e861f59b492 --- /dev/null +++ b/ucb/source/ucp/odma/odma_provider.hxx @@ -0,0 +1,174 @@ +/************************************************************************* + * + * 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 ODMA_PROVIDER_HXX +#define ODMA_PROVIDER_HXX + +#include <ucbhelper/providerhelper.hxx> +#include "odma_lib.hxx" + +#include "rtl/ref.hxx" + +#include <map> +#include "odma_contentprops.hxx" + +namespace odma { + +//========================================================================= + +// UNO service name for the provider. This name will be used by the UCB to +// create instances of the provider. +#define ODMA_CONTENT_PROVIDER_SERVICE_NAME \ + "com.sun.star.ucb.OdmaContentProvider" +// #define ODMA_CONTENT_PROVIDER_SERVICE_NAME_LENGTH 34 + +// URL scheme. This is the scheme the provider will be able to create +// contents for. The UCB will select the provider ( i.e. in order to create +// contents ) according to this scheme. +#define ODMA_URL_ODMAID "::ODMA" +#define ODMA_URL_SCHEME "vnd.sun.star.odma" +#define ODMA_URL_SCHEME_SHORT "odma" +#define ODMA_URL_SHORT ":" +#define ODMA_URL_SHORT_LGTH 5 +#define ODMA_URL_LGTH 18 +#define ODMA_URL_ODMAID_LGTH 6 + +// UCB Content Type. +#define ODMA_CONTENT_TYPE "application/" ODMA_URL_SCHEME "-content" +#define ODMA_ODMA_REGNAME "sodma" +#define ODM_NAME_MAX 64 // Max length of a name document including + // the terminating NULL character. + +//========================================================================= +class ContentProperties; +class ContentProvider : public ::ucbhelper::ContentProviderImplHelper +{ + typedef ::std::map< ::rtl::OString, ::rtl::Reference<ContentProperties> > ContentsMap; + ContentsMap m_aContents; // contains all ContentProperties + static ODMHANDLE m_aOdmHandle; // the one and only ODMA handle to our DMS + + /** fillDocumentProperties fills the given _rProp with ODMA properties + @param _rProp the ContentProperties + */ + void fillDocumentProperties(const ::rtl::Reference<ContentProperties>& _rProp); + + /** + */ + ::rtl::Reference<ContentProperties> getContentProperty(const ::rtl::OUString& _sName, + const ContentPropertiesMemberFunctor& _aFunctor) const; +public: + ContentProvider( const ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XMultiServiceFactory >& rSMgr ); + virtual ~ContentProvider(); + + // XInterface + XINTERFACE_DECL() + + // XTypeProvider + XTYPEPROVIDER_DECL() + + // XServiceInfo + XSERVICEINFO_DECL() + + // XContentProvider + virtual ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XContent > SAL_CALL + queryContent( const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XContentIdentifier >& Identifier ) + throw( ::com::sun::star::ucb::IllegalIdentifierException, + ::com::sun::star::uno::RuntimeException ); + + ////////////////////////////////////////////////////////////////////// + // Additional interfaces + ////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////// + // Non-interface methods. + ////////////////////////////////////////////////////////////////////// + static ODMHANDLE getHandle(); + + /** append add an entry to the internal map + @param _rProp the content properties + */ + void append(const ::rtl::Reference<ContentProperties>& _rProp); + + /** closeDocument closes the document + @param _sDocumentId the id of the document + */ + void closeDocument(const ::rtl::OString& _sDocumentId); + + /** saveDocument saves the document in DMS + @param _sDocumentId the id of the document + */ + void saveDocument(const ::rtl::OString& _sDocumentId); + + /** queryContentProperty query in the DMS for a content which document name is equal to _sDocumentName + @param _sDocumentName the document to query for + + @return the content properties for this content or an empty refernce + */ + ::rtl::Reference<ContentProperties> queryContentProperty(const ::rtl::OUString& _sDocumentName); + + /** getContentProperty returns the ContentProperties for the first content with that title + @param _sTitle the title of the document + + @return the content properties + */ + ::rtl::Reference<ContentProperties> getContentPropertyWithTitle(const ::rtl::OUString& _sTitle) const; + + /** getContentProperty returns the ContentProperties for the first content with that SavedAsName + @param _sSaveAsName the SavedAsName of the document + + @return the content properties + */ + ::rtl::Reference<ContentProperties> getContentPropertyWithSavedAsName(const ::rtl::OUString& _sSaveAsName) const; + + /** openDoc returns the URL for the temporary file for the specific Content and opens it + @param _rProp used for check if already open, the member m_sFileURL will be set if is wan't opened yet + + @return the URL of the temporary file + */ + static ::rtl::OUString openDoc(const ::rtl::Reference<ContentProperties>& _rProp) throw (::com::sun::star::uno::Exception); + + /** convertURL converts a normal URL into an ODMA understandable name + @param _sCanonicURL the URL from ContentIndentifier + + @return the ODMA name + */ + static ::rtl::OUString convertURL(const ::rtl::OUString& _sCanonicURL); + + /** deleteDocument deletes the document inside the DMS and remove the content properties from inside list + @param _rProp the ContentProperties + + @return true when successful + */ + sal_Bool deleteDocument(const ::rtl::Reference<ContentProperties>& _rProp); +}; + +} + +#endif diff --git a/ucb/source/ucp/odma/odma_resultset.cxx b/ucb/source/ucp/odma/odma_resultset.cxx new file mode 100644 index 000000000000..82e6b271fcd3 --- /dev/null +++ b/ucb/source/ucp/odma/odma_resultset.cxx @@ -0,0 +1,96 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + - This implementation is not a dynamic result set!!! It only implements + the necessary interfaces, but never recognizes/notifies changes!!! + + *************************************************************************/ +#include "odma_datasupplier.hxx" +#include "odma_resultset.hxx" + +using namespace com::sun::star::lang; +using namespace com::sun::star::ucb; +using namespace com::sun::star::uno; + +using namespace odma; + +//========================================================================= +//========================================================================= +// +// DynamicResultSet Implementation. +// +//========================================================================= +//========================================================================= + +DynamicResultSet::DynamicResultSet( + const Reference< XMultiServiceFactory >& rxSMgr, + const rtl::Reference< Content >& rxContent, + const OpenCommandArgument2& rCommand, + const Reference< XCommandEnvironment >& rxEnv ) +: ResultSetImplHelper( rxSMgr, rCommand ), + m_xContent( rxContent ), + m_xEnv( rxEnv ) +{ +} + +//========================================================================= +// +// Non-interface methods. +// +//========================================================================= + +void DynamicResultSet::initStatic() +{ + m_xResultSet1 + = new ::ucbhelper::ResultSet( m_xSMgr, + m_aCommand.Properties, + new DataSupplier( m_xSMgr, + m_xContent, + m_aCommand.Mode ), + m_xEnv ); +} + +//========================================================================= +void DynamicResultSet::initDynamic() +{ + m_xResultSet1 + = new ::ucbhelper::ResultSet( m_xSMgr, + m_aCommand.Properties, + new DataSupplier( m_xSMgr, + m_xContent, + m_aCommand.Mode ), + m_xEnv ); + m_xResultSet2 = m_xResultSet1; +} + diff --git a/ucb/source/ucp/odma/odma_resultset.hxx b/ucb/source/ucp/odma/odma_resultset.hxx new file mode 100644 index 000000000000..77787b1fccda --- /dev/null +++ b/ucb/source/ucp/odma/odma_resultset.hxx @@ -0,0 +1,60 @@ +/************************************************************************* + * + * 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 ODMA_RESULTSET_HXX +#define ODMA_RESULTSET_HXX + +#include <ucbhelper/resultsethelper.hxx> + +#include "rtl/ref.hxx" +#include "odma_content.hxx" + +namespace odma { + +class DynamicResultSet : public ::ucbhelper::ResultSetImplHelper +{ + rtl::Reference< Content > m_xContent; + com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > m_xEnv; + +private: + virtual void initStatic(); + virtual void initDynamic(); + +public: + DynamicResultSet( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + const rtl::Reference< Content >& rxContent, + const com::sun::star::ucb::OpenCommandArgument2& rCommand, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment >& rxEnv ); +}; + +} + +#endif diff --git a/ucb/source/ucp/odma/odma_services.cxx b/ucb/source/ucp/odma/odma_services.cxx new file mode 100644 index 000000000000..0f5666e2bb53 --- /dev/null +++ b/ucb/source/ucp/odma/odma_services.cxx @@ -0,0 +1,99 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <com/sun/star/registry/XRegistryKey.hpp> +#include "odma_contentprops.hxx" +#include "odma_provider.hxx" +#include "odma_lib.hxx" + +using namespace rtl; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::registry; + +//========================================================================= +extern "C" void SAL_CALL component_getImplementationEnvironment( + const sal_Char ** ppEnvTypeName, uno_Environment ** /*ppEnv*/ ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + +//========================================================================= +extern "C" sal_Bool SAL_CALL component_writeInfo( + void * /*pServiceManager*/, void * pRegistryKey ) +{ + return pRegistryKey && + + ////////////////////////////////////////////////////////////////////// + // Write info into registry. + ////////////////////////////////////////////////////////////////////// + + // @@@ Adjust namespace names. + writeInfo( pRegistryKey, + ::odma::ContentProvider::getImplementationName_Static(), + ::odma::ContentProvider::getSupportedServiceNames_Static() ); +} + +//========================================================================= +extern "C" void * SAL_CALL component_getFactory( + const sal_Char * pImplName, void * pServiceManager, void * /*pRegistryKey*/ ) +{ + void * pRet = 0; + + Reference< XMultiServiceFactory > xSMgr( + reinterpret_cast< XMultiServiceFactory * >( pServiceManager ) ); + Reference< XSingleServiceFactory > xFactory; + + ////////////////////////////////////////////////////////////////////// + // Create factory, if implementation name matches. + ////////////////////////////////////////////////////////////////////// + + // @@@ Adjust namespace names. + if ( ::odma::ContentProvider::getImplementationName_Static(). + compareToAscii( pImplName ) == 0 ) + { + if(::odma::LoadLibrary()) + xFactory = ::odma::ContentProvider::createServiceFactory( xSMgr ); + else + OSL_ASSERT(!"Could not load library!"); + } + + ////////////////////////////////////////////////////////////////////// + + if ( xFactory.is() ) + { + xFactory->acquire(); + pRet = xFactory.get(); + } + + return pRet; +} + diff --git a/ucb/source/ucp/odma/ucpodma.xml b/ucb/source/ucp/odma/ucpodma.xml new file mode 100644 index 000000000000..1ca36334d966 --- /dev/null +++ b/ucb/source/ucp/odma/ucpodma.xml @@ -0,0 +1,100 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE module-description PUBLIC "-//StarOffice//DTD ComponentDescription 1.0//EN" "module-description.dtd"> +<module-description xmlns:xlink="http://www.w3.org/1999/xlink"> + + <module-name> + ucpodma + </module-name> + + <component-description> + <author> + Ocke Janssen + </author> + <name> + com.sun.star.comp.ucb.OdmaContentProvider + </name> + <description> + This component implements a Content Provider for the Universal + Content Broker. It provides access to contents stored on an document management + system (DMS). + </description> + <loader-name> + com.sun.star.loader.SharedLibrary + </loader-name> + <language> + c++ + </language> + <status value="final"/> + <supported-service> + com.sun.star.ucb.ODMAContentProvider + </supported-service> + + <service-dependency> + com.sun.star.configuration.ConfigurationAccess + </service-dependency> + <service-dependency> + com.sun.star.configuration.ConfigurationProvider + </service-dependency> + </component-description> + + <project-build-dependency> external </project-build-dependency> + <project-build-dependency> sal </project-build-dependency> + <project-build-dependency> cppu </project-build-dependency> + <project-build-dependency> cppuhelper </project-build-dependency> + <project-build-dependency> ucbhelper </project-build-dependency> + + <runtime-module-dependency> sal3 </runtime-module-dependency> + <runtime-module-dependency> cppu3 </runtime-module-dependency> + <runtime-module-dependency> cppuhelper3$(COM) </runtime-module-dependency> + <runtime-module-dependency> ucbhelper4$(COM) </runtime-module-dependency> + + <type> com.sun.star.beans.PropertyAttribute </type> + <type> com.sun.star.beans.PropertyValue </type> + <type> com.sun.star.beans.XPropertiesChangeNotifier </type> + <type> com.sun.star.beans.XPropertyAccess </type> + <type> com.sun.star.beans.XPropertyContainer </type> + <type> com.sun.star.beans.XPropertySetInfoChangeNotifier </type> + <type> com.sun.star.container.XChild </type> + <type> com.sun.star.container.XNameAccess </type> + <type> com.sun.star.io.XActiveDataSink </type> + <type> com.sun.star.io.XInputStream </type> + <type> com.sun.star.io.XOutputStream </type> + <type> com.sun.star.io.XSeekable </type> + <type> com.sun.star.lang.IllegalAccessException </type> + <type> com.sun.star.lang.XComponent </type> + <type> com.sun.star.lang.XMultiServiceFactory </type> + <type> com.sun.star.lang.XServiceInfo </type> + <type> com.sun.star.lang.XSingleServiceFactory </type> + <type> com.sun.star.lang.XTypeProvider </type> + <type> com.sun.star.registry.XRegistryKey </type> + <type> com.sun.star.sdbc.XCloseable </type> + <type> com.sun.star.sdbc.XColumnLocate </type> + <type> com.sun.star.sdbc.XResultSetMetaDataSupplier </type> + <type> com.sun.star.sdbc.XRow </type> + <type> com.sun.star.ucb.ContentCreationException </type> + <type> com.sun.star.ucb.ContentInfoAttribute </type> + <type> com.sun.star.ucb.InsertCommandArgument </type> + <type> com.sun.star.ucb.MissingInputStreamException </type> + <type> com.sun.star.ucb.MissingPropertiesException </type> + <type> com.sun.star.ucb.NameClash </type> + <type> com.sun.star.ucb.NameClashException </type> + <type> com.sun.star.ucb.OpenCommandArgument2 </type> + <type> com.sun.star.ucb.OpenMode </type> + <type> com.sun.star.ucb.PostCommandArgument2 </type> + <type> com.sun.star.ucb.RememberAuthentication </type> + <type> com.sun.star.ucb.ResultSetException </type> + <type> com.sun.star.ucb.TransferInfo </type> + <type> com.sun.star.ucb.XCommandEnvironment </type> + <type> com.sun.star.ucb.UnsupportedCommandException </type> + <type> com.sun.star.ucb.UnsupportedDataSinkException </type> + <type> com.sun.star.ucb.UnsupportedNameClashException </type> + <type> com.sun.star.ucb.UnsupportedOpenModeException </type> + <type> com.sun.star.ucb.XCommandInfo </type> + <type> com.sun.star.ucb.XCommandInfoChangeNotifier </type> + <type> com.sun.star.ucb.XCommandProcessor </type> + <type> com.sun.star.ucb.XContentAccess </type> + <type> com.sun.star.ucb.XContentProvider </type> + <type> com.sun.star.ucb.XDynamicResultSet </type> + <type> com.sun.star.ucb.XPersistentPropertySet </type> + <type> com.sun.star.util.DateTime </type> +</module-description> diff --git a/ucb/source/ucp/package/makefile.mk b/ucb/source/ucp/package/makefile.mk new file mode 100644 index 000000000000..b78150aed2cb --- /dev/null +++ b/ucb/source/ucp/package/makefile.mk @@ -0,0 +1,97 @@ +#************************************************************************* +# +# 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. +# +#************************************************************************* + +# UCP Version - Increase, if UCP libraray becomes incompatible. +UCP_VERSION=1 + +# Name for UCP. Will become part of the library name (See below). +UCP_NAME=pkg + +PRJ=..$/..$/.. + +PRJNAME=ucb + +TARGET=ucp$(UCP_NAME) + +ENABLE_EXCEPTIONS=TRUE +USE_DEFFILE=TRUE +NO_BSYMBOLIC=TRUE + +# --- Settings --------------------------------------------------------- + +.INCLUDE: settings.mk + +# --- General ----------------------------------------------------- +.IF "$(L10N_framework)"=="" + +SLOFILES=\ + $(SLO)$/pkgservices.obj \ + $(SLO)$/pkguri.obj \ + $(SLO)$/pkgprovider.obj \ + $(SLO)$/pkgcontent.obj \ + $(SLO)$/pkgcontentcaps.obj \ + $(SLO)$/pkgresultset.obj \ + $(SLO)$/pkgdatasupplier.obj + +LIB1TARGET=$(SLB)$/_$(TARGET).lib +LIB1OBJFILES=$(SLOFILES) + +# --- Shared-Library --------------------------------------------------- + +SHL1TARGET=$(TARGET)$(UCP_VERSION) +SHL1IMPLIB=i$(TARGET) + +SHL1VERSIONMAP=$(SOLARENV)/src/component.map + +SHL1STDLIBS=\ + $(COMPHELPERLIB) \ + $(CPPUHELPERLIB) \ + $(CPPULIB) \ + $(SALLIB) \ + $(SALHELPERLIB) \ + $(UCBHELPERLIB) + +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +SHL1LIBS=$(LIB1TARGET) + +# --- Def-File --------------------------------------------------------- + +DEF1NAME=$(SHL1TARGET) + +# --- Targets ---------------------------------------------------------- + +.ENDIF # L10N_framework +.INCLUDE: target.mk + + +ALLTAR : $(MISC)/ucppkg1.component + +$(MISC)/ucppkg1.component .ERRREMOVE : $(SOLARENV)/bin/createcomponent.xslt \ + ucppkg1.component + $(XSLTPROC) --nonet --stringparam uri \ + '$(COMPONENTPREFIX_BASIS_NATIVE)$(SHL1TARGETN:f)' -o $@ \ + $(SOLARENV)/bin/createcomponent.xslt ucppkg1.component diff --git a/ucb/source/ucp/package/pkgcontent.cxx b/ucb/source/ucp/package/pkgcontent.cxx new file mode 100644 index 000000000000..8bdebb138467 --- /dev/null +++ b/ucb/source/ucp/package/pkgcontent.cxx @@ -0,0 +1,3012 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + *************************************************************************/ +#include <osl/diagnose.h> + +#include "osl/doublecheckedlocking.h" +#include <rtl/ustring.h> +#include <rtl/ustring.hxx> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/beans/PropertyState.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/beans/XPropertyAccess.hpp> +#include <com/sun/star/container/XEnumerationAccess.hpp> +#include <com/sun/star/container/XHierarchicalNameAccess.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/container/XNamed.hpp> +#include <com/sun/star/io/XActiveDataSink.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/lang/IllegalAccessException.hpp> +#include <com/sun/star/sdbc/XRow.hpp> +#include <com/sun/star/ucb/ContentInfoAttribute.hpp> +#include <com/sun/star/ucb/InsertCommandArgument.hpp> +#include <com/sun/star/ucb/InteractiveBadTransferURLException.hpp> +#include <com/sun/star/ucb/MissingInputStreamException.hpp> +#include <com/sun/star/ucb/NameClash.hpp> +#include <com/sun/star/ucb/NameClashException.hpp> +#include <com/sun/star/ucb/OpenCommandArgument2.hpp> +#include <com/sun/star/ucb/OpenMode.hpp> +#include <com/sun/star/ucb/TransferInfo.hpp> +#include <com/sun/star/ucb/UnsupportedDataSinkException.hpp> +#include <com/sun/star/ucb/UnsupportedNameClashException.hpp> +#include <com/sun/star/ucb/UnsupportedOpenModeException.hpp> +#include <com/sun/star/ucb/XCommandInfo.hpp> +#include <com/sun/star/ucb/XPersistentPropertySet.hpp> +#include <com/sun/star/util/XChangesBatch.hpp> +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/uno/Sequence.hxx> +#include <ucbhelper/contentidentifier.hxx> +#include <ucbhelper/propertyvalueset.hxx> +#include <ucbhelper/cancelcommandexecution.hxx> +#include "pkgcontent.hxx" +#include "pkgprovider.hxx" +#include "pkgresultset.hxx" + +#include "../inc/urihelper.hxx" + +using namespace com::sun::star; +using namespace package_ucp; + +#define NONE_MODIFIED sal_uInt32( 0x00 ) +#define MEDIATYPE_MODIFIED sal_uInt32( 0x01 ) +#define COMPRESSED_MODIFIED sal_uInt32( 0x02 ) +#define ENCRYPTED_MODIFIED sal_uInt32( 0x04 ) +#define ENCRYPTIONKEY_MODIFIED sal_uInt32( 0x08 ) + +//========================================================================= +//========================================================================= +// +// ContentProperties Implementation. +// +//========================================================================= +//========================================================================= + +ContentProperties::ContentProperties( const rtl::OUString& rContentType ) +: aContentType( rContentType ), + nSize( 0 ), + bCompressed( sal_True ), + bEncrypted( sal_False ), + bHasEncryptedEntries( sal_False ) +{ + bIsFolder = rContentType.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( PACKAGE_FOLDER_CONTENT_TYPE ) ) + || rContentType.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( PACKAGE_ZIP_FOLDER_CONTENT_TYPE ) ); + bIsDocument = !bIsFolder; + + OSL_ENSURE( bIsFolder || + rContentType.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( PACKAGE_STREAM_CONTENT_TYPE ) ) + || rContentType.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( PACKAGE_ZIP_STREAM_CONTENT_TYPE ) ), + "ContentProperties::ContentProperties - Unknown type!" ); +} + +//========================================================================= + +uno::Sequence< ucb::ContentInfo > +ContentProperties::getCreatableContentsInfo( PackageUri const & rUri ) const +{ + if ( bIsFolder ) + { + uno::Sequence< beans::Property > aProps( 1 ); + aProps.getArray()[ 0 ] = beans::Property( + rtl::OUString::createFromAscii( "Title" ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND ); + + uno::Sequence< ucb::ContentInfo > aSeq( 2 ); + + // Folder. + aSeq.getArray()[ 0 ].Type + = Content::getContentType( rUri.getScheme(), sal_True ); + aSeq.getArray()[ 0 ].Attributes + = ucb::ContentInfoAttribute::KIND_FOLDER; + aSeq.getArray()[ 0 ].Properties = aProps; + + // Stream. + aSeq.getArray()[ 1 ].Type + = Content::getContentType( rUri.getScheme(), sal_False ); + aSeq.getArray()[ 1 ].Attributes + = ucb::ContentInfoAttribute::INSERT_WITH_INPUTSTREAM + | ucb::ContentInfoAttribute::KIND_DOCUMENT; + aSeq.getArray()[ 1 ].Properties = aProps; + + return aSeq; + } + else + { + return uno::Sequence< ucb::ContentInfo >( 0 ); + } +} + +//========================================================================= +//========================================================================= +// +// Content Implementation. +// +//========================================================================= +//========================================================================= + +// static ( "virtual" ctor ) +Content* Content::create( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + ContentProvider* pProvider, + const uno::Reference< ucb::XContentIdentifier >& Identifier ) +{ + rtl::OUString aURL = Identifier->getContentIdentifier(); + PackageUri aURI( aURL ); + ContentProperties aProps; + uno::Reference< container::XHierarchicalNameAccess > xPackage; + + if ( loadData( pProvider, aURI, aProps, xPackage ) ) + { + // resource exists + + sal_Int32 nLastSlash = aURL.lastIndexOf( '/' ); + if ( ( nLastSlash + 1 ) == aURL.getLength() ) + { + // Client explicitely requested a folder! + if ( !aProps.bIsFolder ) + return 0; + } + + uno::Reference< ucb::XContentIdentifier > xId + = new ::ucbhelper::ContentIdentifier( rxSMgr, aURI.getUri() ); + return new Content( rxSMgr, pProvider, xId, xPackage, aURI, aProps ); + } + else + { + // resource doesn't exist + + sal_Bool bFolder = sal_False; + + // Guess type according to URI. + sal_Int32 nLastSlash = aURL.lastIndexOf( '/' ); + if ( ( nLastSlash + 1 ) == aURL.getLength() ) + bFolder = sal_True; + + uno::Reference< ucb::XContentIdentifier > xId + = new ::ucbhelper::ContentIdentifier( rxSMgr, aURI.getUri() ); + + ucb::ContentInfo aInfo; + if ( bFolder || aURI.isRootFolder() ) + aInfo.Type = getContentType( aURI.getScheme(), sal_True ); + else + aInfo.Type = getContentType( aURI.getScheme(), sal_False ); + + return new Content( rxSMgr, pProvider, xId, xPackage, aURI, aInfo ); + } +} + +//========================================================================= +// static ( "virtual" ctor ) +Content* Content::create( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + ContentProvider* pProvider, + const uno::Reference< ucb::XContentIdentifier >& Identifier, + const ucb::ContentInfo& Info ) +{ + if ( !Info.Type.getLength() ) + return 0; + + PackageUri aURI( Identifier->getContentIdentifier() ); + + if ( !Info.Type.equalsIgnoreAsciiCase( + getContentType( aURI.getScheme(), sal_True ) ) && + !Info.Type.equalsIgnoreAsciiCase( + getContentType( aURI.getScheme(), sal_False ) ) ) + return 0; + + uno::Reference< container::XHierarchicalNameAccess > xPackage; + +#if 0 + // Fail, if content does exist. + if ( hasData( pProvider, aURI, xPackage ) ) + return 0; +#else + xPackage = pProvider->createPackage( aURI.getPackage(), aURI.getParam() ); +#endif + + uno::Reference< ucb::XContentIdentifier > xId + = new ::ucbhelper::ContentIdentifier( rxSMgr, aURI.getUri() ); + return new Content( rxSMgr, pProvider, xId, xPackage, aURI, Info ); +} + +//========================================================================= +// static +::rtl::OUString Content::getContentType( + const ::rtl::OUString& aScheme, sal_Bool bFolder ) +{ + return ( rtl::OUString::createFromAscii( "application/" ) + + aScheme + + ( bFolder + ? rtl::OUString::createFromAscii( "-folder" ) + : rtl::OUString::createFromAscii( "-stream" ) ) ); +} + +//========================================================================= +Content::Content( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + ContentProvider* pProvider, + const uno::Reference< ucb::XContentIdentifier >& Identifier, + const uno::Reference< container::XHierarchicalNameAccess > & Package, + const PackageUri& rUri, + const ContentProperties& rProps ) +: ContentImplHelper( rxSMgr, pProvider, Identifier ), + m_aUri( rUri ), + m_aProps( rProps ), + m_eState( PERSISTENT ), + m_xPackage( Package ), + m_pProvider( pProvider ), + m_nModifiedProps( NONE_MODIFIED ) +{ +} + +//========================================================================= +Content::Content( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + ContentProvider* pProvider, + const uno::Reference< ucb::XContentIdentifier >& Identifier, + const uno::Reference< container::XHierarchicalNameAccess > & Package, + const PackageUri& rUri, + const ucb::ContentInfo& Info ) + : ContentImplHelper( rxSMgr, pProvider, Identifier ), + m_aUri( rUri ), + m_aProps( Info.Type ), + m_eState( TRANSIENT ), + m_xPackage( Package ), + m_pProvider( pProvider ), + m_nModifiedProps( NONE_MODIFIED ) +{ +} + +//========================================================================= +// virtual +Content::~Content() +{ +} + +//========================================================================= +// +// XInterface methods. +// +//========================================================================= + +// virtual +void SAL_CALL Content::acquire() + throw( ) +{ + ContentImplHelper::acquire(); +} + +//========================================================================= +// virtual +void SAL_CALL Content::release() + throw( ) +{ + ContentImplHelper::release(); +} + +//========================================================================= +// virtual +uno::Any SAL_CALL Content::queryInterface( const uno::Type & rType ) + throw ( uno::RuntimeException ) +{ + uno::Any aRet; + + if ( isFolder() ) + aRet = cppu::queryInterface( + rType, static_cast< ucb::XContentCreator * >( this ) ); + + return aRet.hasValue() ? aRet : ContentImplHelper::queryInterface( rType ); +} + +//========================================================================= +// +// XTypeProvider methods. +// +//========================================================================= + +XTYPEPROVIDER_COMMON_IMPL( Content ); + +//========================================================================= +// virtual +uno::Sequence< uno::Type > SAL_CALL Content::getTypes() + throw( uno::RuntimeException ) +{ + cppu::OTypeCollection * pCollection = 0; + + if ( isFolder() ) + { + static cppu::OTypeCollection* pFolderTypes = 0; + + pCollection = pFolderTypes; + if ( !pCollection ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + + pCollection = pFolderTypes; + if ( !pCollection ) + { + static cppu::OTypeCollection aCollection( + CPPU_TYPE_REF( lang::XTypeProvider ), + CPPU_TYPE_REF( lang::XServiceInfo ), + CPPU_TYPE_REF( lang::XComponent ), + CPPU_TYPE_REF( ucb::XContent ), + CPPU_TYPE_REF( ucb::XCommandProcessor ), + CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ), + CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ), + CPPU_TYPE_REF( beans::XPropertyContainer ), + CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ), + CPPU_TYPE_REF( container::XChild ), + CPPU_TYPE_REF( ucb::XContentCreator ) ); // !! + pCollection = &aCollection; + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + pFolderTypes = pCollection; + } + } + else { + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + } + } + else + { + static cppu::OTypeCollection* pDocumentTypes = 0; + + pCollection = pDocumentTypes; + if ( !pCollection ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + + pCollection = pDocumentTypes; + if ( !pCollection ) + { + static cppu::OTypeCollection aCollection( + CPPU_TYPE_REF( lang::XTypeProvider ), + CPPU_TYPE_REF( lang::XServiceInfo ), + CPPU_TYPE_REF( lang::XComponent ), + CPPU_TYPE_REF( ucb::XContent ), + CPPU_TYPE_REF( ucb::XCommandProcessor ), + CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ), + CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ), + CPPU_TYPE_REF( beans::XPropertyContainer ), + CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ), + CPPU_TYPE_REF( container::XChild ) ); + pCollection = &aCollection; + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + pDocumentTypes = pCollection; + } + } + else { + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + } + } + + return (*pCollection).getTypes(); +} + +//========================================================================= +// +// XServiceInfo methods. +// +//========================================================================= + +// virtual +rtl::OUString SAL_CALL Content::getImplementationName() + throw( uno::RuntimeException ) +{ + return rtl::OUString::createFromAscii( + "com.sun.star.comp.ucb.PackageContent" ); +} + +//========================================================================= +// virtual +uno::Sequence< rtl::OUString > SAL_CALL Content::getSupportedServiceNames() + throw( uno::RuntimeException ) +{ + uno::Sequence< rtl::OUString > aSNS( 1 ); + if ( isFolder() ) + aSNS.getArray()[ 0 ] + = rtl::OUString::createFromAscii( + PACKAGE_FOLDER_CONTENT_SERVICE_NAME ); + else + aSNS.getArray()[ 0 ] + = rtl::OUString::createFromAscii( + PACKAGE_STREAM_CONTENT_SERVICE_NAME ); + + return aSNS; +} + +//========================================================================= +// +// XContent methods. +// +//========================================================================= + +// virtual +rtl::OUString SAL_CALL Content::getContentType() + throw( uno::RuntimeException ) +{ + return m_aProps.aContentType; +} + +//========================================================================= +// +// XCommandProcessor methods. +// +//========================================================================= + +// virtual +uno::Any SAL_CALL Content::execute( + const ucb::Command& aCommand, + sal_Int32 /*CommandId*/, + const uno::Reference< ucb::XCommandEnvironment >& Environment ) + throw( uno::Exception, + ucb::CommandAbortedException, + uno::RuntimeException ) +{ + uno::Any aRet; + + if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "getPropertyValues" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // getPropertyValues + ////////////////////////////////////////////////////////////////// + + uno::Sequence< beans::Property > Properties; + if ( !( aCommand.Argument >>= Properties ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Wrong argument type!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + aRet <<= getPropertyValues( Properties ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "setPropertyValues" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // setPropertyValues + ////////////////////////////////////////////////////////////////// + + uno::Sequence< beans::PropertyValue > aProperties; + if ( !( aCommand.Argument >>= aProperties ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Wrong argument type!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + if ( !aProperties.getLength() ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "No properties!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + aRet <<= setPropertyValues( aProperties, Environment ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "getPropertySetInfo" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // getPropertySetInfo + ////////////////////////////////////////////////////////////////// + + // Note: Implemented by base class. + aRet <<= getPropertySetInfo( Environment ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "getCommandInfo" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // getCommandInfo + ////////////////////////////////////////////////////////////////// + + // Note: Implemented by base class. + aRet <<= getCommandInfo( Environment ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "open" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // open + ////////////////////////////////////////////////////////////////// + + ucb::OpenCommandArgument2 aOpenCommand; + if ( !( aCommand.Argument >>= aOpenCommand ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Wrong argument type!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + aRet = open( aOpenCommand, Environment ); + } + else if ( !m_aUri.isRootFolder() + && aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "insert" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // insert + ////////////////////////////////////////////////////////////////// + + ucb::InsertCommandArgument aArg; + if ( !( aCommand.Argument >>= aArg ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Wrong argument type!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + sal_Int32 nNameClash = aArg.ReplaceExisting + ? ucb::NameClash::OVERWRITE + : ucb::NameClash::ERROR; + insert( aArg.Data, nNameClash, Environment ); + } + else if ( !m_aUri.isRootFolder() + && aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "delete" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // delete + ////////////////////////////////////////////////////////////////// + + sal_Bool bDeletePhysical = sal_False; + aCommand.Argument >>= bDeletePhysical; + destroy( bDeletePhysical, Environment ); + + // Remove own and all children's persistent data. + if ( !removeData() ) + { + uno::Any aProps + = uno::makeAny( + beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Uri")), + -1, + uno::makeAny(m_xIdentifier-> + getContentIdentifier()), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_WRITE, + uno::Sequence< uno::Any >(&aProps, 1), + Environment, + rtl::OUString::createFromAscii( + "Cannot remove persistent data!" ), + this ); + // Unreachable + } + + // Remove own and all children's Additional Core Properties. + removeAdditionalPropertySet( sal_True ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "transfer" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // transfer + // ( Not available at stream objects ) + ////////////////////////////////////////////////////////////////// + + ucb::TransferInfo aInfo; + if ( !( aCommand.Argument >>= aInfo ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Wrong argument type!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + transfer( aInfo, Environment ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "createNewContent" ) ) && + isFolder() ) + { + ////////////////////////////////////////////////////////////////// + // createNewContent + // ( Not available at stream objects ) + ////////////////////////////////////////////////////////////////// + + ucb::ContentInfo aInfo; + if ( !( aCommand.Argument >>= aInfo ) ) + { + OSL_ENSURE( sal_False, "Wrong argument type!" ); + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Wrong argument type!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + aRet <<= createNewContent( aInfo ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "flush" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // flush + // ( Not available at stream objects ) + ////////////////////////////////////////////////////////////////// + + if( !flushData() ) + { + uno::Any aProps + = uno::makeAny( + beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Uri")), + -1, + uno::makeAny(m_xIdentifier-> + getContentIdentifier()), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_WRITE, + uno::Sequence< uno::Any >(&aProps, 1), + Environment, + rtl::OUString::createFromAscii( + "Cannot write file to disk!" ), + this ); + // Unreachable + } + } + else + { + ////////////////////////////////////////////////////////////////// + // Unsupported command + ////////////////////////////////////////////////////////////////// + + ucbhelper::cancelCommandExecution( + uno::makeAny( ucb::UnsupportedCommandException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ) ) ), + Environment ); + // Unreachable + } + + return aRet; +} + +//========================================================================= +// virtual +void SAL_CALL Content::abort( sal_Int32 /*CommandId*/ ) + throw( uno::RuntimeException ) +{ + // @@@ Implement logic to abort running commands, if this makes + // sense for your content. +} + +//========================================================================= +// +// XContentCreator methods. +// +//========================================================================= + +// virtual +uno::Sequence< ucb::ContentInfo > SAL_CALL +Content::queryCreatableContentsInfo() + throw( uno::RuntimeException ) +{ + return m_aProps.getCreatableContentsInfo( m_aUri ); +} + +//========================================================================= +// virtual +uno::Reference< ucb::XContent > SAL_CALL +Content::createNewContent( const ucb::ContentInfo& Info ) + throw( uno::RuntimeException ) +{ + if ( isFolder() ) + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + if ( !Info.Type.getLength() ) + return uno::Reference< ucb::XContent >(); + + if ( !Info.Type.equalsIgnoreAsciiCase( + getContentType( m_aUri.getScheme(), sal_True ) ) && + !Info.Type.equalsIgnoreAsciiCase( + getContentType( m_aUri.getScheme(), sal_False ) ) ) + return uno::Reference< ucb::XContent >(); + + rtl::OUString aURL = m_aUri.getUri(); + aURL += rtl::OUString::createFromAscii( "/" ); + + if ( Info.Type.equalsIgnoreAsciiCase( + getContentType( m_aUri.getScheme(), sal_True ) ) ) + aURL += rtl::OUString::createFromAscii( "New_Folder" ); + else + aURL += rtl::OUString::createFromAscii( "New_Stream" ); + + uno::Reference< ucb::XContentIdentifier > xId( + new ::ucbhelper::ContentIdentifier( m_xSMgr, aURL ) ); + + return create( m_xSMgr, m_pProvider, xId, Info ); + } + else + { + OSL_ENSURE( sal_False, + "createNewContent called on non-folder object!" ); + return uno::Reference< ucb::XContent >(); + } +} + +//========================================================================= +// +// Non-interface methods. +// +//========================================================================= + +// virtual +rtl::OUString Content::getParentURL() +{ + return m_aUri.getParentUri(); +} + +//========================================================================= +// static +uno::Reference< sdbc::XRow > Content::getPropertyValues( + const uno::Reference< lang::XMultiServiceFactory >& rSMgr, + const uno::Sequence< beans::Property >& rProperties, + ContentProvider* pProvider, + const rtl::OUString& rContentId ) +{ + ContentProperties aData; + uno::Reference< container::XHierarchicalNameAccess > xPackage; + if ( loadData( pProvider, PackageUri( rContentId ), aData, xPackage ) ) + { + return getPropertyValues( rSMgr, + rProperties, + aData, + rtl::Reference< + ::ucbhelper::ContentProviderImplHelper >( + pProvider ), + rContentId ); + } + else + { + rtl::Reference< ::ucbhelper::PropertyValueSet > xRow + = new ::ucbhelper::PropertyValueSet( rSMgr ); + + sal_Int32 nCount = rProperties.getLength(); + if ( nCount ) + { + const beans::Property* pProps = rProperties.getConstArray(); + for ( sal_Int32 n = 0; n < nCount; ++n ) + xRow->appendVoid( pProps[ n ] ); + } + + return uno::Reference< sdbc::XRow >( xRow.get() ); + } +} + +//========================================================================= +// static +uno::Reference< sdbc::XRow > Content::getPropertyValues( + const uno::Reference< lang::XMultiServiceFactory >& rSMgr, + const uno::Sequence< beans::Property >& rProperties, + const ContentProperties& rData, + const rtl::Reference< ::ucbhelper::ContentProviderImplHelper >& + rProvider, + const rtl::OUString& rContentId ) +{ + // Note: Empty sequence means "get values of all supported properties". + + rtl::Reference< ::ucbhelper::PropertyValueSet > xRow + = new ::ucbhelper::PropertyValueSet( rSMgr ); + + sal_Int32 nCount = rProperties.getLength(); + if ( nCount ) + { + uno::Reference< beans::XPropertySet > xAdditionalPropSet; + sal_Bool bTriedToGetAdditonalPropSet = sal_False; + + const beans::Property* pProps = rProperties.getConstArray(); + for ( sal_Int32 n = 0; n < nCount; ++n ) + { + const beans::Property& rProp = pProps[ n ]; + + // Process Core properties. + + if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) ) + { + xRow->appendString ( rProp, rData.aContentType ); + } + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "Title" ) ) ) + { + xRow->appendString ( rProp, rData.aTitle ); + } + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) ) + { + xRow->appendBoolean( rProp, rData.bIsDocument ); + } + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) ) + { + xRow->appendBoolean( rProp, rData.bIsFolder ); + } + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "CreatableContentsInfo" ) ) ) + { + xRow->appendObject( + rProp, uno::makeAny( + rData.getCreatableContentsInfo( + PackageUri( rContentId ) ) ) ); + } + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "MediaType" ) ) ) + { + xRow->appendString ( rProp, rData.aMediaType ); + } + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "Size" ) ) ) + { + // Property only available for streams. + if ( rData.bIsDocument ) + xRow->appendLong( rProp, rData.nSize ); + else + xRow->appendVoid( rProp ); + } + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "Compressed" ) ) ) + { + // Property only available for streams. + if ( rData.bIsDocument ) + xRow->appendBoolean( rProp, rData.bCompressed ); + else + xRow->appendVoid( rProp ); + } + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "Encrypted" ) ) ) + { + // Property only available for streams. + if ( rData.bIsDocument ) + xRow->appendBoolean( rProp, rData.bEncrypted ); + else + xRow->appendVoid( rProp ); + } + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "HasEncryptedEntries" ) ) ) + { + // Property only available for root folder. + PackageUri aURI( rContentId ); + if ( aURI.isRootFolder() ) + xRow->appendBoolean( rProp, rData.bHasEncryptedEntries ); + else + xRow->appendVoid( rProp ); + } + else + { + // Not a Core Property! Maybe it's an Additional Core Property?! + + if ( !bTriedToGetAdditonalPropSet && !xAdditionalPropSet.is() ) + { + xAdditionalPropSet + = uno::Reference< beans::XPropertySet >( + rProvider->getAdditionalPropertySet( rContentId, + sal_False ), + uno::UNO_QUERY ); + bTriedToGetAdditonalPropSet = sal_True; + } + + if ( xAdditionalPropSet.is() ) + { + if ( !xRow->appendPropertySetValue( + xAdditionalPropSet, + rProp ) ) + { + // Append empty entry. + xRow->appendVoid( rProp ); + } + } + else + { + // Append empty entry. + xRow->appendVoid( rProp ); + } + } + } + } + else + { + // Append all Core Properties. + xRow->appendString ( + beans::Property( + rtl::OUString::createFromAscii( "ContentType" ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ), + rData.aContentType ); + xRow->appendString( + beans::Property( + rtl::OUString::createFromAscii( "Title" ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND ), + rData.aTitle ); + xRow->appendBoolean( + beans::Property( + rtl::OUString::createFromAscii( "IsDocument" ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ), + rData.bIsDocument ); + xRow->appendBoolean( + beans::Property( + rtl::OUString::createFromAscii( "IsFolder" ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ), + rData.bIsFolder ); + xRow->appendObject( + beans::Property( + rtl::OUString::createFromAscii( "CreatableContentsInfo" ), + -1, + getCppuType( static_cast< + const uno::Sequence< ucb::ContentInfo > * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ), + uno::makeAny( + rData.getCreatableContentsInfo( PackageUri( rContentId ) ) ) ); + xRow->appendString( + beans::Property( + rtl::OUString::createFromAscii( "MediaType" ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND ), + rData.aMediaType ); + + // Properties only available for streams. + if ( rData.bIsDocument ) + { + xRow->appendLong( + beans::Property( + rtl::OUString::createFromAscii( "Size" ), + -1, + getCppuType( static_cast< const sal_Int64 * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ), + rData.nSize ); + + xRow->appendBoolean( + beans::Property( + rtl::OUString::createFromAscii( "Compressed" ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND ), + rData.bCompressed ); + + xRow->appendBoolean( + beans::Property( + rtl::OUString::createFromAscii( "Encrypted" ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND ), + rData.bEncrypted ); + } + + // Properties only available for root folder. + PackageUri aURI( rContentId ); + if ( aURI.isRootFolder() ) + { + xRow->appendBoolean( + beans::Property( + rtl::OUString::createFromAscii( "HasEncryptedEntries" ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ), + rData.bHasEncryptedEntries ); + } + + // Append all Additional Core Properties. + + uno::Reference< beans::XPropertySet > xSet( + rProvider->getAdditionalPropertySet( rContentId, sal_False ), + uno::UNO_QUERY ); + xRow->appendPropertySet( xSet ); + } + + return uno::Reference< sdbc::XRow >( xRow.get() ); +} + +//========================================================================= +uno::Reference< sdbc::XRow > Content::getPropertyValues( + const uno::Sequence< beans::Property >& rProperties ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + return getPropertyValues( m_xSMgr, + rProperties, + m_aProps, + rtl::Reference< + ::ucbhelper::ContentProviderImplHelper >( + m_xProvider.get() ), + m_xIdentifier->getContentIdentifier() ); +} + +//========================================================================= +uno::Sequence< uno::Any > Content::setPropertyValues( + const uno::Sequence< beans::PropertyValue >& rValues, + const uno::Reference< ucb::XCommandEnvironment > & xEnv ) + throw( uno::Exception ) +{ + osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); + + uno::Sequence< uno::Any > aRet( rValues.getLength() ); + uno::Sequence< beans::PropertyChangeEvent > aChanges( rValues.getLength() ); + sal_Int32 nChanged = 0; + + beans::PropertyChangeEvent aEvent; + aEvent.Source = static_cast< cppu::OWeakObject * >( this ); + aEvent.Further = sal_False; +// aEvent.PropertyName = + aEvent.PropertyHandle = -1; +// aEvent.OldValue = +// aEvent.NewValue = + + const beans::PropertyValue* pValues = rValues.getConstArray(); + sal_Int32 nCount = rValues.getLength(); + + uno::Reference< ucb::XPersistentPropertySet > xAdditionalPropSet; + sal_Bool bTriedToGetAdditonalPropSet = sal_False; + sal_Bool bExchange = sal_False; + sal_Bool bStore = sal_False; + rtl::OUString aNewTitle; + sal_Int32 nTitlePos = -1; + + for ( sal_Int32 n = 0; n < nCount; ++n ) + { + const beans::PropertyValue& rValue = pValues[ n ]; + + if ( rValue.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) ) + { + // Read-only property! + aRet[ n ] <<= lang::IllegalAccessException( + rtl::OUString::createFromAscii( + "Property is read-only!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + else if ( rValue.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) ) + { + // Read-only property! + aRet[ n ] <<= lang::IllegalAccessException( + rtl::OUString::createFromAscii( + "Property is read-only!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + else if ( rValue.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) ) + { + // Read-only property! + aRet[ n ] <<= lang::IllegalAccessException( + rtl::OUString::createFromAscii( + "Property is read-only!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + else if ( rValue.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "CreatableContentsInfo" ) ) ) + { + // Read-only property! + aRet[ n ] <<= lang::IllegalAccessException( + rtl::OUString::createFromAscii( + "Property is read-only!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + else if ( rValue.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "Title" ) ) ) + { + if ( m_aUri.isRootFolder() ) + { + // Read-only property! + aRet[ n ] <<= lang::IllegalAccessException( + rtl::OUString::createFromAscii( + "Property is read-only!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + else + { + rtl::OUString aNewValue; + if ( rValue.Value >>= aNewValue ) + { + // No empty titles! + if ( aNewValue.getLength() > 0 ) + { + if ( aNewValue != m_aProps.aTitle ) + { + // modified title -> modified URL -> exchange ! + if ( m_eState == PERSISTENT ) + bExchange = sal_True; + + // new value will be set later... + aNewTitle = aNewValue; + + // remember position within sequence of values + // (for error handling). + nTitlePos = n; + } + } + else + { + aRet[ n ] <<= + lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Empty title not allowed!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ); + } + } + else + { + aRet[ n ] <<= + beans::IllegalTypeException( + rtl::OUString::createFromAscii( + "Property value has wrong type!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + } + } + else if ( rValue.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "MediaType" ) ) ) + { + rtl::OUString aNewValue; + if ( rValue.Value >>= aNewValue ) + { + if ( aNewValue != m_aProps.aMediaType ) + { + aEvent.PropertyName = rValue.Name; + aEvent.OldValue = uno::makeAny( m_aProps.aMediaType ); + aEvent.NewValue = uno::makeAny( aNewValue ); + + m_aProps.aMediaType = aNewValue; + nChanged++; + bStore = sal_True; + m_nModifiedProps |= MEDIATYPE_MODIFIED; + } + } + else + { + aRet[ n ] <<= beans::IllegalTypeException( + rtl::OUString::createFromAscii( + "Property value has wrong type!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + } + else if ( rValue.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "Size" ) ) ) + { + // Read-only property! + aRet[ n ] <<= lang::IllegalAccessException( + rtl::OUString::createFromAscii( + "Property is read-only!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + else if ( rValue.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "Compressed" ) ) ) + { + // Property only available for streams. + if ( m_aProps.bIsDocument ) + { + sal_Bool bNewValue; + if ( rValue.Value >>= bNewValue ) + { + if ( bNewValue != m_aProps.bCompressed ) + { + aEvent.PropertyName = rValue.Name; + aEvent.OldValue = uno::makeAny( m_aProps.bCompressed ); + aEvent.NewValue = uno::makeAny( bNewValue ); + + m_aProps.bCompressed = bNewValue; + nChanged++; + bStore = sal_True; + m_nModifiedProps |= COMPRESSED_MODIFIED; + } + } + else + { + aRet[ n ] <<= beans::IllegalTypeException( + rtl::OUString::createFromAscii( + "Property value has wrong type!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + } + else + { + aRet[ n ] <<= beans::UnknownPropertyException( + rtl::OUString::createFromAscii( + "Compressed only supported by streams!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + } + else if ( rValue.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "Encrypted" ) ) ) + { + // Property only available for streams. + if ( m_aProps.bIsDocument ) + { + sal_Bool bNewValue; + if ( rValue.Value >>= bNewValue ) + { + if ( bNewValue != m_aProps.bEncrypted ) + { + aEvent.PropertyName = rValue.Name; + aEvent.OldValue = uno::makeAny( m_aProps.bEncrypted ); + aEvent.NewValue = uno::makeAny( bNewValue ); + + m_aProps.bEncrypted = bNewValue; + nChanged++; + bStore = sal_True; + m_nModifiedProps |= ENCRYPTED_MODIFIED; + } + } + else + { + aRet[ n ] <<= beans::IllegalTypeException( + rtl::OUString::createFromAscii( + "Property value has wrong type!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + } + else + { + aRet[ n ] <<= beans::UnknownPropertyException( + rtl::OUString::createFromAscii( + "Encrypted only supported by streams!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + } + else if ( rValue.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "HasEncryptedEntries" ) ) ) + { + // Read-only property! + aRet[ n ] <<= lang::IllegalAccessException( + rtl::OUString::createFromAscii( + "Property is read-only!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + else if ( rValue.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "EncryptionKey" ) ) ) + { + // @@@ This is a temporary solution. In the future submitting + // the key should be done using an interaction handler! + + // Write-Only property. Only supported by root folder and streams + // (all non-root folders of a package have the same encryption key). + if ( m_aUri.isRootFolder() || m_aProps.bIsDocument ) + { + uno::Sequence < sal_Int8 > aNewValue; + if ( rValue.Value >>= aNewValue ) + { + if ( aNewValue != m_aProps.aEncryptionKey ) + { + aEvent.PropertyName = rValue.Name; + aEvent.OldValue = uno::makeAny( + m_aProps.aEncryptionKey ); + aEvent.NewValue = uno::makeAny( aNewValue ); + + m_aProps.aEncryptionKey = aNewValue; + nChanged++; + bStore = sal_True; + m_nModifiedProps |= ENCRYPTIONKEY_MODIFIED; + } + } + else + { + aRet[ n ] <<= beans::IllegalTypeException( + rtl::OUString::createFromAscii( + "Property value has wrong type!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + } + else + { + aRet[ n ] <<= beans::UnknownPropertyException( + rtl::OUString::createFromAscii( + "EncryptionKey not supported by non-root folder!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + } + else + { + // Not a Core Property! Maybe it's an Additional Core Property?! + + if ( !bTriedToGetAdditonalPropSet && !xAdditionalPropSet.is() ) + { + xAdditionalPropSet = getAdditionalPropertySet( sal_False ); + bTriedToGetAdditonalPropSet = sal_True; + } + + if ( xAdditionalPropSet.is() ) + { + try + { + uno::Any aOldValue + = xAdditionalPropSet->getPropertyValue( rValue.Name ); + if ( aOldValue != rValue.Value ) + { + xAdditionalPropSet->setPropertyValue( + rValue.Name, rValue.Value ); + + aEvent.PropertyName = rValue.Name; + aEvent.OldValue = aOldValue; + aEvent.NewValue = rValue.Value; + + aChanges.getArray()[ nChanged ] = aEvent; + nChanged++; + } + } + catch ( beans::UnknownPropertyException const & e ) + { + aRet[ n ] <<= e; + } + catch ( lang::WrappedTargetException const & e ) + { + aRet[ n ] <<= e; + } + catch ( beans::PropertyVetoException const & e ) + { + aRet[ n ] <<= e; + } + catch ( lang::IllegalArgumentException const & e ) + { + aRet[ n ] <<= e; + } + } + else + { + aRet[ n ] <<= uno::Exception( + rtl::OUString::createFromAscii( + "No property set for storing the value!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + } + } + + if ( bExchange ) + { + uno::Reference< ucb::XContentIdentifier > xOldId = m_xIdentifier; + + // Assemble new content identifier... + rtl::OUString aNewURL = m_aUri.getParentUri(); + aNewURL += rtl::OUString::createFromAscii( "/" ); + aNewURL += ::ucb_impl::urihelper::encodeSegment( aNewTitle ); + uno::Reference< ucb::XContentIdentifier > xNewId + = new ::ucbhelper::ContentIdentifier( m_xSMgr, aNewURL ); + + aGuard.clear(); + if ( exchangeIdentity( xNewId ) ) + { + // Adapt persistent data. + renameData( xOldId, xNewId ); + + // Adapt Additional Core Properties. + renameAdditionalPropertySet( xOldId->getContentIdentifier(), + xNewId->getContentIdentifier(), + sal_True ); + } + else + { + // Do not set new title! + aNewTitle = rtl::OUString(); + + // Set error . + aRet[ nTitlePos ] <<= uno::Exception( + rtl::OUString::createFromAscii( "Exchange failed!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + } + + if ( aNewTitle.getLength() ) + { + aEvent.PropertyName = rtl::OUString::createFromAscii( "Title" ); + aEvent.OldValue = uno::makeAny( m_aProps.aTitle ); + aEvent.NewValue = uno::makeAny( aNewTitle ); + + m_aProps.aTitle = aNewTitle; + + aChanges.getArray()[ nChanged ] = aEvent; + nChanged++; + } + + if ( nChanged > 0 ) + { + // Save changes, if content was already made persistent. + if ( ( m_nModifiedProps & ENCRYPTIONKEY_MODIFIED ) || + ( bStore && ( m_eState == PERSISTENT ) ) ) + { + if ( !storeData( uno::Reference< io::XInputStream >() ) ) + { + uno::Any aProps + = uno::makeAny( + beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Uri")), + -1, + uno::makeAny(m_xIdentifier-> + getContentIdentifier()), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_WRITE, + uno::Sequence< uno::Any >(&aProps, 1), + xEnv, + rtl::OUString::createFromAscii( + "Cannot store persistent data!" ), + this ); + // Unreachable + } + } + + aGuard.clear(); + aChanges.realloc( nChanged ); + notifyPropertiesChange( aChanges ); + } + + return aRet; +} + +//========================================================================= +uno::Any Content::open( + const ucb::OpenCommandArgument2& rArg, + const uno::Reference< ucb::XCommandEnvironment >& xEnv ) + throw( uno::Exception ) +{ + if ( rArg.Mode == ucb::OpenMode::ALL || + rArg.Mode == ucb::OpenMode::FOLDERS || + rArg.Mode == ucb::OpenMode::DOCUMENTS ) + { + ////////////////////////////////////////////////////////////////// + // open command for a folder content + ////////////////////////////////////////////////////////////////// + + uno::Reference< ucb::XDynamicResultSet > xSet + = new DynamicResultSet( m_xSMgr, this, rArg, xEnv ); + return uno::makeAny( xSet ); + } + else + { + ////////////////////////////////////////////////////////////////// + // open command for a document content + ////////////////////////////////////////////////////////////////// + + if ( ( rArg.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_NONE ) || + ( rArg.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE ) ) + { + // Currently(?) unsupported. + ucbhelper::cancelCommandExecution( + uno::makeAny( ucb::UnsupportedOpenModeException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + sal_Int16( rArg.Mode ) ) ), + xEnv ); + // Unreachable + } + + rtl::OUString aURL = m_xIdentifier->getContentIdentifier(); + uno::Reference< io::XOutputStream > xOut( rArg.Sink, uno::UNO_QUERY ); + if ( xOut.is() ) + { + // PUSH: write data into xOut + + uno::Reference< io::XInputStream > xIn = getInputStream(); + if ( !xIn.is() ) + { + // No interaction if we are not persistent! + uno::Any aProps + = uno::makeAny( + beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Uri")), + -1, + uno::makeAny(m_xIdentifier-> + getContentIdentifier()), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_READ, + uno::Sequence< uno::Any >(&aProps, 1), + m_eState == PERSISTENT + ? xEnv + : uno::Reference< ucb::XCommandEnvironment >(), + rtl::OUString::createFromAscii( "Got no data stream!" ), + this ); + // Unreachable + } + + try + { + uno::Sequence< sal_Int8 > aBuffer; + sal_Int32 nRead = xIn->readSomeBytes( aBuffer, 65536 ); + + while ( nRead > 0 ) + { + aBuffer.realloc( nRead ); + xOut->writeBytes( aBuffer ); + aBuffer.realloc( 0 ); + nRead = xIn->readSomeBytes( aBuffer, 65536 ); + } + + xOut->closeOutput(); + } + catch ( io::NotConnectedException const & ) + { + // closeOutput, readSomeBytes, writeBytes + } + catch ( io::BufferSizeExceededException const & ) + { + // closeOutput, readSomeBytes, writeBytes + } + catch ( io::IOException const & ) + { + // closeOutput, readSomeBytes, writeBytes + } + } + else + { + uno::Reference< io::XActiveDataSink > xDataSink( + rArg.Sink, uno::UNO_QUERY ); + if ( xDataSink.is() ) + { + // PULL: wait for client read + + uno::Reference< io::XInputStream > xIn = getInputStream(); + if ( !xIn.is() ) + { + // No interaction if we are not persistent! + uno::Any aProps + = uno::makeAny( + beans::PropertyValue( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("Uri")), + -1, + uno::makeAny(m_xIdentifier-> + getContentIdentifier()), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_READ, + uno::Sequence< uno::Any >(&aProps, 1), + m_eState == PERSISTENT + ? xEnv + : uno::Reference< + ucb::XCommandEnvironment >(), + rtl::OUString::createFromAscii( + "Got no data stream!" ), + this ); + // Unreachable + } + + // Done. + xDataSink->setInputStream( xIn ); + } + else + { + // Note: aOpenCommand.Sink may contain an XStream + // implementation. Support for this type of + // sink is optional... + ucbhelper::cancelCommandExecution( + uno::makeAny( + ucb::UnsupportedDataSinkException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + rArg.Sink ) ), + xEnv ); + // Unreachable + } + } + } + + return uno::Any(); +} + +//========================================================================= +void Content::insert( + const uno::Reference< io::XInputStream >& xStream, + sal_Int32 nNameClashResolve, + const uno::Reference< ucb::XCommandEnvironment >& xEnv ) + throw( uno::Exception ) +{ + osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); + + // Check, if all required properties were set. + if ( isFolder() ) + { + // Required: Title + + if ( !m_aProps.aTitle.getLength() ) + m_aProps.aTitle = m_aUri.getName(); + } + else + { + // Required: rArg.Data + + if ( !xStream.is() ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( ucb::MissingInputStreamException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ) ) ), + xEnv ); + // Unreachable + } + + // Required: Title + + if ( !m_aProps.aTitle.getLength() ) + m_aProps.aTitle = m_aUri.getName(); + } + + rtl::OUString aNewURL = m_aUri.getParentUri(); + if (1 + aNewURL.lastIndexOf('/') != aNewURL.getLength()) + aNewURL += rtl::OUString::createFromAscii( "/" ); + aNewURL += ::ucb_impl::urihelper::encodeSegment( m_aProps.aTitle ); + PackageUri aNewUri( aNewURL ); + + // Handle possible name clash... + switch ( nNameClashResolve ) + { + // fail. + case ucb::NameClash::ERROR: + if ( hasData( aNewUri ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( ucb::NameClashException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + task::InteractionClassification_ERROR, + m_aProps.aTitle ) ), + xEnv ); + // Unreachable + } + break; + + // replace (possibly) existing object. + case ucb::NameClash::OVERWRITE: + break; + + // "invent" a new valid title. + case ucb::NameClash::RENAME: + if ( hasData( aNewUri ) ) + { + sal_Int32 nTry = 0; + + do + { + rtl::OUString aNew = aNewUri.getUri(); + aNew += rtl::OUString::createFromAscii( "_" ); + aNew += rtl::OUString::valueOf( ++nTry ); + aNewUri.setUri( aNew ); + } + while ( hasData( aNewUri ) && ( nTry < 1000 ) ); + + if ( nTry == 1000 ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( + ucb::UnsupportedNameClashException( + rtl::OUString::createFromAscii( + "Unable to resolve name clash!" ), + static_cast< cppu::OWeakObject * >( this ), + nNameClashResolve ) ), + xEnv ); + // Unreachable + } + else + { + m_aProps.aTitle += rtl::OUString::createFromAscii( "_" ); + m_aProps.aTitle += rtl::OUString::valueOf( nTry ); + } + } + break; + + case ucb::NameClash::KEEP: // deprecated + case ucb::NameClash::ASK: + default: + if ( hasData( aNewUri ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( + ucb::UnsupportedNameClashException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + nNameClashResolve ) ), + xEnv ); + // Unreachable + } + break; + } + + // Identifier changed? + sal_Bool bNewId = ( m_aUri.getUri() != aNewUri.getUri() ); + + if ( bNewId ) + { + m_xIdentifier = new ::ucbhelper::ContentIdentifier( m_xSMgr, aNewURL ); + m_aUri = aNewUri; + } + + if ( !storeData( xStream ) ) + { + uno::Any aProps + = uno::makeAny(beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Uri")), + -1, + uno::makeAny(m_xIdentifier-> + getContentIdentifier()), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_WRITE, + uno::Sequence< uno::Any >(&aProps, 1), + xEnv, + rtl::OUString::createFromAscii( "Cannot store persistent data!" ), + this ); + // Unreachable + } + + m_eState = PERSISTENT; + + if ( bNewId ) + { + // Take over correct default values from underlying packager... + uno::Reference< container::XHierarchicalNameAccess > xXHierarchicalNameAccess; + loadData( m_pProvider, + m_aUri, + m_aProps, + xXHierarchicalNameAccess ); + + aGuard.clear(); + inserted(); + } +} + +//========================================================================= +void Content::destroy( + sal_Bool bDeletePhysical, + const uno::Reference< ucb::XCommandEnvironment >& xEnv ) + throw( uno::Exception ) +{ + // @@@ take care about bDeletePhysical -> trashcan support + + osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); + + uno::Reference< ucb::XContent > xThis = this; + + // Persistent? + if ( m_eState != PERSISTENT ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( ucb::UnsupportedCommandException( + rtl::OUString::createFromAscii( + "Not persistent!" ), + static_cast< cppu::OWeakObject * >( this ) ) ), + xEnv ); + // Unreachable + } + + m_eState = DEAD; + + aGuard.clear(); + deleted(); + + if ( isFolder() ) + { + // Process instanciated children... + + ContentRefList aChildren; + queryChildren( aChildren ); + + ContentRefList::const_iterator it = aChildren.begin(); + ContentRefList::const_iterator end = aChildren.end(); + + while ( it != end ) + { + (*it)->destroy( bDeletePhysical, xEnv ); + ++it; + } + } +} + +//========================================================================= +void Content::transfer( + const ucb::TransferInfo& rInfo, + const uno::Reference< ucb::XCommandEnvironment > & xEnv ) + throw( uno::Exception ) +{ + osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); + + // Persistent? + if ( m_eState != PERSISTENT ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( ucb::UnsupportedCommandException( + rtl::OUString::createFromAscii( + "Not persistent!" ), + static_cast< cppu::OWeakObject * >( this ) ) ), + xEnv ); + // Unreachable + } + + // Is source a package content? + if ( ( rInfo.SourceURL.getLength() == 0 ) || + ( rInfo.SourceURL.compareTo( + m_aUri.getUri(), PACKAGE_URL_SCHEME_LENGTH + 3 ) != 0 ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( ucb::InteractiveBadTransferURLException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ) ) ), + xEnv ); + // Unreachable + } + + // Is source not a parent of me / not me? + rtl::OUString aId = m_aUri.getParentUri(); + aId += rtl::OUString::createFromAscii( "/" ); + + if ( rInfo.SourceURL.getLength() <= aId.getLength() ) + { + if ( aId.compareTo( + rInfo.SourceURL, rInfo.SourceURL.getLength() ) == 0 ) + { + uno::Any aProps + = uno::makeAny(beans::PropertyValue( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("Uri")), + -1, + uno::makeAny(rInfo.SourceURL), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_RECURSIVE, + uno::Sequence< uno::Any >(&aProps, 1), + xEnv, + rtl::OUString::createFromAscii( + "Target is equal to or is a child of source!" ), + this ); + // Unreachable + } + } + + ////////////////////////////////////////////////////////////////////// + // 0) Obtain content object for source. + ////////////////////////////////////////////////////////////////////// + + uno::Reference< ucb::XContentIdentifier > xId + = new ::ucbhelper::ContentIdentifier( m_xSMgr, rInfo.SourceURL ); + + // Note: The static cast is okay here, because its sure that + // m_xProvider is always the PackageContentProvider. + rtl::Reference< Content > xSource; + + try + { + xSource = static_cast< Content * >( + m_xProvider->queryContent( xId ).get() ); + } + catch ( ucb::IllegalIdentifierException const & ) + { + // queryContent + } + + if ( !xSource.is() ) + { + uno::Any aProps + = uno::makeAny(beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Uri")), + -1, + uno::makeAny(xId->getContentIdentifier()), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_READ, + uno::Sequence< uno::Any >(&aProps, 1), + xEnv, + rtl::OUString::createFromAscii( + "Cannot instanciate source object!" ), + this ); + // Unreachable + } + + ////////////////////////////////////////////////////////////////////// + // 1) Create new child content. + ////////////////////////////////////////////////////////////////////// + + rtl::OUString aType = xSource->isFolder() + ? getContentType( m_aUri.getScheme(), sal_True ) + : getContentType( m_aUri.getScheme(), sal_False ); + ucb::ContentInfo aContentInfo; + aContentInfo.Type = aType; + aContentInfo.Attributes = 0; + + // Note: The static cast is okay here, because its sure that + // createNewContent always creates a Content. + rtl::Reference< Content > xTarget + = static_cast< Content * >( createNewContent( aContentInfo ).get() ); + if ( !xTarget.is() ) + { + uno::Any aProps + = uno::makeAny(beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Folder")), + -1, + uno::makeAny(aId), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_CREATE, + uno::Sequence< uno::Any >(&aProps, 1), + xEnv, + rtl::OUString::createFromAscii( + "XContentCreator::createNewContent failed!" ), + this ); + // Unreachable + } + + ////////////////////////////////////////////////////////////////////// + // 2) Copy data from source content to child content. + ////////////////////////////////////////////////////////////////////// + + uno::Sequence< beans::Property > aSourceProps + = xSource->getPropertySetInfo( xEnv )->getProperties(); + sal_Int32 nCount = aSourceProps.getLength(); + + if ( nCount ) + { + sal_Bool bHadTitle = ( rInfo.NewTitle.getLength() == 0 ); + + // Get all source values. + uno::Reference< sdbc::XRow > xRow + = xSource->getPropertyValues( aSourceProps ); + + uno::Sequence< beans::PropertyValue > aValues( nCount ); + beans::PropertyValue* pValues = aValues.getArray(); + + const beans::Property* pProps = aSourceProps.getConstArray(); + for ( sal_Int32 n = 0; n < nCount; ++n ) + { + const beans::Property& rProp = pProps[ n ]; + beans::PropertyValue& rValue = pValues[ n ]; + + rValue.Name = rProp.Name; + rValue.Handle = rProp.Handle; + + if ( !bHadTitle && rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "Title" ) ) ) + { + // Set new title instead of original. + bHadTitle = sal_True; + rValue.Value <<= rInfo.NewTitle; + } + else + rValue.Value + = xRow->getObject( n + 1, + uno::Reference< + container::XNameAccess >() ); + + rValue.State = beans::PropertyState_DIRECT_VALUE; + + if ( rProp.Attributes & beans::PropertyAttribute::REMOVABLE ) + { + // Add Additional Core Property. + try + { + xTarget->addProperty( rProp.Name, + rProp.Attributes, + rValue.Value ); + } + catch ( beans::PropertyExistException const & ) + { + } + catch ( beans::IllegalTypeException const & ) + { + } + catch ( lang::IllegalArgumentException const & ) + { + } + } + } + + // Set target values. + xTarget->setPropertyValues( aValues, xEnv ); + } + + ////////////////////////////////////////////////////////////////////// + // 3) Commit (insert) child. + ////////////////////////////////////////////////////////////////////// + + xTarget->insert( xSource->getInputStream(), rInfo.NameClash, xEnv ); + + ////////////////////////////////////////////////////////////////////// + // 4) Transfer (copy) children of source. + ////////////////////////////////////////////////////////////////////// + + if ( xSource->isFolder() ) + { + uno::Reference< container::XEnumeration > xIter + = xSource->getIterator(); + if ( xIter.is() ) + { + while ( xIter->hasMoreElements() ) + { + try + { + uno::Reference< container::XNamed > xNamed; + xIter->nextElement() >>= xNamed; + + if ( !xNamed.is() ) + { + OSL_ENSURE( sal_False, + "Content::transfer - Got no XNamed!" ); + break; + } + + rtl::OUString aName = xNamed->getName(); + + if ( !aName.getLength() ) + { + OSL_ENSURE( sal_False, + "Content::transfer - Empty name!" ); + break; + } + + rtl::OUString aChildId = xId->getContentIdentifier(); + if ( ( aChildId.lastIndexOf( '/' ) + 1 ) + != aChildId.getLength() ) + aChildId += rtl::OUString::createFromAscii( "/" ); + + aChildId += ::ucb_impl::urihelper::encodeSegment( aName ); + + ucb::TransferInfo aInfo; + aInfo.MoveData = sal_False; + aInfo.NewTitle = rtl::OUString(); + aInfo.SourceURL = aChildId; + aInfo.NameClash = rInfo.NameClash; + + // Transfer child to target. + xTarget->transfer( aInfo, xEnv ); + } + catch ( container::NoSuchElementException const & ) + { + } + catch ( lang::WrappedTargetException const & ) + { + } + } + } + } + + ////////////////////////////////////////////////////////////////////// + // 5) Destroy source ( when moving only ) . + ////////////////////////////////////////////////////////////////////// + + if ( rInfo.MoveData ) + { + xSource->destroy( sal_True, xEnv ); + + // Remove all persistent data of source and its children. + if ( !xSource->removeData() ) + { + uno::Any aProps + = uno::makeAny( + beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Uri")), + -1, + uno::makeAny( + xSource->m_xIdentifier-> + getContentIdentifier()), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_WRITE, + uno::Sequence< uno::Any >(&aProps, 1), + xEnv, + rtl::OUString::createFromAscii( + "Cannot remove persistent data of source object!" ), + this ); + // Unreachable + } + + // Remove own and all children's Additional Core Properties. + xSource->removeAdditionalPropertySet( sal_True ); + } +} + +//========================================================================= +sal_Bool Content::exchangeIdentity( + const uno::Reference< ucb::XContentIdentifier >& xNewId ) +{ + if ( !xNewId.is() ) + return sal_False; + + osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); + + uno::Reference< ucb::XContent > xThis = this; + + // Already persistent? + if ( m_eState != PERSISTENT ) + { + OSL_ENSURE( sal_False, + "Content::exchangeIdentity - Not persistent!" ); + return sal_False; + } + + // Exchange own identitity. + + // Fail, if a content with given id already exists. + PackageUri aNewUri( xNewId->getContentIdentifier() ); + if ( !hasData( aNewUri ) ) + { + rtl::OUString aOldURL = m_xIdentifier->getContentIdentifier(); + + aGuard.clear(); + if ( exchange( xNewId ) ) + { + m_aUri = aNewUri; + if ( isFolder() ) + { + // Process instanciated children... + + ContentRefList aChildren; + queryChildren( aChildren ); + + ContentRefList::const_iterator it = aChildren.begin(); + ContentRefList::const_iterator end = aChildren.end(); + + while ( it != end ) + { + ContentRef xChild = (*it); + + // Create new content identifier for the child... + uno::Reference< ucb::XContentIdentifier > xOldChildId + = xChild->getIdentifier(); + rtl::OUString aOldChildURL + = xOldChildId->getContentIdentifier(); + rtl::OUString aNewChildURL + = aOldChildURL.replaceAt( + 0, + aOldURL.getLength(), + xNewId->getContentIdentifier() ); + uno::Reference< ucb::XContentIdentifier > xNewChildId + = new ::ucbhelper::ContentIdentifier( + m_xSMgr, aNewChildURL ); + + if ( !xChild->exchangeIdentity( xNewChildId ) ) + return sal_False; + + ++it; + } + } + return sal_True; + } + } + + OSL_ENSURE( sal_False, + "Content::exchangeIdentity - Panic! Cannot exchange identity!" ); + return sal_False; +} + +//========================================================================= +void Content::queryChildren( ContentRefList& rChildren ) +{ + // Obtain a list with a snapshot of all currently instanciated contents + // from provider and extract the contents which are direct children + // of this content. + + ::ucbhelper::ContentRefList aAllContents; + m_xProvider->queryExistingContents( aAllContents ); + + rtl::OUString aURL = m_xIdentifier->getContentIdentifier(); + + OSL_ENSURE( aURL.lastIndexOf( '/' ) != ( aURL.getLength() - 1 ), + "Content::queryChildren - Invalid URL!" ); + + aURL += rtl::OUString::createFromAscii( "/" ); + + sal_Int32 nLen = aURL.getLength(); + + ::ucbhelper::ContentRefList::const_iterator it = aAllContents.begin(); + ::ucbhelper::ContentRefList::const_iterator end = aAllContents.end(); + + while ( it != end ) + { + ::ucbhelper::ContentImplHelperRef xChild = (*it); + rtl::OUString aChildURL + = xChild->getIdentifier()->getContentIdentifier(); + + // Is aURL a prefix of aChildURL? + if ( ( aChildURL.getLength() > nLen ) && + ( aChildURL.compareTo( aURL, nLen ) == 0 ) ) + { + if ( aChildURL.indexOf( '/', nLen ) == -1 ) + { + // No further slashes. It's a child! + rChildren.push_back( + ContentRef( + static_cast< Content * >( xChild.get() ) ) ); + } + } + ++it; + } +} + +//========================================================================= +uno::Reference< container::XHierarchicalNameAccess > Content::getPackage( + const PackageUri& rURI ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + uno::Reference< container::XHierarchicalNameAccess > xPackage; + if ( rURI.getPackage() == m_aUri.getPackage() ) + { + if ( !m_xPackage.is() ) + m_xPackage = m_pProvider->createPackage( m_aUri.getPackage(), m_aUri.getParam() ); + + return m_xPackage; + } + + return m_pProvider->createPackage( rURI.getPackage(), rURI.getParam() ); +} + +//========================================================================= +uno::Reference< container::XHierarchicalNameAccess > Content::getPackage() +{ + return getPackage( m_aUri ); +} + +//========================================================================= +// static +sal_Bool Content::hasData( + ContentProvider* pProvider, + const PackageUri& rURI, + uno::Reference< container::XHierarchicalNameAccess > & rxPackage ) +{ + rxPackage = pProvider->createPackage( rURI.getPackage(), rURI.getParam() ); + if ( !rxPackage.is() ) + return sal_False; + + return rxPackage->hasByHierarchicalName( rURI.getPath() ); +} + +//========================================================================= +sal_Bool Content::hasData( const PackageUri& rURI ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + uno::Reference< container::XHierarchicalNameAccess > xPackage; + if ( rURI.getPackage() == m_aUri.getPackage() ) + { + xPackage = getPackage(); + if ( !xPackage.is() ) + return sal_False; + + return xPackage->hasByHierarchicalName( rURI.getPath() ); + } + + return hasData( m_pProvider, rURI, xPackage ); +} + +//========================================================================= +//static +sal_Bool Content::loadData( + ContentProvider* pProvider, + const PackageUri& rURI, + ContentProperties& rProps, + uno::Reference< container::XHierarchicalNameAccess > & rxPackage ) +{ + rxPackage = pProvider->createPackage( rURI.getPackage(), rURI.getParam() ); + if ( !rxPackage.is() ) + return sal_False; + + if ( rURI.isRootFolder() ) + { + // Properties available only from package + uno::Reference< beans::XPropertySet > xPackagePropSet( + rxPackage, uno::UNO_QUERY ); + + OSL_ENSURE( xPackagePropSet.is(), + "Content::loadData - " + "Got no XPropertySet interface from package!" ); + + if ( xPackagePropSet.is() ) + { + // HasEncryptedEntries ( only avalibale at root folder ) + try + { + uno::Any aHasEncryptedEntries + = xPackagePropSet->getPropertyValue( + rtl::OUString::createFromAscii( + "HasEncryptedEntries" ) ); + if ( !( aHasEncryptedEntries >>= rProps.bHasEncryptedEntries ) ) + { + OSL_ENSURE( sal_False, + "Content::loadData - " + "Got no HasEncryptedEntries value!" ); + return sal_False; + } + } + catch ( beans::UnknownPropertyException const & ) + { + OSL_ENSURE( sal_False, + "Content::loadData - " + "Got no HasEncryptedEntries value!" ); + return sal_False; + } + catch ( lang::WrappedTargetException const & ) + { + OSL_ENSURE( sal_False, + "Content::loadData - " + "Got no HasEncryptedEntries value!" ); + return sal_False; + } + } + } + + if ( !rxPackage->hasByHierarchicalName( rURI.getPath() ) ) + return sal_False; + + try + { + uno::Any aEntry = rxPackage->getByHierarchicalName( rURI.getPath() ); + if ( aEntry.hasValue() ) + { + uno::Reference< beans::XPropertySet > xPropSet; + aEntry >>= xPropSet; + + if ( !xPropSet.is() ) + { + OSL_ENSURE( sal_False, + "Content::loadData - Got no XPropertySet interface!" ); + return sal_False; + } + + // Title + rProps.aTitle = rURI.getName(); + + // MediaType + try + { + uno::Any aMediaType + = xPropSet->getPropertyValue( + rtl::OUString::createFromAscii( "MediaType" ) ); + if ( !( aMediaType >>= rProps.aMediaType ) ) + { + OSL_ENSURE( sal_False, + "Content::loadData - Got no MediaType value!" ); + return sal_False; + } + } + catch ( beans::UnknownPropertyException const & ) + { + OSL_ENSURE( sal_False, + "Content::loadData - Got no MediaType value!" ); + return sal_False; + } + catch ( lang::WrappedTargetException const & ) + { + OSL_ENSURE( sal_False, + "Content::loadData - Got no MediaType value!" ); + return sal_False; + } + + uno::Reference< container::XEnumerationAccess > xEnumAccess; + aEntry >>= xEnumAccess; + + // ContentType / IsFolder / IsDocument + if ( xEnumAccess.is() ) + { + // folder + rProps.aContentType = getContentType( rURI.getScheme(), sal_True ); + rProps.bIsDocument = sal_False; + rProps.bIsFolder = sal_True; + } + else + { + // stream + rProps.aContentType = getContentType( rURI.getScheme(), sal_False ); + rProps.bIsDocument = sal_True; + rProps.bIsFolder = sal_False; + } + + if ( rProps.bIsDocument ) + { + // Size ( only available for streams ) + try + { + uno::Any aSize + = xPropSet->getPropertyValue( + rtl::OUString::createFromAscii( "Size" ) ); + if ( !( aSize >>= rProps.nSize ) ) + { + OSL_ENSURE( sal_False, + "Content::loadData - Got no Size value!" ); + return sal_False; + } + } + catch ( beans::UnknownPropertyException const & ) + { + OSL_ENSURE( sal_False, + "Content::loadData - Got no Size value!" ); + return sal_False; + } + catch ( lang::WrappedTargetException const & ) + { + OSL_ENSURE( sal_False, + "Content::loadData - Got no Size value!" ); + return sal_False; + } + + // Compressed ( only available for streams ) + try + { + uno::Any aCompressed + = xPropSet->getPropertyValue( + rtl::OUString::createFromAscii( "Compressed" ) ); + if ( !( aCompressed >>= rProps.bCompressed ) ) + { + OSL_ENSURE( sal_False, + "Content::loadData - Got no Compressed value!" ); + return sal_False; + } + } + catch ( beans::UnknownPropertyException const & ) + { + OSL_ENSURE( sal_False, + "Content::loadData - Got no Compressed value!" ); + return sal_False; + } + catch ( lang::WrappedTargetException const & ) + { + OSL_ENSURE( sal_False, + "Content::loadData - Got no Compressed value!" ); + return sal_False; + } + + // Encrypted ( only available for streams ) + try + { + uno::Any aEncrypted + = xPropSet->getPropertyValue( + rtl::OUString::createFromAscii( "Encrypted" ) ); + if ( !( aEncrypted >>= rProps.bEncrypted ) ) + { + OSL_ENSURE( sal_False, + "Content::loadData - Got no Encrypted value!" ); + return sal_False; + } + } + catch ( beans::UnknownPropertyException const & ) + { + OSL_ENSURE( sal_False, + "Content::loadData - Got no Encrypted value!" ); + return sal_False; + } + catch ( lang::WrappedTargetException const & ) + { + OSL_ENSURE( sal_False, + "Content::loadData - Got no Encrypted value!" ); + return sal_False; + } + } + return sal_True; + } + } + catch ( container::NoSuchElementException const & ) + { + // getByHierarchicalName + } + + return sal_False; +} + +//========================================================================= +sal_Bool Content::renameData( + const uno::Reference< ucb::XContentIdentifier >& xOldId, + const uno::Reference< ucb::XContentIdentifier >& xNewId ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + PackageUri aURI( xOldId->getContentIdentifier() ); + uno::Reference< container::XHierarchicalNameAccess > xNA = getPackage( + aURI ); + if ( !xNA.is() ) + return sal_False; + + if ( !xNA->hasByHierarchicalName( aURI.getPath() ) ) + return sal_False; + + try + { + uno::Any aEntry = xNA->getByHierarchicalName( aURI.getPath() ); + uno::Reference< container::XNamed > xNamed; + aEntry >>= xNamed; + + if ( !xNamed.is() ) + { + OSL_ENSURE( sal_False, + "Content::renameData - Got no XNamed interface!" ); + return sal_False; + } + + PackageUri aNewURI( xNewId->getContentIdentifier() ); + + // No success indicator!? No return value / exceptions specified. + xNamed->setName( aNewURI.getName() ); + + return sal_True; + } + catch ( container::NoSuchElementException const & ) + { + // getByHierarchicalName + } + + return sal_False; +} + +//========================================================================= +sal_Bool Content::storeData( const uno::Reference< io::XInputStream >& xStream ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + uno::Reference< container::XHierarchicalNameAccess > xNA = getPackage(); + if ( !xNA.is() ) + return sal_False; + + uno::Reference< beans::XPropertySet > xPackagePropSet( + xNA, uno::UNO_QUERY ); + OSL_ENSURE( xPackagePropSet.is(), + "Content::storeData - " + "Got no XPropertySet interface from package!" ); + + if ( !xPackagePropSet.is() ) + return sal_False; + + if ( m_nModifiedProps & ENCRYPTIONKEY_MODIFIED ) + { + if ( m_aUri.isRootFolder() ) + { + // Property available only from package and from streams (see below) + try + { + xPackagePropSet->setPropertyValue( + rtl::OUString::createFromAscii( "EncryptionKey" ), + uno::makeAny( m_aProps.aEncryptionKey ) ); + m_nModifiedProps &= ~ENCRYPTIONKEY_MODIFIED; + } + catch ( beans::UnknownPropertyException const & ) + { + // setPropertyValue + } + catch ( beans::PropertyVetoException const & ) + { + // setPropertyValue + } + catch ( lang::IllegalArgumentException const & ) + { + // setPropertyValue + } + catch ( lang::WrappedTargetException const & ) + { + // setPropertyValue + } + } + } + + if ( !xNA->hasByHierarchicalName( m_aUri.getPath() ) ) + { +// if ( !bCreate ) +// return sal_True; + + try + { + // Create new resource... + uno::Reference< lang::XSingleServiceFactory > xFac( + xNA, uno::UNO_QUERY ); + if ( !xFac.is() ) + { + OSL_ENSURE( sal_False, + "Content::storeData - " + "Got no XSingleServiceFactory interface!" ); + return sal_False; + } + + uno::Sequence< uno::Any > aArgs( 1 ); + aArgs[ 0 ] <<= isFolder(); + + uno::Reference< uno::XInterface > xNew + = xFac->createInstanceWithArguments( aArgs ); + + if ( !xNew.is() ) + { + OSL_ENSURE( sal_False, + "Content::storeData - createInstance failed!" ); + return sal_False; + } + + PackageUri aParentUri( getParentURL() ); + uno::Any aEntry + = xNA->getByHierarchicalName( aParentUri.getPath() ); + uno::Reference< container::XNameContainer > xParentContainer; + aEntry >>= xParentContainer; + + if ( !xParentContainer.is() ) + { + OSL_ENSURE( sal_False, + "Content::storeData - " + "Got no XNameContainer interface!" ); + return sal_False; + } + + xParentContainer->insertByName( m_aProps.aTitle, + uno::makeAny( xNew ) ); + } + catch ( uno::RuntimeException const & ) + { + throw; + } + catch ( lang::IllegalArgumentException const & ) + { + // insertByName + OSL_ENSURE( sal_False, + "Content::storeData - insertByName failed!" ); + return sal_False; + } + catch ( container::ElementExistException const & ) + { + // insertByName + OSL_ENSURE( sal_False, + "Content::storeData - insertByName failed!" ); + return sal_False; + } + catch ( lang::WrappedTargetException const & ) + { + // insertByName + OSL_ENSURE( sal_False, + "Content::storeData - insertByName failed!" ); + return sal_False; + } + catch ( container::NoSuchElementException const & ) + { + // getByHierarchicalName + OSL_ENSURE( sal_False, + "Content::storeData - getByHierarchicalName failed!" ); + return sal_False; + } + catch ( uno::Exception const & ) + { + // createInstanceWithArguments + OSL_ENSURE( sal_False, "Content::storeData - Error!" ); + return sal_False; + } + } + + if ( !xNA->hasByHierarchicalName( m_aUri.getPath() ) ) + return sal_False; + + try + { + uno::Reference< beans::XPropertySet > xPropSet; + xNA->getByHierarchicalName( m_aUri.getPath() ) >>= xPropSet; + + if ( !xPropSet.is() ) + { + OSL_ENSURE( sal_False, + "Content::storeData - Got no XPropertySet interface!" ); + return sal_False; + } + + ////////////////////////////////////////////////////////////////// + // Store property values... + ////////////////////////////////////////////////////////////////// + + if ( m_nModifiedProps & MEDIATYPE_MODIFIED ) + { + xPropSet->setPropertyValue( + rtl::OUString::createFromAscii( "MediaType" ), + uno::makeAny( m_aProps.aMediaType ) ); + m_nModifiedProps &= ~MEDIATYPE_MODIFIED; + } + + if ( m_nModifiedProps & COMPRESSED_MODIFIED ) + { + if ( !isFolder() ) + xPropSet->setPropertyValue( + rtl::OUString::createFromAscii( "Compressed" ), + uno::makeAny( m_aProps.bCompressed ) ); + + m_nModifiedProps &= ~COMPRESSED_MODIFIED; + } + + if ( m_nModifiedProps & ENCRYPTED_MODIFIED ) + { + if ( !isFolder() ) + xPropSet->setPropertyValue( + rtl::OUString::createFromAscii( "Encrypted" ), + uno::makeAny( m_aProps.bEncrypted ) ); + + m_nModifiedProps &= ~ENCRYPTED_MODIFIED; + } + + if ( m_nModifiedProps & ENCRYPTIONKEY_MODIFIED ) + { + if ( !isFolder() ) + xPropSet->setPropertyValue( + rtl::OUString::createFromAscii( "EncryptionKey" ), + uno::makeAny( m_aProps.aEncryptionKey ) ); + + m_nModifiedProps &= ~ENCRYPTIONKEY_MODIFIED; + } + + ////////////////////////////////////////////////////////////////// + // Store data stream... + ////////////////////////////////////////////////////////////////// + + if ( xStream.is() && !isFolder() ) + { + uno::Reference< io::XActiveDataSink > xSink( + xPropSet, uno::UNO_QUERY ); + + if ( !xSink.is() ) + { + OSL_ENSURE( sal_False, + "Content::storeData - " + "Got no XActiveDataSink interface!" ); + return sal_False; + } + + xSink->setInputStream( xStream ); + } + + return sal_True; + } + catch ( container::NoSuchElementException const & ) + { + // getByHierarchicalName + } + catch ( beans::UnknownPropertyException const & ) + { + // setPropertyValue + } + catch ( beans::PropertyVetoException const & ) + { + // setPropertyValue + } + catch ( lang::IllegalArgumentException const & ) + { + // setPropertyValue + } + catch ( lang::WrappedTargetException const & ) + { + // setPropertyValue + } + + OSL_ENSURE( sal_False, "Content::storeData - Error!" ); + return sal_False; +} + +//========================================================================= +sal_Bool Content::removeData() +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + uno::Reference< container::XHierarchicalNameAccess > xNA = getPackage(); + if ( !xNA.is() ) + return sal_False; + + PackageUri aParentUri( getParentURL() ); + if ( !xNA->hasByHierarchicalName( aParentUri.getPath() ) ) + return sal_False; + + try + { + uno::Any aEntry = xNA->getByHierarchicalName( aParentUri.getPath() ); + uno::Reference< container::XNameContainer > xContainer; + aEntry >>= xContainer; + + if ( !xContainer.is() ) + { + OSL_ENSURE( sal_False, + "Content::removeData - " + "Got no XNameContainer interface!" ); + return sal_False; + } + + xContainer->removeByName( m_aUri.getName() ); + return sal_True; + } + catch ( container::NoSuchElementException const & ) + { + // getByHierarchicalName, removeByName + } + catch ( lang::WrappedTargetException const & ) + { + // removeByName + } + + OSL_ENSURE( sal_False, "Content::removeData - Error!" ); + return sal_False; +} + +//========================================================================= +sal_Bool Content::flushData() +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + // Note: XChangesBatch is only implemented by the package itself, not + // by the single entries. Maybe this has to change... + + uno::Reference< container::XHierarchicalNameAccess > xNA = getPackage(); + if ( !xNA.is() ) + return sal_False; + + uno::Reference< util::XChangesBatch > xBatch( xNA, uno::UNO_QUERY ); + if ( !xBatch.is() ) + { + OSL_ENSURE( sal_False, + "Content::flushData - Got no XChangesBatch interface!" ); + return sal_False; + } + + try + { + xBatch->commitChanges(); + return sal_True; + } + catch ( lang::WrappedTargetException const & ) + { + } + + OSL_ENSURE( sal_False, "Content::flushData - Error!" ); + return sal_False; +} + +//========================================================================= +uno::Reference< io::XInputStream > Content::getInputStream() +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + uno::Reference< io::XInputStream > xStream; + uno::Reference< container::XHierarchicalNameAccess > xNA = getPackage(); + if ( !xNA.is() ) + return xStream; + + if ( !xNA->hasByHierarchicalName( m_aUri.getPath() ) ) + return xStream; + + try + { + uno::Any aEntry = xNA->getByHierarchicalName( m_aUri.getPath() ); + uno::Reference< io::XActiveDataSink > xSink; + aEntry >>= xSink; + + if ( !xSink.is() ) + { + OSL_ENSURE( sal_False, + "Content::getInputStream - " + "Got no XActiveDataSink interface!" ); + return xStream; + } + + xStream = xSink->getInputStream(); + + OSL_ENSURE( xStream.is(), + "Content::getInputStream - Got no stream!" ); + } + catch ( container::NoSuchElementException const & ) + { + // getByHierarchicalName + } + + return xStream; +} + +//========================================================================= +uno::Reference< container::XEnumeration > Content::getIterator() +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + uno::Reference< container::XEnumeration > xIter; + uno::Reference< container::XHierarchicalNameAccess > xNA = getPackage(); + if ( !xNA.is() ) + return xIter; + + if ( !xNA->hasByHierarchicalName( m_aUri.getPath() ) ) + return xIter; + + try + { + uno::Any aEntry = xNA->getByHierarchicalName( m_aUri.getPath() ); + uno::Reference< container::XEnumerationAccess > xIterFac; + aEntry >>= xIterFac; + + if ( !xIterFac.is() ) + { + OSL_ENSURE( sal_False, + "Content::getIterator - " + "Got no XEnumerationAccess interface!" ); + return xIter; + } + + xIter = xIterFac->createEnumeration(); + + OSL_ENSURE( xIter.is(), + "Content::getIterator - Got no iterator!" ); + } + catch ( container::NoSuchElementException const & ) + { + // getByHierarchicalName + } + + return xIter; +} diff --git a/ucb/source/ucp/package/pkgcontent.hxx b/ucb/source/ucp/package/pkgcontent.hxx new file mode 100644 index 000000000000..5dbc8a69c1de --- /dev/null +++ b/ucb/source/ucp/package/pkgcontent.hxx @@ -0,0 +1,335 @@ +/************************************************************************* + * + * 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 _PKGCONTENT_HXX +#define _PKGCONTENT_HXX + +#include <list> +#include <rtl/ref.hxx> + +#include <com/sun/star/ucb/InteractiveBadTransferURLException.hpp> +#include <com/sun/star/ucb/XContentCreator.hpp> +#include <ucbhelper/contenthelper.hxx> +#include "pkguri.hxx" + +namespace com { namespace sun { namespace star { + namespace beans + { + struct Property; + struct PropertyValue; + } + namespace container + { + class XHierarchicalNameAccess; + class XEnumeration; + } + namespace io + { + class XInputStream; + } + namespace sdbc + { + class XRow; + } + namespace ucb + { + struct OpenCommandArgument2; + struct TransferInfo; + } +} } } + +namespace package_ucp +{ + +//========================================================================= + +// UNO service name for the content. +#define PACKAGE_FOLDER_CONTENT_SERVICE_NAME \ + "com.sun.star.ucb.PackageFolderContent" +#define PACKAGE_STREAM_CONTENT_SERVICE_NAME \ + "com.sun.star.ucb.PackageStreamContent" + +//========================================================================= + +struct ContentProperties +{ + ::rtl::OUString aTitle; // Title + ::rtl::OUString aContentType; // ContentType + sal_Bool bIsDocument; // IsDocument + sal_Bool bIsFolder; // IsFolder + ::rtl::OUString aMediaType; // MediaType + com::sun::star::uno::Sequence < + sal_Int8 > aEncryptionKey; // EncryptionKey + sal_Int64 nSize; // Size + sal_Bool bCompressed; // Compressed + sal_Bool bEncrypted; // Encrypted + sal_Bool bHasEncryptedEntries; // HasEncryptedEntries + + ContentProperties() + : bIsDocument( sal_True ), bIsFolder( sal_False ), nSize( 0 ), + bCompressed( sal_True ), bEncrypted( sal_False ), + bHasEncryptedEntries( sal_False ) {} + + ContentProperties( const ::rtl::OUString& rContentType ); + + com::sun::star::uno::Sequence< com::sun::star::ucb::ContentInfo > + getCreatableContentsInfo( PackageUri const & rUri ) const; +}; + +//========================================================================= + +class ContentProvider; + +class Content : public ::ucbhelper::ContentImplHelper, + public com::sun::star::ucb::XContentCreator +{ + enum ContentState { TRANSIENT, // created via CreateNewContent, + // but did not process "insert" yet + PERSISTENT, // processed "insert" + DEAD // processed "delete" + }; + + PackageUri m_aUri; + ContentProperties m_aProps; + ContentState m_eState; + com::sun::star::uno::Reference< + com::sun::star::container::XHierarchicalNameAccess > m_xPackage; + ContentProvider* m_pProvider; + sal_uInt32 m_nModifiedProps; + +private: + Content( const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + ContentProvider* pProvider, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& Identifier, + const ::com::sun::star::uno::Reference< + com::sun::star::container::XHierarchicalNameAccess >& Package, + const PackageUri& rUri, + const ContentProperties& rProps ); + Content( const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + ContentProvider* pProvider, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& Identifier, + const com::sun::star::uno::Reference< + com::sun::star::container::XHierarchicalNameAccess >& Package, + const PackageUri& rUri, + const com::sun::star::ucb::ContentInfo& Info ); + + virtual com::sun::star::uno::Sequence< com::sun::star::beans::Property > + getProperties( const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv ); + virtual com::sun::star::uno::Sequence< com::sun::star::ucb::CommandInfo > + getCommands( const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv ); + virtual ::rtl::OUString getParentURL(); + + static ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRow > + getPropertyValues( const ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XMultiServiceFactory >& rSMgr, + const ::com::sun::star::uno::Sequence< + ::com::sun::star::beans::Property >& rProperties, + const ContentProperties& rData, + const rtl::Reference< + ::ucbhelper::ContentProviderImplHelper >& rProvider, + const ::rtl::OUString& rContentId ); + + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRow > + getPropertyValues( const ::com::sun::star::uno::Sequence< + ::com::sun::star::beans::Property >& rProperties ); + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > + setPropertyValues( const ::com::sun::star::uno::Sequence< + ::com::sun::star::beans::PropertyValue >& rValues, + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw( ::com::sun::star::uno::Exception ); + + com::sun::star::uno::Reference< + com::sun::star::container::XHierarchicalNameAccess > + getPackage( const PackageUri& rURI ); + com::sun::star::uno::Reference< + com::sun::star::container::XHierarchicalNameAccess > + getPackage(); + + static sal_Bool + loadData( ContentProvider* pProvider, + const PackageUri& rURI, + ContentProperties& rProps, + com::sun::star::uno::Reference< + com::sun::star::container::XHierarchicalNameAccess > & + rxPackage ); + static sal_Bool + hasData( ContentProvider* pProvider, + const PackageUri& rURI, + com::sun::star::uno::Reference< + com::sun::star::container::XHierarchicalNameAccess > & + rxPackage ); + + sal_Bool + hasData( const PackageUri& rURI ); + sal_Bool + renameData( const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& xOldId, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& xNewId ); + sal_Bool + storeData( const com::sun::star::uno::Reference< + com::sun::star::io::XInputStream >& xStream ); + sal_Bool + removeData(); + + sal_Bool + flushData(); + + typedef rtl::Reference< Content > ContentRef; + typedef std::list< ContentRef > ContentRefList; + void queryChildren( ContentRefList& rChildren ); + + sal_Bool + exchangeIdentity( const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XContentIdentifier >& xNewId ); + + ::com::sun::star::uno::Any + open( const ::com::sun::star::ucb::OpenCommandArgument2& rArg, + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw( ::com::sun::star::uno::Exception ); + + void insert( const ::com::sun::star::uno::Reference< + ::com::sun::star::io::XInputStream >& xStream, + sal_Int32 nNameClashResolve, + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw( ::com::sun::star::uno::Exception ); + + void destroy( sal_Bool bDeletePhysical, + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw( ::com::sun::star::uno::Exception ); + + void transfer( const ::com::sun::star::ucb::TransferInfo& rInfo, + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw( ::com::sun::star::uno::Exception ); + + ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > + getInputStream(); + + sal_Bool isFolder() const { return m_aProps.bIsFolder; } + +public: + // Create existing content. Fail, if not already exists. + static Content* create( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + ContentProvider* pProvider, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& Identifier ); + + // Create new content. Fail, if already exists. + static Content* create( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + ContentProvider* pProvider, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& Identifier, + const com::sun::star::ucb::ContentInfo& Info ); + + virtual ~Content(); + + // XInterface + XINTERFACE_DECL() + + // XTypeProvider + XTYPEPROVIDER_DECL() + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL + getImplementationName() + throw( ::com::sun::star::uno::RuntimeException ); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL + getSupportedServiceNames() + throw( ::com::sun::star::uno::RuntimeException ); + + // XContent + virtual rtl::OUString SAL_CALL + getContentType() + throw( com::sun::star::uno::RuntimeException ); + + // XCommandProcessor + virtual com::sun::star::uno::Any SAL_CALL + execute( const com::sun::star::ucb::Command& aCommand, + sal_Int32 CommandId, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment >& Environment ) + throw( com::sun::star::uno::Exception, + com::sun::star::ucb::CommandAbortedException, + com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + abort( sal_Int32 CommandId ) + throw( com::sun::star::uno::RuntimeException ); + + ////////////////////////////////////////////////////////////////////// + // Additional interfaces + ////////////////////////////////////////////////////////////////////// + + // XContentCreator + virtual com::sun::star::uno::Sequence< + com::sun::star::ucb::ContentInfo > SAL_CALL + queryCreatableContentsInfo() + throw( com::sun::star::uno::RuntimeException ); + virtual com::sun::star::uno::Reference< + com::sun::star::ucb::XContent > SAL_CALL + createNewContent( const com::sun::star::ucb::ContentInfo& Info ) + throw( com::sun::star::uno::RuntimeException ); + + ////////////////////////////////////////////////////////////////////// + // Non-interface methods. + ////////////////////////////////////////////////////////////////////// + + // Called from resultset data supplier. + static ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRow > + getPropertyValues( const ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XMultiServiceFactory >& rSMgr, + const ::com::sun::star::uno::Sequence< + ::com::sun::star::beans::Property >& rProperties, + ContentProvider* pProvider, + const ::rtl::OUString& rContentId ); + + // Called from resultset data supplier. + ::com::sun::star::uno::Reference< + ::com::sun::star::container::XEnumeration > + getIterator(); + + static ::rtl::OUString + getContentType( const ::rtl::OUString& aScheme, sal_Bool bFolder ); +}; + +} + +#endif diff --git a/ucb/source/ucp/package/pkgcontentcaps.cxx b/ucb/source/ucp/package/pkgcontentcaps.cxx new file mode 100644 index 000000000000..88807d900275 --- /dev/null +++ b/ucb/source/ucp/package/pkgcontentcaps.cxx @@ -0,0 +1,562 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + Props/Commands: + + rootfolder folder stream + --------------------------------------------- + ContentType r r r + IsDocument r r r + IsFolder r r r + MediaType (w) (w) w + Title r w w + Size - - r + CreatableContentsInfo r r r + Compressed - - w + Encrypted - - w + HasEncryptedEntries r - - + + getCommandInfo x x x + getPropertySetInfo x x x + getPropertyValues x x x + setPropertyValues x x x + insert - x x + delete - x x + open x x x + transfer x x - + flush x x - + createNewContent x x - + + *************************************************************************/ +#include <com/sun/star/beans/Property.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/ucb/CommandInfo.hpp> +#include <com/sun/star/ucb/OpenCommandArgument2.hpp> +#include <com/sun/star/ucb/TransferInfo.hpp> +#include <com/sun/star/uno/Sequence.hxx> +#include "pkgcontent.hxx" + +using namespace com::sun::star; +using namespace package_ucp; + +//========================================================================= +// +// Content implementation. +// +//========================================================================= + +#define MAKEPROPSEQUENCE( a ) \ + uno::Sequence< beans::Property >( a, sizeof( a ) / sizeof( a[ 0 ] ) ) + +#define MAKECMDSEQUENCE( a ) \ + uno::Sequence< ucb::CommandInfo >( a, sizeof( a ) / sizeof( a[ 0 ] ) ) + +//========================================================================= +// +// IMPORTENT: If any property data ( name / type / ... ) are changed, then +// Content::getPropertyValues(...) must be adapted too! +// +//========================================================================= + +// virtual +uno::Sequence< beans::Property > Content::getProperties( + const uno::Reference< ucb::XCommandEnvironment > & /*xEnv*/ ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + if ( isFolder() ) + { + if ( m_aUri.isRootFolder() ) + { + //================================================================= + // + // Root Folder: Supported properties + // + //================================================================= + + static const beans::Property aRootFolderPropertyInfoTable[] = + { + /////////////////////////////////////////////////////////////// + // Required properties + /////////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "ContentType" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "IsDocument" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + /////////////////////////////////////////////////////////////// + // Optional standard properties + /////////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "CreatableContentsInfo" ) ), + -1, + getCppuType( static_cast< + const uno::Sequence< ucb::ContentInfo > * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + /////////////////////////////////////////////////////////////// + // New properties + /////////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "HasEncryptedEntries" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ) + }; + return MAKEPROPSEQUENCE( aRootFolderPropertyInfoTable ); + } + else + { + //================================================================= + // + // Folder: Supported properties + // + //================================================================= + + static const beans::Property aFolderPropertyInfoTable[] = + { + /////////////////////////////////////////////////////////////// + // Required properties + /////////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "ContentType" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "IsDocument" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + ), + /////////////////////////////////////////////////////////////// + // Optional standard properties + /////////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "CreatableContentsInfo" ) ), + -1, + getCppuType( static_cast< + const uno::Sequence< ucb::ContentInfo > * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ) + /////////////////////////////////////////////////////////////// + // New properties + /////////////////////////////////////////////////////////////// + }; + return MAKEPROPSEQUENCE( aFolderPropertyInfoTable ); + } + } + else + { + //================================================================= + // + // Stream: Supported properties + // + //================================================================= + + static const beans::Property aStreamPropertyInfoTable[] = + { + /////////////////////////////////////////////////////////////// + // Required properties + /////////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ContentType" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsDocument" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + ), + /////////////////////////////////////////////////////////////// + // Optional standard properties + /////////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Size" ) ), + -1, + getCppuType( static_cast< const sal_Int64 * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "CreatableContentsInfo" ) ), + -1, + getCppuType( static_cast< + const uno::Sequence< ucb::ContentInfo > * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + /////////////////////////////////////////////////////////////// + // New properties + /////////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Compressed" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Encrypted" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + ) + }; + return MAKEPROPSEQUENCE( aStreamPropertyInfoTable ); + } +} + +//========================================================================= +// virtual +uno::Sequence< ucb::CommandInfo > Content::getCommands( + const uno::Reference< ucb::XCommandEnvironment > & /*xEnv*/ ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + if ( isFolder() ) + { + if ( m_aUri.isRootFolder() ) + { + //================================================================= + // + // Root Folder: Supported commands + // + //================================================================= + + static const ucb::CommandInfo aRootFolderCommandInfoTable[] = + { + /////////////////////////////////////////////////////////// + // Required commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getCommandInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertySetInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertyValues" ) ), + -1, + getCppuType( + static_cast< + uno::Sequence< beans::Property > * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ), + -1, + getCppuType( + static_cast< + uno::Sequence< beans::PropertyValue > * >( 0 ) ) + ), + /////////////////////////////////////////////////////////// + // Optional standard commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "open" ) ), + -1, + getCppuType( + static_cast< ucb::OpenCommandArgument2 * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "transfer" ) ), + -1, + getCppuType( + static_cast< ucb::TransferInfo * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "createNewContent" ) ), + -1, + getCppuType( static_cast< ucb::ContentInfo * >( 0 ) ) + ), + /////////////////////////////////////////////////////////// + // New commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "flush" ) ), + -1, + getCppuVoidType() + ) + }; + + return MAKECMDSEQUENCE( aRootFolderCommandInfoTable ); + } + else + { + //================================================================= + // + // Folder: Supported commands + // + //================================================================= + + static const ucb::CommandInfo aFolderCommandInfoTable[] = + { + /////////////////////////////////////////////////////////// + // Required commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getCommandInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertySetInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertyValues" ) ), + -1, + getCppuType( + static_cast< + uno::Sequence< beans::Property > * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ), + -1, + getCppuType( + static_cast< + uno::Sequence< beans::PropertyValue > * >( 0 ) ) + ), + /////////////////////////////////////////////////////////// + // Optional standard commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "delete" ) ), + -1, + getCppuBooleanType() + ), + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "insert" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "open" ) ), + -1, + getCppuType( + static_cast< ucb::OpenCommandArgument2 * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "transfer" ) ), + -1, + getCppuType( + static_cast< ucb::TransferInfo * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "createNewContent" ) ), + -1, + getCppuType( static_cast< ucb::ContentInfo * >( 0 ) ) + ), + /////////////////////////////////////////////////////////// + // New commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "flush" ) ), + -1, + getCppuVoidType() + ) + }; + + return MAKECMDSEQUENCE( aFolderCommandInfoTable ); + } + } + else + { + //================================================================= + // + // Stream: Supported commands + // + //================================================================= + + static const ucb::CommandInfo aStreamCommandInfoTable[] = + { + /////////////////////////////////////////////////////////////// + // Required commands + /////////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getCommandInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertySetInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertyValues" ) ), + -1, + getCppuType( + static_cast< uno::Sequence< beans::Property > * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ), + -1, + getCppuType( + static_cast< + uno::Sequence< beans::PropertyValue > * >( 0 ) ) + ), + /////////////////////////////////////////////////////////////// + // Optional standard commands + /////////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "delete" ) ), + -1, + getCppuBooleanType() + ), + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "insert" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "open" ) ), + -1, + getCppuType( + static_cast< ucb::OpenCommandArgument2 * >( 0 ) ) + ) + /////////////////////////////////////////////////////////////// + // New commands + /////////////////////////////////////////////////////////////// + }; + + return MAKECMDSEQUENCE( aStreamCommandInfoTable ); + } +} diff --git a/ucb/source/ucp/package/pkgdatasupplier.cxx b/ucb/source/ucp/package/pkgdatasupplier.cxx new file mode 100644 index 000000000000..133e16dc7ed8 --- /dev/null +++ b/ucb/source/ucp/package/pkgdatasupplier.cxx @@ -0,0 +1,498 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ + +#include <vector> +#include <osl/diagnose.h> +#include <com/sun/star/container/XEnumeration.hpp> +#include <com/sun/star/container/XNamed.hpp> +#include <ucbhelper/contentidentifier.hxx> +#include <ucbhelper/providerhelper.hxx> +#include "pkgdatasupplier.hxx" +#include "pkgcontent.hxx" +#include "pkgprovider.hxx" + +#include "../inc/urihelper.hxx" + +using namespace com::sun::star; +using namespace package_ucp; + +namespace package_ucp +{ + +//========================================================================= +// +// struct ResultListEntry. +// +//========================================================================= + +struct ResultListEntry +{ + rtl::OUString aURL; + uno::Reference< ucb::XContentIdentifier > xId; + uno::Reference< ucb::XContent > xContent; + uno::Reference< sdbc::XRow > xRow; + + ResultListEntry( const rtl::OUString& rURL ) : aURL( rURL ) {} +}; + +//========================================================================= +// +// ResultList. +// +//========================================================================= + +typedef std::vector< ResultListEntry* > ResultList; + +//========================================================================= +// +// struct DataSupplier_Impl. +// +//========================================================================= + +struct DataSupplier_Impl +{ + osl::Mutex m_aMutex; + ResultList m_aResults; + rtl::Reference< Content > m_xContent; + uno::Reference< lang::XMultiServiceFactory > m_xSMgr; + uno::Reference< container::XEnumeration > m_xFolderEnum; + sal_Int32 m_nOpenMode; + sal_Bool m_bCountFinal; + sal_Bool m_bThrowException; + + DataSupplier_Impl( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + const rtl::Reference< Content >& rContent, + sal_Int32 nOpenMode ) + : m_xContent( rContent ), m_xSMgr( rxSMgr ), + m_xFolderEnum( rContent->getIterator() ), m_nOpenMode( nOpenMode ), + m_bCountFinal( !m_xFolderEnum.is() ), m_bThrowException( m_bCountFinal ) + {} + ~DataSupplier_Impl(); +}; + +//========================================================================= +DataSupplier_Impl::~DataSupplier_Impl() +{ + ResultList::const_iterator it = m_aResults.begin(); + ResultList::const_iterator end = m_aResults.end(); + + while ( it != end ) + { + delete (*it); + it++; + } +} + +} + +//========================================================================= +//========================================================================= +// +// DataSupplier Implementation. +// +//========================================================================= +//========================================================================= + +DataSupplier::DataSupplier( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + const rtl::Reference< Content >& rContent, + sal_Int32 nOpenMode ) +: m_pImpl( new DataSupplier_Impl( rxSMgr, rContent, nOpenMode ) ) +{ +} + +//========================================================================= +// virtual +DataSupplier::~DataSupplier() +{ + delete m_pImpl; +} + +//========================================================================= +// virtual +rtl::OUString DataSupplier::queryContentIdentifierString( sal_uInt32 nIndex ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( nIndex < m_pImpl->m_aResults.size() ) + { + rtl::OUString aId = m_pImpl->m_aResults[ nIndex ]->aURL; + if ( aId.getLength() ) + { + // Already cached. + return aId; + } + } + + if ( getResult( nIndex ) ) + { + // Note: getResult fills m_pImpl->m_aResults[ nIndex ]->aURL. + return m_pImpl->m_aResults[ nIndex ]->aURL; + } + return rtl::OUString(); +} + +//========================================================================= +// virtual +uno::Reference< ucb::XContentIdentifier > +DataSupplier::queryContentIdentifier( sal_uInt32 nIndex ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( nIndex < m_pImpl->m_aResults.size() ) + { + uno::Reference< ucb::XContentIdentifier > xId + = m_pImpl->m_aResults[ nIndex ]->xId; + if ( xId.is() ) + { + // Already cached. + return xId; + } + } + + rtl::OUString aId = queryContentIdentifierString( nIndex ); + if ( aId.getLength() ) + { + uno::Reference< ucb::XContentIdentifier > xId + = new ::ucbhelper::ContentIdentifier( aId ); + m_pImpl->m_aResults[ nIndex ]->xId = xId; + return xId; + } + return uno::Reference< ucb::XContentIdentifier >(); +} + +//========================================================================= +// virtual +uno::Reference< ucb::XContent > DataSupplier::queryContent( + sal_uInt32 nIndex ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( nIndex < m_pImpl->m_aResults.size() ) + { + uno::Reference< ucb::XContent > xContent + = m_pImpl->m_aResults[ nIndex ]->xContent; + if ( xContent.is() ) + { + // Already cached. + return xContent; + } + } + + uno::Reference< ucb::XContentIdentifier > xId + = queryContentIdentifier( nIndex ); + if ( xId.is() ) + { + try + { + uno::Reference< ucb::XContent > xContent + = m_pImpl->m_xContent->getProvider()->queryContent( xId ); + m_pImpl->m_aResults[ nIndex ]->xContent = xContent; + return xContent; + + } + catch ( ucb::IllegalIdentifierException const & ) + { + } + } + return uno::Reference< ucb::XContent >(); +} + +//========================================================================= +// virtual +sal_Bool DataSupplier::getResult( sal_uInt32 nIndex ) +{ + osl::ClearableGuard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( m_pImpl->m_aResults.size() > nIndex ) + { + // Result already present. + return sal_True; + } + + // Result not (yet) present. + + if ( m_pImpl->m_bCountFinal ) + return sal_False; + + // Try to obtain result... + + sal_uInt32 nOldCount = m_pImpl->m_aResults.size(); + sal_Bool bFound = sal_False; + sal_uInt32 nPos = nOldCount; + + while ( m_pImpl->m_xFolderEnum->hasMoreElements() ) + { + try + { + uno::Reference< container::XNamed > xNamed; + m_pImpl->m_xFolderEnum->nextElement() >>= xNamed; + + if ( !xNamed.is() ) + { + OSL_ENSURE( sal_False, + "DataSupplier::getResult - Got no XNamed!" ); + break; + } + + rtl::OUString aName = xNamed->getName(); + + if ( !aName.getLength() ) + { + OSL_ENSURE( sal_False, + "DataSupplier::getResult - Empty name!" ); + break; + } + + // Assemble URL for child. + rtl::OUString aURL = assembleChildURL( aName ); + + m_pImpl->m_aResults.push_back( new ResultListEntry( aURL ) ); + + if ( nPos == nIndex ) + { + // Result obtained. + bFound = sal_True; + break; + } + + nPos++; + } + catch ( container::NoSuchElementException const & ) + { + m_pImpl->m_bThrowException = sal_True; + break; + } + catch ( lang::WrappedTargetException const & ) + { + m_pImpl->m_bThrowException = sal_True; + break; + } + } + + if ( !bFound ) + m_pImpl->m_bCountFinal = sal_True; + + rtl::Reference< ::ucbhelper::ResultSet > xResultSet = getResultSet().get(); + if ( xResultSet.is() ) + { + // Callbacks follow! + aGuard.clear(); + + if ( nOldCount < m_pImpl->m_aResults.size() ) + xResultSet->rowCountChanged( + nOldCount, m_pImpl->m_aResults.size() ); + + if ( m_pImpl->m_bCountFinal ) + xResultSet->rowCountFinal(); + } + + return bFound; +} + +//========================================================================= +// virtual +sal_uInt32 DataSupplier::totalCount() +{ + osl::ClearableGuard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( m_pImpl->m_bCountFinal ) + return m_pImpl->m_aResults.size(); + + sal_uInt32 nOldCount = m_pImpl->m_aResults.size(); + + while ( m_pImpl->m_xFolderEnum->hasMoreElements() ) + { + try + { + uno::Reference< container::XNamed > xNamed; + m_pImpl->m_xFolderEnum->nextElement() >>= xNamed; + + if ( !xNamed.is() ) + { + OSL_ENSURE( sal_False, + "DataSupplier::getResult - Got no XNamed!" ); + break; + } + + rtl::OUString aName = xNamed->getName(); + + if ( !aName.getLength() ) + { + OSL_ENSURE( sal_False, + "DataSupplier::getResult - Empty name!" ); + break; + } + + // Assemble URL for child. + rtl::OUString aURL = assembleChildURL( aName ); + + m_pImpl->m_aResults.push_back( new ResultListEntry( aURL ) ); + } + catch ( container::NoSuchElementException const & ) + { + m_pImpl->m_bThrowException = sal_True; + break; + } + catch ( lang::WrappedTargetException const & ) + { + m_pImpl->m_bThrowException = sal_True; + break; + } + } + + m_pImpl->m_bCountFinal = sal_True; + + rtl::Reference< ::ucbhelper::ResultSet > xResultSet = getResultSet().get(); + if ( xResultSet.is() ) + { + // Callbacks follow! + aGuard.clear(); + + if ( nOldCount < m_pImpl->m_aResults.size() ) + xResultSet->rowCountChanged( + nOldCount, m_pImpl->m_aResults.size() ); + + xResultSet->rowCountFinal(); + } + + return m_pImpl->m_aResults.size(); +} + +//========================================================================= +// virtual +sal_uInt32 DataSupplier::currentCount() +{ + return m_pImpl->m_aResults.size(); +} + +//========================================================================= +// virtual +sal_Bool DataSupplier::isCountFinal() +{ + return m_pImpl->m_bCountFinal; +} + +//========================================================================= +// virtual +uno::Reference< sdbc::XRow > DataSupplier::queryPropertyValues( + sal_uInt32 nIndex ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( nIndex < m_pImpl->m_aResults.size() ) + { + uno::Reference< sdbc::XRow > xRow = m_pImpl->m_aResults[ nIndex ]->xRow; + if ( xRow.is() ) + { + // Already cached. + return xRow; + } + } + + if ( getResult( nIndex ) ) + { + uno::Reference< sdbc::XRow > xRow = Content::getPropertyValues( + m_pImpl->m_xSMgr, + getResultSet()->getProperties(), + static_cast< ContentProvider * >( + m_pImpl->m_xContent->getProvider().get() ), + queryContentIdentifierString( nIndex ) ); + m_pImpl->m_aResults[ nIndex ]->xRow = xRow; + return xRow; + } + + return uno::Reference< sdbc::XRow >(); +} + +//========================================================================= +// virtual +void DataSupplier::releasePropertyValues( sal_uInt32 nIndex ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( nIndex < m_pImpl->m_aResults.size() ) + m_pImpl->m_aResults[ nIndex ]->xRow = uno::Reference< sdbc::XRow >(); +} + +//========================================================================= +// virtual +void DataSupplier::close() +{ +} + +//========================================================================= +// virtual +void DataSupplier::validate() + throw( ucb::ResultSetException ) +{ + if ( m_pImpl->m_bThrowException ) + throw ucb::ResultSetException(); +} + +//========================================================================= +::rtl::OUString DataSupplier::assembleChildURL( const ::rtl::OUString& aName ) +{ + rtl::OUString aURL; + rtl::OUString aContURL + = m_pImpl->m_xContent->getIdentifier()->getContentIdentifier(); + sal_Int32 nParam = aContURL.indexOf( '?' ); + if ( nParam >= 0 ) + { + aURL = aContURL.copy( 0, nParam ); + + sal_Int32 nPackageUrlEnd = aURL.lastIndexOf( '/' ); + if ( nPackageUrlEnd != aURL.getLength() - 1 ) + aURL += rtl::OUString::createFromAscii( "/" ); + + aURL += ::ucb_impl::urihelper::encodeSegment( aName ); + aURL += aContURL.copy( nParam ); + } + else + { + aURL = aContURL; + + sal_Int32 nPackageUrlEnd = aURL.lastIndexOf( '/' ); + if ( nPackageUrlEnd != aURL.getLength() - 1 ) + aURL += rtl::OUString::createFromAscii( "/" ); + + aURL += ::ucb_impl::urihelper::encodeSegment( aName ); + } + return aURL; +} + + diff --git a/ucb/source/ucp/package/pkgdatasupplier.hxx b/ucb/source/ucp/package/pkgdatasupplier.hxx new file mode 100644 index 000000000000..2342becad8eb --- /dev/null +++ b/ucb/source/ucp/package/pkgdatasupplier.hxx @@ -0,0 +1,77 @@ +/************************************************************************* + * + * 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 _PKGDATASUPPLIER_HXX +#define _PKGDATASUPPLIER_HXX + +#include <rtl/ref.hxx> +#include <ucbhelper/resultset.hxx> + +namespace package_ucp { + +struct DataSupplier_Impl; +class Content; + +class DataSupplier : public ::ucbhelper::ResultSetDataSupplier +{ + DataSupplier_Impl* m_pImpl; + +public: + DataSupplier( const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + const rtl::Reference< Content >& rContent, + sal_Int32 nOpenMode ); + virtual ~DataSupplier(); + + virtual rtl::OUString queryContentIdentifierString( sal_uInt32 nIndex ); + virtual com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier > + queryContentIdentifier( sal_uInt32 nIndex ); + virtual com::sun::star::uno::Reference< com::sun::star::ucb::XContent > + queryContent( sal_uInt32 nIndex ); + + virtual sal_Bool getResult( sal_uInt32 nIndex ); + + virtual sal_uInt32 totalCount(); + virtual sal_uInt32 currentCount(); + virtual sal_Bool isCountFinal(); + + virtual com::sun::star::uno::Reference< com::sun::star::sdbc::XRow > + queryPropertyValues( sal_uInt32 nIndex ); + virtual void releasePropertyValues( sal_uInt32 nIndex ); + + virtual void close(); + + virtual void validate() + throw( com::sun::star::ucb::ResultSetException ); + + ::rtl::OUString assembleChildURL( const ::rtl::OUString& aName ); +}; + +} + +#endif diff --git a/ucb/source/ucp/package/pkgprovider.cxx b/ucb/source/ucp/package/pkgprovider.cxx new file mode 100644 index 000000000000..92c35fe78bb9 --- /dev/null +++ b/ucb/source/ucp/package/pkgprovider.cxx @@ -0,0 +1,330 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ + +#include <hash_map> +#include <osl/diagnose.h> +#include <cppuhelper/weak.hxx> +#include <ucbhelper/contentidentifier.hxx> +#include <com/sun/star/container/XHierarchicalNameAccess.hpp> +#include "pkgprovider.hxx" +#include "pkgcontent.hxx" +#include "pkguri.hxx" + +using namespace com::sun::star; + +namespace package_ucp +{ + +//========================================================================= +// +// class Package. +// +//========================================================================= + +class Package : public cppu::OWeakObject, + public container::XHierarchicalNameAccess +{ + friend class ContentProvider; + + rtl::OUString m_aName; + uno::Reference< container::XHierarchicalNameAccess > m_xNA; + ContentProvider* m_pOwner; + +public: + Package( const rtl::OUString& rName, + const uno::Reference< container::XHierarchicalNameAccess > & xNA, + ContentProvider* pOwner ) + : m_aName( rName ), m_xNA( xNA ), m_pOwner( pOwner ) {} + virtual ~Package() { m_pOwner->removePackage( m_aName ); } + + // XInterface + virtual uno::Any SAL_CALL + queryInterface( const uno::Type& aType ) + throw( uno::RuntimeException ) + { return m_xNA->queryInterface( aType ); } + virtual void SAL_CALL + acquire() throw() + { OWeakObject::acquire(); } + virtual void SAL_CALL + release() throw() + { OWeakObject::release(); } + + // XHierarchicalNameAccess + virtual uno::Any SAL_CALL + getByHierarchicalName( const rtl::OUString& aName ) + throw( container::NoSuchElementException, uno::RuntimeException ) + { return m_xNA->getByHierarchicalName( aName ); } + virtual sal_Bool SAL_CALL + hasByHierarchicalName( const rtl::OUString& aName ) + throw( uno::RuntimeException ) + { return m_xNA->hasByHierarchicalName( aName ); } +}; + +//========================================================================= +// +// Packages. +// +//========================================================================= + +struct equalString +{ + bool operator()( + const rtl::OUString& rKey1, const rtl::OUString& rKey2 ) const + { + return !!( rKey1 == rKey2 ); + } +}; + +struct hashString +{ + size_t operator()( const rtl::OUString & rName ) const + { + return rName.hashCode(); + } +}; + +typedef std::hash_map +< + rtl::OUString, + Package*, + hashString, + equalString +> +PackageMap; + +class Packages : public PackageMap {}; + +} + +using namespace package_ucp; + +//========================================================================= +//========================================================================= +// +// ContentProvider Implementation. +// +//========================================================================= +//========================================================================= + +ContentProvider::ContentProvider( + const uno::Reference< lang::XMultiServiceFactory >& rSMgr ) +: ::ucbhelper::ContentProviderImplHelper( rSMgr ), + m_pPackages( 0 ) +{ +} + +//========================================================================= +// virtual +ContentProvider::~ContentProvider() +{ + delete m_pPackages; +} + +//========================================================================= +// +// XInterface methods. +// +//========================================================================= + +XINTERFACE_IMPL_3( ContentProvider, + lang::XTypeProvider, + lang::XServiceInfo, + ucb::XContentProvider ); + +//========================================================================= +// +// XTypeProvider methods. +// +//========================================================================= + +XTYPEPROVIDER_IMPL_3( ContentProvider, + lang::XTypeProvider, + lang::XServiceInfo, + ucb::XContentProvider ); + +//========================================================================= +// +// XServiceInfo methods. +// +//========================================================================= + +XSERVICEINFO_IMPL_1( ContentProvider, + rtl::OUString::createFromAscii( + "com.sun.star.comp.ucb.PackageContentProvider" ), + rtl::OUString::createFromAscii( + PACKAGE_CONTENT_PROVIDER_SERVICE_NAME ) ); + +//========================================================================= +// +// Service factory implementation. +// +//========================================================================= + +ONE_INSTANCE_SERVICE_FACTORY_IMPL( ContentProvider ); + +//========================================================================= +// +// XContentProvider methods. +// +//========================================================================= + +// virtual +uno::Reference< ucb::XContent > SAL_CALL ContentProvider::queryContent( + const uno::Reference< ucb::XContentIdentifier >& Identifier ) + throw( ucb::IllegalIdentifierException, uno::RuntimeException ) +{ + if ( !Identifier.is() ) + return uno::Reference< ucb::XContent >(); + + PackageUri aUri( Identifier->getContentIdentifier() ); + if ( !aUri.isValid() ) + throw ucb::IllegalIdentifierException(); + + // Create a new identifier for the mormalized URL returned by + // PackageUri::getUri(). + uno::Reference< ucb::XContentIdentifier > xId + = new ::ucbhelper::ContentIdentifier( m_xSMgr, aUri.getUri() ); + + osl::MutexGuard aGuard( m_aMutex ); + + // Check, if a content with given id already exists... + uno::Reference< ucb::XContent > xContent + = queryExistingContent( xId ).get(); + if ( xContent.is() ) + return xContent; + + // Create a new content. + + xContent = Content::create( m_xSMgr, this, Identifier ); // not xId!!! + registerNewContent( xContent ); + + if ( xContent.is() && !xContent->getIdentifier().is() ) + throw ucb::IllegalIdentifierException(); + + return xContent; +} + +//========================================================================= +// +// Other methods. +// +//========================================================================= + +uno::Reference< container::XHierarchicalNameAccess > +ContentProvider::createPackage( const rtl::OUString & rName, const rtl::OUString & rParam ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + if ( !rName.getLength() ) + { + OSL_ENSURE( sal_False, + "ContentProvider::createPackage - Invalid URL!" ); + return uno::Reference< container::XHierarchicalNameAccess >(); + } + + rtl::OUString rURL = rName + rParam; + + if ( m_pPackages ) + { + Packages::const_iterator it = m_pPackages->find( rURL ); + if ( it != m_pPackages->end() ) + { + // Already instanciated. Return package. + return (*it).second->m_xNA; + } + } + else + m_pPackages = new Packages; + + // Create new package... + try + { + uno::Sequence< uno::Any > aArguments( 1 ); + aArguments[ 0 ] <<= rURL; + + uno::Reference< uno::XInterface > xIfc + = m_xSMgr->createInstanceWithArguments( + rtl::OUString::createFromAscii( + "com.sun.star.packages.comp.ZipPackage" ), + aArguments ); + + if ( xIfc.is() ) + { + uno::Reference< + container::XHierarchicalNameAccess > xNameAccess( + xIfc, uno::UNO_QUERY ); + + OSL_ENSURE( xNameAccess.is(), + "ContentProvider::createPackage - " + "Got no hierarchical name access!" ); + + rtl::Reference< Package> xPackage + = new Package( rURL, xNameAccess, this ); + + (*m_pPackages)[ rURL ] = xPackage.get(); + + return xPackage.get(); + } + } + catch ( uno::RuntimeException const & ) + { + // createInstanceWithArguemts + } + catch ( uno::Exception const & ) + { + // createInstanceWithArguemts + } + + return uno::Reference< container::XHierarchicalNameAccess >(); +} + +//========================================================================= +sal_Bool ContentProvider::removePackage( const rtl::OUString & rName ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + if ( m_pPackages ) + { + Packages::iterator it = m_pPackages->find( rName ); + if ( it != m_pPackages->end() ) + { + m_pPackages->erase( it ); + return sal_True; + } + } + return sal_False; +} + diff --git a/ucb/source/ucp/package/pkgprovider.hxx b/ucb/source/ucp/package/pkgprovider.hxx new file mode 100644 index 000000000000..89843f192cc1 --- /dev/null +++ b/ucb/source/ucp/package/pkgprovider.hxx @@ -0,0 +1,105 @@ +/************************************************************************* + * + * 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 _PKGPROVIDER_HXX +#define _PKGPROVIDER_HXX + +#include <ucbhelper/providerhelper.hxx> +#include "pkguri.hxx" + +namespace com { namespace sun { namespace star { namespace container { + class XHierarchicalNameAccess; +} } } } + +namespace package_ucp { + +//========================================================================= + +// UNO service name for the provider. This name will be used by the UCB to +// create instances of the provider. +#define PACKAGE_CONTENT_PROVIDER_SERVICE_NAME \ + "com.sun.star.ucb.PackageContentProvider" +#define PACKAGE_CONTENT_PROVIDER_SERVICE_NAME_LENGTH 39 + +// UCB Content Type. +#define PACKAGE_FOLDER_CONTENT_TYPE \ + "application/" PACKAGE_URL_SCHEME "-folder" +#define PACKAGE_STREAM_CONTENT_TYPE \ + "application/" PACKAGE_URL_SCHEME "-stream" +#define PACKAGE_ZIP_FOLDER_CONTENT_TYPE \ + "application/" PACKAGE_ZIP_URL_SCHEME "-folder" +#define PACKAGE_ZIP_STREAM_CONTENT_TYPE \ + "application/" PACKAGE_ZIP_URL_SCHEME "-stream" + +//========================================================================= + +class Packages; + +class ContentProvider : public ::ucbhelper::ContentProviderImplHelper +{ + Packages* m_pPackages; + +public: + ContentProvider( const ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XMultiServiceFactory >& rSMgr ); + virtual ~ContentProvider(); + + // XInterface + XINTERFACE_DECL() + + // XTypeProvider + XTYPEPROVIDER_DECL() + + // XServiceInfo + XSERVICEINFO_DECL() + + // XContentProvider + virtual ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XContent > SAL_CALL + queryContent( const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XContentIdentifier >& Identifier ) + throw( ::com::sun::star::ucb::IllegalIdentifierException, + ::com::sun::star::uno::RuntimeException ); + + ////////////////////////////////////////////////////////////////////// + // Additional interfaces + ////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////// + // Non-interface methods. + ////////////////////////////////////////////////////////////////////// + + ::com::sun::star::uno::Reference< + ::com::sun::star::container::XHierarchicalNameAccess > + createPackage( const rtl::OUString & rName, const rtl::OUString & rParam ); + sal_Bool + removePackage( const rtl::OUString & rName ); +}; + +} + +#endif diff --git a/ucb/source/ucp/package/pkgresultset.cxx b/ucb/source/ucp/package/pkgresultset.cxx new file mode 100644 index 000000000000..076e7aa69132 --- /dev/null +++ b/ucb/source/ucp/package/pkgresultset.cxx @@ -0,0 +1,94 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + - This implementation is not a dynamic result set!!! It only implements + the necessary interfaces, but never recognizes/notifies changes!!! + + *************************************************************************/ +#include "pkgdatasupplier.hxx" +#include "pkgresultset.hxx" + +using namespace com::sun::star; + +using namespace package_ucp; + +//========================================================================= +//========================================================================= +// +// DynamicResultSet Implementation. +// +//========================================================================= +//========================================================================= + +DynamicResultSet::DynamicResultSet( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + const rtl::Reference< Content >& rxContent, + const ucb::OpenCommandArgument2& rCommand, + const uno::Reference< ucb::XCommandEnvironment >& rxEnv ) +: ResultSetImplHelper( rxSMgr, rCommand ), + m_xContent( rxContent ), + m_xEnv( rxEnv ) +{ +} + +//========================================================================= +// +// Non-interface methods. +// +//========================================================================= + +void DynamicResultSet::initStatic() +{ + m_xResultSet1 + = new ::ucbhelper::ResultSet( m_xSMgr, + m_aCommand.Properties, + new DataSupplier( m_xSMgr, + m_xContent, + m_aCommand.Mode ), + m_xEnv ); +} + +//========================================================================= +void DynamicResultSet::initDynamic() +{ + m_xResultSet1 + = new ::ucbhelper::ResultSet( m_xSMgr, + m_aCommand.Properties, + new DataSupplier( m_xSMgr, + m_xContent, + m_aCommand.Mode ), + m_xEnv ); + m_xResultSet2 = m_xResultSet1; +} + diff --git a/ucb/source/ucp/package/pkgresultset.hxx b/ucb/source/ucp/package/pkgresultset.hxx new file mode 100644 index 000000000000..43621f8adf90 --- /dev/null +++ b/ucb/source/ucp/package/pkgresultset.hxx @@ -0,0 +1,59 @@ +/************************************************************************* + * + * 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 _PKGRESULTSET_HXX +#define _PKGRESULTSET_HXX + +#include <rtl/ref.hxx> +#include <ucbhelper/resultsethelper.hxx> +#include "pkgcontent.hxx" + +namespace package_ucp { + +class DynamicResultSet : public ::ucbhelper::ResultSetImplHelper +{ + rtl::Reference< Content > m_xContent; + com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > m_xEnv; + +private: + virtual void initStatic(); + virtual void initDynamic(); + +public: + DynamicResultSet( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + const rtl::Reference< Content >& rxContent, + const com::sun::star::ucb::OpenCommandArgument2& rCommand, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment >& rxEnv ); +}; + +} + +#endif diff --git a/ucb/source/ucp/package/pkgservices.cxx b/ucb/source/ucp/package/pkgservices.cxx new file mode 100644 index 000000000000..ad4af686d2d6 --- /dev/null +++ b/ucb/source/ucp/package/pkgservices.cxx @@ -0,0 +1,74 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <com/sun/star/registry/XRegistryKey.hpp> +#include "pkgprovider.hxx" + +using namespace com::sun::star; + +//========================================================================= +extern "C" void SAL_CALL component_getImplementationEnvironment( + const sal_Char ** ppEnvTypeName, uno_Environment ** /*ppEnv*/ ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + +//========================================================================= +extern "C" void * SAL_CALL component_getFactory( + const sal_Char * pImplName, void * pServiceManager, void * /*pRegistryKey*/ ) +{ + void * pRet = 0; + + uno::Reference< lang::XMultiServiceFactory > xSMgr( + reinterpret_cast< lang::XMultiServiceFactory * >( pServiceManager ) ); + uno::Reference< lang::XSingleServiceFactory > xFactory; + + ////////////////////////////////////////////////////////////////////// + // Create factory, if implementation name matches. + ////////////////////////////////////////////////////////////////////// + + if ( ::package_ucp::ContentProvider::getImplementationName_Static(). + compareToAscii( pImplName ) == 0 ) + { + xFactory = ::package_ucp::ContentProvider::createServiceFactory( xSMgr ); + } + + ////////////////////////////////////////////////////////////////////// + + if ( xFactory.is() ) + { + xFactory->acquire(); + pRet = xFactory.get(); + } + + return pRet; +} + diff --git a/ucb/source/ucp/package/pkguri.cxx b/ucb/source/ucp/package/pkguri.cxx new file mode 100644 index 000000000000..8424ed906e92 --- /dev/null +++ b/ucb/source/ucp/package/pkguri.cxx @@ -0,0 +1,249 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ + +#include "rtl/ustrbuf.hxx" +#include "osl/diagnose.h" +#include "comphelper/storagehelper.hxx" + +#include "../inc/urihelper.hxx" + +#include "pkguri.hxx" + +using namespace package_ucp; +using namespace rtl; + +//========================================================================= +//========================================================================= +// +// PackageUri Implementation. +// +//========================================================================= +//========================================================================= + +static void normalize( OUString& rURL ) +{ + sal_Int32 nPos = 0; + do + { + nPos = rURL.indexOf( '%', nPos ); + if ( nPos != -1 ) + { + if ( nPos < ( rURL.getLength() - 2 ) ) + { + OUString aTmp = rURL.copy( nPos + 1, 2 ); + rURL = rURL.replaceAt( nPos + 1, 2, aTmp.toAsciiUpperCase() ); + nPos++; + } + } + } + while ( nPos != -1 ); +} + +//========================================================================= +void PackageUri::init() const +{ + // Already inited? + if ( m_aUri.getLength() && !m_aPath.getLength() ) + { + // Note: Maybe it's a re-init, setUri only resets m_aPath! + m_aPackage = m_aParentUri = m_aName = m_aParam = m_aScheme + = OUString(); + + // URI must match at least: <sheme>://<non_empty_url_to_file> + if ( ( m_aUri.getLength() < PACKAGE_URL_SCHEME_LENGTH + 4 ) ) + { + // error, but remember that we did a init(). + m_aPath = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/" ) ); + return; + } + + // Scheme must be followed by '://' + if ( ( m_aUri.getStr()[ PACKAGE_URL_SCHEME_LENGTH ] + != sal_Unicode( ':' ) ) + || + ( m_aUri.getStr()[ PACKAGE_URL_SCHEME_LENGTH + 1 ] + != sal_Unicode( '/' ) ) + || + ( m_aUri.getStr()[ PACKAGE_URL_SCHEME_LENGTH + 2 ] + != sal_Unicode( '/' ) ) ) + { + // error, but remember that we did a init(). + m_aPath = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/" ) ); + return; + } + + rtl::OUString aPureUri; + sal_Int32 nParam = m_aUri.indexOf( '?' ); + if( nParam >= 0 ) + { + m_aParam = m_aUri.copy( nParam ); + aPureUri = m_aUri.copy( 0, nParam ); + } + else + aPureUri = m_aUri; + + // Scheme is case insensitive. + m_aScheme = aPureUri.copy( + 0, PACKAGE_URL_SCHEME_LENGTH ).toAsciiLowerCase(); + + if ( m_aScheme.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( PACKAGE_URL_SCHEME ) ) + || m_aScheme.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( PACKAGE_ZIP_URL_SCHEME ) ) ) + { + if ( m_aScheme.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( PACKAGE_ZIP_URL_SCHEME ) ) ) + { + m_aParam += + ( m_aParam.getLength() + ? ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "&purezip" ) ) + : ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "?purezip" ) ) ); + } + + aPureUri = aPureUri.replaceAt( 0, + m_aScheme.getLength(), + m_aScheme ); + + sal_Int32 nStart = PACKAGE_URL_SCHEME_LENGTH + 3; + sal_Int32 nEnd = aPureUri.lastIndexOf( '/' ); + if ( nEnd == PACKAGE_URL_SCHEME_LENGTH + 3 ) + { + // Only <scheme>:/// - Empty authority + + // error, but remember that we did a init(). + m_aPath = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/" ) ); + return; + } + else if ( nEnd == ( aPureUri.getLength() - 1 ) ) + { + if ( aPureUri.getStr()[ aPureUri.getLength() - 2 ] + == sal_Unicode( '/' ) ) + { + // Only <scheme>://// or <scheme>://<something>// + + // error, but remember that we did a init(). + m_aPath = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/" ) ); + return; + } + + // Remove trailing slash. + aPureUri = aPureUri.copy( 0, nEnd ); + } + + + nEnd = aPureUri.indexOf( '/', nStart ); + if ( nEnd == -1 ) + { + // root folder. + + OUString aNormPackage = aPureUri.copy( nStart ); + normalize( aNormPackage ); + + aPureUri = aPureUri.replaceAt( + nStart, aPureUri.getLength() - nStart, aNormPackage ); + m_aPackage + = ::ucb_impl::urihelper::decodeSegment( aNormPackage ); + m_aPath = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/" ) ); + m_aUri = m_aUri.replaceAt( 0, + ( nParam >= 0 ) + ? nParam + : m_aUri.getLength(), aPureUri ); + + sal_Int32 nLastSlash = m_aPackage.lastIndexOf( '/' ); + if ( nLastSlash != -1 ) + m_aName = ::ucb_impl::urihelper::decodeSegment( + m_aPackage.copy( nLastSlash + 1 ) ); + else + m_aName + = ::ucb_impl::urihelper::decodeSegment( m_aPackage ); + } + else + { + m_aPath = aPureUri.copy( nEnd + 1 ); + + // Unexpected sequences of characters: + // - empty path segments + // - encoded slashes + // - parent folder segments ".." + // - current folder segments "." + if ( m_aPath.indexOf( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "//" ) ) ) != -1 + || m_aPath.indexOf( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "%2F" ) ) ) != -1 + || m_aPath.indexOf( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "%2f" ) ) ) != -1 + || ::comphelper::OStorageHelper::PathHasSegment( m_aPath, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".." ) ) ) + || ::comphelper::OStorageHelper::PathHasSegment( m_aPath, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "." ) ) ) ) + { + // error, but remember that we did a init(). + m_aPath = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/" ) ); + return; + } + + OUString aNormPackage = aPureUri.copy( nStart, nEnd - nStart ); + normalize( aNormPackage ); + + aPureUri = aPureUri.replaceAt( + nStart, nEnd - nStart, aNormPackage ); + aPureUri = aPureUri.replaceAt( + nEnd + 1, + aPureUri.getLength() - nEnd - 1, + ::ucb_impl::urihelper::encodeURI( m_aPath ) ); + + m_aPackage + = ::ucb_impl::urihelper::decodeSegment( aNormPackage ); + m_aPath = ::ucb_impl::urihelper::decodeSegment( m_aPath ); + m_aUri = m_aUri.replaceAt( 0, + ( nParam >= 0 ) + ? nParam + : m_aUri.getLength(), aPureUri ); + + sal_Int32 nLastSlash = aPureUri.lastIndexOf( '/' ); + if ( nLastSlash != -1 ) + { + m_aParentUri = aPureUri.copy( 0, nLastSlash ); + m_aName = ::ucb_impl::urihelper::decodeSegment( + aPureUri.copy( nLastSlash + 1 ) ); + } + } + + // success + m_bValid = true; + } + else + { + // error, but remember that we did a init(). + m_aPath = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/" ) ); + } + } +} diff --git a/ucb/source/ucp/package/pkguri.hxx b/ucb/source/ucp/package/pkguri.hxx new file mode 100644 index 000000000000..68513bcfa940 --- /dev/null +++ b/ucb/source/ucp/package/pkguri.hxx @@ -0,0 +1,101 @@ +/************************************************************************* + * + * 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 _PKGURI_HXX +#define _PKGURI_HXX + +#include <rtl/ustring.hxx> + +namespace package_ucp { + +//========================================================================= + +#define PACKAGE_URL_SCHEME "vnd.sun.star.pkg" +#define PACKAGE_ZIP_URL_SCHEME "vnd.sun.star.zip" +#define PACKAGE_URL_SCHEME_LENGTH 16 + +//========================================================================= + +class PackageUri +{ + mutable ::rtl::OUString m_aUri; + mutable ::rtl::OUString m_aParentUri; + mutable ::rtl::OUString m_aPackage; + mutable ::rtl::OUString m_aPath; + mutable ::rtl::OUString m_aName; + mutable ::rtl::OUString m_aParam; + mutable ::rtl::OUString m_aScheme; + mutable bool m_bValid; + +private: + void init() const; + +public: + PackageUri() : m_bValid( false ) {} + PackageUri( const ::rtl::OUString & rPackageUri ) + : m_aUri( rPackageUri ), m_bValid( false ) {} + + sal_Bool isValid() const + { init(); return m_bValid; } + + const ::rtl::OUString & getUri() const + { init(); return m_aUri; } + + void setUri( const ::rtl::OUString & rPackageUri ) + { m_aPath = ::rtl::OUString(); m_aUri = rPackageUri; m_bValid = false; } + + const ::rtl::OUString & getParentUri() const + { init(); return m_aParentUri; } + + const ::rtl::OUString & getPackage() const + { init(); return m_aPackage; } + + const ::rtl::OUString & getPath() const + { init(); return m_aPath; } + + const ::rtl::OUString & getName() const + { init(); return m_aName; } + + const ::rtl::OUString & getParam() const + { init(); return m_aParam; } + + const ::rtl::OUString & getScheme() const + { init(); return m_aScheme; } + + inline sal_Bool isRootFolder() const; +}; + +inline sal_Bool PackageUri::isRootFolder() const +{ + init(); + return ( ( m_aPath.getLength() == 1 ) && + ( m_aPath.getStr()[ 0 ] == sal_Unicode( '/' ) ) ); +} + +} + +#endif diff --git a/ucb/source/ucp/package/ucppkg.xml b/ucb/source/ucp/package/ucppkg.xml new file mode 100644 index 000000000000..6b71fca63486 --- /dev/null +++ b/ucb/source/ucp/package/ucppkg.xml @@ -0,0 +1,92 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE module-description PUBLIC "-//StarOffice//DTD ComponentDescription 1.0//EN" "module-description.dtd"> +<module-description xmlns:xlink="http://www.w3.org/1999/xlink"> + + <module-name> + ucppkg + </module-name> + + <component-description> + <author> + Kai Sommerfeld + </author> + <name> + com.sun.star.comp.ucb.PackageContentProvider + </name> + <description> + This component implements a Content Provider for the Universal + Content Broker. It provides access to the contents of package (zip + archive) files. + </description> + <loader-name> + com.sun.star.loader.SharedLibrary + </loader-name> + <language> + c++ + </language> + <status value="final"/> + <supported-service> + com.sun.star.ucb.PackageContentProvider + </supported-service> + + <service-dependency> + com.sun.star.packages.comp.ZipPackage + </service-dependency> + </component-description> + + <project-build-dependency> sal </project-build-dependency> + <project-build-dependency> cppu </project-build-dependency> + <project-build-dependency> cppuhelper </project-build-dependency> + <project-build-dependency> ucbhelper </project-build-dependency> + + <runtime-module-dependency> sal3 </runtime-module-dependency> + <runtime-module-dependency> cppu3 </runtime-module-dependency> + <runtime-module-dependency> cppuhelper3$(COM) </runtime-module-dependency> + <runtime-module-dependency> ucbhelper4$(COM) </runtime-module-dependency> + + <type> com.sun.star.beans.PropertyAttribute </type> + <type> com.sun.star.beans.XPropertiesChangeNotifier </type> + <type> com.sun.star.beans.XPropertyAccess </type> + <type> com.sun.star.beans.XPropertyContainer </type> + <type> com.sun.star.beans.XPropertySetInfoChangeNotifier </type> + <type> com.sun.star.container.XChild </type> + <type> com.sun.star.container.XEnumerationAccess </type> + <type> com.sun.star.container.XHierarchicalNameAccess </type> + <type> com.sun.star.container.XNamed </type> + <type> com.sun.star.container.XNameContainer </type> + <type> com.sun.star.io.XActiveDataSink </type> + <type> com.sun.star.io.XOutputStream </type> + <type> com.sun.star.lang.IllegalAccessException </type> + <type> com.sun.star.lang.XComponent </type> + <type> com.sun.star.lang.XMultiServiceFactory </type> + <type> com.sun.star.lang.XServiceInfo </type> + <type> com.sun.star.lang.XSingleServiceFactory </type> + <type> com.sun.star.lang.XTypeProvider </type> + <type> com.sun.star.registry.XRegistryKey </type> + <type> com.sun.star.sdbc.XCloseable </type> + <type> com.sun.star.sdbc.XColumnLocate </type> + <type> com.sun.star.sdbc.XResultSetMetaDataSupplier </type> + <type> com.sun.star.sdbc.XRow </type> + <type> com.sun.star.ucb.ContentInfoAttribute </type> + <type> com.sun.star.ucb.InsertCommandArgument </type> + <type> com.sun.star.ucb.InteractiveBadTransferURLException </type> + <type> com.sun.star.ucb.MissingInputStreamException </type> + <type> com.sun.star.ucb.NameClash </type> + <type> com.sun.star.ucb.NameClashException </type> + <type> com.sun.star.ucb.OpenCommandArgument2 </type> + <type> com.sun.star.ucb.OpenMode </type> + <type> com.sun.star.ucb.ResultSetException </type> + <type> com.sun.star.ucb.TransferInfo </type> + <type> com.sun.star.ucb.UnsupportedDataSinkException </type> + <type> com.sun.star.ucb.UnsupportedNameClashException </type> + <type> com.sun.star.ucb.UnsupportedOpenModeException </type> + <type> com.sun.star.ucb.XCommandInfo </type> + <type> com.sun.star.ucb.XCommandProcessor </type> + <type> com.sun.star.ucb.XContentAccess </type> + <type> com.sun.star.ucb.XContentCreator </type> + <type> com.sun.star.ucb.XContentProvider </type> + <type> com.sun.star.ucb.XDynamicResultSet </type> + <type> com.sun.star.ucb.XPersistentPropertySet </type> + <type> com.sun.star.uno.XWeak </type> + <type> com.sun.star.util.XChangesBatch </type> +</module-description> diff --git a/ucb/source/ucp/package/ucppkg1.component b/ucb/source/ucp/package/ucppkg1.component new file mode 100644 index 000000000000..a2e2418b5602 --- /dev/null +++ b/ucb/source/ucp/package/ucppkg1.component @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* 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. +* +**********************************************************************--> + +<component loader="com.sun.star.loader.SharedLibrary" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.ucb.PackageContentProvider"> + <service name="com.sun.star.ucb.PackageContentProvider"/> + </implementation> +</component> diff --git a/ucb/source/ucp/tdoc/makefile.mk b/ucb/source/ucp/tdoc/makefile.mk new file mode 100644 index 000000000000..82c76b34b206 --- /dev/null +++ b/ucb/source/ucp/tdoc/makefile.mk @@ -0,0 +1,102 @@ +#************************************************************************* +# +# 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=ucb +# Version +UCPTDOC_MAJOR=1 +TARGET=ucptdoc$(UCPTDOC_MAJOR).uno +ENABLE_EXCEPTIONS=TRUE +USE_DEFFILE=TRUE +NO_BSYMBOLIC=TRUE + +# --- Settings --------------------------------------------------------- + +.INCLUDE: settings.mk + +# --- General ----------------------------------------------------- +.IF "$(L10N_framework)"=="" + +# no "lib" prefix +DLLPRE = + +SLOFILES=\ + $(SLO)$/tdoc_provider.obj \ + $(SLO)$/tdoc_services.obj \ + $(SLO)$/tdoc_uri.obj \ + $(SLO)$/tdoc_content.obj \ + $(SLO)$/tdoc_contentcaps.obj \ + $(SLO)$/tdoc_storage.obj \ + $(SLO)$/tdoc_docmgr.obj \ + $(SLO)$/tdoc_datasupplier.obj \ + $(SLO)$/tdoc_resultset.obj \ + $(SLO)$/tdoc_documentcontentfactory.obj \ + $(SLO)$/tdoc_passwordrequest.obj \ + $(SLO)$/tdoc_stgelems.obj + +LIB1TARGET=$(SLB)$/_$(TARGET).lib +LIB1OBJFILES=$(SLOFILES) + +# --- Shared-Library --------------------------------------------------- + +SHL1TARGET=$(TARGET) +SHL1IMPLIB=i$(TARGET) + +SHL1VERSIONMAP=$(SOLARENV)/src/component.map + +SHL1STDLIBS=\ + $(COMPHELPERLIB) \ + $(CPPUHELPERLIB) \ + $(CPPULIB) \ + $(SALLIB) \ + $(SALHELPERLIB) \ + $(UCBHELPERLIB) + +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +SHL1LIBS=$(LIB1TARGET) + +# Make symbol renaming match library name for Mac OS X +.IF "$(OS)"=="MACOSX" +SYMBOLPREFIX=$(TARGET) +.ENDIF + +DEF1NAME=$(SHL1TARGET) + +.ENDIF # L10N_framework + +# --- Targets ---------------------------------------------------------- + +.INCLUDE: target.mk + + +ALLTAR : $(MISC)/ucptdoc1.component + +$(MISC)/ucptdoc1.component .ERRREMOVE : $(SOLARENV)/bin/createcomponent.xslt \ + ucptdoc1.component + $(XSLTPROC) --nonet --stringparam uri \ + '$(COMPONENTPREFIX_BASIS_NATIVE)$(SHL1TARGETN:f)' -o $@ \ + $(SOLARENV)/bin/createcomponent.xslt ucptdoc1.component diff --git a/ucb/source/ucp/tdoc/tdoc_content.cxx b/ucb/source/ucp/tdoc/tdoc_content.cxx new file mode 100644 index 000000000000..2c2103e46224 --- /dev/null +++ b/ucb/source/ucp/tdoc/tdoc_content.cxx @@ -0,0 +1,3135 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ + +#include "osl/diagnose.h" +#include "osl/doublecheckedlocking.h" +#include "rtl/ustrbuf.hxx" + +#include "com/sun/star/beans/PropertyAttribute.hpp" +#include "com/sun/star/beans/PropertyValue.hpp" +#include "com/sun/star/beans/XPropertySet.hpp" +#include "com/sun/star/embed/ElementModes.hpp" +#include "com/sun/star/embed/XStorage.hpp" +#include "com/sun/star/embed/XTransactedObject.hpp" +#include "com/sun/star/io/XActiveDataSink.hpp" +#include "com/sun/star/io/XActiveDataStreamer.hpp" +#include "com/sun/star/lang/IllegalAccessException.hpp" +#include "com/sun/star/sdbc/XRow.hpp" +#include "com/sun/star/ucb/ContentAction.hpp" +#include "com/sun/star/ucb/ContentInfoAttribute.hpp" +#include "com/sun/star/ucb/InsertCommandArgument.hpp" +#include "com/sun/star/ucb/InteractiveBadTransferURLException.hpp" +#include "com/sun/star/ucb/MissingInputStreamException.hpp" +#include "com/sun/star/ucb/MissingPropertiesException.hpp" +#include "com/sun/star/ucb/NameClash.hpp" +#include "com/sun/star/ucb/NameClashException.hpp" +#include "com/sun/star/ucb/OpenCommandArgument2.hpp" +#include "com/sun/star/ucb/OpenMode.hpp" +#include "com/sun/star/ucb/TransferInfo.hpp" +#include "com/sun/star/ucb/UnsupportedCommandException.hpp" +#include "com/sun/star/ucb/UnsupportedDataSinkException.hpp" +#include "com/sun/star/ucb/UnsupportedNameClashException.hpp" +#include "com/sun/star/ucb/UnsupportedOpenModeException.hpp" +#include "com/sun/star/ucb/XCommandInfo.hpp" +#include "com/sun/star/ucb/XPersistentPropertySet.hpp" + +#include "ucbhelper/cancelcommandexecution.hxx" +#include "ucbhelper/contentidentifier.hxx" +#include "ucbhelper/propertyvalueset.hxx" + +#include "tdoc_content.hxx" +#include "tdoc_resultset.hxx" +#include "tdoc_passwordrequest.hxx" + +#include "../inc/urihelper.hxx" + +using namespace com::sun::star; +using namespace tdoc_ucp; + +//========================================================================= +static ContentType lcl_getContentType( const rtl::OUString & rType ) +{ + if ( rType.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( TDOC_ROOT_CONTENT_TYPE ) ) ) + return ROOT; + else if ( rType.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( TDOC_DOCUMENT_CONTENT_TYPE ) ) ) + return DOCUMENT; + else if ( rType.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( TDOC_FOLDER_CONTENT_TYPE ) ) ) + return FOLDER; + else if ( rType.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( TDOC_STREAM_CONTENT_TYPE ) ) ) + return STREAM; + else + { + OSL_ENSURE( sal_False, + "Content::Content - unsupported content type string" ); + return STREAM; + } +} + +//========================================================================= +//========================================================================= +// +// Content Implementation. +// +//========================================================================= +//========================================================================= + +// static ( "virtual" ctor ) +Content* Content::create( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + ContentProvider* pProvider, + const uno::Reference< ucb::XContentIdentifier >& Identifier ) +{ + // Fail, if resource does not exist. + ContentProperties aProps; + if ( !Content::loadData( pProvider, + Uri( Identifier->getContentIdentifier() ), + aProps ) ) + return 0; + + return new Content( rxSMgr, pProvider, Identifier, aProps ); +} + +//========================================================================= +// static ( "virtual" ctor ) +Content* Content::create( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + ContentProvider* pProvider, + const uno::Reference< ucb::XContentIdentifier >& Identifier, + const ucb::ContentInfo& Info ) +{ + if ( !Info.Type.getLength() ) + return 0; + + if ( !Info.Type.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( TDOC_FOLDER_CONTENT_TYPE ) ) && + !Info.Type.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( TDOC_STREAM_CONTENT_TYPE ) ) ) + { + OSL_ENSURE( sal_False, "Content::create - unsupported content type!" ); + return 0; + } + +#if 0 + // Fail, if content does exist. + if ( Content::hasData( pProvider, + Uri( Identifier->getContentIdentifier() ) ) ) + return 0; +#endif + + return new Content( rxSMgr, pProvider, Identifier, Info ); +} + +//========================================================================= +Content::Content( + const uno::Reference< lang::XMultiServiceFactory > & rxSMgr, + ContentProvider * pProvider, + const uno::Reference< ucb::XContentIdentifier > & Identifier, + const ContentProperties & rProps ) +: ContentImplHelper( rxSMgr, pProvider, Identifier ), + m_aProps( rProps ), + m_eState( PERSISTENT ), + m_pProvider( pProvider ) +{ +} + +//========================================================================= +// ctor for a content just created via XContentCreator::createNewContent() +Content::Content( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + ContentProvider* pProvider, + const uno::Reference< ucb::XContentIdentifier >& Identifier, + const ucb::ContentInfo& Info ) + : ContentImplHelper( rxSMgr, pProvider, Identifier ), + m_aProps( lcl_getContentType( Info.Type ), rtl::OUString() ), // no Title (yet) + m_eState( TRANSIENT ), + m_pProvider( pProvider ) +{ +} + +//========================================================================= +// virtual +Content::~Content() +{ +} + +//========================================================================= +// +// XInterface methods. +// +//========================================================================= + +// virtual +void SAL_CALL Content::acquire() + throw( ) +{ + ContentImplHelper::acquire(); +} + +//========================================================================= +// virtual +void SAL_CALL Content::release() + throw( ) +{ + ContentImplHelper::release(); +} + +//========================================================================= +// virtual +uno::Any SAL_CALL Content::queryInterface( const uno::Type & rType ) + throw ( uno::RuntimeException ) +{ + uno::Any aRet = ContentImplHelper::queryInterface( rType ); + + if ( !aRet.hasValue() ) + { + aRet = cppu::queryInterface( + rType, static_cast< ucb::XContentCreator * >( this ) ); + if ( aRet.hasValue() ) + { + if ( !m_aProps.isContentCreator() ) + return uno::Any(); + } + } + + return aRet; +} + +//========================================================================= +// +// XTypeProvider methods. +// +//========================================================================= + +XTYPEPROVIDER_COMMON_IMPL( Content ); + +//========================================================================= +// virtual +uno::Sequence< uno::Type > SAL_CALL Content::getTypes() + throw( uno::RuntimeException ) +{ + cppu::OTypeCollection * pCollection = 0; + + if ( m_aProps.isContentCreator() ) + { + static cppu::OTypeCollection* pFolderTypes = 0; + + pCollection = pFolderTypes; + if ( !pCollection ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + + pCollection = pFolderTypes; + if ( !pCollection ) + { + static cppu::OTypeCollection aCollection( + CPPU_TYPE_REF( lang::XTypeProvider ), + CPPU_TYPE_REF( lang::XServiceInfo ), + CPPU_TYPE_REF( lang::XComponent ), + CPPU_TYPE_REF( ucb::XContent ), + CPPU_TYPE_REF( ucb::XCommandProcessor ), + CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ), + CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ), + CPPU_TYPE_REF( beans::XPropertyContainer ), + CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ), + CPPU_TYPE_REF( container::XChild ), + CPPU_TYPE_REF( ucb::XContentCreator ) ); // !! + pCollection = &aCollection; + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + pFolderTypes = pCollection; + } + } + else { + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + } + } + else + { + static cppu::OTypeCollection* pDocumentTypes = 0; + + pCollection = pDocumentTypes; + if ( !pCollection ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + + pCollection = pDocumentTypes; + if ( !pCollection ) + { + static cppu::OTypeCollection aCollection( + CPPU_TYPE_REF( lang::XTypeProvider ), + CPPU_TYPE_REF( lang::XServiceInfo ), + CPPU_TYPE_REF( lang::XComponent ), + CPPU_TYPE_REF( ucb::XContent ), + CPPU_TYPE_REF( ucb::XCommandProcessor ), + CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ), + CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ), + CPPU_TYPE_REF( beans::XPropertyContainer ), + CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ), + CPPU_TYPE_REF( container::XChild ) ); + pCollection = &aCollection; + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + pDocumentTypes = pCollection; + } + } + else { + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + } + } + + return (*pCollection).getTypes(); +} + +//========================================================================= +// +// XServiceInfo methods. +// +//========================================================================= + +// virtual +rtl::OUString SAL_CALL Content::getImplementationName() + throw( uno::RuntimeException ) +{ + return rtl::OUString::createFromAscii( + "com.sun.star.comp.ucb.TransientDocumentsContent" ); +} + +//========================================================================= +// virtual +uno::Sequence< rtl::OUString > SAL_CALL Content::getSupportedServiceNames() + throw( uno::RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + uno::Sequence< rtl::OUString > aSNS( 1 ); + + if ( m_aProps.getType() == STREAM ) + aSNS.getArray()[ 0 ] = rtl::OUString::createFromAscii( + TDOC_STREAM_CONTENT_SERVICE_NAME ); + else if ( m_aProps.getType() == FOLDER ) + aSNS.getArray()[ 0 ] = rtl::OUString::createFromAscii( + TDOC_FOLDER_CONTENT_SERVICE_NAME ); + else if ( m_aProps.getType() == DOCUMENT ) + aSNS.getArray()[ 0 ] = rtl::OUString::createFromAscii( + TDOC_DOCUMENT_CONTENT_SERVICE_NAME ); + else + aSNS.getArray()[ 0 ] = rtl::OUString::createFromAscii( + TDOC_ROOT_CONTENT_SERVICE_NAME ); + + return aSNS; +} + +//========================================================================= +// +// XContent methods. +// +//========================================================================= + +// virtual +rtl::OUString SAL_CALL Content::getContentType() + throw( uno::RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + return m_aProps.getContentType(); +} + +//========================================================================= +// virtual +uno::Reference< ucb::XContentIdentifier > SAL_CALL +Content::getIdentifier() + throw( uno::RuntimeException ) +{ + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + // Transient? + if ( m_eState == TRANSIENT ) + { + // Transient contents have no identifier. + return uno::Reference< ucb::XContentIdentifier >(); + } + } + return ContentImplHelper::getIdentifier(); +} + +//========================================================================= +// +// XCommandProcessor methods. +// +//========================================================================= + +// virtual +uno::Any SAL_CALL Content::execute( + const ucb::Command& aCommand, + sal_Int32 /*CommandId*/, + const uno::Reference< ucb::XCommandEnvironment >& Environment ) + throw( uno::Exception, + ucb::CommandAbortedException, + uno::RuntimeException ) +{ + uno::Any aRet; + + if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "getPropertyValues" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // getPropertyValues + ////////////////////////////////////////////////////////////////// + + uno::Sequence< beans::Property > Properties; + if ( !( aCommand.Argument >>= Properties ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Wrong argument type!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + aRet <<= getPropertyValues( Properties ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "setPropertyValues" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // setPropertyValues + ////////////////////////////////////////////////////////////////// + + uno::Sequence< beans::PropertyValue > aProperties; + if ( !( aCommand.Argument >>= aProperties ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Wrong argument type!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + if ( !aProperties.getLength() ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "No properties!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + aRet <<= setPropertyValues( aProperties, Environment ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "getPropertySetInfo" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // getPropertySetInfo + ////////////////////////////////////////////////////////////////// + + aRet <<= getPropertySetInfo( Environment ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "getCommandInfo" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // getCommandInfo + ////////////////////////////////////////////////////////////////// + + aRet <<= getCommandInfo( Environment ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "open" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // open + ////////////////////////////////////////////////////////////////// + + ucb::OpenCommandArgument2 aOpenCommand; + if ( !( aCommand.Argument >>= aOpenCommand ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Wrong argument type!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + aRet = open( aOpenCommand, Environment ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "insert" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // insert ( Supported by folders and streams only ) + ////////////////////////////////////////////////////////////////// + + ContentType eType = m_aProps.getType(); + if ( ( eType != FOLDER ) && ( eType != STREAM ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( ucb::UnsupportedCommandException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "insert command only supported by " + "folders and streams!" ) ), + static_cast< cppu::OWeakObject * >( this ) ) ), + Environment ); + // Unreachable + } + +#ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT + if ( eType == STREAM ) + { + Uri aUri( m_xIdentifier->getContentIdentifier() ); + Uri aParentUri( aUri.getParentUri() ); + if ( aParentUri.isDocument() ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( ucb::UnsupportedCommandException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "insert command not supported by " + "streams that are direct children " + "of document root!" ) ), + static_cast< cppu::OWeakObject * >( + this ) ) ), + Environment ); + // Unreachable + } + } +#endif + ucb::InsertCommandArgument aArg; + if ( !( aCommand.Argument >>= aArg ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Wrong argument type!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + sal_Int32 nNameClash = aArg.ReplaceExisting + ? ucb::NameClash::OVERWRITE + : ucb::NameClash::ERROR; + insert( aArg.Data, nNameClash, Environment ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "delete" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // delete ( Supported by folders and streams only ) + ////////////////////////////////////////////////////////////////// + + { + osl::MutexGuard aGuard( m_aMutex ); + + ContentType eType = m_aProps.getType(); + if ( ( eType != FOLDER ) && ( eType != STREAM ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( ucb::UnsupportedCommandException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "delete command only supported by " + "folders and streams!" ) ), + static_cast< cppu::OWeakObject * >( + this ) ) ), + Environment ); + // Unreachable + } + } + + sal_Bool bDeletePhysical = sal_False; + aCommand.Argument >>= bDeletePhysical; + destroy( bDeletePhysical, Environment ); + + // Remove own and all children's persistent data. + if ( !removeData() ) + { + uno::Any aProps + = uno::makeAny( + beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Uri")), + -1, + uno::makeAny(m_xIdentifier-> + getContentIdentifier()), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_WRITE, + uno::Sequence< uno::Any >(&aProps, 1), + Environment, + rtl::OUString::createFromAscii( + "Cannot remove persistent data!" ), + this ); + // Unreachable + } + + // Remove own and all children's Additional Core Properties. + removeAdditionalPropertySet( sal_True ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "transfer" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // transfer ( Supported by document and folders only ) + ////////////////////////////////////////////////////////////////// + + { + osl::MutexGuard aGuard( m_aMutex ); + + ContentType eType = m_aProps.getType(); + if ( ( eType != FOLDER ) && ( eType != DOCUMENT ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( ucb::UnsupportedCommandException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "transfer command only supported " + "by folders and documents!" ) ), + static_cast< cppu::OWeakObject * >( + this ) ) ), + Environment ); + // Unreachable + } + } + + ucb::TransferInfo aInfo; + if ( !( aCommand.Argument >>= aInfo ) ) + { + OSL_ENSURE( sal_False, "Wrong argument type!" ); + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Wrong argument type!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + transfer( aInfo, Environment ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "createNewContent" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // createNewContent ( Supported by document and folders only ) + ////////////////////////////////////////////////////////////////// + + { + osl::MutexGuard aGuard( m_aMutex ); + + ContentType eType = m_aProps.getType(); + if ( ( eType != FOLDER ) && ( eType != DOCUMENT ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( ucb::UnsupportedCommandException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "createNewContent command only " + "supported by folders and " + "documents!" ) ), + static_cast< cppu::OWeakObject * >( + this ) ) ), + Environment ); + // Unreachable + } + } + + ucb::ContentInfo aInfo; + if ( !( aCommand.Argument >>= aInfo ) ) + { + OSL_ENSURE( sal_False, "Wrong argument type!" ); + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Wrong argument type!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + aRet <<= createNewContent( aInfo ); + } + else + { + ////////////////////////////////////////////////////////////////// + // Unsupported command + ////////////////////////////////////////////////////////////////// + + ucbhelper::cancelCommandExecution( + uno::makeAny( ucb::UnsupportedCommandException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ) ) ), + Environment ); + // Unreachable + } + + return aRet; +} + +//========================================================================= +// virtual +void SAL_CALL Content::abort( sal_Int32 /*CommandId*/ ) + throw( uno::RuntimeException ) +{ +} + +//========================================================================= +// +// XContentCreator methods. +// +//========================================================================= + +// virtual +uno::Sequence< ucb::ContentInfo > SAL_CALL +Content::queryCreatableContentsInfo() + throw( uno::RuntimeException ) +{ + return m_aProps.getCreatableContentsInfo(); +} + +//========================================================================= +// virtual +uno::Reference< ucb::XContent > SAL_CALL +Content::createNewContent( const ucb::ContentInfo& Info ) + throw( uno::RuntimeException ) +{ + if ( m_aProps.isContentCreator() ) + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + if ( !Info.Type.getLength() ) + return uno::Reference< ucb::XContent >(); + + sal_Bool bCreateFolder = + Info.Type.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( TDOC_FOLDER_CONTENT_TYPE ) ); + +#ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT + // streams cannot be created as direct children of document root + if ( !bCreateFolder && ( m_aProps.getType() == DOCUMENT ) ) + { + OSL_ENSURE( sal_False, + "Content::createNewContent - streams cannot be " + "created as direct children of document root!" ); + return uno::Reference< ucb::XContent >(); + } +#endif + if ( !bCreateFolder && + !Info.Type.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( TDOC_STREAM_CONTENT_TYPE ) ) ) + { + OSL_ENSURE( sal_False, + "Content::createNewContent - unsupported type!" ); + return uno::Reference< ucb::XContent >(); + } + + rtl::OUString aURL = m_xIdentifier->getContentIdentifier(); + + OSL_ENSURE( aURL.getLength() > 0, + "Content::createNewContent - empty identifier!" ); + + if ( ( aURL.lastIndexOf( '/' ) + 1 ) != aURL.getLength() ) + aURL += rtl::OUString::createFromAscii( "/" ); + + if ( bCreateFolder ) + aURL += rtl::OUString::createFromAscii( "New_Folder" ); + else + aURL += rtl::OUString::createFromAscii( "New_Stream" ); + + uno::Reference< ucb::XContentIdentifier > xId + = new ::ucbhelper::ContentIdentifier( m_xSMgr, aURL ); + + return create( m_xSMgr, m_pProvider, xId, Info ); + } + else + { + OSL_ENSURE( sal_False, + "createNewContent called on non-contentcreator object!" ); + return uno::Reference< ucb::XContent >(); + } +} + +//========================================================================= +// virtual +rtl::OUString Content::getParentURL() +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + Uri aUri( m_xIdentifier->getContentIdentifier() ); + return aUri.getParentUri(); +} + +//========================================================================= +uno::Reference< ucb::XContentIdentifier > +Content::makeNewIdentifier( const rtl::OUString& rTitle ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + // Assemble new content identifier... + Uri aUri( m_xIdentifier->getContentIdentifier() ); + rtl::OUStringBuffer aNewURL = aUri.getParentUri(); + aNewURL.append( ::ucb_impl::urihelper::encodeSegment( rTitle ) ); + + return + uno::Reference< ucb::XContentIdentifier >( + new ::ucbhelper::ContentIdentifier( + m_xSMgr, aNewURL.makeStringAndClear() ) ); +} + +//========================================================================= +void Content::queryChildren( ContentRefList& rChildren ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + // Only folders (root, documents, folders) have children. + if ( !m_aProps.getIsFolder() ) + return; + + // Obtain a list with a snapshot of all currently instanciated contents + // from provider and extract the contents which are direct children + // of this content. + + ::ucbhelper::ContentRefList aAllContents; + m_xProvider->queryExistingContents( aAllContents ); + + rtl::OUString aURL = m_xIdentifier->getContentIdentifier(); + sal_Int32 nURLPos = aURL.lastIndexOf( '/' ); + + if ( nURLPos != ( aURL.getLength() - 1 ) ) + { + // No trailing slash found. Append. + aURL += rtl::OUString::createFromAscii( "/" ); + } + + sal_Int32 nLen = aURL.getLength(); + + ::ucbhelper::ContentRefList::const_iterator it = aAllContents.begin(); + ::ucbhelper::ContentRefList::const_iterator end = aAllContents.end(); + + while ( it != end ) + { + ::ucbhelper::ContentImplHelperRef xChild = (*it); + rtl::OUString aChildURL + = xChild->getIdentifier()->getContentIdentifier(); + + // Is aURL a prefix of aChildURL? + if ( ( aChildURL.getLength() > nLen ) && + ( aChildURL.compareTo( aURL, nLen ) == 0 ) ) + { + sal_Int32 nPos = nLen; + nPos = aChildURL.indexOf( '/', nPos ); + + if ( ( nPos == -1 ) || + ( nPos == ( aChildURL.getLength() - 1 ) ) ) + { + // No further slashes / only a final slash. It's a child! + rChildren.push_back( + ContentRef( + static_cast< Content * >( xChild.get() ) ) ); + } + } + ++it; + } +} + +//========================================================================= +sal_Bool Content::exchangeIdentity( + const uno::Reference< ucb::XContentIdentifier >& xNewId ) +{ + if ( !xNewId.is() ) + return sal_False; + + osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); + + uno::Reference< ucb::XContent > xThis = this; + + // Already persistent? + if ( m_eState != PERSISTENT ) + { + OSL_ENSURE( sal_False, + "Content::exchangeIdentity - Not persistent!" ); + return sal_False; + } + + // Only folders and streams can be renamed -> exchange identity. + ContentType eType = m_aProps.getType(); + if ( ( eType == ROOT ) || ( eType == DOCUMENT ) ) + { + OSL_ENSURE( sal_False, "Content::exchangeIdentity - " + "Not supported by root or document!" ); + return sal_False; + } + + // Exchange own identitity. + + // Fail, if a content with given id already exists. + if ( !hasData( Uri( xNewId->getContentIdentifier() ) ) ) + { + rtl::OUString aOldURL = m_xIdentifier->getContentIdentifier(); + + aGuard.clear(); + if ( exchange( xNewId ) ) + { + if ( eType == FOLDER ) + { + // Process instanciated children... + + ContentRefList aChildren; + queryChildren( aChildren ); + + ContentRefList::const_iterator it = aChildren.begin(); + ContentRefList::const_iterator end = aChildren.end(); + + while ( it != end ) + { + ContentRef xChild = (*it); + + // Create new content identifier for the child... + uno::Reference< ucb::XContentIdentifier > xOldChildId + = xChild->getIdentifier(); + rtl::OUString aOldChildURL + = xOldChildId->getContentIdentifier(); + rtl::OUString aNewChildURL + = aOldChildURL.replaceAt( + 0, + aOldURL.getLength(), + xNewId->getContentIdentifier() ); + uno::Reference< ucb::XContentIdentifier > xNewChildId + = new ::ucbhelper::ContentIdentifier( + m_xSMgr, aNewChildURL ); + + if ( !xChild->exchangeIdentity( xNewChildId ) ) + return sal_False; + + ++it; + } + } + return sal_True; + } + } + + OSL_ENSURE( sal_False, + "Content::exchangeIdentity - " + "Panic! Cannot exchange identity!" ); + return sal_False; +} + +//========================================================================= +// static +uno::Reference< sdbc::XRow > Content::getPropertyValues( + const uno::Reference< lang::XMultiServiceFactory >& rSMgr, + const uno::Sequence< beans::Property >& rProperties, + ContentProvider* pProvider, + const rtl::OUString& rContentId ) +{ + ContentProperties aData; + if ( loadData( pProvider, rContentId, aData ) ) + { + return getPropertyValues( + rSMgr, rProperties, aData, pProvider, rContentId ); + } + else + { + rtl::Reference< ::ucbhelper::PropertyValueSet > xRow + = new ::ucbhelper::PropertyValueSet( rSMgr ); + + sal_Int32 nCount = rProperties.getLength(); + if ( nCount ) + { + const beans::Property* pProps = rProperties.getConstArray(); + for ( sal_Int32 n = 0; n < nCount; ++n ) + xRow->appendVoid( pProps[ n ] ); + } + + return uno::Reference< sdbc::XRow >( xRow.get() ); + } +} + +//========================================================================= +// static +uno::Reference< sdbc::XRow > Content::getPropertyValues( + const uno::Reference< lang::XMultiServiceFactory >& rSMgr, + const uno::Sequence< beans::Property >& rProperties, + const ContentProperties& rData, + ContentProvider* pProvider, + const rtl::OUString& rContentId ) +{ + // Note: Empty sequence means "get values of all supported properties". + + rtl::Reference< ::ucbhelper::PropertyValueSet > xRow + = new ::ucbhelper::PropertyValueSet( rSMgr ); + + sal_Int32 nCount = rProperties.getLength(); + if ( nCount ) + { + uno::Reference< beans::XPropertySet > xAdditionalPropSet; + sal_Bool bTriedToGetAdditonalPropSet = sal_False; + + const beans::Property* pProps = rProperties.getConstArray(); + for ( sal_Int32 n = 0; n < nCount; ++n ) + { + const beans::Property& rProp = pProps[ n ]; + + // Process Core properties. + + if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) ) + { + xRow->appendString ( rProp, rData.getContentType() ); + } + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "Title" ) ) ) + { + xRow->appendString ( rProp, rData.getTitle() ); + } + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) ) + { + xRow->appendBoolean( rProp, rData.getIsDocument() ); + } + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) ) + { + xRow->appendBoolean( rProp, rData.getIsFolder() ); + } + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "CreatableContentsInfo" ) ) ) + { + xRow->appendObject( + rProp, uno::makeAny( rData.getCreatableContentsInfo() ) ); + } + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "Storage" ) ) ) + { + // Storage is only supported by folders. + ContentType eType = rData.getType(); + if ( eType == FOLDER ) + xRow->appendObject( + rProp, + uno::makeAny( + pProvider->queryStorageClone( rContentId ) ) ); + else + xRow->appendVoid( rProp ); + } + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "DocumentModel" ) ) ) + { + // DocumentModel is only supported by documents. + ContentType eType = rData.getType(); + if ( eType == DOCUMENT ) + xRow->appendObject( + rProp, + uno::makeAny( + pProvider->queryDocumentModel( rContentId ) ) ); + else + xRow->appendVoid( rProp ); + } + else + { + // Not a Core Property! Maybe it's an Additional Core Property?! + + if ( !bTriedToGetAdditonalPropSet && !xAdditionalPropSet.is() ) + { + xAdditionalPropSet + = uno::Reference< beans::XPropertySet >( + pProvider->getAdditionalPropertySet( rContentId, + sal_False ), + uno::UNO_QUERY ); + bTriedToGetAdditonalPropSet = sal_True; + } + + if ( xAdditionalPropSet.is() ) + { + if ( !xRow->appendPropertySetValue( + xAdditionalPropSet, + rProp ) ) + { + // Append empty entry. + xRow->appendVoid( rProp ); + } + } + else + { + // Append empty entry. + xRow->appendVoid( rProp ); + } + } + } + } + else + { + // Append all Core Properties. + xRow->appendString ( + beans::Property( rtl::OUString::createFromAscii( "ContentType" ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ), + rData.getContentType() ); + + ContentType eType = rData.getType(); + + xRow->appendString ( + beans::Property( rtl::OUString::createFromAscii( "Title" ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + // Title is read-only for root and documents. + beans::PropertyAttribute::BOUND || + ( ( eType == ROOT ) || ( eType == DOCUMENT ) ) + ? beans::PropertyAttribute::READONLY + : 0 ), + rData.getTitle() ); + xRow->appendBoolean( + beans::Property( rtl::OUString::createFromAscii( "IsDocument" ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ), + rData.getIsDocument() ); + xRow->appendBoolean( + beans::Property( rtl::OUString::createFromAscii( "IsFolder" ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ), + rData.getIsFolder() ); + xRow->appendObject( + beans::Property( + rtl::OUString::createFromAscii( "CreatableContentsInfo" ), + -1, + getCppuType( static_cast< + const uno::Sequence< ucb::ContentInfo > * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ), + uno::makeAny( rData.getCreatableContentsInfo() ) ); + + // Storage is only supported by folders. + if ( eType == FOLDER ) + xRow->appendObject( + beans::Property( rtl::OUString::createFromAscii( "Storage" ), + -1, + getCppuType( + static_cast< + const uno::Reference< embed::XStorage > * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ), + uno::makeAny( pProvider->queryStorageClone( rContentId ) ) ); + + // DocumentModel is only supported by documents. + if ( eType == DOCUMENT ) + xRow->appendObject( + beans::Property( rtl::OUString::createFromAscii( "DocumentModel" ), + -1, + getCppuType( + static_cast< + const uno::Reference< frame::XModel > * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ), + uno::makeAny( + pProvider->queryDocumentModel( rContentId ) ) ); + + // Append all Additional Core Properties. + + uno::Reference< beans::XPropertySet > xSet( + pProvider->getAdditionalPropertySet( rContentId, sal_False ), + uno::UNO_QUERY ); + xRow->appendPropertySet( xSet ); + } + + return uno::Reference< sdbc::XRow >( xRow.get() ); +} + +//========================================================================= +uno::Reference< sdbc::XRow > Content::getPropertyValues( + const uno::Sequence< beans::Property >& rProperties ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + return getPropertyValues( m_xSMgr, + rProperties, + m_aProps, + m_pProvider, + m_xIdentifier->getContentIdentifier() ); +} + +//========================================================================= +uno::Sequence< uno::Any > Content::setPropertyValues( + const uno::Sequence< beans::PropertyValue >& rValues, + const uno::Reference< ucb::XCommandEnvironment > & xEnv ) + throw( uno::Exception ) +{ + osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); + + uno::Sequence< uno::Any > aRet( rValues.getLength() ); + uno::Sequence< beans::PropertyChangeEvent > aChanges( rValues.getLength() ); + sal_Int32 nChanged = 0; + + beans::PropertyChangeEvent aEvent; + aEvent.Source = static_cast< cppu::OWeakObject * >( this ); + aEvent.Further = sal_False; + // aEvent.PropertyName = + aEvent.PropertyHandle = -1; + // aEvent.OldValue = + // aEvent.NewValue = + + const beans::PropertyValue* pValues = rValues.getConstArray(); + sal_Int32 nCount = rValues.getLength(); + + uno::Reference< ucb::XPersistentPropertySet > xAdditionalPropSet; + sal_Bool bTriedToGetAdditonalPropSet = sal_False; + + sal_Bool bExchange = sal_False; + rtl::OUString aOldTitle; + sal_Int32 nTitlePos = -1; + + for ( sal_Int32 n = 0; n < nCount; ++n ) + { + const beans::PropertyValue& rValue = pValues[ n ]; + + if ( rValue.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) ) + { + // Read-only property! + aRet[ n ] <<= lang::IllegalAccessException( + rtl::OUString::createFromAscii( + "Property is read-only!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + else if ( rValue.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) ) + { + // Read-only property! + aRet[ n ] <<= lang::IllegalAccessException( + rtl::OUString::createFromAscii( + "Property is read-only!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + else if ( rValue.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) ) + { + // Read-only property! + aRet[ n ] <<= lang::IllegalAccessException( + rtl::OUString::createFromAscii( + "Property is read-only!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + else if ( rValue.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "CreatableContentsInfo" ) ) ) + { + // Read-only property! + aRet[ n ] <<= lang::IllegalAccessException( + rtl::OUString::createFromAscii( + "Property is read-only!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + else if ( rValue.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "Title" ) ) ) + { + // Title is read-only for root and documents. + ContentType eType = m_aProps.getType(); + if ( ( eType == ROOT ) || ( eType == DOCUMENT ) ) + { + aRet[ n ] <<= lang::IllegalAccessException( + rtl::OUString::createFromAscii( + "Property is read-only!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + else + { + rtl::OUString aNewValue; + if ( rValue.Value >>= aNewValue ) + { + // No empty titles! + if ( aNewValue.getLength() > 0 ) + { + if ( aNewValue != m_aProps.getTitle() ) + { + // modified title -> modified URL -> exchange ! + if ( m_eState == PERSISTENT ) + bExchange = sal_True; + + aOldTitle = m_aProps.getTitle(); + m_aProps.setTitle( aNewValue ); + + // property change event will be sent later... + + // remember position within sequence of values + // (for error handling). + nTitlePos = n; + } + } + else + { + aRet[ n ] <<= lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Empty Title not allowed!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ); + } + } + else + { + aRet[ n ] <<= beans::IllegalTypeException( + rtl::OUString::createFromAscii( + "Title Property value has wrong type!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + } + } + else if ( rValue.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "Storage" ) ) ) + { + ContentType eType = m_aProps.getType(); + if ( eType == FOLDER ) + { + aRet[ n ] <<= lang::IllegalAccessException( + rtl::OUString::createFromAscii( + "Property is read-only!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + else + { + // Storage is only supported by folders. + aRet[ n ] <<= beans::UnknownPropertyException( + rtl::OUString::createFromAscii( + "Storage property only supported by folders" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + } + else if ( rValue.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "DocumentModel" ) ) ) + { + ContentType eType = m_aProps.getType(); + if ( eType == DOCUMENT ) + { + aRet[ n ] <<= lang::IllegalAccessException( + rtl::OUString::createFromAscii( + "Property is read-only!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + else + { + // Storage is only supported by folders. + aRet[ n ] <<= beans::UnknownPropertyException( + rtl::OUString::createFromAscii( + "DocumentModel property only supported by " + "documents" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + } + else + { + // Not a Core Property! Maybe it's an Additional Core Property?! + + if ( !bTriedToGetAdditonalPropSet && !xAdditionalPropSet.is() ) + { + xAdditionalPropSet = getAdditionalPropertySet( sal_False ); + bTriedToGetAdditonalPropSet = sal_True; + } + + if ( xAdditionalPropSet.is() ) + { + try + { + uno::Any aOldValue = xAdditionalPropSet->getPropertyValue( + rValue.Name ); + if ( aOldValue != rValue.Value ) + { + xAdditionalPropSet->setPropertyValue( + rValue.Name, rValue.Value ); + + aEvent.PropertyName = rValue.Name; + aEvent.OldValue = aOldValue; + aEvent.NewValue = rValue.Value; + + aChanges.getArray()[ nChanged ] = aEvent; + nChanged++; + } + } + catch ( beans::UnknownPropertyException const & e ) + { + aRet[ n ] <<= e; + } + catch ( lang::WrappedTargetException const & e ) + { + aRet[ n ] <<= e; + } + catch ( beans::PropertyVetoException const & e ) + { + aRet[ n ] <<= e; + } + catch ( lang::IllegalArgumentException const & e ) + { + aRet[ n ] <<= e; + } + } + else + { + aRet[ n ] <<= uno::Exception( + rtl::OUString::createFromAscii( + "No property set for storing the value!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + } + } + + if ( bExchange ) + { + uno::Reference< ucb::XContentIdentifier > xOldId + = m_xIdentifier; + uno::Reference< ucb::XContentIdentifier > xNewId + = makeNewIdentifier( m_aProps.getTitle() ); + + aGuard.clear(); + if ( exchangeIdentity( xNewId ) ) + { + // Adapt persistent data. + renameData( xOldId, xNewId ); + + // Adapt Additional Core Properties. + renameAdditionalPropertySet( xOldId->getContentIdentifier(), + xNewId->getContentIdentifier(), + sal_True ); + } + else + { + // Roll-back. + m_aProps.setTitle( aOldTitle ); + aOldTitle = rtl::OUString(); + + // Set error . + aRet[ nTitlePos ] <<= uno::Exception( + rtl::OUString::createFromAscii( "Exchange failed!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + } + + if ( aOldTitle.getLength() ) + { + aEvent.PropertyName = rtl::OUString::createFromAscii( "Title" ); + aEvent.OldValue = uno::makeAny( aOldTitle ); + aEvent.NewValue = uno::makeAny( m_aProps.getTitle() ); + + aChanges.getArray()[ nChanged ] = aEvent; + nChanged++; + } + + if ( nChanged > 0 ) + { + // Save changes, if content was already made persistent. + if ( !bExchange && ( m_eState == PERSISTENT ) ) + { + if ( !storeData( uno::Reference< io::XInputStream >(), xEnv ) ) + { + uno::Any aProps + = uno::makeAny( + beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Uri")), + -1, + uno::makeAny(m_xIdentifier-> + getContentIdentifier()), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_WRITE, + uno::Sequence< uno::Any >(&aProps, 1), + xEnv, + rtl::OUString::createFromAscii( + "Cannot store persistent data!" ), + this ); + // Unreachable + } + } + + aChanges.realloc( nChanged ); + + aGuard.clear(); + notifyPropertiesChange( aChanges ); + } + + return aRet; +} + +//========================================================================= +uno::Any Content::open( + const ucb::OpenCommandArgument2& rArg, + const uno::Reference< ucb::XCommandEnvironment >& xEnv ) + throw( uno::Exception ) +{ + if ( rArg.Mode == ucb::OpenMode::ALL || + rArg.Mode == ucb::OpenMode::FOLDERS || + rArg.Mode == ucb::OpenMode::DOCUMENTS ) + { + ////////////////////////////////////////////////////////////////// + // open command for a folder content + ////////////////////////////////////////////////////////////////// + + uno::Reference< ucb::XDynamicResultSet > xSet + = new DynamicResultSet( m_xSMgr, this, rArg ); + return uno::makeAny( xSet ); + } + else + { + ////////////////////////////////////////////////////////////////// + // open command for a document content + ////////////////////////////////////////////////////////////////// + + if ( ( rArg.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_NONE ) || + ( rArg.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE ) ) + { + // Currently(?) unsupported. + ucbhelper::cancelCommandExecution( + uno::makeAny( ucb::UnsupportedOpenModeException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + sal_Int16( rArg.Mode ) ) ), + xEnv ); + // Unreachable + } + + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + rtl::OUString aURL = m_xIdentifier->getContentIdentifier(); + + uno::Reference< io::XActiveDataStreamer > xDataStreamer( + rArg.Sink, uno::UNO_QUERY ); + if ( xDataStreamer.is() ) + { + // May throw CommandFailedException, DocumentPasswordRequest! + uno::Reference< io::XStream > xStream = getStream( xEnv ); + if ( !xStream.is() ) + { + // No interaction if we are not persistent! + uno::Any aProps + = uno::makeAny( + beans::PropertyValue( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("Uri")), + -1, + uno::makeAny(m_xIdentifier-> + getContentIdentifier()), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_READ, + uno::Sequence< uno::Any >(&aProps, 1), + m_eState == PERSISTENT + ? xEnv + : uno::Reference< ucb::XCommandEnvironment >(), + rtl::OUString::createFromAscii( + "Got no data stream!" ), + this ); + // Unreachable + } + + // Done. + xDataStreamer->setStream( xStream ); + } + else + { + uno::Reference< io::XOutputStream > xOut( rArg.Sink, uno::UNO_QUERY ); + if ( xOut.is() ) + { + // PUSH: write data into xOut + + // May throw CommandFailedException, DocumentPasswordRequest! + uno::Reference< io::XInputStream > xIn = getInputStream( xEnv ); + if ( !xIn.is() ) + { + // No interaction if we are not persistent! + uno::Any aProps + = uno::makeAny( + beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Uri")), + -1, + uno::makeAny(m_xIdentifier-> + getContentIdentifier()), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_READ, + uno::Sequence< uno::Any >(&aProps, 1), + m_eState == PERSISTENT + ? xEnv + : uno::Reference< ucb::XCommandEnvironment >(), + rtl::OUString::createFromAscii( "Got no data stream!" ), + this ); + // Unreachable + } + + try + { + uno::Sequence< sal_Int8 > aBuffer; + sal_Int32 nRead = xIn->readSomeBytes( aBuffer, 65536 ); + + while ( nRead > 0 ) + { + aBuffer.realloc( nRead ); + xOut->writeBytes( aBuffer ); + aBuffer.realloc( 0 ); + nRead = xIn->readSomeBytes( aBuffer, 65536 ); + } + + xOut->closeOutput(); + } + catch ( io::NotConnectedException const & ) + { + // closeOutput, readSomeBytes, writeBytes + } + catch ( io::BufferSizeExceededException const & ) + { + // closeOutput, readSomeBytes, writeBytes + } + catch ( io::IOException const & ) + { + // closeOutput, readSomeBytes, writeBytes + } + } + else + { + uno::Reference< io::XActiveDataSink > xDataSink( + rArg.Sink, uno::UNO_QUERY ); + if ( xDataSink.is() ) + { + // PULL: wait for client read + + // May throw CommandFailedException, DocumentPasswordRequest! + uno::Reference< io::XInputStream > xIn = getInputStream( xEnv ); + if ( !xIn.is() ) + { + // No interaction if we are not persistent! + uno::Any aProps + = uno::makeAny( + beans::PropertyValue( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("Uri")), + -1, + uno::makeAny(m_xIdentifier-> + getContentIdentifier()), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_READ, + uno::Sequence< uno::Any >(&aProps, 1), + m_eState == PERSISTENT + ? xEnv + : uno::Reference< + ucb::XCommandEnvironment >(), + rtl::OUString::createFromAscii( + "Got no data stream!" ), + this ); + // Unreachable + } + + // Done. + xDataSink->setInputStream( xIn ); + } + else + { + ucbhelper::cancelCommandExecution( + uno::makeAny( + ucb::UnsupportedDataSinkException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + rArg.Sink ) ), + xEnv ); + // Unreachable + } + } + } + } + + return uno::Any(); +} + +//========================================================================= +void Content::insert( const uno::Reference< io::XInputStream >& xData, + sal_Int32 nNameClashResolve, + const uno::Reference< + ucb::XCommandEnvironment > & xEnv ) + throw( uno::Exception ) +{ + osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); + + ContentType eType = m_aProps.getType(); + + OSL_ENSURE( ( eType == FOLDER ) || ( eType == STREAM ), + "insert command only supported by streams and folders!" ); + + Uri aUri( m_xIdentifier->getContentIdentifier() ); + +#ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT +#if OSL_DEBUG_LEVEL > 0 + if ( eType == STREAM ) + { + Uri aParentUri( aUri.getParentUri() ); + OSL_ENSURE( !aParentUri.isDocument(), + "insert command not supported by streams that are direct " + "children of document root!" ); + } +#endif +#endif + + // Check, if all required properties were set. + if ( eType == FOLDER ) + { + // Required: Title + + if ( m_aProps.getTitle().getLength() == 0 ) + m_aProps.setTitle( aUri.getDecodedName() ); + } + else // stream + { + // Required: data + + if ( !xData.is() ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( ucb::MissingInputStreamException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ) ) ), + xEnv ); + // Unreachable + } + + // Required: Title + + if ( m_aProps.getTitle().getLength() == 0 ) + m_aProps.setTitle( aUri.getDecodedName() ); + } + + rtl::OUStringBuffer aNewURL = aUri.getParentUri(); + aNewURL.append( m_aProps.getTitle() ); + Uri aNewUri( aNewURL.makeStringAndClear() ); + + // Handle possible name clash... + switch ( nNameClashResolve ) + { + // fail. + case ucb::NameClash::ERROR: + if ( hasData( aNewUri ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( ucb::NameClashException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + task::InteractionClassification_ERROR, + m_aProps.getTitle() ) ), + xEnv ); + // Unreachable + } + break; + + // replace (possibly) existing object. + case ucb::NameClash::OVERWRITE: + break; + + // "invent" a new valid title. + case ucb::NameClash::RENAME: + if ( hasData( aNewUri ) ) + { + sal_Int32 nTry = 0; + + do + { + rtl::OUStringBuffer aNew = aNewUri.getUri(); + aNew.appendAscii( "_" ); + aNew.append( rtl::OUString::valueOf( ++nTry ) ); + aNewUri.setUri( aNew.makeStringAndClear() ); + } + while ( hasData( aNewUri ) && ( nTry < 1000 ) ); + + if ( nTry == 1000 ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( + ucb::UnsupportedNameClashException( + rtl::OUString::createFromAscii( + "Unable to resolve name clash!" ), + static_cast< cppu::OWeakObject * >( this ), + nNameClashResolve ) ), + xEnv ); + // Unreachable + } + else + { + rtl::OUStringBuffer aNewTitle = m_aProps.getTitle(); + aNewTitle.appendAscii( "_" ); + aNewTitle.append( rtl::OUString::valueOf( ++nTry ) ); + m_aProps.setTitle( aNewTitle.makeStringAndClear() ); + } + } + break; + + case ucb::NameClash::KEEP: // deprecated + case ucb::NameClash::ASK: + default: + if ( hasData( aNewUri ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( + ucb::UnsupportedNameClashException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + nNameClashResolve ) ), + xEnv ); + // Unreachable + } + break; + } + + // Identifier changed? + sal_Bool bNewId = ( aUri != aNewUri ); + + if ( bNewId ) + { + m_xIdentifier + = new ::ucbhelper::ContentIdentifier( m_xSMgr, aNewUri.getUri() ); + } + + if ( !storeData( xData, xEnv ) ) + { + uno::Any aProps + = uno::makeAny(beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Uri")), + -1, + uno::makeAny(m_xIdentifier-> + getContentIdentifier()), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_WRITE, + uno::Sequence< uno::Any >(&aProps, 1), + xEnv, + rtl::OUString::createFromAscii( "Cannot store persistent data!" ), + this ); + // Unreachable + } + + m_eState = PERSISTENT; + + if ( bNewId ) + { + //loadData( m_pProvider, m_aUri, m_aProps ); + + aGuard.clear(); + inserted(); + } +} + +//========================================================================= +void Content::destroy( sal_Bool bDeletePhysical, + const uno::Reference< + ucb::XCommandEnvironment > & xEnv ) + throw( uno::Exception ) +{ + // @@@ take care about bDeletePhysical -> trashcan support + + osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); + + ContentType eType = m_aProps.getType(); + + OSL_ENSURE( ( eType == FOLDER ) || ( eType == STREAM ), + "delete command only supported by streams and folders!" ); + + uno::Reference< ucb::XContent > xThis = this; + + // Persistent? + if ( m_eState != PERSISTENT ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( ucb::UnsupportedCommandException( + rtl::OUString::createFromAscii( + "Not persistent!" ), + static_cast< cppu::OWeakObject * >( this ) ) ), + xEnv ); + // Unreachable + } + + m_eState = DEAD; + + aGuard.clear(); + deleted(); + + if ( eType == FOLDER ) + { + // Process instanciated children... + + ContentRefList aChildren; + queryChildren( aChildren ); + + ContentRefList::const_iterator it = aChildren.begin(); + ContentRefList::const_iterator end = aChildren.end(); + + while ( it != end ) + { + (*it)->destroy( bDeletePhysical, xEnv ); + ++it; + } + } +} + +//========================================================================= +void Content::notifyDocumentClosed() +{ + osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); + + m_eState = DEAD; + + // @@@ anything else to reset or such? + + // callback follows! + aGuard.clear(); + + // Propagate destruction to content event listeners + // Remove this from provider's content list. + deleted(); +} + +//========================================================================= +uno::Reference< ucb::XContent > +Content::queryChildContent( const rtl::OUString & rRelativeChildUri ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + const rtl::OUString aMyId = getIdentifier()->getContentIdentifier(); + rtl::OUStringBuffer aBuf( aMyId ); + if ( aMyId.getStr()[ aMyId.getLength() - 1 ] != sal_Unicode( '/' ) ) + aBuf.appendAscii( "/" ); + if ( rRelativeChildUri.getStr()[ 0 ] != sal_Unicode( '/' ) ) + aBuf.append( rRelativeChildUri ); + else + aBuf.append( rRelativeChildUri.copy( 1 ) ); + + uno::Reference< ucb::XContentIdentifier > xChildId + = new ::ucbhelper::ContentIdentifier( + m_xSMgr, aBuf.makeStringAndClear() ); + + uno::Reference< ucb::XContent > xChild; + try + { + xChild = m_pProvider->queryContent( xChildId ); + } + catch ( ucb::IllegalIdentifierException const & ) + { + // handled below. + } + + OSL_ENSURE( xChild.is(), + "Content::queryChildContent - unable to create child content!" ); + return xChild; +} + +//========================================================================= +void Content::notifyChildRemoved( const rtl::OUString & rRelativeChildUri ) +{ + osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); + + // Ugly! Need to create child content object, just to fill event properly. + uno::Reference< ucb::XContent > xChild + = queryChildContent( rRelativeChildUri ); + + if ( xChild.is() ) + { + // callback follows! + aGuard.clear(); + + // Notify "REMOVED" event. + ucb::ContentEvent aEvt( + static_cast< cppu::OWeakObject * >( this ), + ucb::ContentAction::REMOVED, + xChild, + getIdentifier() ); + notifyContentEvent( aEvt ); + } +} + +//========================================================================= +void Content::notifyChildInserted( const rtl::OUString & rRelativeChildUri ) +{ + osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); + + // Ugly! Need to create child content object, just to fill event properly. + uno::Reference< ucb::XContent > xChild + = queryChildContent( rRelativeChildUri ); + + if ( xChild.is() ) + { + // callback follows! + aGuard.clear(); + + // Notify "INSERTED" event. + ucb::ContentEvent aEvt( + static_cast< cppu::OWeakObject * >( this ), + ucb::ContentAction::INSERTED, + xChild, + getIdentifier() ); + notifyContentEvent( aEvt ); + } +} + +//========================================================================= +void Content::transfer( + const ucb::TransferInfo& rInfo, + const uno::Reference< ucb::XCommandEnvironment > & xEnv ) + throw( uno::Exception ) +{ + osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); + + // Persistent? + if ( m_eState != PERSISTENT ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( ucb::UnsupportedCommandException( + rtl::OUString::createFromAscii( + "Not persistent!" ), + static_cast< cppu::OWeakObject * >( this ) ) ), + xEnv ); + // Unreachable + } + + // Does source URI scheme match? Only vnd.sun.star.tdoc is supported. + + if ( ( rInfo.SourceURL.getLength() < TDOC_URL_SCHEME_LENGTH + 2 ) ) + { + // Invaild length (to short). + ucbhelper::cancelCommandExecution( + uno::makeAny( ucb::InteractiveBadTransferURLException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ) ) ), + xEnv ); + // Unreachable + } + + rtl::OUString aScheme + = rInfo.SourceURL.copy( 0, TDOC_URL_SCHEME_LENGTH + 2 ) + .toAsciiLowerCase(); + if ( !aScheme.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( TDOC_URL_SCHEME ":/" ) ) ) + { + // Invalid scheme. + ucbhelper::cancelCommandExecution( + uno::makeAny( ucb::InteractiveBadTransferURLException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ) ) ), + xEnv ); + // Unreachable + } + + // Does source URI describe a tdoc folder or stream? + Uri aSourceUri( rInfo.SourceURL ); + if ( !aSourceUri.isValid() ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Invalid source URI! Syntax!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + xEnv ); + // Unreachable + } + + if ( aSourceUri.isRoot() || aSourceUri.isDocument() ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Invalid source URI! " + "Must describe a folder or stream!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + xEnv ); + // Unreachable + } + + // Is source not a parent of me / not me? + rtl::OUString aId = m_xIdentifier->getContentIdentifier(); + sal_Int32 nPos = aId.lastIndexOf( '/' ); + if ( nPos != ( aId.getLength() - 1 ) ) + { + // No trailing slash found. Append. + aId += rtl::OUString::createFromAscii( "/" ); + } + + if ( rInfo.SourceURL.getLength() <= aId.getLength() ) + { + if ( aId.compareTo( + rInfo.SourceURL, rInfo.SourceURL.getLength() ) == 0 ) + { + uno::Any aProps + = uno::makeAny(beans::PropertyValue( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("Uri")), + -1, + uno::makeAny( rInfo.SourceURL ), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_RECURSIVE, + uno::Sequence< uno::Any >(&aProps, 1), + xEnv, + rtl::OUString::createFromAscii( + "Target is equal to or is a child of source!" ), + this ); + // Unreachable + } + } + +#ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT + if ( m_aProps.getType() == DOCUMENT ) + { + bool bOK = false; + + uno::Reference< embed::XStorage > xStorage + = m_pProvider->queryStorage( + aSourceUri.getParentUri(), READ_WRITE_NOCREATE ); + if ( xStorage.is() ) + { + try + { + if ( xStorage->isStreamElement( aSourceUri.getDecodedName() ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Invalid source URI! " + "Streams cannot be created as " + "children of document root!" ), + static_cast< cppu::OWeakObject * >( + this ), + -1 ) ), + xEnv ); + // Unreachable + } + bOK = true; + } + catch ( container::NoSuchElementException const & ) + { + // handled below. + } + catch ( lang::IllegalArgumentException const & ) + { + // handled below. + } + catch ( embed::InvalidStorageException const & ) + { + // handled below. + } + } + + if ( !bOK ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Invalid source URI! " + "Unabale to determine source type!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + xEnv ); + // Unreachable + } + } +#endif + + ///////////////////////////////////////////////////////////////////////// + // Copy data. + ///////////////////////////////////////////////////////////////////////// + + rtl::OUString aNewName( rInfo.NewTitle.getLength() > 0 + ? rInfo.NewTitle + : aSourceUri.getDecodedName() ); + + if ( !copyData( aSourceUri, aNewName ) ) + { + uno::Any aProps + = uno::makeAny( + beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Uri")), + -1, + uno::makeAny( rInfo.SourceURL ), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_WRITE, + uno::Sequence< uno::Any >(&aProps, 1), + xEnv, + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "Cannot copy data!" ) ), + this ); + // Unreachable + } + + ///////////////////////////////////////////////////////////////////////// + // Copy own and all children's Additional Core Properties. + ///////////////////////////////////////////////////////////////////////// + + rtl::OUString aTargetUri = m_xIdentifier->getContentIdentifier(); + if ( ( aTargetUri.lastIndexOf( '/' ) + 1 ) != aTargetUri.getLength() ) + aTargetUri += rtl::OUString::createFromAscii( "/" ); + + if ( rInfo.NewTitle.getLength() > 0 ) + aTargetUri += ::ucb_impl::urihelper::encodeSegment( rInfo.NewTitle ); + else + aTargetUri += aSourceUri.getName(); + + if ( !copyAdditionalPropertySet( + aSourceUri.getUri(), aTargetUri, sal_True ) ) + { + uno::Any aProps + = uno::makeAny( + beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Uri")), + -1, + uno::makeAny( rInfo.SourceURL ), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_WRITE, + uno::Sequence< uno::Any >(&aProps, 1), + xEnv, + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "Cannot copy additional properties!" ) ), + this ); + // Unreachable + } + + ///////////////////////////////////////////////////////////////////////// + // Propagate new content. + ///////////////////////////////////////////////////////////////////////// + + rtl::Reference< Content > xTarget; + try + { + uno::Reference< ucb::XContentIdentifier > xTargetId + = new ::ucbhelper::ContentIdentifier( m_xSMgr, aTargetUri ); + + // Note: The static cast is okay here, because its sure that + // m_xProvider is always the WebDAVContentProvider. + xTarget = static_cast< Content * >( + m_pProvider->queryContent( xTargetId ).get() ); + + } + catch ( ucb::IllegalIdentifierException const & ) + { + // queryContent + } + + if ( !xTarget.is() ) + { + uno::Any aProps + = uno::makeAny(beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Uri")), + -1, + uno::makeAny( aTargetUri ), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_READ, + uno::Sequence< uno::Any >(&aProps, 1), + xEnv, + rtl::OUString::createFromAscii( + "Cannot instanciate target object!" ), + this ); + // Unreachable + } + + // Announce transfered content in its new folder. + xTarget->inserted(); + + ///////////////////////////////////////////////////////////////////////// + // Remove source, if requested + ///////////////////////////////////////////////////////////////////////// + + if ( rInfo.MoveData ) + { + rtl::Reference< Content > xSource; + try + { + uno::Reference< ucb::XContentIdentifier > + xSourceId = new ::ucbhelper::ContentIdentifier( + m_xSMgr, rInfo.SourceURL ); + + // Note: The static cast is okay here, because its sure + // that m_xProvider is always the ContentProvider. + xSource = static_cast< Content * >( + m_xProvider->queryContent( xSourceId ).get() ); + } + catch ( ucb::IllegalIdentifierException const & ) + { + // queryContent + } + + if ( !xSource.is() ) + { + uno::Any aProps + = uno::makeAny(beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Uri")), + -1, + uno::makeAny( rInfo.SourceURL ), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_READ, + uno::Sequence< uno::Any >(&aProps, 1), + xEnv, + rtl::OUString::createFromAscii( + "Cannot instanciate target object!" ), + this ); + // Unreachable + } + + // Propagate destruction (recursively). + xSource->destroy( sal_True, xEnv ); + + // Remove all persistent data of source and its children. + if ( !xSource->removeData() ) + { + uno::Any aProps + = uno::makeAny( + beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Uri")), + -1, + uno::makeAny( rInfo.SourceURL ), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_WRITE, + uno::Sequence< uno::Any >(&aProps, 1), + xEnv, + rtl::OUString::createFromAscii( + "Cannot remove persistent data of source object!" ), + this ); + // Unreachable + } + + // Remove own and all children's Additional Core Properties. + if ( !xSource->removeAdditionalPropertySet( sal_True ) ) + { + uno::Any aProps + = uno::makeAny( + beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Uri")), + -1, + uno::makeAny( rInfo.SourceURL ), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_WRITE, + uno::Sequence< uno::Any >(&aProps, 1), + xEnv, + rtl::OUString::createFromAscii( + "Cannot remove additional properties of source object!" ), + this ); + // Unreachable + } + + } // rInfo.MoveData +} + +//========================================================================= +//static +bool Content::hasData( ContentProvider* pProvider, const Uri & rUri ) +{ + if ( rUri.isRoot() ) + { + return true; // root has no storage + } + else if ( rUri.isDocument() ) + { + uno::Reference< embed::XStorage > xStorage + = pProvider->queryStorage( rUri.getUri(), READ ); + return xStorage.is(); + } + else + { + // folder or stream + + // Ask parent storage. In case that rUri describes a stream, + // ContentProvider::queryStorage( rUri ) would return null. + + uno::Reference< embed::XStorage > xStorage + = pProvider->queryStorage( rUri.getParentUri(), READ ); + + if ( !xStorage.is() ) + return false; + + uno::Reference< container::XNameAccess > xParentNA( + xStorage, uno::UNO_QUERY ); + + OSL_ENSURE( xParentNA.is(), "Got no css.container.XNameAccess!" ); + + return xParentNA->hasByName( rUri.getDecodedName() ); + } +} + +//========================================================================= +//static +bool Content::loadData( ContentProvider* pProvider, + const Uri & rUri, + ContentProperties& rProps ) +{ + if ( rUri.isRoot() ) // root has no storage, but can always be created + { + rProps + = ContentProperties( + ROOT, pProvider->queryStorageTitle( rUri.getUri() ) ); + } + else if ( rUri.isDocument() ) // document must have storage + { + uno::Reference< embed::XStorage > xStorage + = pProvider->queryStorage( rUri.getUri(), READ ); + + if ( !xStorage.is() ) + return false; + + rProps + = ContentProperties( + DOCUMENT, pProvider->queryStorageTitle( rUri.getUri() ) ); + } + else // stream or folder; stream has no storage; folder has storage + { + uno::Reference< embed::XStorage > xStorage + = pProvider->queryStorage( rUri.getParentUri(), READ ); + + if ( !xStorage.is() ) + return false; + + // Check whether exists at all, is stream or folder + try + { + // return: true -> folder + // return: false -> stream + // NoSuchElementException -> neither folder nor stream + bool bIsFolder + = xStorage->isStorageElement( rUri.getDecodedName() ); + + rProps + = ContentProperties( + bIsFolder ? FOLDER : STREAM, + pProvider->queryStorageTitle( rUri.getUri() ) ); + } + catch ( container::NoSuchElementException const & ) + { + // there is no element with such name + //OSL_ENSURE( false, "Caught NoSuchElementException!" ); + return false; + } + catch ( lang::IllegalArgumentException const & ) + { + // an illegal argument is provided + OSL_ENSURE( false, "Caught IllegalArgumentException!" ); + return false; + } + catch ( embed::InvalidStorageException const & ) + { + // this storage is in invalid state for any reason + OSL_ENSURE( false, "Caught InvalidStorageException!" ); + return false; + } + } + return true; +} + +//========================================================================= +bool Content::storeData( const uno::Reference< io::XInputStream >& xData, + const uno::Reference< + ucb::XCommandEnvironment >& xEnv ) + throw ( ucb::CommandFailedException, + task::DocumentPasswordRequest ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + ContentType eType = m_aProps.getType(); + if ( ( eType == ROOT ) || ( eType == DOCUMENT ) ) + { + OSL_ENSURE( false, "storeData not supported by root and documents!" ); + return false; + } + + Uri aUri( m_xIdentifier->getContentIdentifier() ); + + if ( eType == FOLDER ) + { + uno::Reference< embed::XStorage > xStorage + = m_pProvider->queryStorage( aUri.getUri(), READ_WRITE_CREATE ); + + if ( !xStorage.is() ) + return false; + + uno::Reference< beans::XPropertySet > xPropSet( + xStorage, uno::UNO_QUERY ); + OSL_ENSURE( xPropSet.is(), + "Content::storeData - Got no XPropertySet interface!" ); + if ( !xPropSet.is() ) + return false; + + try + { + // According to MBA, if no mediatype is set, folder and all + // its contents will be lost on save of the document!!! + xPropSet->setPropertyValue( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ), + uno::makeAny( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + // @@@ better mediatype + "application/binary" ) ) ) ); + } + catch ( beans::UnknownPropertyException const & ) + { + OSL_ENSURE( false, "Property MediaType not supported!" ); + return false; + } + catch ( beans::PropertyVetoException const & ) + { + OSL_ENSURE( false, "Caught PropertyVetoException!" ); + return false; + } + catch ( lang::IllegalArgumentException const & ) + { + OSL_ENSURE( false, "Caught IllegalArgumentException!" ); + return false; + } + catch ( lang::WrappedTargetException const & ) + { + OSL_ENSURE( false, "Caught WrappedTargetException!" ); + return false; + } + + if ( !commitStorage( xStorage ) ) + return false; + } + else if ( eType == STREAM ) + { + // stream + + // Important: Parent storage and output stream must be kept alive until + // changes have been committed! + uno::Reference< embed::XStorage > xStorage + = m_pProvider->queryStorage( + aUri.getParentUri(), READ_WRITE_CREATE ); + uno::Reference< io::XOutputStream > xOut; + + if ( !xStorage.is() ) + return false; + + if ( xData.is() ) + { + // May throw CommandFailedException, DocumentPasswordRequest! + xOut = getTruncatedOutputStream( xEnv ); + + OSL_ENSURE( xOut.is(), "No target data stream!" ); + + try + { + uno::Sequence< sal_Int8 > aBuffer; + sal_Int32 nRead = xData->readSomeBytes( aBuffer, 65536 ); + + while ( nRead > 0 ) + { + aBuffer.realloc( nRead ); + xOut->writeBytes( aBuffer ); + aBuffer.realloc( 0 ); + nRead = xData->readSomeBytes( aBuffer, 65536 ); + } + + closeOutputStream( xOut ); + } + catch ( io::NotConnectedException const & ) + { + // readSomeBytes, writeBytes + OSL_ENSURE( false, "Caught NotConnectedException!" ); + closeOutputStream( xOut ); + return false; + } + catch ( io::BufferSizeExceededException const & ) + { + // readSomeBytes, writeBytes + OSL_ENSURE( false, "Caught BufferSizeExceededException!" ); + closeOutputStream( xOut ); + return false; + } + catch ( io::IOException const & ) + { + // readSomeBytes, writeBytes + OSL_ENSURE( false, "Caught IOException!" ); + closeOutputStream( xOut ); + return false; + } + catch ( ... ) + { + closeOutputStream( xOut ); + throw; + } + } + + // Commit changes. + if ( !commitStorage( xStorage ) ) + return false; + } + else + { + OSL_ENSURE( false, "Unknown content type!" ); + return false; + } + return true; +} + +//========================================================================= +bool Content::renameData( + const uno::Reference< ucb::XContentIdentifier >& xOldId, + const uno::Reference< ucb::XContentIdentifier >& xNewId ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + ContentType eType = m_aProps.getType(); + if ( ( eType == ROOT ) || ( eType == DOCUMENT ) ) + { + OSL_ENSURE( false, "renameData not supported by root and documents!" ); + return false; + } + + Uri aOldUri( xOldId->getContentIdentifier() ); + uno::Reference< embed::XStorage > xStorage + = m_pProvider->queryStorage( + aOldUri.getParentUri(), READ_WRITE_NOCREATE ); + + if ( !xStorage.is() ) + return false; + + try + { + Uri aNewUri( xNewId->getContentIdentifier() ); + xStorage->renameElement( + aOldUri.getDecodedName(), aNewUri.getDecodedName() ); + } + catch ( embed::InvalidStorageException const & ) + { + // this storage is in invalid state for eny reason + OSL_ENSURE( false, "Caught InvalidStorageException!" ); + return false; + } + catch ( lang::IllegalArgumentException const & ) + { + // an illegal argument is provided + OSL_ENSURE( false, "Caught IllegalArgumentException!" ); + return false; + } + catch ( container::NoSuchElementException const & ) + { + // there is no element with old name in this storage + OSL_ENSURE( false, "Caught NoSuchElementException!" ); + return false; + } + catch ( container::ElementExistException const & ) + { + // an element with new name already exists in this storage + OSL_ENSURE( false, "Caught ElementExistException!" ); + return false; + } + catch ( io::IOException const & ) + { + // in case of io errors during renaming + OSL_ENSURE( false, "Caught IOException!" ); + return false; + } + catch ( embed::StorageWrappedTargetException const & ) + { + // wraps other exceptions + OSL_ENSURE( false, "Caught StorageWrappedTargetException!" ); + return false; + } + + return commitStorage( xStorage ); +} + +//========================================================================= +bool Content::removeData() +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + ContentType eType = m_aProps.getType(); + if ( ( eType == ROOT ) || ( eType == DOCUMENT ) ) + { + OSL_ENSURE( false, "removeData not supported by root and documents!" ); + return false; + } + + Uri aUri( m_xIdentifier->getContentIdentifier() ); + uno::Reference< embed::XStorage > xStorage + = m_pProvider->queryStorage( + aUri.getParentUri(), READ_WRITE_NOCREATE ); + + if ( !xStorage.is() ) + return false; + + try + { + xStorage->removeElement( aUri.getDecodedName() ); + } + catch ( embed::InvalidStorageException const & ) + { + // this storage is in invalid state for eny reason + OSL_ENSURE( false, "Caught InvalidStorageException!" ); + return false; + } + catch ( lang::IllegalArgumentException const & ) + { + // an illegal argument is provided + OSL_ENSURE( false, "Caught IllegalArgumentException!" ); + return false; + } + catch ( container::NoSuchElementException const & ) + { + // there is no element with this name in this storage + OSL_ENSURE( false, "Caught NoSuchElementException!" ); + return false; + } + catch ( io::IOException const & ) + { + // in case of io errors during renaming + OSL_ENSURE( false, "Caught IOException!" ); + return false; + } + catch ( embed::StorageWrappedTargetException const & ) + { + // wraps other exceptions + OSL_ENSURE( false, "Caught StorageWrappedTargetException!" ); + return false; + } + + return commitStorage( xStorage ); +} + +//========================================================================= +bool Content::copyData( const Uri & rSourceUri, const rtl::OUString & rNewName ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + ContentType eType = m_aProps.getType(); + if ( ( eType == ROOT ) || ( eType == STREAM ) ) + { + OSL_ENSURE( false, "copyData not supported by root and streams!" ); + return false; + } + + Uri aDestUri( m_xIdentifier->getContentIdentifier() ); + uno::Reference< embed::XStorage > xDestStorage + = m_pProvider->queryStorage( aDestUri.getUri(), READ_WRITE_NOCREATE ); + + if ( !xDestStorage.is() ) + return false; + + uno::Reference< embed::XStorage > xSourceStorage + = m_pProvider->queryStorage( rSourceUri.getParentUri(), READ ); + + if ( !xSourceStorage.is() ) + return false; + + try + { + xSourceStorage->copyElementTo( rSourceUri.getDecodedName(), + xDestStorage, + rNewName ); + } + catch ( embed::InvalidStorageException const & ) + { + // this storage is in invalid state for eny reason + OSL_ENSURE( false, "Caught InvalidStorageException!" ); + return false; + } + catch ( lang::IllegalArgumentException const & ) + { + // an illegal argument is provided + OSL_ENSURE( false, "Caught IllegalArgumentException!" ); + return false; + } + catch ( container::NoSuchElementException const & ) + { + // there is no element with this name in this storage + OSL_ENSURE( false, "Caught NoSuchElementException!" ); + return false; + } + catch ( container::ElementExistException const & ) + { + // there is no element with this name in this storage + OSL_ENSURE( false, "Caught ElementExistException!" ); + return false; + } + catch ( io::IOException const & ) + { + // in case of io errors during renaming + OSL_ENSURE( false, "Caught IOException!" ); + return false; + } + catch ( embed::StorageWrappedTargetException const & ) + { + // wraps other exceptions + OSL_ENSURE( false, "Caught StorageWrappedTargetException!" ); + return false; + } + + return commitStorage( xDestStorage ); +} + +//========================================================================= +// static +bool Content::commitStorage( const uno::Reference< embed::XStorage > & xStorage ) +{ + // Commit changes + uno::Reference< embed::XTransactedObject > xTO( xStorage, uno::UNO_QUERY ); + + OSL_ENSURE( xTO.is(), + "Required interface css.embed.XTransactedObject missing!" ); + try + { + xTO->commit(); + } + catch ( io::IOException const & ) + { + OSL_ENSURE( false, "Caught IOException!" ); + return false; + } + catch ( lang::WrappedTargetException const & ) + { + OSL_ENSURE( false, "Caught WrappedTargetException!" ); + return false; + } + + return true; +} + +//========================================================================= +// static +bool Content::closeOutputStream( + const uno::Reference< io::XOutputStream > & xOut ) +{ + if ( xOut.is() ) + { + try + { + xOut->closeOutput(); + return true; + } + catch ( io::NotConnectedException const & ) + { + OSL_ENSURE( false, "Caught NotConnectedException!" ); + } + catch ( io::BufferSizeExceededException const & ) + { + OSL_ENSURE( false, "Caught BufferSizeExceededException!" ); + } + catch ( io::IOException const & ) + { + OSL_ENSURE( false, "Caught IOException!" ); + } + } + return false; +} + +//========================================================================= +static rtl::OUString obtainPassword( + const rtl::OUString & rName, + task::PasswordRequestMode eMode, + const uno::Reference< ucb::XCommandEnvironment > & xEnv ) + throw ( ucb::CommandFailedException, + task::DocumentPasswordRequest ) +{ + rtl::Reference< DocumentPasswordRequest > xRequest + = new DocumentPasswordRequest( eMode, rName ); + + if ( xEnv.is() ) + { + uno::Reference< task::XInteractionHandler > xIH + = xEnv->getInteractionHandler(); + if ( xIH.is() ) + { + xIH->handle( xRequest.get() ); + + rtl::Reference< ucbhelper::InteractionContinuation > xSelection + = xRequest->getSelection(); + + if ( xSelection.is() ) + { + // Handler handled the request. + uno::Reference< task::XInteractionAbort > xAbort( + xSelection.get(), uno::UNO_QUERY ); + if ( xAbort.is() ) + { + throw ucb::CommandFailedException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "Abort requested by Interaction Handler." ) ), + uno::Reference< uno::XInterface >(), + xRequest->getRequest() ); + } + + uno::Reference< task::XInteractionPassword > xPassword( + xSelection.get(), uno::UNO_QUERY ); + if ( xPassword.is() ) + { + return xPassword->getPassword(); + } + + // Unknown selection. Should never happen. + throw ucb::CommandFailedException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "Interaction Handler selected unknown continuation!" ) ), + uno::Reference< uno::XInterface >(), + xRequest->getRequest() ); + } + } + } + + // No IH or IH did not handle exception. + task::DocumentPasswordRequest aRequest; + xRequest->getRequest() >>= aRequest; + throw aRequest; +} + +//========================================================================= +uno::Reference< io::XInputStream > Content::getInputStream( + const uno::Reference< ucb::XCommandEnvironment > & xEnv ) + throw ( ucb::CommandFailedException, + task::DocumentPasswordRequest ) +{ + rtl::OUString aUri; + rtl::OUString aPassword; + bool bPasswordRequested = false; + + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + OSL_ENSURE( m_aProps.getType() == STREAM, + "Content::getInputStream - content is no stream!" ); + + aUri = Uri( m_xIdentifier->getContentIdentifier() ).getUri(); + } + + for ( ;; ) + { + try + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + return uno::Reference< io::XInputStream >( + m_pProvider->queryInputStream( aUri, aPassword ) ); + } + catch ( packages::WrongPasswordException const & ) + { + // Obtain (new) password. + aPassword + = obtainPassword( aUri, /* @@@ find better title */ + bPasswordRequested + ? task::PasswordRequestMode_PASSWORD_REENTER + : task::PasswordRequestMode_PASSWORD_ENTER, + xEnv ); + bPasswordRequested = true; + } + } +} + +//========================================================================= +static uno::Reference< io::XOutputStream > lcl_getTruncatedOutputStream( + const rtl::OUString & rUri, + ContentProvider * pProvider, + const uno::Reference< ucb::XCommandEnvironment > & xEnv ) + throw ( ucb::CommandFailedException, + task::DocumentPasswordRequest ) +{ + rtl::OUString aPassword; + bool bPasswordRequested = false; + for ( ;; ) + { + try + { + return uno::Reference< io::XOutputStream >( + pProvider->queryOutputStream( + rUri, aPassword, true /* truncate */ ) ); + } + catch ( packages::WrongPasswordException const & ) + { + // Obtain (new) password. + aPassword + = obtainPassword( rUri, /* @@@ find better title */ + bPasswordRequested + ? task::PasswordRequestMode_PASSWORD_REENTER + : task::PasswordRequestMode_PASSWORD_ENTER, + xEnv ); + bPasswordRequested = true; + } + } +} + +//========================================================================= +uno::Reference< io::XOutputStream > Content::getTruncatedOutputStream( + const uno::Reference< ucb::XCommandEnvironment > & xEnv ) + throw ( ucb::CommandFailedException, + task::DocumentPasswordRequest ) +{ + OSL_ENSURE( m_aProps.getType() == STREAM, + "Content::getTruncatedOutputStream - content is no stream!" ); + + return lcl_getTruncatedOutputStream( + Uri( m_xIdentifier->getContentIdentifier() ).getUri(), + m_pProvider, + xEnv ); +} + +//========================================================================= +uno::Reference< io::XStream > Content::getStream( + const uno::Reference< ucb::XCommandEnvironment > & xEnv ) + throw ( ucb::CommandFailedException, + task::DocumentPasswordRequest ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + OSL_ENSURE( m_aProps.getType() == STREAM, + "Content::getStream - content is no stream!" ); + + rtl::OUString aUri( Uri( m_xIdentifier->getContentIdentifier() ).getUri() ); + rtl::OUString aPassword; + bool bPasswordRequested = false; + for ( ;; ) + { + try + { + return uno::Reference< io::XStream >( + m_pProvider->queryStream( + aUri, aPassword, false /* no truncate */ ) ); + } + catch ( packages::WrongPasswordException const & ) + { + // Obtain (new) password. + aPassword + = obtainPassword( aUri, /* @@@ find better title */ + bPasswordRequested + ? task::PasswordRequestMode_PASSWORD_REENTER + : task::PasswordRequestMode_PASSWORD_ENTER, + xEnv ); + bPasswordRequested = true; + } + } +} + +//========================================================================= +//========================================================================= +// +// ContentProperties Implementation. +// +//========================================================================= +//========================================================================= + +uno::Sequence< ucb::ContentInfo > +ContentProperties::getCreatableContentsInfo() const +{ + if ( isContentCreator() ) + { + uno::Sequence< beans::Property > aProps( 1 ); + aProps.getArray()[ 0 ] = beans::Property( + rtl::OUString::createFromAscii( "Title" ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND ); + +#ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT + if ( getType() == DOCUMENT ) + { + // streams cannot be created as direct children of document root + uno::Sequence< ucb::ContentInfo > aSeq( 1 ); + + // Folder. + aSeq.getArray()[ 0 ].Type + = rtl::OUString::createFromAscii( TDOC_FOLDER_CONTENT_TYPE ); + aSeq.getArray()[ 0 ].Attributes + = ucb::ContentInfoAttribute::KIND_FOLDER; + aSeq.getArray()[ 0 ].Properties = aProps; + + return aSeq; + } + else + { +#endif + uno::Sequence< ucb::ContentInfo > aSeq( 2 ); + + // Folder. + aSeq.getArray()[ 0 ].Type + = rtl::OUString::createFromAscii( TDOC_FOLDER_CONTENT_TYPE ); + aSeq.getArray()[ 0 ].Attributes + = ucb::ContentInfoAttribute::KIND_FOLDER; + aSeq.getArray()[ 0 ].Properties = aProps; + + // Stream. + aSeq.getArray()[ 1 ].Type + = rtl::OUString::createFromAscii( TDOC_STREAM_CONTENT_TYPE ); + aSeq.getArray()[ 1 ].Attributes + = ucb::ContentInfoAttribute::INSERT_WITH_INPUTSTREAM + | ucb::ContentInfoAttribute::KIND_DOCUMENT; + aSeq.getArray()[ 1 ].Properties = aProps; + + return aSeq; +#ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT + } +#endif + } + else + { + OSL_ENSURE( sal_False, + "getCreatableContentsInfo called on non-contentcreator " + "object!" ); + + return uno::Sequence< ucb::ContentInfo >( 0 ); + } +} + +//========================================================================= +bool ContentProperties::isContentCreator() const +{ + return ( getType() == FOLDER ) || ( getType() == DOCUMENT ); +} diff --git a/ucb/source/ucp/tdoc/tdoc_content.hxx b/ucb/source/ucp/tdoc/tdoc_content.hxx new file mode 100644 index 000000000000..b3a3270292be --- /dev/null +++ b/ucb/source/ucp/tdoc/tdoc_content.hxx @@ -0,0 +1,342 @@ +/************************************************************************* + * + * 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 INCLUDED_TDOC_CONTENT_HXX +#define INCLUDED_TDOC_CONTENT_HXX + +#include <ucbhelper/contenthelper.hxx> +#include <com/sun/star/task/DocumentPasswordRequest.hpp> +#include <com/sun/star/ucb/XContentCreator.hpp> +#include <com/sun/star/ucb/CommandFailedException.hpp> +#include "tdoc_provider.hxx" + +#define NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT 1 + +namespace com { namespace sun { namespace star { + namespace sdbc { class XRow; } + namespace io { class XInputStream; class XOutputStream; } + namespace beans { struct PropertyValue; } + namespace ucb { struct OpenCommandArgument2; struct TransferInfo; + struct ContentInfo; } +} } } + +namespace tdoc_ucp +{ + +//========================================================================= + +#define TDOC_ROOT_CONTENT_SERVICE_NAME \ + "com.sun.star.ucb.TransientDocumentsRootContent" +#define TDOC_DOCUMENT_CONTENT_SERVICE_NAME \ + "com.sun.star.ucb.TransientDocumentsDocumentContent" +#define TDOC_FOLDER_CONTENT_SERVICE_NAME \ + "com.sun.star.ucb.TransientDocumentsFolderContent" +#define TDOC_STREAM_CONTENT_SERVICE_NAME \ + "com.sun.star.ucb.TransientDocumentsStreamContent" + +//========================================================================= + +enum ContentType { STREAM, FOLDER, DOCUMENT, ROOT }; + +class ContentProperties +{ +public: + ContentProperties() + {} + + ContentProperties( const ContentType & rType, const rtl::OUString & rTitle ) + : m_eType( rType ), + m_aContentType( rType == STREAM + ? rtl::OUString::createFromAscii( TDOC_STREAM_CONTENT_TYPE ) + : rType == FOLDER + ? rtl::OUString::createFromAscii( TDOC_FOLDER_CONTENT_TYPE ) + : rType == DOCUMENT + ? rtl::OUString::createFromAscii( TDOC_DOCUMENT_CONTENT_TYPE ) + : rtl::OUString::createFromAscii( TDOC_ROOT_CONTENT_TYPE ) ), + m_aTitle( rTitle ) + {} + + ContentType getType() const { return m_eType; } + + // Properties + + const rtl::OUString & getContentType() const { return m_aContentType; } + + bool getIsFolder() const { return m_eType > STREAM; } + bool getIsDocument() const { return !getIsFolder(); } + + const rtl::OUString & getTitle() const { return m_aTitle; } + void setTitle( const rtl::OUString & rTitle ) { m_aTitle = rTitle; } + + com::sun::star::uno::Sequence< com::sun::star::ucb::ContentInfo > + getCreatableContentsInfo() const; + + bool isContentCreator() const; + +private: + ContentType m_eType; + rtl::OUString m_aContentType; + rtl::OUString m_aTitle; +}; + +//========================================================================= + +class Content : public ::ucbhelper::ContentImplHelper, + public com::sun::star::ucb::XContentCreator +{ + enum ContentState { TRANSIENT, // created via createNewContent, + // but did not process "insert" yet + PERSISTENT, // processed "insert" + DEAD // processed "delete" / document was closed + }; + + ContentProperties m_aProps; + ContentState m_eState; + ContentProvider* m_pProvider; + +private: + Content( const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + ContentProvider* pProvider, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& Identifier, + const ContentProperties & rProps ); + Content( const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + ContentProvider* pProvider, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& Identifier, + const com::sun::star::ucb::ContentInfo& Info ); + + virtual com::sun::star::uno::Sequence< com::sun::star::beans::Property > + getProperties( const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv ); + virtual com::sun::star::uno::Sequence< com::sun::star::ucb::CommandInfo > + getCommands( const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv ); + virtual ::rtl::OUString getParentURL(); + + static bool hasData( ContentProvider* pProvider, const Uri & rUri ); + bool hasData( const Uri & rUri ) { return hasData( m_pProvider, rUri ); } + + static bool loadData( ContentProvider* pProvider, + const Uri & rUri, + ContentProperties& rProps ); + bool storeData( const com::sun::star::uno::Reference< + com::sun::star::io::XInputStream >& xData, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment >& xEnv ) + throw ( ::com::sun::star::ucb::CommandFailedException, + ::com::sun::star::task::DocumentPasswordRequest ); + bool renameData( const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& xOldId, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& xNewId ); + bool removeData(); + + bool copyData( const Uri & rSourceUri, const rtl::OUString & rNewName ); + + ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XContentIdentifier > + makeNewIdentifier( const rtl::OUString& rTitle ); + + typedef rtl::Reference< Content > ContentRef; + typedef std::list< ContentRef > ContentRefList; + void queryChildren( ContentRefList& rChildren ); + + sal_Bool exchangeIdentity( + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XContentIdentifier >& xNewId ); + + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRow > + getPropertyValues( const ::com::sun::star::uno::Sequence< + ::com::sun::star::beans::Property >& rProperties ); + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > + setPropertyValues( + const ::com::sun::star::uno::Sequence< + ::com::sun::star::beans::PropertyValue >& rValues, + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw( ::com::sun::star::uno::Exception ); + + com::sun::star::uno::Any + open( const ::com::sun::star::ucb::OpenCommandArgument2& rArg, + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment >& xEnv ) + throw( ::com::sun::star::uno::Exception ); + + void insert( const ::com::sun::star::uno::Reference< + ::com::sun::star::io::XInputStream >& xData, + sal_Int32 nNameClashResolve, + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw( ::com::sun::star::uno::Exception ); + + void destroy( sal_Bool bDeletePhysical, + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw( ::com::sun::star::uno::Exception ); + + void transfer( const ::com::sun::star::ucb::TransferInfo& rInfo, + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw( ::com::sun::star::uno::Exception ); + + static ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRow > + getPropertyValues( const ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XMultiServiceFactory >& rSMgr, + const ::com::sun::star::uno::Sequence< + ::com::sun::star::beans::Property >& rProperties, + const ContentProperties& rData, + ContentProvider* pProvider, + const ::rtl::OUString& rContentId ); + + + static bool commitStorage( + const com::sun::star::uno::Reference< + com::sun::star::embed::XStorage > & xStorage ); + + static bool closeOutputStream( + const com::sun::star::uno::Reference< + com::sun::star::io::XOutputStream > & xOut ); + + ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > + getInputStream( const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment > & + xEnv ) + throw ( ::com::sun::star::ucb::CommandFailedException, + ::com::sun::star::task::DocumentPasswordRequest ); + + ::com::sun::star::uno::Reference< ::com::sun::star::io::XOutputStream > + getTruncatedOutputStream( + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw ( ::com::sun::star::ucb::CommandFailedException, + ::com::sun::star::task::DocumentPasswordRequest ); + + ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContent > + queryChildContent( const rtl::OUString & rRelativeChildUri ); + + ::com::sun::star::uno::Reference< ::com::sun::star::io::XStream > + getStream( const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw ( ::com::sun::star::ucb::CommandFailedException, + ::com::sun::star::task::DocumentPasswordRequest ); + +public: + // Create existing content. Fail, if not already exists. + static Content* create( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + ContentProvider* pProvider, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& Identifier ); + + // Create new content. Fail, if already exists. + static Content* create( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + ContentProvider* pProvider, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& Identifier, + const com::sun::star::ucb::ContentInfo& Info ); + + virtual ~Content(); + + // XInterface + XINTERFACE_DECL() + + // XTypeProvider + XTYPEPROVIDER_DECL() + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL + getImplementationName() + throw( ::com::sun::star::uno::RuntimeException ); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL + getSupportedServiceNames() + throw( ::com::sun::star::uno::RuntimeException ); + + // XContent + virtual rtl::OUString SAL_CALL + getContentType() + throw( com::sun::star::uno::RuntimeException ); + virtual com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier > SAL_CALL + getIdentifier() + throw( com::sun::star::uno::RuntimeException ); + + // XCommandProcessor + virtual com::sun::star::uno::Any SAL_CALL + execute( const com::sun::star::ucb::Command& aCommand, + sal_Int32 CommandId, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment >& Environment ) + throw( com::sun::star::uno::Exception, + com::sun::star::ucb::CommandAbortedException, + com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + abort( sal_Int32 CommandId ) + throw( com::sun::star::uno::RuntimeException ); + + ////////////////////////////////////////////////////////////////////// + // Additional interfaces + ////////////////////////////////////////////////////////////////////// + + // XContentCreator + virtual com::sun::star::uno::Sequence< + com::sun::star::ucb::ContentInfo > SAL_CALL + queryCreatableContentsInfo() + throw( com::sun::star::uno::RuntimeException ); + virtual com::sun::star::uno::Reference< + com::sun::star::ucb::XContent > SAL_CALL + createNewContent( const com::sun::star::ucb::ContentInfo& Info ) + throw( com::sun::star::uno::RuntimeException ); + + ////////////////////////////////////////////////////////////////////// + // Non-interface methods. + ////////////////////////////////////////////////////////////////////// + + static ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRow > + getPropertyValues( const ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XMultiServiceFactory >& rSMgr, + const ::com::sun::star::uno::Sequence< + ::com::sun::star::beans::Property >& rProperties, + ContentProvider* pProvider, + const ::rtl::OUString& rContentId ); + + void notifyDocumentClosed(); + void notifyChildRemoved( const rtl::OUString & rRelativeChildUri ); + void notifyChildInserted( const rtl::OUString & rRelativeChildUri ); + + rtl::Reference< ContentProvider > getContentProvider() const + { return rtl::Reference< ContentProvider >( m_pProvider ); } +}; + +} // namespace tdoc_ucp + +#endif /* !INCLUDED_TDOC_CONTENT_HXX */ diff --git a/ucb/source/ucp/tdoc/tdoc_contentcaps.cxx b/ucb/source/ucp/tdoc/tdoc_contentcaps.cxx new file mode 100644 index 000000000000..d8c89c351c89 --- /dev/null +++ b/ucb/source/ucp/tdoc/tdoc_contentcaps.cxx @@ -0,0 +1,705 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + ************************************************************************** + + Props/Commands: + + root document folder folder stream stream + (new) (new) + ---------------------------------------------------------------- + ContentType r r r r r r + IsDocument r r r r r r + IsFolder r r r r r r + Title r r w w w w + CreatableContentsInfo r r r r r r + Storage - - r r - - + DocumentModel - r - - - - + + getCommandInfo x x x x x x + getPropertySetInfo x x x x x x + getPropertyValues x x x x x x + setPropertyValues x x x x x x + insert - - x x x(*) x(*) + delete - - x - x - + open x x x - x - + transfer - x x - - - + createNewContent - x x - - - + +#ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT + (*) not supported by streams that are direct children of document +#endif + + *************************************************************************/ + +#include "com/sun/star/beans/Property.hpp" +#include "com/sun/star/beans/PropertyAttribute.hpp" +#include "com/sun/star/beans/PropertyValue.hpp" +#include "com/sun/star/embed/XStorage.hpp" +#include "com/sun/star/frame/XModel.hpp" +#include "com/sun/star/ucb/CommandInfo.hpp" +#include "com/sun/star/ucb/OpenCommandArgument2.hpp" +#include "com/sun/star/ucb/TransferInfo.hpp" + +#include "tdoc_content.hxx" + +namespace com { namespace sun { namespace star { namespace embed { + class XStorage; +} } } } + +using namespace com::sun::star; +using namespace tdoc_ucp; + +//========================================================================= +// +// Content implementation. +// +//========================================================================= + +#define MAKEPROPSEQUENCE( a ) \ + uno::Sequence< beans::Property >( a, sizeof( a ) / sizeof( a[ 0 ] ) ) + +#define MAKECMDSEQUENCE( a ) \ + uno::Sequence< ucb::CommandInfo >( a, sizeof( a ) / sizeof( a[ 0 ] ) ) + +//========================================================================= +// +// IMPORTENT: If any property data ( name / type / ... ) are changed, then +// Content::getPropertyValues(...) must be adapted too! +// +//========================================================================= + +// virtual +uno::Sequence< beans::Property > Content::getProperties( + const uno::Reference< ucb::XCommandEnvironment > & /*xEnv*/ ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + if ( m_aProps.getType() == STREAM ) + { + //================================================================= + // + // Stream: Supported properties + // + //================================================================= + + static const beans::Property aStreamPropertyInfoTable[] = + { + /////////////////////////////////////////////////////////// + // Mandatory properties + /////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "ContentType" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "IsDocument" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + ), + /////////////////////////////////////////////////////////// + // Optional standard properties + /////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "CreatableContentsInfo" ) ), + -1, + getCppuType( static_cast< + const uno::Sequence< ucb::ContentInfo > * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ) + /////////////////////////////////////////////////////////// + // New properties + /////////////////////////////////////////////////////////// + }; + return MAKEPROPSEQUENCE( aStreamPropertyInfoTable ); + } + else if ( m_aProps.getType() == FOLDER ) + { + //================================================================= + // + // Folder: Supported properties + // + //================================================================= + + static const beans::Property aFolderPropertyInfoTable[] = + { + /////////////////////////////////////////////////////////// + // Mandatory properties + /////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "ContentType" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "IsDocument" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + ), + /////////////////////////////////////////////////////////// + // Optional standard properties + /////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "CreatableContentsInfo" ) ), + -1, + getCppuType( static_cast< + const uno::Sequence< ucb::ContentInfo > * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + /////////////////////////////////////////////////////////// + // New properties + /////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Storage" ) ), + -1, + getCppuType( static_cast< + const uno::Reference< embed::XStorage > * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ) + }; + return MAKEPROPSEQUENCE( aFolderPropertyInfoTable ); + } + else if ( m_aProps.getType() == DOCUMENT ) + { + //================================================================= + // + // Document: Supported properties + // + //================================================================= + + static const beans::Property aDocPropertyInfoTable[] = + { + /////////////////////////////////////////////////////////// + // Mandatory properties + /////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "ContentType" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "IsDocument" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + /////////////////////////////////////////////////////////// + // Optional standard properties + /////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "CreatableContentsInfo" ) ), + -1, + getCppuType( static_cast< + const uno::Sequence< ucb::ContentInfo > * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + /////////////////////////////////////////////////////////// + // New properties + /////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DocumentModel" ) ), + -1, + getCppuType( static_cast< + const uno::Reference< frame::XModel > * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ) + }; + return MAKEPROPSEQUENCE( aDocPropertyInfoTable ); + } + else + { + //================================================================= + // + // Root: Supported properties + // + //================================================================= + + OSL_ENSURE( m_aProps.getType() == ROOT, "Wrong content type!" ); + + static const beans::Property aRootPropertyInfoTable[] = + { + /////////////////////////////////////////////////////////////// + // Mandatory properties + /////////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ContentType" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsDocument" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + /////////////////////////////////////////////////////////////// + // Optional standard properties + /////////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "CreatableContentsInfo" ) ), + -1, + getCppuType( static_cast< + const uno::Sequence< ucb::ContentInfo > * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ) + /////////////////////////////////////////////////////////////// + // New properties + /////////////////////////////////////////////////////////////// + }; + return MAKEPROPSEQUENCE( aRootPropertyInfoTable ); + } +} + +//========================================================================= +// virtual +uno::Sequence< ucb::CommandInfo > Content::getCommands( + const uno::Reference< ucb::XCommandEnvironment > & /*xEnv*/ ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + if ( m_aProps.getType() == STREAM ) + { +#ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT + Uri aUri( m_xIdentifier->getContentIdentifier() ); + Uri aParentUri( aUri.getParentUri() ); + + if ( aParentUri.isDocument() ) + { + //================================================================= + // + // Stream, that is a child of a document: Supported commands + // + //================================================================= + + static const ucb::CommandInfo aStreamCommandInfoTable1[] = + { + /////////////////////////////////////////////////////////// + // Mandatory commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getCommandInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertySetInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertyValues" ) ), + -1, + getCppuType( + static_cast< uno::Sequence< beans::Property > * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ), + -1, + getCppuType( + static_cast< + uno::Sequence< beans::PropertyValue > * >( 0 ) ) + ), + /////////////////////////////////////////////////////////// + // Optional standard commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "delete" ) ), + -1, + getCppuBooleanType() + ), + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "open" ) ), + -1, + getCppuType( + static_cast< ucb::OpenCommandArgument2 * >( 0 ) ) + ) + /////////////////////////////////////////////////////////// + // New commands + /////////////////////////////////////////////////////////// + }; + return MAKECMDSEQUENCE( aStreamCommandInfoTable1 ); + } +#endif + //================================================================= + // + // Stream: Supported commands + // + //================================================================= + + static const ucb::CommandInfo aStreamCommandInfoTable[] = + { + /////////////////////////////////////////////////////////// + // Mandatory commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getCommandInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertySetInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertyValues" ) ), + -1, + getCppuType( + static_cast< uno::Sequence< beans::Property > * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ), + -1, + getCppuType( + static_cast< + uno::Sequence< beans::PropertyValue > * >( 0 ) ) + ), + /////////////////////////////////////////////////////////// + // Optional standard commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "delete" ) ), + -1, + getCppuBooleanType() + ), + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "insert" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "open" ) ), + -1, + getCppuType( + static_cast< ucb::OpenCommandArgument2 * >( 0 ) ) + ) + /////////////////////////////////////////////////////////// + // New commands + /////////////////////////////////////////////////////////// + }; + return MAKECMDSEQUENCE( aStreamCommandInfoTable ); + } + else if ( m_aProps.getType() == FOLDER ) + { + //================================================================= + // + // Folder: Supported commands + // + //================================================================= + + static const ucb::CommandInfo aFolderCommandInfoTable[] = + { + /////////////////////////////////////////////////////////// + // Mandatory commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getCommandInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertySetInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertyValues" ) ), + -1, + getCppuType( + static_cast< uno::Sequence< beans::Property > * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ), + -1, + getCppuType( + static_cast< + uno::Sequence< beans::PropertyValue > * >( 0 ) ) + ), + /////////////////////////////////////////////////////////// + // Optional standard commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "delete" ) ), + -1, + getCppuBooleanType() + ), + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "insert" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "open" ) ), + -1, + getCppuType( + static_cast< ucb::OpenCommandArgument2 * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "transfer" ) ), + -1, + getCppuType( static_cast< ucb::TransferInfo * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "createNewContent" ) ), + -1, + getCppuType( static_cast< ucb::ContentInfo * >( 0 ) ) + ) + /////////////////////////////////////////////////////////// + // New commands + /////////////////////////////////////////////////////////// + }; + return MAKECMDSEQUENCE( aFolderCommandInfoTable ); + } + else if ( m_aProps.getType() == DOCUMENT ) + { + //================================================================= + // + // Document: Supported commands + // + //================================================================= + + static const ucb::CommandInfo aDocCommandInfoTable[] = + { + /////////////////////////////////////////////////////////// + // Mandatory commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getCommandInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertySetInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertyValues" ) ), + -1, + getCppuType( + static_cast< uno::Sequence< beans::Property > * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ), + -1, + getCppuType( + static_cast< + uno::Sequence< beans::PropertyValue > * >( 0 ) ) + ), + /////////////////////////////////////////////////////////// + // Optional standard commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "open" ) ), + -1, + getCppuType( + static_cast< ucb::OpenCommandArgument2 * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "transfer" ) ), + -1, + getCppuType( static_cast< ucb::TransferInfo * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "createNewContent" ) ), + -1, + getCppuType( static_cast< ucb::ContentInfo * >( 0 ) ) + ) + /////////////////////////////////////////////////////////// + // New commands + /////////////////////////////////////////////////////////// + }; + return MAKECMDSEQUENCE( aDocCommandInfoTable ); + } + else + { + //================================================================= + // + // Root: Supported commands + // + //================================================================= + + OSL_ENSURE( m_aProps.getType() == ROOT, "Wrong content type!" ); + + static const ucb::CommandInfo aRootCommandInfoTable[] = + { + /////////////////////////////////////////////////////////// + // Mandatory commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getCommandInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertySetInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertyValues" ) ), + -1, + getCppuType( + static_cast< uno::Sequence< beans::Property > * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ), + -1, + getCppuType( + static_cast< + uno::Sequence< beans::PropertyValue > * >( 0 ) ) + ), + /////////////////////////////////////////////////////////// + // Optional standard commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "open" ) ), + -1, + getCppuType( + static_cast< ucb::OpenCommandArgument2 * >( 0 ) ) + ) + /////////////////////////////////////////////////////////// + // New commands + /////////////////////////////////////////////////////////// + }; + return MAKECMDSEQUENCE( aRootCommandInfoTable ); + } +} diff --git a/ucb/source/ucp/tdoc/tdoc_datasupplier.cxx b/ucb/source/ucp/tdoc/tdoc_datasupplier.cxx new file mode 100644 index 000000000000..c9931c872b16 --- /dev/null +++ b/ucb/source/ucp/tdoc/tdoc_datasupplier.cxx @@ -0,0 +1,468 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ + +#include <vector> + +#include "osl/diagnose.h" +#include "ucbhelper/contentidentifier.hxx" + +#include "tdoc_datasupplier.hxx" +#include "tdoc_content.hxx" + +using namespace com::sun::star; +using namespace tdoc_ucp; + +namespace tdoc_ucp +{ + +//========================================================================= +// +// struct ResultListEntry. +// +//========================================================================= + +struct ResultListEntry +{ + rtl::OUString aURL; + uno::Reference< ucb::XContentIdentifier > xId; + uno::Reference< ucb::XContent > xContent; + uno::Reference< sdbc::XRow > xRow; + + ResultListEntry( const rtl::OUString& rURL ) : aURL( rURL ) {} +}; + +//========================================================================= +// +// ResultList. +// +//========================================================================= + +typedef std::vector< ResultListEntry* > ResultList; + +//========================================================================= +// +// struct DataSupplier_Impl. +// +//========================================================================= + +struct DataSupplier_Impl +{ + osl::Mutex m_aMutex; + ResultList m_aResults; + rtl::Reference< Content > m_xContent; + uno::Reference< lang::XMultiServiceFactory > m_xSMgr; + uno::Sequence< rtl::OUString > * m_pNamesOfChildren; + sal_Int32 m_nOpenMode; + bool m_bCountFinal; + bool m_bThrowException; + + DataSupplier_Impl( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + const rtl::Reference< Content >& rContent, + sal_Int32 nOpenMode ) + : m_xContent( rContent ), m_xSMgr( rxSMgr ), + m_pNamesOfChildren( 0 ), m_nOpenMode( nOpenMode ), + m_bCountFinal( false ), m_bThrowException( false ) + {} + ~DataSupplier_Impl(); +}; + +//========================================================================= +DataSupplier_Impl::~DataSupplier_Impl() +{ + ResultList::const_iterator it = m_aResults.begin(); + ResultList::const_iterator end = m_aResults.end(); + + while ( it != end ) + { + delete (*it); + it++; + } + + delete m_pNamesOfChildren; +} + +} + +//========================================================================= +//========================================================================= +// +// DataSupplier Implementation. +// +//========================================================================= +//========================================================================= + +ResultSetDataSupplier::ResultSetDataSupplier( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + const rtl::Reference< Content >& rContent, + sal_Int32 nOpenMode ) +: m_pImpl( new DataSupplier_Impl( rxSMgr, rContent, nOpenMode ) ) +{ +} + +//========================================================================= +// virtual +ResultSetDataSupplier::~ResultSetDataSupplier() +{ + delete m_pImpl; +} + +//========================================================================= +// virtual +rtl::OUString +ResultSetDataSupplier::queryContentIdentifierString( sal_uInt32 nIndex ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( nIndex < m_pImpl->m_aResults.size() ) + { + rtl::OUString aId = m_pImpl->m_aResults[ nIndex ]->aURL; + if ( aId.getLength() ) + { + // Already cached. + return aId; + } + } + + if ( getResult( nIndex ) ) + { + // Note: getResult fills m_pImpl->m_aResults[ nIndex ]->aURL. + return m_pImpl->m_aResults[ nIndex ]->aURL; + } + return rtl::OUString(); +} + +//========================================================================= +// virtual +uno::Reference< ucb::XContentIdentifier > +ResultSetDataSupplier::queryContentIdentifier( sal_uInt32 nIndex ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( nIndex < m_pImpl->m_aResults.size() ) + { + uno::Reference< ucb::XContentIdentifier > xId + = m_pImpl->m_aResults[ nIndex ]->xId; + if ( xId.is() ) + { + // Already cached. + return xId; + } + } + + rtl::OUString aId = queryContentIdentifierString( nIndex ); + if ( aId.getLength() ) + { + uno::Reference< ucb::XContentIdentifier > xId + = new ::ucbhelper::ContentIdentifier( aId ); + m_pImpl->m_aResults[ nIndex ]->xId = xId; + return xId; + } + return uno::Reference< ucb::XContentIdentifier >(); +} + +//========================================================================= +// virtual +uno::Reference< ucb::XContent > +ResultSetDataSupplier::queryContent( sal_uInt32 nIndex ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( nIndex < m_pImpl->m_aResults.size() ) + { + uno::Reference< ucb::XContent > xContent + = m_pImpl->m_aResults[ nIndex ]->xContent; + if ( xContent.is() ) + { + // Already cached. + return xContent; + } + } + + uno::Reference< ucb::XContentIdentifier > xId + = queryContentIdentifier( nIndex ); + if ( xId.is() ) + { + try + { + uno::Reference< ucb::XContent > xContent + = m_pImpl->m_xContent->getProvider()->queryContent( xId ); + m_pImpl->m_aResults[ nIndex ]->xContent = xContent; + return xContent; + + } + catch ( ucb::IllegalIdentifierException const & ) + { + } + } + return uno::Reference< ucb::XContent >(); +} + +//========================================================================= +// virtual +sal_Bool ResultSetDataSupplier::getResult( sal_uInt32 nIndex ) +{ + osl::ClearableGuard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( m_pImpl->m_aResults.size() > nIndex ) + { + // Result already present. + return sal_True; + } + + // Result not (yet) present. + + if ( m_pImpl->m_bCountFinal ) + return sal_False; + + // Try to obtain result... + + sal_uInt32 nOldCount = m_pImpl->m_aResults.size(); + bool bFound = false; + + if ( queryNamesOfChildren() ) + { + for ( sal_uInt32 n = nOldCount; + n < sal::static_int_cast<sal_uInt32>( + m_pImpl->m_pNamesOfChildren->getLength()); + ++n ) + { + const rtl::OUString & rName + = m_pImpl->m_pNamesOfChildren->getConstArray()[ n ]; + + if ( !rName.getLength() ) + { + OSL_ENSURE( sal_False, + "ResultDataSupplier::getResult - Empty name!" ); + break; + } + + // Assemble URL for child. + rtl::OUString aURL = assembleChildURL( rName ); + + m_pImpl->m_aResults.push_back( new ResultListEntry( aURL ) ); + + if ( n == nIndex ) + { + // Result obtained. + bFound = true; + break; + } + } + } + + if ( !bFound ) + m_pImpl->m_bCountFinal = sal_True; + + rtl::Reference< ::ucbhelper::ResultSet > xResultSet = getResultSet().get(); + if ( xResultSet.is() ) + { + // Callbacks follow! + aGuard.clear(); + + if ( nOldCount < m_pImpl->m_aResults.size() ) + xResultSet->rowCountChanged( nOldCount, m_pImpl->m_aResults.size() ); + + if ( m_pImpl->m_bCountFinal ) + xResultSet->rowCountFinal(); + } + + return bFound; +} + +//========================================================================= +// virtual +sal_uInt32 ResultSetDataSupplier::totalCount() +{ + osl::ClearableGuard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( m_pImpl->m_bCountFinal ) + return m_pImpl->m_aResults.size(); + + sal_uInt32 nOldCount = m_pImpl->m_aResults.size(); + + if ( queryNamesOfChildren() ) + { + for ( sal_uInt32 n = nOldCount; + n < sal::static_int_cast<sal_uInt32>( + m_pImpl->m_pNamesOfChildren->getLength()); + ++n ) + { + const rtl::OUString & rName + = m_pImpl->m_pNamesOfChildren->getConstArray()[ n ]; + + if ( !rName.getLength() ) + { + OSL_ENSURE( sal_False, + "ResultDataSupplier::getResult - Empty name!" ); + break; + } + + // Assemble URL for child. + rtl::OUString aURL = assembleChildURL( rName ); + + m_pImpl->m_aResults.push_back( new ResultListEntry( aURL ) ); + } + } + + m_pImpl->m_bCountFinal = sal_True; + + rtl::Reference< ::ucbhelper::ResultSet > xResultSet = getResultSet().get(); + if ( xResultSet.is() ) + { + // Callbacks follow! + aGuard.clear(); + + if ( nOldCount < m_pImpl->m_aResults.size() ) + xResultSet->rowCountChanged( nOldCount, m_pImpl->m_aResults.size() ); + + xResultSet->rowCountFinal(); + } + + return m_pImpl->m_aResults.size(); +} + +//========================================================================= +// virtual +sal_uInt32 ResultSetDataSupplier::currentCount() +{ + return m_pImpl->m_aResults.size(); +} + +//========================================================================= +// virtual +sal_Bool ResultSetDataSupplier::isCountFinal() +{ + return m_pImpl->m_bCountFinal; +} + +//========================================================================= +// virtual +uno::Reference< sdbc::XRow > +ResultSetDataSupplier::queryPropertyValues( sal_uInt32 nIndex ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( nIndex < m_pImpl->m_aResults.size() ) + { + uno::Reference< sdbc::XRow > xRow = m_pImpl->m_aResults[ nIndex ]->xRow; + if ( xRow.is() ) + { + // Already cached. + return xRow; + } + } + + if ( getResult( nIndex ) ) + { + uno::Reference< sdbc::XRow > xRow = Content::getPropertyValues( + m_pImpl->m_xSMgr, + getResultSet()->getProperties(), + m_pImpl->m_xContent->getContentProvider().get(), + queryContentIdentifierString( nIndex ) ); + m_pImpl->m_aResults[ nIndex ]->xRow = xRow; + return xRow; + } + + return uno::Reference< sdbc::XRow >(); +} + +//========================================================================= +// virtual +void ResultSetDataSupplier::releasePropertyValues( sal_uInt32 nIndex ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( nIndex < m_pImpl->m_aResults.size() ) + m_pImpl->m_aResults[ nIndex ]->xRow = uno::Reference< sdbc::XRow >(); +} + +//========================================================================= +// virtual +void ResultSetDataSupplier::close() +{ +} + +//========================================================================= +// virtual +void ResultSetDataSupplier::validate() + throw( ucb::ResultSetException ) +{ + if ( m_pImpl->m_bThrowException ) + throw ucb::ResultSetException(); +} + +//========================================================================= +bool ResultSetDataSupplier::queryNamesOfChildren() +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( m_pImpl->m_pNamesOfChildren == 0 ) + { + uno::Sequence< rtl::OUString > * pNamesOfChildren + = new uno::Sequence< rtl::OUString >(); + + if ( !m_pImpl->m_xContent->getContentProvider()->queryNamesOfChildren( + m_pImpl->m_xContent->getIdentifier()->getContentIdentifier(), + *pNamesOfChildren ) ) + { + OSL_ENSURE( false, "Got no list of children!" ); + m_pImpl->m_bThrowException = sal_True; + return false; + } + else + { + m_pImpl->m_pNamesOfChildren = pNamesOfChildren; + } + } + return true; +} + +//========================================================================= +::rtl::OUString +ResultSetDataSupplier::assembleChildURL( const ::rtl::OUString& aName ) +{ + rtl::OUString aContURL + = m_pImpl->m_xContent->getIdentifier()->getContentIdentifier(); + rtl::OUString aURL( aContURL ); + + sal_Int32 nUrlEnd = aURL.lastIndexOf( '/' ); + if ( nUrlEnd != aURL.getLength() - 1 ) + aURL += rtl::OUString::createFromAscii( "/" ); + + aURL += aName; + return aURL; +} diff --git a/ucb/source/ucp/tdoc/tdoc_datasupplier.hxx b/ucb/source/ucp/tdoc/tdoc_datasupplier.hxx new file mode 100644 index 000000000000..28d9a4eba9a2 --- /dev/null +++ b/ucb/source/ucp/tdoc/tdoc_datasupplier.hxx @@ -0,0 +1,81 @@ +/************************************************************************* + * + * 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 INCLUDED_TDOC_DATASUPPLIER_HXX +#define INCLUDED_TDOC_DATASUPPLIER_HXX + +#include <rtl/ref.hxx> +#include <com/sun/star/ucb/OpenMode.hpp> +#include <ucbhelper/resultset.hxx> + +namespace tdoc_ucp { + +struct DataSupplier_Impl; +class Content; + +class ResultSetDataSupplier : public ::ucbhelper::ResultSetDataSupplier +{ + DataSupplier_Impl* m_pImpl; + +private: + bool queryNamesOfChildren(); + ::rtl::OUString assembleChildURL( const ::rtl::OUString& aName ); + +public: + ResultSetDataSupplier( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + const rtl::Reference< Content >& rContent, + sal_Int32 nOpenMode = com::sun::star::ucb::OpenMode::ALL ); + virtual ~ResultSetDataSupplier(); + + virtual rtl::OUString queryContentIdentifierString( sal_uInt32 nIndex ); + virtual com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier > + queryContentIdentifier( sal_uInt32 nIndex ); + virtual com::sun::star::uno::Reference< com::sun::star::ucb::XContent > + queryContent( sal_uInt32 nIndex ); + + virtual sal_Bool getResult( sal_uInt32 nIndex ); + + virtual sal_uInt32 totalCount(); + virtual sal_uInt32 currentCount(); + virtual sal_Bool isCountFinal(); + + virtual com::sun::star::uno::Reference< com::sun::star::sdbc::XRow > + queryPropertyValues( sal_uInt32 nIndex ); + virtual void releasePropertyValues( sal_uInt32 nIndex ); + + virtual void close(); + + virtual void validate() + throw( com::sun::star::ucb::ResultSetException ); +}; + +} // namespace tdoc_ucp + +#endif /* !INCLUDED_TDOC_DATASUPPLIER_HXX */ diff --git a/ucb/source/ucp/tdoc/tdoc_docmgr.cxx b/ucb/source/ucp/tdoc/tdoc_docmgr.cxx new file mode 100644 index 000000000000..46aa1ae69ec3 --- /dev/null +++ b/ucb/source/ucp/tdoc/tdoc_docmgr.cxx @@ -0,0 +1,691 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" +/************************************************************************** + TODO + ************************************************************************** + + - filter unwanted models notified by global document event broadcaster + - help documents + - others, which I don't know yet + + *************************************************************************/ + +#include "osl/diagnose.h" +#include "rtl/ref.hxx" +#include "cppuhelper/weak.hxx" + +#include "comphelper/namedvaluecollection.hxx" +#include "comphelper/documentinfo.hxx" + +#include "com/sun/star/beans/XPropertySet.hpp" +#include "com/sun/star/container/XEnumerationAccess.hpp" +#include "com/sun/star/frame/XStorable.hpp" +#include "com/sun/star/lang/DisposedException.hpp" +#include "com/sun/star/document/XStorageBasedDocument.hpp" +#include "com/sun/star/awt/XTopWindow.hpp" + +#include "tdoc_docmgr.hxx" + +using namespace com::sun::star; +using namespace tdoc_ucp; +using ::comphelper::DocumentInfo; + +//========================================================================= +//========================================================================= +// +// OfficeDocumentsManager Implementation. +// +//========================================================================= +//========================================================================= + +OfficeDocumentsManager::OfficeDocumentsManager( + const uno::Reference< lang::XMultiServiceFactory > & xSMgr, + OfficeDocumentsEventListener * pDocEventListener ) +: m_xSMgr( xSMgr ), + m_xDocEvtNotifier( createDocumentEventNotifier( xSMgr ) ), + m_pDocEventListener( pDocEventListener ) +{ + if ( m_xDocEvtNotifier.is() ) + { + // Order is important (multithreaded environment) + m_xDocEvtNotifier->addEventListener( this ); + buildDocumentsList(); + } +} + +//========================================================================= +// virtual +OfficeDocumentsManager::~OfficeDocumentsManager() +{ + OSL_ENSURE( m_aDocs.empty(), "document list not empty!" ); +} + +//========================================================================= +void OfficeDocumentsManager::destroy() +{ + if ( m_xDocEvtNotifier.is() ) + m_xDocEvtNotifier->removeEventListener( this ); +} + +//========================================================================= +static rtl::OUString +getDocumentId( const uno::Reference< uno::XInterface > & xDoc ) +{ + rtl::OUString aId; + + // Try to get the UID directly from the document. + uno::Reference< beans::XPropertySet > xPropSet( xDoc, uno::UNO_QUERY ); + if ( xPropSet.is() ) + { + try + { + uno::Any aValue = xPropSet->getPropertyValue( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "RuntimeUID" ) ) ); + aValue >>= aId; + } + catch ( beans::UnknownPropertyException const & ) + { + // Not actually an error. Property is optional. + } + catch ( lang::WrappedTargetException const & ) + { + OSL_ENSURE( false, "Caught WrappedTargetException!" ); + } + } + + if ( aId.getLength() == 0 ) + { + // fallback: generate UID from document's this pointer. + // normalize the interface pointer first. Else, calls with different + // interfaces to the same object (say, XFoo and XBar) will produce + // different IDs + uno::Reference< uno::XInterface > xNormalizedIFace( xDoc, uno::UNO_QUERY ); + sal_Int64 nId = reinterpret_cast< sal_Int64 >( xNormalizedIFace.get() ); + aId = rtl::OUString::valueOf( nId ); + } + + OSL_ENSURE( aId.getLength() > 0, "getDocumentId - Empty id!" ); + return aId; +} + +//========================================================================= +// +// document::XEventListener +// +//========================================================================= + +// virtual +void SAL_CALL OfficeDocumentsManager::notifyEvent( + const document::EventObject & Event ) + throw ( uno::RuntimeException ) +{ +/* + Events documentation: OOo Developer's Guide / Writing UNO Components / Jobs +*/ + + if ( Event.EventName.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "OnLoadFinished" ) ) // document loaded + || Event.EventName.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "OnCreate" ) ) ) // document created + { + if ( isOfficeDocument( Event.Source ) ) + { + osl::MutexGuard aGuard( m_aMtx ); + + uno::Reference< frame::XModel > + xModel( Event.Source, uno::UNO_QUERY ); + OSL_ENSURE( xModel.is(), "Got no frame::XModel!" ); + + DocumentList::const_iterator it = m_aDocs.begin(); + while ( it != m_aDocs.end() ) + { + if ( (*it).second.xModel == xModel ) + { + // already known. + break; + } + ++it; + } + + if ( it == m_aDocs.end() ) + { + // new document + + uno::Reference< document::XStorageBasedDocument > + xDoc( Event.Source, uno::UNO_QUERY ); + OSL_ENSURE( xDoc.is(), "Got no document::XStorageBasedDocument!" ); + + uno::Reference< embed::XStorage > xStorage + = xDoc->getDocumentStorage(); + OSL_ENSURE( xStorage.is(), "Got no document storage!" ); + + rtl:: OUString aDocId = getDocumentId( Event.Source ); + rtl:: OUString aTitle = DocumentInfo::getDocumentTitle( uno::Reference< frame::XModel >( Event.Source, uno::UNO_QUERY ) ); + + m_aDocs[ aDocId ] = StorageInfo( aTitle, xStorage, xModel ); + + // Propagate document closure. + OSL_ENSURE( m_pDocEventListener, + "OnLoadFinished/OnCreate event: no owner for insert event propagation!" ); + + if ( m_pDocEventListener ) + m_pDocEventListener->notifyDocumentOpened( aDocId ); + } + } + } + else if ( Event.EventName.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "OnUnload" ) ) ) + { + if ( isOfficeDocument( Event.Source ) ) + { + // Document has been closed (unloaded) + + osl::MutexGuard aGuard( m_aMtx ); + + uno::Reference< frame::XModel > + xModel( Event.Source, uno::UNO_QUERY ); + OSL_ENSURE( xModel.is(), "Got no frame::XModel!" ); + + DocumentList::iterator it = m_aDocs.begin(); + while ( it != m_aDocs.end() ) + { + if ( (*it).second.xModel == xModel ) + { + // Propagate document closure. + OSL_ENSURE( m_pDocEventListener, + "OnUnload event: no owner for close event propagation!" ); + + if ( m_pDocEventListener ) + { + rtl::OUString aDocId( (*it).first ); + m_pDocEventListener->notifyDocumentClosed( aDocId ); + } + + + break; + } + ++it; + } + + OSL_ENSURE( it != m_aDocs.end(), + "OnUnload event notified for unknown document!" ); + + if( it != m_aDocs.end() ) + m_aDocs.erase( it ); + } + } + else if ( Event.EventName.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "OnSaveDone" ) ) ) + { + if ( isOfficeDocument( Event.Source ) ) + { + osl::MutexGuard aGuard( m_aMtx ); + + uno::Reference< frame::XModel > + xModel( Event.Source, uno::UNO_QUERY ); + OSL_ENSURE( xModel.is(), "Got no frame::XModel!" ); + + DocumentList::iterator it = m_aDocs.begin(); + while ( it != m_aDocs.end() ) + { + if ( (*it).second.xModel == xModel ) + { + // Storage gets exchanged while saving. + uno::Reference< document::XStorageBasedDocument > + xDoc( Event.Source, uno::UNO_QUERY ); + OSL_ENSURE( xDoc.is(), + "Got no document::XStorageBasedDocument!" ); + + uno::Reference< embed::XStorage > xStorage + = xDoc->getDocumentStorage(); + OSL_ENSURE( xStorage.is(), "Got no document storage!" ); + + (*it).second.xStorage = xStorage; + break; + } + ++it; + } + + OSL_ENSURE( it != m_aDocs.end(), + "OnSaveDone event notified for unknown document!" ); + } + } + else if ( Event.EventName.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "OnSaveAsDone" ) ) ) + { + if ( isOfficeDocument( Event.Source ) ) + { + osl::MutexGuard aGuard( m_aMtx ); + + uno::Reference< frame::XModel > + xModel( Event.Source, uno::UNO_QUERY ); + OSL_ENSURE( xModel.is(), "Got no frame::XModel!" ); + + DocumentList::iterator it = m_aDocs.begin(); + while ( it != m_aDocs.end() ) + { + if ( (*it).second.xModel == xModel ) + { + // Storage gets exchanged while saving. + uno::Reference< document::XStorageBasedDocument > + xDoc( Event.Source, uno::UNO_QUERY ); + OSL_ENSURE( xDoc.is(), + "Got no document::XStorageBasedDocument!" ); + + uno::Reference< embed::XStorage > xStorage + = xDoc->getDocumentStorage(); + OSL_ENSURE( xStorage.is(), "Got no document storage!" ); + + (*it).second.xStorage = xStorage; + + // Adjust title. + (*it).second.aTitle = DocumentInfo::getDocumentTitle( uno::Reference< frame::XModel >( Event.Source, uno::UNO_QUERY ) ); + break; + } + ++it; + } + + OSL_ENSURE( it != m_aDocs.end(), + "OnSaveAsDone event notified for unknown document!" ); + } + } + else if ( Event.EventName.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "OnTitleChanged" ) ) ) + { + if ( isOfficeDocument( Event.Source ) ) + { + osl::MutexGuard aGuard( m_aMtx ); + + uno::Reference< frame::XModel > + xModel( Event.Source, uno::UNO_QUERY ); + OSL_ENSURE( xModel.is(), "Got no frame::XModel!" ); + + DocumentList::iterator it = m_aDocs.begin(); + while ( it != m_aDocs.end() ) + { + if ( (*it).second.xModel == xModel ) + { + // Adjust title. + rtl:: OUString aTitle = DocumentInfo::getDocumentTitle( uno::Reference< frame::XModel >( Event.Source, uno::UNO_QUERY ) ); + (*it).second.aTitle = aTitle; + + // Adjust storage. + uno::Reference< document::XStorageBasedDocument > + xDoc( Event.Source, uno::UNO_QUERY ); + OSL_ENSURE( xDoc.is(), "Got no document::XStorageBasedDocument!" ); + + uno::Reference< embed::XStorage > xStorage + = xDoc->getDocumentStorage(); + OSL_ENSURE( xDoc.is(), "Got no document storage!" ); + + rtl:: OUString aDocId = getDocumentId( Event.Source ); + + m_aDocs[ aDocId ] = StorageInfo( aTitle, xStorage, xModel ); + break; + } + ++it; + } + + OSL_ENSURE( it != m_aDocs.end(), + "TitleChanged event notified for unknown document!" ); + } + } +} + +//========================================================================= +// +// lang::XEventListener (base of document::XEventListener) +// +//========================================================================= + +// virtual +void SAL_CALL OfficeDocumentsManager::disposing( + const lang::EventObject& /*Source*/ ) + throw ( uno::RuntimeException ) +{ +} + +//========================================================================= +// +// Non-interface. +// +//========================================================================= + +// static +uno::Reference< document::XEventBroadcaster > +OfficeDocumentsManager::createDocumentEventNotifier( + const uno::Reference< lang::XMultiServiceFactory >& rXSMgr ) +{ + uno::Reference< uno::XInterface > xIfc; + try + { + xIfc = rXSMgr->createInstance( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.frame.GlobalEventBroadcaster" ) ) ); + } + catch ( uno::Exception const & ) + { + // handled below. + } + + OSL_ENSURE( + xIfc.is(), + "Could not instanciate com.sun.star.frame.GlobalEventBroadcaster" ); + + if ( xIfc.is() ) + { + uno::Reference< document::XEventBroadcaster > xBC( + xIfc, uno::UNO_QUERY ); + + OSL_ENSURE( + xBC.is(), + "com.sun.star.frame.GlobalEventBroadcaster does not implement " + "interface com.sun.star.document.XEventBroadcaster!" ); + + return xBC; + } + else + return uno::Reference< document::XEventBroadcaster >(); +} + +//========================================================================= +void OfficeDocumentsManager::buildDocumentsList() +{ + OSL_ENSURE( m_xDocEvtNotifier.is(), + "OfficeDocumentsManager::buildDocumentsList - " + "No document event notifier!" ); + + uno::Reference< container::XEnumerationAccess > xEnumAccess( + m_xDocEvtNotifier, uno::UNO_QUERY_THROW ); + + uno::Reference< container::XEnumeration > xEnum + = xEnumAccess->createEnumeration(); + + osl::MutexGuard aGuard( m_aMtx ); + + while ( xEnum->hasMoreElements() ) + { + uno::Any aValue = xEnum->nextElement(); + // container::NoSuchElementException + // lang::WrappedTargetException + + try + { + uno::Reference< frame::XModel > xModel; + aValue >>= xModel; + + if ( xModel.is() ) + { + if ( isOfficeDocument( xModel ) ) + { + DocumentList::const_iterator it = m_aDocs.begin(); + while ( it != m_aDocs.end() ) + { + if ( (*it).second.xModel == xModel ) + { + // already known. + break; + } + ++it; + } + + if ( it == m_aDocs.end() ) + { + // new document + rtl::OUString aDocId = getDocumentId( xModel ); + rtl::OUString aTitle = DocumentInfo::getDocumentTitle( xModel ); + + uno::Reference< document::XStorageBasedDocument > + xDoc( xModel, uno::UNO_QUERY ); + OSL_ENSURE( xDoc.is(), + "Got no document::XStorageBasedDocument!" ); + + uno::Reference< embed::XStorage > xStorage + = xDoc->getDocumentStorage(); + OSL_ENSURE( xDoc.is(), "Got no document storage!" ); + + m_aDocs[ aDocId ] + = StorageInfo( aTitle, xStorage, xModel ); + } + } + } + } + catch ( lang::DisposedException const & ) + { + // Note: Due to race conditions the XEnumeration can + // contains docs that already have been closed + } + } +} + +//========================================================================= +uno::Reference< embed::XStorage > +OfficeDocumentsManager::queryStorage( const rtl::OUString & rDocId ) +{ + osl::MutexGuard aGuard( m_aMtx ); + + DocumentList::const_iterator it = m_aDocs.find( rDocId ); + if ( it == m_aDocs.end() ) + return uno::Reference< embed::XStorage >(); + + return (*it).second.xStorage; +} + +//========================================================================= +rtl::OUString OfficeDocumentsManager::queryDocumentId( + const uno::Reference< frame::XModel > & xModel ) +{ + return getDocumentId( xModel ); +} + +//========================================================================= +uno::Reference< frame::XModel > +OfficeDocumentsManager::queryDocumentModel( const rtl::OUString & rDocId ) +{ + osl::MutexGuard aGuard( m_aMtx ); + + DocumentList::const_iterator it = m_aDocs.find( rDocId ); + if ( it == m_aDocs.end() ) + return uno::Reference< frame::XModel >(); + + return (*it).second.xModel; +} + +//========================================================================= +uno::Sequence< rtl::OUString > OfficeDocumentsManager::queryDocuments() +{ + osl::MutexGuard aGuard( m_aMtx ); + + uno::Sequence< rtl::OUString > aRet( m_aDocs.size() ); + sal_Int32 nPos = 0; + + DocumentList::const_iterator it = m_aDocs.begin(); + while ( it != m_aDocs.end() ) + { + aRet[ nPos ] = (*it).first; + ++it; + ++nPos; + } + return aRet; +} + +//========================================================================= +rtl::OUString +OfficeDocumentsManager::queryStorageTitle( const rtl::OUString & rDocId ) +{ + osl::MutexGuard aGuard( m_aMtx ); + + DocumentList::const_iterator it = m_aDocs.find( rDocId ); + if ( it == m_aDocs.end() ) + return rtl::OUString(); + + return (*it).second.aTitle; +} + +//========================================================================= +bool OfficeDocumentsManager::isDocumentPreview( + const uno::Reference< frame::XModel > & xModel ) +{ + if ( !xModel.is() ) + return false; + + ::comphelper::NamedValueCollection aArgs( + xModel->getArgs() ); + sal_Bool bIsPreview = aArgs.getOrDefault( "Preview", sal_False ); + return bIsPreview; +} + +//========================================================================= +bool OfficeDocumentsManager::isHelpDocument( + const uno::Reference< frame::XModel > & xModel ) +{ + if ( !xModel.is() ) + return false; + + ::rtl::OUString sURL( xModel->getURL() ); + if ( sURL.matchAsciiL( RTL_CONSTASCII_STRINGPARAM( "vnd.sun.star.help://" ) ) ) + return true; + + return false; +} + +//========================================================================= +bool OfficeDocumentsManager::isWithoutOrInTopLevelFrame( + const uno::Reference< frame::XModel > & xModel ) +{ + if ( !xModel.is() ) + return false; + + uno::Reference< frame::XController > xController + = xModel->getCurrentController(); + if ( xController.is() ) + { + uno::Reference< frame::XFrame > xFrame + = xController->getFrame(); + if ( xFrame.is() ) + { + // don't use XFrame::isTop here. This nowadays excludes + // "sub documents" such as forms embedded in database documents + uno::Reference< awt::XTopWindow > xFrameContainer( + xFrame->getContainerWindow(), uno::UNO_QUERY ); + if ( !xFrameContainer.is() ) + return false; + } + } + + return true; +} + +//========================================================================= +bool OfficeDocumentsManager::isBasicIDE( + const uno::Reference< frame::XModel > & xModel ) +{ + if ( !m_xModuleMgr.is() ) + { + osl::MutexGuard aGuard( m_aMtx ); + if ( !m_xModuleMgr.is() ) + { + try + { + m_xModuleMgr + = uno::Reference< + frame::XModuleManager >( + m_xSMgr->createInstance( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.frame.ModuleManager" ) ) ), + uno::UNO_QUERY ); + } + catch ( uno::Exception const & ) + { + // handled below. + } + + OSL_ENSURE( m_xModuleMgr .is(), + "Could not instanciate ModuleManager service!" ); + } + } + + if ( m_xModuleMgr.is() ) + { + rtl::OUString aModule; + try + { + aModule = m_xModuleMgr->identify( xModel ); + } + catch ( lang::IllegalArgumentException const & ) + { + OSL_ENSURE( false, "Caught IllegalArgumentException!" ); + } + catch ( frame::UnknownModuleException const & ) + { + OSL_ENSURE( false, "Caught UnknownModuleException!" ); + } + + if ( aModule.getLength() > 0 ) + { + // Filter unwanted items, that are no real documents. + if ( aModule.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( + "com.sun.star.script.BasicIDE" ) ) ) + { + return true; + } + } + } + + return false; +} + +//========================================================================= +bool OfficeDocumentsManager::isOfficeDocument( + const uno::Reference< uno::XInterface > & xDoc ) +{ + uno::Reference< frame::XModel > xModel( xDoc, uno::UNO_QUERY ); + uno::Reference< document::XStorageBasedDocument > + xStorageBasedDoc( xModel, uno::UNO_QUERY ); + if ( !xStorageBasedDoc.is() ) + return false; + + if ( !isWithoutOrInTopLevelFrame( xModel ) ) + return false; + + if ( isDocumentPreview( xModel ) ) + return false; + + if ( isHelpDocument( xModel ) ) + return false; + + if ( isBasicIDE( xModel ) ) + return false; + + return true; +} diff --git a/ucb/source/ucp/tdoc/tdoc_docmgr.hxx b/ucb/source/ucp/tdoc/tdoc_docmgr.hxx new file mode 100644 index 000000000000..8f8b2fc117f0 --- /dev/null +++ b/ucb/source/ucp/tdoc/tdoc_docmgr.hxx @@ -0,0 +1,173 @@ +/************************************************************************* + * + * 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 INCLUDED_TDOC_DOCMGR_HXX +#define INCLUDED_TDOC_DOCMGR_HXX + +#include <map> + +#include "osl/mutex.hxx" + +#include "cppuhelper/implbase1.hxx" + +#include "com/sun/star/document/XEventBroadcaster.hpp" +#include "com/sun/star/document/XEventListener.hpp" +#include "com/sun/star/embed/XStorage.hpp" +#include "com/sun/star/frame/XModel.hpp" +#include "com/sun/star/frame/XModuleManager.hpp" + +namespace tdoc_ucp { + + class OfficeDocumentsEventListener + { + public: + virtual void notifyDocumentOpened( const rtl::OUString & rDocId ) = 0; + virtual void notifyDocumentClosed( const rtl::OUString & rDocId ) = 0; + }; + + //======================================================================= + + struct StorageInfo + { + rtl::OUString aTitle; + com::sun::star::uno::Reference< + com::sun::star::embed::XStorage > xStorage; + com::sun::star::uno::Reference< + com::sun::star::frame::XModel > xModel; + + StorageInfo() {}; // needed for STL map only. + + StorageInfo( + const rtl::OUString & rTitle, + const com::sun::star::uno::Reference< + com::sun::star::embed::XStorage > & rxStorage, + const com::sun::star::uno::Reference< + com::sun::star::frame::XModel > & rxModel ) + : aTitle( rTitle ), xStorage( rxStorage ), xModel( rxModel ) {} + }; + + //======================================================================= + + struct ltref + { + bool operator()( + const rtl::OUString & r1, const rtl::OUString & r2 ) const + { + return r1 < r2; + } + }; + + typedef std::map< rtl::OUString, StorageInfo, ltref > DocumentList; + + //======================================================================= + + class OfficeDocumentsManager : + public cppu::WeakImplHelper1< com::sun::star::document::XEventListener > + { + public: + OfficeDocumentsManager( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory > & xSMgr, + OfficeDocumentsEventListener * pDocEventListener ); + virtual ~OfficeDocumentsManager(); + + void destroy(); + + // document::XEventListener + virtual void SAL_CALL notifyEvent( + const com::sun::star::document::EventObject & Event ) + throw ( com::sun::star::uno::RuntimeException ); + + // lang::XEventListener (base of document::XEventListener) + virtual void SAL_CALL disposing( + const com::sun::star::lang::EventObject & Source ) + throw ( com::sun::star::uno::RuntimeException ); + + // Non-interface + com::sun::star::uno::Reference< com::sun::star::embed::XStorage > + queryStorage( const rtl::OUString & rDocId ); + + rtl::OUString + queryDocumentId( + const com::sun::star::uno::Reference< + com::sun::star::frame::XModel > & xModel ); + + com::sun::star::uno::Reference< com::sun::star::frame::XModel > + queryDocumentModel( const rtl::OUString & rDocId ); + + com::sun::star::uno::Sequence< rtl::OUString > + queryDocuments(); + + rtl::OUString + queryStorageTitle( const rtl::OUString & rDocId ); + + private: + static com::sun::star::uno::Reference< + com::sun::star::document::XEventBroadcaster > + createDocumentEventNotifier( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rXSMgr ); + void buildDocumentsList(); + bool + isOfficeDocument( + const com::sun::star::uno::Reference< + com::sun::star::uno::XInterface > & xDoc ); + + bool + isDocumentPreview( + const com::sun::star::uno::Reference< + com::sun::star::frame::XModel > & xModel ); + + bool + isWithoutOrInTopLevelFrame( + const com::sun::star::uno::Reference< + com::sun::star::frame::XModel > & xModel ); + + bool + isBasicIDE( + const com::sun::star::uno::Reference< + com::sun::star::frame::XModel > & xModel ); + + bool + isHelpDocument( + const com::sun::star::uno::Reference< + com::sun::star::frame::XModel > & xModel ); + + osl::Mutex m_aMtx; + com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory > m_xSMgr; + com::sun::star::uno::Reference< + com::sun::star::document::XEventBroadcaster > m_xDocEvtNotifier; + com::sun::star::uno::Reference< + com::sun::star::frame::XModuleManager > m_xModuleMgr; + DocumentList m_aDocs; + OfficeDocumentsEventListener * m_pDocEventListener; + }; + +} // namespace tdoc_ucp + +#endif /* !INCLUDED_TDOC_DOCMGR_HXX */ diff --git a/ucb/source/ucp/tdoc/tdoc_documentcontentfactory.cxx b/ucb/source/ucp/tdoc/tdoc_documentcontentfactory.cxx new file mode 100644 index 000000000000..72c5f700aa2c --- /dev/null +++ b/ucb/source/ucp/tdoc/tdoc_documentcontentfactory.cxx @@ -0,0 +1,188 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ + +#include "cppuhelper/factory.hxx" + +#include "tdoc_documentcontentfactory.hxx" + +using namespace com::sun::star; +using namespace tdoc_ucp; + +//========================================================================= +//========================================================================= +// +// DocumentContentFactory Implementation. +// +//========================================================================= +//========================================================================= + +DocumentContentFactory::DocumentContentFactory( + const uno::Reference< lang::XMultiServiceFactory >& xSMgr ) +: m_xSMgr( xSMgr ) +{ +} + +//========================================================================= +// virtual +DocumentContentFactory::~DocumentContentFactory() +{ +} + +//========================================================================= +// +// XServiceInfo methods. +// +//========================================================================= + +// virtual +::rtl::OUString SAL_CALL DocumentContentFactory::getImplementationName() + throw ( uno::RuntimeException ) +{ + return getImplementationName_Static(); +} + +//========================================================================= +// virtual +sal_Bool SAL_CALL +DocumentContentFactory::supportsService( const ::rtl::OUString& ServiceName ) + throw ( uno::RuntimeException ) +{ + uno::Sequence< rtl::OUString > aSNL = getSupportedServiceNames(); + const rtl::OUString * pArray = aSNL.getConstArray(); + for ( sal_Int32 i = 0; i < aSNL.getLength(); i++ ) + { + if ( pArray[ i ] == ServiceName ) + return sal_True; + } + return sal_False; +} + +//========================================================================= +// virtual +uno::Sequence< ::rtl::OUString > SAL_CALL +DocumentContentFactory::getSupportedServiceNames() + throw ( uno::RuntimeException ) +{ + return getSupportedServiceNames_Static(); +} + +//========================================================================= +// static +rtl::OUString DocumentContentFactory::getImplementationName_Static() +{ + return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.comp.ucb.TransientDocumentsDocumentContentFactory" ) ); +} + +//========================================================================= +// static +uno::Sequence< rtl::OUString > +DocumentContentFactory::getSupportedServiceNames_Static() +{ + uno::Sequence< rtl::OUString > aSNS( 1 ); + aSNS.getArray()[ 0 ] + = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.frame.TransientDocumentsDocumentContentFactory" ) ); + return aSNS; +} + +//========================================================================= +// +// XTransientDocumentsDocumentContentFactory methods. +// +//========================================================================= + +// virtual +uno::Reference< ucb::XContent > SAL_CALL +DocumentContentFactory::createDocumentContent( + const uno::Reference< frame::XModel >& Model ) + throw ( lang::IllegalArgumentException, uno::RuntimeException ) +{ + uno::Reference< frame::XTransientDocumentsDocumentContentFactory > xDocFac; + try + { + xDocFac + = uno::Reference< frame::XTransientDocumentsDocumentContentFactory >( + m_xSMgr->createInstance( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.ucb.TransientDocumentsContentProvider" ) ) + ), + uno::UNO_QUERY ); + } + catch ( uno::Exception const & ) + { + // handled below. + } + + if ( xDocFac.is() ) + return xDocFac->createDocumentContent( Model ); + + throw uno::RuntimeException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "Unable to obtain document content factory!" ) ), + static_cast< cppu::OWeakObject * >( this ) ); +} + +//========================================================================= +// +// Service factory implementation. +// +//========================================================================= + +static uno::Reference< uno::XInterface > SAL_CALL +DocumentContentFactory_CreateInstance( + const uno::Reference< lang::XMultiServiceFactory> & rSMgr ) + throw( uno::Exception ) +{ + lang::XServiceInfo * pX = static_cast< lang::XServiceInfo * >( + new DocumentContentFactory( rSMgr ) ); + return uno::Reference< uno::XInterface >::query( pX ); +} + +//========================================================================= +// static +uno::Reference< lang::XSingleServiceFactory > +DocumentContentFactory::createServiceFactory( + const uno::Reference< lang::XMultiServiceFactory >& rxServiceMgr ) +{ + return uno::Reference< lang::XSingleServiceFactory >( + cppu::createOneInstanceFactory( + rxServiceMgr, + DocumentContentFactory::getImplementationName_Static(), + DocumentContentFactory_CreateInstance, + DocumentContentFactory::getSupportedServiceNames_Static() ) ); +} + diff --git a/ucb/source/ucp/tdoc/tdoc_documentcontentfactory.hxx b/ucb/source/ucp/tdoc/tdoc_documentcontentfactory.hxx new file mode 100644 index 000000000000..7a2d919e5708 --- /dev/null +++ b/ucb/source/ucp/tdoc/tdoc_documentcontentfactory.hxx @@ -0,0 +1,86 @@ +/************************************************************************* + * + * 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 INCLUDED_TDOC_DOCUMENTCONTENTFACTORY_HXX +#define INCLUDED_TDOC_DOCUMENTCONTENTFACTORY_HXX + +#include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/lang/XSingleServiceFactory.hpp" +#include "com/sun/star/frame/XTransientDocumentsDocumentContentFactory.hpp" + +#include "cppuhelper/implbase2.hxx" + +namespace tdoc_ucp { + +class DocumentContentFactory : + public cppu::WeakImplHelper2< + com::sun::star::frame::XTransientDocumentsDocumentContentFactory, + com::sun::star::lang::XServiceInfo > +{ +public: + DocumentContentFactory( const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rXSMgr ); + virtual ~DocumentContentFactory(); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName() + throw ( com::sun::star::uno::RuntimeException ); + + virtual sal_Bool SAL_CALL + supportsService( const ::rtl::OUString& ServiceName ) + throw ( com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL + getSupportedServiceNames() + throw ( com::sun::star::uno::RuntimeException ); + + // XTransientDocumentsDocumentContentFactory + virtual com::sun::star::uno::Reference< + com::sun::star::ucb::XContent > SAL_CALL + createDocumentContent( const ::com::sun::star::uno::Reference< + com::sun::star::frame::XModel >& Model ) + throw ( com::sun::star::lang::IllegalArgumentException, + com::sun::star::uno::RuntimeException ); + + // Non-UNO interfaces + static rtl::OUString + getImplementationName_Static(); + static com::sun::star::uno::Sequence< rtl::OUString > + getSupportedServiceNames_Static(); + + static com::sun::star::uno::Reference< + com::sun::star::lang::XSingleServiceFactory > + createServiceFactory( const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory > & rxServiceMgr ); +private: + com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory > m_xSMgr; +}; + +} // namespace tdoc_ucp + +#endif /* !INCLUDED_TDOC_DOCUMENTCONTENTFACTORY_HXX */ diff --git a/ucb/source/ucp/tdoc/tdoc_passwordrequest.cxx b/ucb/source/ucp/tdoc/tdoc_passwordrequest.cxx new file mode 100644 index 000000000000..c7ce1b893372 --- /dev/null +++ b/ucb/source/ucp/tdoc/tdoc_passwordrequest.cxx @@ -0,0 +1,242 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +#include "osl/mutex.hxx" + +#include "com/sun/star/lang/XTypeProvider.hpp" +#include "com/sun/star/task/DocumentPasswordRequest.hpp" + +#include "cppuhelper/typeprovider.hxx" +#include "ucbhelper/interactionrequest.hxx" + +#include "tdoc_passwordrequest.hxx" + +using namespace com::sun::star; +using namespace tdoc_ucp; + +namespace tdoc_ucp +{ + class InteractionSupplyPassword : + public ucbhelper::InteractionContinuation, + public lang::XTypeProvider, + public task::XInteractionPassword + { + public: + InteractionSupplyPassword( ucbhelper::InteractionRequest * pRequest ) + : InteractionContinuation( pRequest ) {} + + // XInterface + virtual uno::Any SAL_CALL queryInterface( const uno::Type & rType ) + throw ( uno::RuntimeException ); + virtual void SAL_CALL acquire() + throw (); + virtual void SAL_CALL release() + throw (); + + // XTypeProvider + virtual uno::Sequence< uno::Type > SAL_CALL getTypes() + throw ( uno::RuntimeException ); + virtual uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() + throw ( uno::RuntimeException ); + + // XInteractionContinuation + virtual void SAL_CALL select() + throw ( uno::RuntimeException ); + + // XInteractionPassword + virtual void SAL_CALL setPassword( const rtl::OUString & aPasswd ) + throw ( uno::RuntimeException ); + virtual rtl::OUString SAL_CALL getPassword() + throw ( uno::RuntimeException ); + + private: + osl::Mutex m_aMutex; + rtl::OUString m_aPassword; + }; +} // namespace tdoc_ucp + +//========================================================================= +//========================================================================= +// +// InteractionSupplyPassword Implementation. +// +//========================================================================= +//========================================================================= + +//========================================================================= +// +// XInterface methods. +// +//========================================================================= + +// virtual +void SAL_CALL InteractionSupplyPassword::acquire() + throw() +{ + OWeakObject::acquire(); +} + +//========================================================================= +// virtual +void SAL_CALL InteractionSupplyPassword::release() + throw() +{ + OWeakObject::release(); +} + +//========================================================================= +// virtual +uno::Any SAL_CALL +InteractionSupplyPassword::queryInterface( const uno::Type & rType ) + throw ( uno::RuntimeException ) +{ + uno::Any aRet = cppu::queryInterface( rType, + static_cast< lang::XTypeProvider * >( this ), + static_cast< task::XInteractionContinuation * >( this ), + static_cast< task::XInteractionPassword * >( this ) ); + + return aRet.hasValue() + ? aRet : InteractionContinuation::queryInterface( rType ); +} + +//========================================================================= +// +// XTypeProvider methods. +// +//========================================================================= + +// virtual +uno::Sequence< sal_Int8 > SAL_CALL +InteractionSupplyPassword::getImplementationId() + throw( uno::RuntimeException ) +{ + static cppu::OImplementationId * pId = 0; + if ( !pId ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + if ( !pId ) + { + static cppu::OImplementationId id( sal_False ); + pId = &id; + } + } + return (*pId).getImplementationId(); +} + +//========================================================================= +// virtual +uno::Sequence< uno::Type > SAL_CALL InteractionSupplyPassword::getTypes() + throw( uno::RuntimeException ) +{ + static cppu::OTypeCollection * pCollection = 0; + if ( !pCollection ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + if ( !pCollection ) + { + static cppu::OTypeCollection collection( + getCppuType( static_cast< + uno::Reference< lang::XTypeProvider > * >( 0 ) ), + getCppuType( static_cast< + uno::Reference< task::XInteractionPassword > * >( 0 ) ) ); + pCollection = &collection; + } + } + return (*pCollection).getTypes(); +} + +//========================================================================= +// +// XInteractionContinuation methods. +// +//========================================================================= + +// virtual +void SAL_CALL InteractionSupplyPassword::select() + throw( uno::RuntimeException ) +{ + recordSelection(); +} + +//========================================================================= +// +// XInteractionPassword methods. +// +//========================================================================= + +// virtual +void SAL_CALL +InteractionSupplyPassword::setPassword( const ::rtl::OUString& aPasswd ) + throw ( uno::RuntimeException ) +{ + osl::MutexGuard aGuard( m_aMutex ); + m_aPassword = aPasswd; +} + +// virtual +rtl::OUString SAL_CALL InteractionSupplyPassword::getPassword() + throw ( uno::RuntimeException ) +{ + osl::MutexGuard aGuard( m_aMutex ); + return m_aPassword; +} + +//========================================================================= +//========================================================================= +// +// DocumentPasswordRequest Implementation. +// +//========================================================================= +//========================================================================= + +DocumentPasswordRequest::DocumentPasswordRequest( + task::PasswordRequestMode eMode, + const rtl::OUString & rDocumentName ) +{ + // Fill request... + task::DocumentPasswordRequest aRequest; +// aRequest.Message = // OUString +// aRequest.Context = // XInterface + aRequest.Classification = task::InteractionClassification_ERROR; + aRequest.Mode = eMode; + aRequest.Name = rDocumentName; + + setRequest( uno::makeAny( aRequest ) ); + + // Fill continuations... + uno::Sequence< + uno::Reference< task::XInteractionContinuation > > aContinuations( 3 ); + aContinuations[ 0 ] = new ucbhelper::InteractionAbort( this ); + aContinuations[ 1 ] = new ucbhelper::InteractionRetry( this ); + aContinuations[ 2 ] = new InteractionSupplyPassword( this ); + + setContinuations( aContinuations ); +} + diff --git a/ucb/source/ucp/tdoc/tdoc_passwordrequest.hxx b/ucb/source/ucp/tdoc/tdoc_passwordrequest.hxx new file mode 100644 index 000000000000..bc170bece65b --- /dev/null +++ b/ucb/source/ucp/tdoc/tdoc_passwordrequest.hxx @@ -0,0 +1,100 @@ +/************************************************************************* + * + * 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 INCLUDED_TDOC_PASSWORDREQUEST_HXX +#define INCLUDED_TDOC_PASSWORDREQUEST_HXX + +#include "com/sun/star/task/PasswordRequestMode.hpp" +#include "com/sun/star/task/XInteractionPassword.hpp" + +#include "ucbhelper/interactionrequest.hxx" + +namespace tdoc_ucp { + + /* + @usage: + + uno::Reference< ucb::XCommandEnvironment > Environment = ...; + + if ( Environment.is() ) + { + uno::Reference< task::XInteractionHandler > xIH + = Environment->getInteractionHandler(); + if ( xIH.is() ) + { + rtl::Reference< DocumentPasswordRequest > xRequest + = new DocumentPasswordRequest( + task::PasswordRequestMode_PASSWORD_ENTER, + m_xIdentifier->getContentIdentifier() ); + xIH->handle( xRequest.get() ); + + rtl::Reference< ucbhelper::InteractionContinuation > xSelection + = xRequest->getSelection(); + + if ( xSelection.is() ) + { + // Handler handled the request. + uno::Reference< task::XInteractionAbort > xAbort( + xSelection.get(), uno::UNO_QUERY ); + if ( xAbort.is() ) + { + // @@@ + } + + uno::Reference< task::XInteractionRetry > xRetry( + xSelection.get(), uno::UNO_QUERY ); + if ( xRetry.is() ) + { + // @@@ + } + + uno::Reference< task::XInteractionPassword > xPassword( + xSelection.get(), uno::UNO_QUERY ); + if ( xPassword.is() ) + { + rtl::OUString aPassword = xPassword->getPassword(); + + // @@@ + } + } + } + } + + */ + + class DocumentPasswordRequest : public ucbhelper::InteractionRequest + { + public: + DocumentPasswordRequest( + com::sun::star::task::PasswordRequestMode eMode, + const rtl::OUString & rDocumentName ); + }; + +} // namespace tdoc_ucp + +#endif /* !INCLUDED_TDOC_PASSWORDREQUEST_HXX */ + diff --git a/ucb/source/ucp/tdoc/tdoc_provider.cxx b/ucb/source/ucp/tdoc/tdoc_provider.cxx new file mode 100644 index 000000000000..7ffedfcf1932 --- /dev/null +++ b/ucb/source/ucp/tdoc/tdoc_provider.cxx @@ -0,0 +1,629 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ + +#include "rtl/ustrbuf.hxx" + +#include "com/sun/star/container/XNameAccess.hpp" +#include "com/sun/star/embed/XStorage.hpp" + +#include "ucbhelper/contentidentifier.hxx" + +#include "tdoc_provider.hxx" +#include "tdoc_content.hxx" +#include "tdoc_uri.hxx" +#include "tdoc_docmgr.hxx" +#include "tdoc_storage.hxx" + +using namespace com::sun::star; +using namespace tdoc_ucp; + +//========================================================================= +//========================================================================= +// +// ContentProvider Implementation. +// +//========================================================================= +//========================================================================= + +ContentProvider::ContentProvider( + const uno::Reference< lang::XMultiServiceFactory >& xSMgr ) +: ::ucbhelper::ContentProviderImplHelper( xSMgr ), + m_xDocsMgr( new OfficeDocumentsManager( xSMgr, this ) ), + m_xStgElemFac( new StorageElementFactory( xSMgr, m_xDocsMgr ) ) +{ +} + +//========================================================================= +// virtual +ContentProvider::~ContentProvider() +{ + if ( m_xDocsMgr.is() ) + m_xDocsMgr->destroy(); +} + +//========================================================================= +// +// XInterface methods. +// +//========================================================================= + +XINTERFACE_IMPL_4( ContentProvider, + lang::XTypeProvider, + lang::XServiceInfo, + ucb::XContentProvider, + frame::XTransientDocumentsDocumentContentFactory ); + +//========================================================================= +// +// XTypeProvider methods. +// +//========================================================================= + +XTYPEPROVIDER_IMPL_4( ContentProvider, + lang::XTypeProvider, + lang::XServiceInfo, + ucb::XContentProvider, + frame::XTransientDocumentsDocumentContentFactory ); + +//========================================================================= +// +// XServiceInfo methods. +// +//========================================================================= + +XSERVICEINFO_IMPL_1( + ContentProvider, + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.comp.ucb.TransientDocumentsContentProvider" ) ), + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + TDOC_CONTENT_PROVIDER_SERVICE_NAME ) ) ); + +//========================================================================= +// +// Service factory implementation. +// +//========================================================================= + +ONE_INSTANCE_SERVICE_FACTORY_IMPL( ContentProvider ); + +//========================================================================= +// +// XContentProvider methods. +// +//========================================================================= + +// virtual +uno::Reference< ucb::XContent > SAL_CALL +ContentProvider::queryContent( + const uno::Reference< ucb::XContentIdentifier >& Identifier ) + throw( ucb::IllegalIdentifierException, uno::RuntimeException ) +{ + Uri aUri( Identifier->getContentIdentifier() ); + if ( !aUri.isValid() ) + throw ucb::IllegalIdentifierException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Invalid URL!" ) ), + Identifier ); + + // Normalize URI. + uno::Reference< ucb::XContentIdentifier > xCanonicId + = new ::ucbhelper::ContentIdentifier( m_xSMgr, aUri.getUri() ); + + osl::MutexGuard aGuard( m_aMutex ); + + // Check, if a content with given id already exists... + uno::Reference< ucb::XContent > xContent + = queryExistingContent( xCanonicId ).get(); + + if ( !xContent.is() ) + { + // Create a new content. + xContent = Content::create( m_xSMgr, this, xCanonicId ); + registerNewContent( xContent ); + } + + return xContent; +} + +//========================================================================= +// +// XTransientDocumentsDocumentContentFactory methods. +// +//========================================================================= + +// virtual +uno::Reference< ucb::XContent > SAL_CALL +ContentProvider::createDocumentContent( + const uno::Reference< frame::XModel >& Model ) + throw ( lang::IllegalArgumentException, uno::RuntimeException ) +{ + // model -> id -> content identifier -> queryContent + if ( m_xDocsMgr.is() ) + { + rtl::OUString aDocId = m_xDocsMgr->queryDocumentId( Model ); + if ( aDocId.getLength() > 0 ) + { + rtl::OUStringBuffer aBuffer; + aBuffer.appendAscii( TDOC_URL_SCHEME ":/" ); + aBuffer.append( aDocId ); + + uno::Reference< ucb::XContentIdentifier > xId + = new ::ucbhelper::ContentIdentifier( + m_xSMgr, aBuffer.makeStringAndClear() ); + + osl::MutexGuard aGuard( m_aMutex ); + + // Check, if a content with given id already exists... + uno::Reference< ucb::XContent > xContent + = queryExistingContent( xId ).get(); + + if ( !xContent.is() ) + { + // Create a new content. + xContent = Content::create( m_xSMgr, this, xId ); + } + + if ( xContent.is() ) + return xContent; + + // no content. + throw lang::IllegalArgumentException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "Illegal Content Identifier!" ) ), + static_cast< cppu::OWeakObject * >( this ), + 1 ); + } + else + { + throw lang::IllegalArgumentException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "Unable to obtain document id from model!" ) ), + static_cast< cppu::OWeakObject * >( this ), + 1 ); + } + } + else + { + throw lang::IllegalArgumentException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "No Document Manager!" ) ), + static_cast< cppu::OWeakObject * >( this ), + 1 ); + } +} + +//========================================================================= +// +// interface OfficeDocumentsEventListener +// +//========================================================================= + +// virtual +void ContentProvider::notifyDocumentClosed( const rtl::OUString & rDocId ) +{ + osl::MutexGuard aGuard( getContentListMutex() ); + + ::ucbhelper::ContentRefList aAllContents; + queryExistingContents( aAllContents ); + + ::ucbhelper::ContentRefList::const_iterator it = aAllContents.begin(); + ::ucbhelper::ContentRefList::const_iterator end = aAllContents.end(); + + // Notify all content objects related to the closed doc. + + bool bFoundDocumentContent = false; + rtl::Reference< Content > xRoot; + + while ( it != end ) + { + Uri aUri( (*it)->getIdentifier()->getContentIdentifier() ); + OSL_ENSURE( aUri.isValid(), + "ContentProvider::notifyDocumentClosed - Invalid URI!" ); + + if ( !bFoundDocumentContent ) + { + if ( aUri.isRoot() ) + { + xRoot = static_cast< Content * >( (*it).get() ); + } + else if ( aUri.isDocument() ) + { + if ( aUri.getDocumentId() == rDocId ) + { + bFoundDocumentContent = true; + + // document content will notify removal of child itself; + // no need for the root to propagate this. + xRoot.clear(); + } + } + } + + if ( aUri.getDocumentId() == rDocId ) + { + // Inform content. + rtl::Reference< Content > xContent + = static_cast< Content * >( (*it).get() ); + + xContent->notifyDocumentClosed(); + } + + ++it; + } + + if ( xRoot.is() ) + { + // No document content found for rDocId but root content + // instanciated. Root content must announce document removal + // to content event listeners. + xRoot->notifyChildRemoved( rDocId ); + } +} + +//========================================================================= +// virtual +void ContentProvider::notifyDocumentOpened( const rtl::OUString & rDocId ) +{ + osl::MutexGuard aGuard( getContentListMutex() ); + + ::ucbhelper::ContentRefList aAllContents; + queryExistingContents( aAllContents ); + + ::ucbhelper::ContentRefList::const_iterator it = aAllContents.begin(); + ::ucbhelper::ContentRefList::const_iterator end = aAllContents.end(); + + // Find root content. If instanciated let it propagate document insertion. + + while ( it != end ) + { + Uri aUri( (*it)->getIdentifier()->getContentIdentifier() ); + OSL_ENSURE( aUri.isValid(), + "ContentProvider::notifyDocumentOpened - Invalid URI!" ); + + if ( aUri.isRoot() ) + { + rtl::Reference< Content > xRoot + = static_cast< Content * >( (*it).get() ); + xRoot->notifyChildInserted( rDocId ); + + // Done. + break; + } + + ++it; + } +} + +//========================================================================= +// +// Non-UNO +// +//========================================================================= + +uno::Reference< embed::XStorage > +ContentProvider::queryStorage( const rtl::OUString & rUri, + StorageAccessMode eMode ) const +{ + if ( m_xStgElemFac.is() ) + { + try + { + return m_xStgElemFac->createStorage( rUri, eMode ); + } + catch ( embed::InvalidStorageException const & ) + { + OSL_ENSURE( false, "Caught InvalidStorageException!" ); + } + catch ( lang::IllegalArgumentException const & ) + { + OSL_ENSURE( false, "Caught IllegalArgumentException!" ); + } + catch ( io::IOException const & ) + { + // Okay to happen, for instance when the storage does not exist. + //OSL_ENSURE( false, "Caught IOException!" ); + } + catch ( embed::StorageWrappedTargetException const & ) + { + OSL_ENSURE( false, "Caught embed::StorageWrappedTargetException!" ); + } + } + return uno::Reference< embed::XStorage >(); +} + +//========================================================================= +uno::Reference< embed::XStorage > +ContentProvider::queryStorageClone( const rtl::OUString & rUri ) const +{ + if ( m_xStgElemFac.is() ) + { + try + { + Uri aUri( rUri ); + uno::Reference< embed::XStorage > xParentStorage + = m_xStgElemFac->createStorage( aUri.getParentUri(), READ ); + uno::Reference< embed::XStorage > xStorage + = m_xStgElemFac->createTemporaryStorage(); + + xParentStorage->copyStorageElementLastCommitTo( + aUri.getDecodedName(), xStorage ); + return xStorage; + } + catch ( embed::InvalidStorageException const & ) + { + OSL_ENSURE( false, "Caught InvalidStorageException!" ); + } + catch ( lang::IllegalArgumentException const & ) + { + OSL_ENSURE( false, "Caught IllegalArgumentException!" ); + } + catch ( io::IOException const & ) + { + // Okay to happen, for instance when the storage does not exist. + //OSL_ENSURE( false, "Caught IOException!" ); + } + catch ( embed::StorageWrappedTargetException const & ) + { + OSL_ENSURE( false, "Caught embed::StorageWrappedTargetException!" ); + } + } + + return uno::Reference< embed::XStorage >(); +} + +//========================================================================= +uno::Reference< io::XInputStream > +ContentProvider::queryInputStream( const rtl::OUString & rUri, + const rtl::OUString & rPassword ) const + throw ( packages::WrongPasswordException ) +{ + if ( m_xStgElemFac.is() ) + { + try + { + return m_xStgElemFac->createInputStream( rUri, rPassword ); + } + catch ( embed::InvalidStorageException const & ) + { + OSL_ENSURE( false, "Caught InvalidStorageException!" ); + } + catch ( lang::IllegalArgumentException const & ) + { + OSL_ENSURE( false, "Caught IllegalArgumentException!" ); + } + catch ( io::IOException const & ) + { + OSL_ENSURE( false, "Caught IOException!" ); + } + catch ( embed::StorageWrappedTargetException const & ) + { + OSL_ENSURE( false, "Caught embed::StorageWrappedTargetException!" ); + } +// catch ( packages::WrongPasswordException const & ) +// { +// // the key provided is wrong; rethrow; to be handled by caller. +// throw; +// } + } + return uno::Reference< io::XInputStream >(); +} + +//========================================================================= +uno::Reference< io::XOutputStream > +ContentProvider::queryOutputStream( const rtl::OUString & rUri, + const rtl::OUString & rPassword, + bool bTruncate ) const + throw ( packages::WrongPasswordException ) +{ + if ( m_xStgElemFac.is() ) + { + try + { + return + m_xStgElemFac->createOutputStream( rUri, rPassword, bTruncate ); + } + catch ( embed::InvalidStorageException const & ) + { + OSL_ENSURE( false, "Caught InvalidStorageException!" ); + } + catch ( lang::IllegalArgumentException const & ) + { + OSL_ENSURE( false, "Caught IllegalArgumentException!" ); + } + catch ( io::IOException const & ) + { + // Okay to happen, for instance when the storage does not exist. + //OSL_ENSURE( false, "Caught IOException!" ); + } + catch ( embed::StorageWrappedTargetException const & ) + { + OSL_ENSURE( false, "Caught embed::StorageWrappedTargetException!" ); + } +// catch ( packages::WrongPasswordException const & ) +// { +// // the key provided is wrong; rethrow; to be handled by caller. +// throw; +// } + } + return uno::Reference< io::XOutputStream >(); +} + +//========================================================================= +uno::Reference< io::XStream > +ContentProvider::queryStream( const rtl::OUString & rUri, + const rtl::OUString & rPassword, + bool bTruncate ) const + throw ( packages::WrongPasswordException ) +{ + if ( m_xStgElemFac.is() ) + { + try + { + return m_xStgElemFac->createStream( rUri, rPassword, bTruncate ); + } + catch ( embed::InvalidStorageException const & ) + { + OSL_ENSURE( false, "Caught InvalidStorageException!" ); + } + catch ( lang::IllegalArgumentException const & ) + { + OSL_ENSURE( false, "Caught IllegalArgumentException!" ); + } + catch ( io::IOException const & ) + { + // Okay to happen, for instance when the storage does not exist. + //OSL_ENSURE( false, "Caught IOException!" ); + } + catch ( embed::StorageWrappedTargetException const & ) + { + OSL_ENSURE( false, "Caught embed::StorageWrappedTargetException!" ); + } +// catch ( packages::WrongPasswordException const & ) +// { +// // the key provided is wrong; rethrow; to be handled by caller. +// throw; +// } + } + return uno::Reference< io::XStream >(); +} + +//========================================================================= +bool ContentProvider::queryNamesOfChildren( + const rtl::OUString & rUri, uno::Sequence< rtl::OUString > & rNames ) const +{ + Uri aUri( rUri ); + if ( aUri.isRoot() ) + { + // special handling for root, which has no storage, but children. + if ( m_xDocsMgr.is() ) + { + rNames = m_xDocsMgr->queryDocuments(); + return true; + } + } + else + { + if ( m_xStgElemFac.is() ) + { + try + { + uno::Reference< embed::XStorage > xStorage + = m_xStgElemFac->createStorage( rUri, READ ); + + OSL_ENSURE( xStorage.is(), "Got no Storage!" ); + + if ( xStorage.is() ) + { + uno::Reference< container::XNameAccess > xNA( + xStorage, uno::UNO_QUERY ); + + OSL_ENSURE( xNA.is(), "Got no css.container.XNameAccess!" ); + if ( xNA.is() ) + { + rNames = xNA->getElementNames(); + return true; + } + } + } + catch ( embed::InvalidStorageException const & ) + { + OSL_ENSURE( false, "Caught InvalidStorageException!" ); + } + catch ( lang::IllegalArgumentException const & ) + { + OSL_ENSURE( false, "Caught IllegalArgumentException!" ); + } + catch ( io::IOException const & ) + { + // Okay to happen, for instance if the storage does not exist. + //OSL_ENSURE( false, "Caught IOException!" ); + } + catch ( embed::StorageWrappedTargetException const & ) + { + OSL_ENSURE( false, + "Caught embed::StorageWrappedTargetException!" ); + } + } + } + return false; +} + +//========================================================================= +rtl::OUString +ContentProvider::queryStorageTitle( const rtl::OUString & rUri ) const +{ + rtl::OUString aTitle; + + Uri aUri( rUri ); + if ( aUri.isRoot() ) + { + // always empty. + aTitle = rtl::OUString(); + } + else if ( aUri.isDocument() ) + { + // for documents, title shall not be derived from URL. It shall + // be somethimg more 'speaking' than just the document UID. + if ( m_xDocsMgr.is() ) + aTitle = m_xDocsMgr->queryStorageTitle( aUri.getDocumentId() ); + } + else + { + // derive title from URL + aTitle = aUri.getDecodedName(); + } + + OSL_ENSURE( ( aTitle.getLength() > 0 ) || aUri.isRoot(), + "ContentProvider::queryStorageTitle - empty title!" ); + return aTitle; +} + +//========================================================================= +uno::Reference< frame::XModel > +ContentProvider::queryDocumentModel( const rtl::OUString & rUri ) const +{ + uno::Reference< frame::XModel > xModel; + + if ( m_xDocsMgr.is() ) + { + Uri aUri( rUri ); + xModel = m_xDocsMgr->queryDocumentModel( aUri.getDocumentId() ); + } + + OSL_ENSURE( xModel.is(), + "ContentProvider::queryDocumentModel - no model!" ); + return xModel; +} + diff --git a/ucb/source/ucp/tdoc/tdoc_provider.hxx b/ucb/source/ucp/tdoc/tdoc_provider.hxx new file mode 100644 index 000000000000..70f61e130980 --- /dev/null +++ b/ucb/source/ucp/tdoc/tdoc_provider.hxx @@ -0,0 +1,148 @@ +/************************************************************************* + * + * 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 INCLUDED_TDOC_PROVIDER_HXX +#define INCLUDED_TDOC_PROVIDER_HXX + +#include "rtl/ref.hxx" +#include <com/sun/star/frame/XTransientDocumentsDocumentContentFactory.hpp> +#include <com/sun/star/packages/WrongPasswordException.hpp> +#include "ucbhelper/providerhelper.hxx" +#include "tdoc_uri.hxx" // for TDOC_URL_SCHEME +#include "tdoc_docmgr.hxx" +#include "tdoc_storage.hxx" // for StorageAccessMode + +namespace com { namespace sun { namespace star { namespace embed { + class XStorage; +} } } } + +namespace com { namespace sun { namespace star { namespace frame { + class XModel; +} } } } + +namespace tdoc_ucp { + +//========================================================================= + +#define TDOC_CONTENT_PROVIDER_SERVICE_NAME \ + "com.sun.star.ucb.TransientDocumentsContentProvider" +#define TDOC_CONTENT_PROVIDER_SERVICE_NAME_LENGTH 50 + +#define TDOC_ROOT_CONTENT_TYPE \ + "application/" TDOC_URL_SCHEME "-root" +#define TDOC_DOCUMENT_CONTENT_TYPE \ + "application/" TDOC_URL_SCHEME "-document" +#define TDOC_FOLDER_CONTENT_TYPE \ + "application/" TDOC_URL_SCHEME "-folder" +#define TDOC_STREAM_CONTENT_TYPE \ + "application/" TDOC_URL_SCHEME "-stream" + +//========================================================================= + +class StorageElementFactory; + +class ContentProvider : + public ::ucbhelper::ContentProviderImplHelper, + public com::sun::star::frame::XTransientDocumentsDocumentContentFactory, + public OfficeDocumentsEventListener +{ +public: + ContentProvider( const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rXSMgr ); + virtual ~ContentProvider(); + + // XInterface + XINTERFACE_DECL() + + // XTypeProvider + XTYPEPROVIDER_DECL() + + // XServiceInfo + XSERVICEINFO_DECL() + + // XContentProvider + virtual com::sun::star::uno::Reference< + com::sun::star::ucb::XContent > SAL_CALL + queryContent( const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& Identifier ) + throw( com::sun::star::ucb::IllegalIdentifierException, + com::sun::star::uno::RuntimeException ); + + // XTransientDocumentsDocumentContentFactory + virtual com::sun::star::uno::Reference< + com::sun::star::ucb::XContent > SAL_CALL + createDocumentContent( const ::com::sun::star::uno::Reference< + com::sun::star::frame::XModel >& Model ) + throw ( com::sun::star::lang::IllegalArgumentException, + com::sun::star::uno::RuntimeException ); + + // Non-UNO interfaces + com::sun::star::uno::Reference< com::sun::star::embed::XStorage > + queryStorage( const rtl::OUString & rUri, StorageAccessMode eMode ) const; + + com::sun::star::uno::Reference< com::sun::star::embed::XStorage > + queryStorageClone( const rtl::OUString & rUri ) const; + + com::sun::star::uno::Reference< com::sun::star::io::XInputStream > + queryInputStream( const rtl::OUString & rUri, + const rtl::OUString & rPassword ) const + throw ( com::sun::star::packages::WrongPasswordException ); + + com::sun::star::uno::Reference< com::sun::star::io::XOutputStream > + queryOutputStream( const rtl::OUString & rUri, + const rtl::OUString & rPassword, + bool bTruncate ) const + throw ( com::sun::star::packages::WrongPasswordException ); + + com::sun::star::uno::Reference< com::sun::star::io::XStream > + queryStream( const rtl::OUString & rUri, + const rtl::OUString & rPassword, + bool bTruncate ) const + throw ( com::sun::star::packages::WrongPasswordException ); + + bool queryNamesOfChildren( + const rtl::OUString & rUri, + com::sun::star::uno::Sequence< rtl::OUString > & rNames ) const; + + // storage properties + rtl::OUString queryStorageTitle( const rtl::OUString & rUri ) const; + + com::sun::star::uno::Reference< com::sun::star::frame::XModel > + queryDocumentModel( const rtl::OUString & rUri ) const; + + // interface OfficeDocumentsEventListener + virtual void notifyDocumentOpened( const rtl::OUString & rDocId ); + virtual void notifyDocumentClosed( const rtl::OUString & rDocId ); + +private: + rtl::Reference< OfficeDocumentsManager > m_xDocsMgr; + rtl::Reference< StorageElementFactory > m_xStgElemFac; +}; + +} // namespace tdoc_ucp + +#endif /* !INCLUDED_TDOC_PROVIDER_HXX */ diff --git a/ucb/source/ucp/tdoc/tdoc_resultset.cxx b/ucb/source/ucp/tdoc/tdoc_resultset.cxx new file mode 100644 index 000000000000..d8212fa028bb --- /dev/null +++ b/ucb/source/ucp/tdoc/tdoc_resultset.cxx @@ -0,0 +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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + - This implementation is not a dynamic result set!!! It only implements + the necessary interfaces, but never recognizes/notifies changes!!! + + *************************************************************************/ + +#include "ucbhelper/resultset.hxx" + +#include "tdoc_datasupplier.hxx" +#include "tdoc_resultset.hxx" +#include "tdoc_content.hxx" + +using namespace com::sun::star; +using namespace tdoc_ucp; + +//========================================================================= +//========================================================================= +// +// DynamicResultSet Implementation. +// +//========================================================================= +//========================================================================= + +DynamicResultSet::DynamicResultSet( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + const rtl::Reference< Content >& rxContent, + const ucb::OpenCommandArgument2& rCommand ) +: ResultSetImplHelper( rxSMgr, rCommand ), + m_xContent( rxContent ) +{ +} + +//========================================================================= +// +// Non-interface methods. +// +//========================================================================= + +void DynamicResultSet::initStatic() +{ + m_xResultSet1 + = new ::ucbhelper::ResultSet( + m_xSMgr, + m_aCommand.Properties, + new ResultSetDataSupplier( m_xSMgr, + m_xContent, + m_aCommand.Mode ) ); +} + +//========================================================================= +void DynamicResultSet::initDynamic() +{ + m_xResultSet1 + = new ::ucbhelper::ResultSet( + m_xSMgr, + m_aCommand.Properties, + new ResultSetDataSupplier( m_xSMgr, + m_xContent, + m_aCommand.Mode ) ); + m_xResultSet2 = m_xResultSet1; +} + diff --git a/ucb/source/ucp/tdoc/tdoc_resultset.hxx b/ucb/source/ucp/tdoc/tdoc_resultset.hxx new file mode 100644 index 000000000000..a3e420894ade --- /dev/null +++ b/ucb/source/ucp/tdoc/tdoc_resultset.hxx @@ -0,0 +1,56 @@ +/************************************************************************* + * + * 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 INCLUDED_TDOC_RESULTSET_HXX +#define INCLUDED_TDOC_RESULTSET_HXX + +#include <rtl/ref.hxx> +#include <ucbhelper/resultsethelper.hxx> + +namespace tdoc_ucp { + +class Content; + +class DynamicResultSet : public ::ucbhelper::ResultSetImplHelper +{ + rtl::Reference< Content > m_xContent; + +private: + virtual void initStatic(); + virtual void initDynamic(); + +public: + DynamicResultSet( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + const rtl::Reference< Content >& rxContent, + const com::sun::star::ucb::OpenCommandArgument2& rCommand ); +}; + +} + +#endif /* !INCLUDED_TDOC_RESULTSET_HXX */ diff --git a/ucb/source/ucp/tdoc/tdoc_services.cxx b/ucb/source/ucp/tdoc/tdoc_services.cxx new file mode 100644 index 000000000000..fc34fd78b1a4 --- /dev/null +++ b/ucb/source/ucp/tdoc/tdoc_services.cxx @@ -0,0 +1,89 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +#include "com/sun/star/lang/XMultiServiceFactory.hpp" +#include "com/sun/star/lang/XSingleServiceFactory.hpp" +#include "com/sun/star/registry/XRegistryKey.hpp" + +#include "tdoc_provider.hxx" +#include "tdoc_documentcontentfactory.hxx" + +using namespace com::sun::star; +using namespace tdoc_ucp; + +//========================================================================= +extern "C" void SAL_CALL component_getImplementationEnvironment( + const sal_Char ** ppEnvTypeName, uno_Environment ** /*ppEnv*/ ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + +//========================================================================= +extern "C" void * SAL_CALL component_getFactory( + const sal_Char * pImplName, void * pServiceManager, void * /*pRegistryKey*/ ) +{ + void * pRet = 0; + + uno::Reference< lang::XMultiServiceFactory > xSMgr( + reinterpret_cast< lang::XMultiServiceFactory * >( + pServiceManager ) ); + uno::Reference< lang::XSingleServiceFactory > xFactory; + + ////////////////////////////////////////////////////////////////////// + // Transient Documents Content Provider. + ////////////////////////////////////////////////////////////////////// + + if ( ContentProvider::getImplementationName_Static(). + compareToAscii( pImplName ) == 0 ) + { + xFactory = ContentProvider::createServiceFactory( xSMgr ); + } + + ////////////////////////////////////////////////////////////////////// + // Transient Documents Document Content Factory. + ////////////////////////////////////////////////////////////////////// + + else if ( DocumentContentFactory::getImplementationName_Static(). + compareToAscii( pImplName ) == 0 ) + { + xFactory = DocumentContentFactory::createServiceFactory( xSMgr ); + } + + ////////////////////////////////////////////////////////////////////// + + if ( xFactory.is() ) + { + xFactory->acquire(); + pRet = xFactory.get(); + } + + return pRet; +} + diff --git a/ucb/source/ucp/tdoc/tdoc_stgelems.cxx b/ucb/source/ucp/tdoc/tdoc_stgelems.cxx new file mode 100644 index 000000000000..0bd25f94d096 --- /dev/null +++ b/ucb/source/ucp/tdoc/tdoc_stgelems.cxx @@ -0,0 +1,1108 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + - remove root storage access workaround + + *************************************************************************/ + +#include "com/sun/star/lang/DisposedException.hpp" +#include "com/sun/star/reflection/XProxyFactory.hpp" + +#include "tdoc_uri.hxx" + +#include "tdoc_stgelems.hxx" + +using namespace com::sun::star; +using namespace tdoc_ucp; + +//========================================================================= +//========================================================================= +// +// ParentStorageHolder Implementation. +// +//========================================================================= +//========================================================================= + +ParentStorageHolder::ParentStorageHolder( + const uno::Reference< embed::XStorage > & xParentStorage, + const rtl::OUString & rUri ) +: m_xParentStorage( xParentStorage ), + m_bParentIsRootStorage( false ) +{ + Uri aUri( rUri ); + if ( aUri.isDocument() ) + m_bParentIsRootStorage = true; +} + +//========================================================================= +//========================================================================= +// +// Storage Implementation. +// +//========================================================================= +//========================================================================= + +Storage::Storage( const uno::Reference< lang::XMultiServiceFactory > & xSMgr, + const rtl::Reference< StorageElementFactory > & xFactory, + const rtl::OUString & rUri, + const uno::Reference< embed::XStorage > & xParentStorage, + const uno::Reference< embed::XStorage > & xStorageToWrap ) +: ParentStorageHolder( xParentStorage, Uri( rUri ).getParentUri() ), + m_xFactory( xFactory ), + m_xWrappedStorage( xStorageToWrap ), + m_xWrappedTransObj( xStorageToWrap, uno::UNO_QUERY ), // optional interface + m_xWrappedComponent( xStorageToWrap, uno::UNO_QUERY ), + m_xWrappedTypeProv( xStorageToWrap, uno::UNO_QUERY ), + m_bIsDocumentStorage( Uri( rUri ).isDocument() ) +{ + OSL_ENSURE( m_xWrappedStorage.is(), + "Storage::Storage: No storage to wrap!" ); + + OSL_ENSURE( m_xWrappedComponent.is(), + "Storage::Storage: No component to wrap!" ); + + OSL_ENSURE( m_xWrappedTypeProv.is(), + "Storage::Storage: No Type Provider!" ); + + // Use proxy factory service to create aggregatable proxy. + try + { + uno::Reference< reflection::XProxyFactory > xProxyFac( + xSMgr->createInstance( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.reflection.ProxyFactory" ) ) ), + uno::UNO_QUERY ); + if ( xProxyFac.is() ) + { + m_xAggProxy = xProxyFac->createProxy( m_xWrappedStorage ); + } + } + catch ( uno::Exception const & ) + { + OSL_ENSURE( false, "Storage::Storage: Caught exception!" ); + } + + OSL_ENSURE( m_xAggProxy.is(), + "Storage::Storage: Wrapped storage cannot be aggregated!" ); + + if ( m_xAggProxy.is() ) + { + osl_incrementInterlockedCount( &m_refCount ); + { + // Solaris compiler problem: + // Extra block to enforce destruction of temporary object created + // in next statement _before_ osl_decrementInterlockedCount is + // called. Otherwise 'this' will destroy itself even before ctor + // is completed (See impl. of XInterface::release())! + + m_xAggProxy->setDelegator( + static_cast< cppu::OWeakObject * >( this ) ); + } + osl_decrementInterlockedCount( &m_refCount ); + } +} + +//========================================================================= +// virtual +Storage::~Storage() +{ + if ( m_xAggProxy.is() ) + m_xAggProxy->setDelegator( uno::Reference< uno::XInterface >() ); + + // Never dispose a document storage. Not owner! + if ( !isDocumentStorage() ) + { + if ( m_xWrappedComponent.is() ) + { + // "Auto-dispose"... + try + { + m_xWrappedComponent->dispose(); + } + catch ( lang::DisposedException const & ) + { + // might happen. + } + catch ( ... ) + { + OSL_ENSURE( false, "Storage::~Storage - Caught exception!" ); + } + } + } +} + +//========================================================================= +// +// uno::XInterface +// +//========================================================================= + +// virtual +uno::Any SAL_CALL Storage::queryInterface( const uno::Type& aType ) + throw ( uno::RuntimeException ) +{ + // First, try to use interfaces implemented by myself and base class(es) + uno::Any aRet = StorageUNOBase::queryInterface( aType ); + + if ( aRet.hasValue() ) + return aRet; + + // Try to use requested interface from aggregated storage + return m_xAggProxy->queryAggregation( aType ); +} + +//========================================================================= +// virtual +void SAL_CALL Storage::acquire() + throw () +{ + osl_incrementInterlockedCount( &m_refCount ); +} + +//========================================================================= +// virtual +void SAL_CALL Storage::release() + throw () +{ + if ( osl_decrementInterlockedCount( &m_refCount ) == 0 ) + { + m_xFactory->releaseElement( this ); + delete this; + } +} + +//========================================================================= +// +// lang::XTypeProvider +// +//========================================================================= + +// virtual +uno::Sequence< uno::Type > SAL_CALL Storage::getTypes() + throw ( uno::RuntimeException ) +{ + return m_xWrappedTypeProv->getTypes(); +} + +//========================================================================= +// virtual +uno::Sequence< sal_Int8 > SAL_CALL Storage::getImplementationId() + throw ( uno::RuntimeException ) +{ + return m_xWrappedTypeProv->getImplementationId(); +} + +//========================================================================= +// +// lang::XComponent (base of embed::XStorage) +// +//========================================================================= +// virtual +void SAL_CALL Storage::dispose() + throw ( uno::RuntimeException ) +{ + m_xWrappedStorage->dispose(); +} + +//========================================================================= +// virtual +void SAL_CALL Storage::addEventListener( + const uno::Reference< lang::XEventListener >& xListener ) + throw ( uno::RuntimeException ) +{ + m_xWrappedStorage->addEventListener( xListener ); +} +//========================================================================= +// virtual +void SAL_CALL Storage::removeEventListener( + const uno::Reference< lang::XEventListener >& aListener ) + throw (uno::RuntimeException) +{ + m_xWrappedStorage->removeEventListener( aListener ); +} + +//========================================================================= +// +// container::XElementAccess (base of container::XNameAccess) +// +//========================================================================= + +// virtual +uno::Type SAL_CALL Storage::getElementType() + throw ( uno::RuntimeException ) +{ + return m_xWrappedStorage->getElementType(); +} + +//========================================================================= +// virtual +::sal_Bool SAL_CALL Storage::hasElements() + throw ( uno::RuntimeException ) +{ + return m_xWrappedStorage->hasElements(); +} + +//========================================================================= +// +// container::XNameAccess (base of embed::XStorage) +// +//========================================================================= + +// virtual +uno::Any SAL_CALL Storage::getByName( const ::rtl::OUString& aName ) + throw ( container::NoSuchElementException, + lang::WrappedTargetException, + uno::RuntimeException ) +{ + return m_xWrappedStorage->getByName( aName ); +} + +//========================================================================= +// virtual +uno::Sequence< ::rtl::OUString > SAL_CALL Storage::getElementNames() + throw ( uno::RuntimeException ) +{ + return m_xWrappedStorage->getElementNames(); +} + +//========================================================================= +// virtual +::sal_Bool SAL_CALL Storage::hasByName( const ::rtl::OUString& aName ) + throw ( uno::RuntimeException ) +{ + return m_xWrappedStorage->hasByName( aName ); +} + +//========================================================================= +// +// embed::XStorage +// +//========================================================================= + +// virtual +void SAL_CALL Storage::copyToStorage( + const uno::Reference< embed::XStorage >& xDest ) + throw ( embed::InvalidStorageException, + lang::IllegalArgumentException, + io::IOException, + embed::StorageWrappedTargetException, + uno::RuntimeException ) +{ + m_xWrappedStorage->copyToStorage( xDest ); +} + +//========================================================================= +// virtual +uno::Reference< io::XStream > SAL_CALL Storage::openStreamElement( + const ::rtl::OUString& aStreamName, sal_Int32 nOpenMode ) + throw ( embed::InvalidStorageException, + lang::IllegalArgumentException, + packages::WrongPasswordException, + io::IOException, + embed::StorageWrappedTargetException, + uno::RuntimeException ) +{ + return m_xWrappedStorage->openStreamElement( aStreamName, nOpenMode ); +} + +//========================================================================= +// virtual +uno::Reference< io::XStream > SAL_CALL Storage::openEncryptedStreamElement( + const ::rtl::OUString& aStreamName, + sal_Int32 nOpenMode, + const ::rtl::OUString& aPassword ) + throw ( embed::InvalidStorageException, + lang::IllegalArgumentException, + packages::NoEncryptionException, + packages::WrongPasswordException, + io::IOException, + embed::StorageWrappedTargetException, + uno::RuntimeException ) +{ + return m_xWrappedStorage->openEncryptedStreamElement( + aStreamName, nOpenMode, aPassword ); +} + +//========================================================================= +// virtual +uno::Reference< embed::XStorage > SAL_CALL Storage::openStorageElement( + const ::rtl::OUString& aStorName, sal_Int32 nOpenMode ) + throw ( embed::InvalidStorageException, + lang::IllegalArgumentException, + io::IOException, + embed::StorageWrappedTargetException, + uno::RuntimeException ) +{ + return m_xWrappedStorage->openStorageElement( aStorName, nOpenMode ); +} + +//========================================================================= +// virtual +uno::Reference< io::XStream > SAL_CALL Storage::cloneStreamElement( + const ::rtl::OUString& aStreamName ) + throw ( embed::InvalidStorageException, + lang::IllegalArgumentException, + packages::WrongPasswordException, + io::IOException, + embed::StorageWrappedTargetException, + uno::RuntimeException ) +{ + return m_xWrappedStorage->cloneStreamElement( aStreamName ); +} + +//========================================================================= +// virtual +uno::Reference< io::XStream > SAL_CALL Storage::cloneEncryptedStreamElement( + const ::rtl::OUString& aStreamName, + const ::rtl::OUString& aPassword ) + throw ( embed::InvalidStorageException, + lang::IllegalArgumentException, + packages::NoEncryptionException, + packages::WrongPasswordException, + io::IOException, + embed::StorageWrappedTargetException, + uno::RuntimeException ) +{ + return m_xWrappedStorage->cloneEncryptedStreamElement( aStreamName, + aPassword ); +} + +//========================================================================= +// virtual +void SAL_CALL Storage::copyLastCommitTo( + const uno::Reference< embed::XStorage >& xTargetStorage ) + throw ( embed::InvalidStorageException, + lang::IllegalArgumentException, + io::IOException, + embed::StorageWrappedTargetException, + uno::RuntimeException) +{ + m_xWrappedStorage->copyLastCommitTo( xTargetStorage ); +} + +//========================================================================= +// virtual +void SAL_CALL Storage::copyStorageElementLastCommitTo( + const ::rtl::OUString& aStorName, + const uno::Reference< embed::XStorage >& xTargetStorage ) + throw ( embed::InvalidStorageException, + lang::IllegalArgumentException, + io::IOException, + embed::StorageWrappedTargetException, + uno::RuntimeException) +{ + m_xWrappedStorage->copyStorageElementLastCommitTo( aStorName, xTargetStorage ); +} + +//========================================================================= +// virtual +sal_Bool SAL_CALL Storage::isStreamElement( + const ::rtl::OUString& aElementName ) + throw ( container::NoSuchElementException, + lang::IllegalArgumentException, + embed::InvalidStorageException, + uno::RuntimeException ) +{ + return m_xWrappedStorage->isStreamElement( aElementName ); +} + +//========================================================================= +// virtual +sal_Bool SAL_CALL Storage::isStorageElement( + const ::rtl::OUString& aElementName ) + throw ( container::NoSuchElementException, + lang::IllegalArgumentException, + embed::InvalidStorageException, + uno::RuntimeException ) +{ + return m_xWrappedStorage->isStorageElement( aElementName ); +} + +//========================================================================= +// virtual +void SAL_CALL Storage::removeElement( const ::rtl::OUString& aElementName ) + throw ( embed::InvalidStorageException, + lang::IllegalArgumentException, + container::NoSuchElementException, + io::IOException, + embed::StorageWrappedTargetException, + uno::RuntimeException ) +{ + m_xWrappedStorage->removeElement( aElementName ); +} + +//========================================================================= +// virtual +void SAL_CALL Storage::renameElement( const ::rtl::OUString& aEleName, + const ::rtl::OUString& aNewName ) + throw ( embed::InvalidStorageException, + lang::IllegalArgumentException, + container::NoSuchElementException, + container::ElementExistException, + io::IOException, + embed::StorageWrappedTargetException, + uno::RuntimeException ) +{ + m_xWrappedStorage->renameElement( aEleName, aNewName ); +} + +//========================================================================= +// virtual +void SAL_CALL Storage::copyElementTo( + const ::rtl::OUString& aElementName, + const uno::Reference< embed::XStorage >& xDest, + const ::rtl::OUString& aNewName ) + throw ( embed::InvalidStorageException, + lang::IllegalArgumentException, + container::NoSuchElementException, + container::ElementExistException, + io::IOException, + embed::StorageWrappedTargetException, + uno::RuntimeException ) +{ + m_xWrappedStorage->copyElementTo( aElementName, xDest, aNewName ); +} + +//========================================================================= +// virtual +void SAL_CALL Storage::moveElementTo( + const ::rtl::OUString& aElementName, + const uno::Reference< embed::XStorage >& xDest, + const ::rtl::OUString& rNewName ) + throw ( embed::InvalidStorageException, + lang::IllegalArgumentException, + container::NoSuchElementException, + container::ElementExistException, + io::IOException, + embed::StorageWrappedTargetException, + uno::RuntimeException ) +{ + m_xWrappedStorage->moveElementTo( aElementName, xDest, rNewName ); +} + +//========================================================================= +// +// embed::XTransactedObject +// +//========================================================================= + +// virtual +void SAL_CALL Storage::commit() + throw ( io::IOException, + lang::WrappedTargetException, + uno::RuntimeException ) +{ + // Never commit a root storage (-> has no parent)! + // Would lead in writing the whole document to disk. + + uno::Reference< embed::XStorage > xParentStorage = getParentStorage(); + if ( xParentStorage.is() ) + { + OSL_ENSURE( m_xWrappedTransObj.is(), "No XTransactedObject interface!" ); + + if ( m_xWrappedTransObj.is() ) + { + m_xWrappedTransObj->commit(); + + if ( !isParentARootStorage() ) + { + uno::Reference< embed::XTransactedObject > xParentTA( + xParentStorage, uno::UNO_QUERY ); + OSL_ENSURE( xParentTA.is(), "No XTransactedObject interface!" ); + + if ( xParentTA.is() ) + xParentTA->commit(); + } + } + } +} + +//========================================================================= +// virtual +void SAL_CALL Storage::revert() + throw ( io::IOException, + lang::WrappedTargetException, + uno::RuntimeException ) +{ + uno::Reference< embed::XStorage > xParentStorage = getParentStorage(); + if ( xParentStorage.is() ) + { + OSL_ENSURE( m_xWrappedTransObj.is(), "No XTransactedObject interface!" ); + + if ( m_xWrappedTransObj.is() ) + { + m_xWrappedTransObj->revert(); + + if ( !isParentARootStorage() ) + { + uno::Reference< embed::XTransactedObject > xParentTA( + xParentStorage, uno::UNO_QUERY ); + OSL_ENSURE( xParentTA.is(), "No XTransactedObject interface!" ); + + if ( xParentTA.is() ) + xParentTA->revert(); + } + } + } +} + +//========================================================================= +//========================================================================= +// +// OutputStream Implementation. +// +//========================================================================= +//========================================================================= + +OutputStream::OutputStream( + const uno::Reference< lang::XMultiServiceFactory > & xSMgr, + const rtl::OUString & rUri, + const uno::Reference< embed::XStorage > & xParentStorage, + const uno::Reference< io::XOutputStream > & xStreamToWrap ) +: ParentStorageHolder( xParentStorage, Uri( rUri ).getParentUri() ), + m_xWrappedStream( xStreamToWrap ), + m_xWrappedComponent( xStreamToWrap, uno::UNO_QUERY ), + m_xWrappedTypeProv( xStreamToWrap, uno::UNO_QUERY ) +{ + OSL_ENSURE( m_xWrappedStream.is(), + "OutputStream::OutputStream: No stream to wrap!" ); + + OSL_ENSURE( m_xWrappedComponent.is(), + "OutputStream::OutputStream: No component to wrap!" ); + + OSL_ENSURE( m_xWrappedTypeProv.is(), + "OutputStream::OutputStream: No Type Provider!" ); + + // Use proxy factory service to create aggregatable proxy. + try + { + uno::Reference< reflection::XProxyFactory > xProxyFac( + xSMgr->createInstance( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.reflection.ProxyFactory" ) ) ), + uno::UNO_QUERY ); + if ( xProxyFac.is() ) + { + m_xAggProxy = xProxyFac->createProxy( m_xWrappedStream ); + } + } + catch ( uno::Exception const & ) + { + OSL_ENSURE( false, "OutputStream::OutputStream: Caught exception!" ); + } + + OSL_ENSURE( m_xAggProxy.is(), + "OutputStream::OutputStream: Wrapped stream cannot be aggregated!" ); + + if ( m_xAggProxy.is() ) + { + osl_incrementInterlockedCount( &m_refCount ); + { + // Solaris compiler problem: + // Extra block to enforce destruction of temporary object created + // in next statement _before_ osl_decrementInterlockedCount is + // called. Otherwise 'this' will destroy itself even before ctor + // is completed (See impl. of XInterface::release())! + + m_xAggProxy->setDelegator( + static_cast< cppu::OWeakObject * >( this ) ); + } + osl_decrementInterlockedCount( &m_refCount ); + } +} + +//========================================================================= +// virtual +OutputStream::~OutputStream() +{ + if ( m_xAggProxy.is() ) + m_xAggProxy->setDelegator( uno::Reference< uno::XInterface >() ); +} + +//========================================================================= +// +// uno::XInterface +// +//========================================================================= + +// virtual +uno::Any SAL_CALL OutputStream::queryInterface( const uno::Type& aType ) + throw ( uno::RuntimeException ) +{ + uno::Any aRet = OutputStreamUNOBase::queryInterface( aType ); + + if ( aRet.hasValue() ) + return aRet; + + if ( m_xAggProxy.is() ) + return m_xAggProxy->queryAggregation( aType ); + else + return uno::Any(); +} + +//========================================================================= +// +// lang::XTypeProvider +// +//========================================================================= + +// virtual +uno::Sequence< uno::Type > SAL_CALL OutputStream::getTypes() + throw ( uno::RuntimeException ) +{ + return m_xWrappedTypeProv->getTypes(); +} + +//========================================================================= +// virtual +uno::Sequence< sal_Int8 > SAL_CALL OutputStream::getImplementationId() + throw ( uno::RuntimeException ) +{ + return m_xWrappedTypeProv->getImplementationId(); +} + +//========================================================================= +// +// io::XOutputStream +// +//========================================================================= + +// virtual +void SAL_CALL +OutputStream::writeBytes( const uno::Sequence< sal_Int8 >& aData ) + throw ( io::NotConnectedException, + io::BufferSizeExceededException, + io::IOException, + uno::RuntimeException ) +{ + m_xWrappedStream->writeBytes( aData ); +} + +//========================================================================= +// virtual +void SAL_CALL +OutputStream::flush() + throw ( io::NotConnectedException, + io::BufferSizeExceededException, + io::IOException, + uno::RuntimeException ) +{ + m_xWrappedStream->flush(); +} + +//========================================================================= +// virtual +void SAL_CALL +OutputStream::closeOutput( ) + throw ( io::NotConnectedException, + io::BufferSizeExceededException, + io::IOException, + uno::RuntimeException ) +{ + m_xWrappedStream->closeOutput(); + + // Release parent storage. + // Now, that the stream is closed/disposed it is not needed any longer. + setParentStorage( uno::Reference< embed::XStorage >() ); +} + +//========================================================================= +// +// lang::XComponent +// +//========================================================================= + +// virtual +void SAL_CALL +OutputStream::dispose() + throw ( uno::RuntimeException ) +{ + m_xWrappedComponent->dispose(); + + // Release parent storage. + // Now, that the stream is closed/disposed it is not needed any longer. + setParentStorage( uno::Reference< embed::XStorage >() ); +} + +//========================================================================= +// virtual +void SAL_CALL +OutputStream::addEventListener( + const uno::Reference< lang::XEventListener >& xListener ) + throw ( uno::RuntimeException ) +{ + m_xWrappedComponent->addEventListener( xListener ); +} + +//========================================================================= +// virtual +void SAL_CALL +OutputStream::removeEventListener( + const uno::Reference< lang::XEventListener >& aListener ) + throw ( uno::RuntimeException ) +{ + m_xWrappedComponent->removeEventListener( aListener ); +} + +//========================================================================= +//========================================================================= +// +// Stream Implementation. +// +//========================================================================= +//========================================================================= + +Stream::Stream( + const uno::Reference< lang::XMultiServiceFactory > & xSMgr, + const rtl::OUString & rUri, + const uno::Reference< embed::XStorage > & xParentStorage, + const uno::Reference< io::XStream > & xStreamToWrap ) +: ParentStorageHolder( xParentStorage, Uri( rUri ).getParentUri() ), + m_xWrappedStream( xStreamToWrap ), + m_xWrappedOutputStream( xStreamToWrap->getOutputStream() ), // might be empty + m_xWrappedTruncate( m_xWrappedOutputStream, uno::UNO_QUERY ), // might be empty + m_xWrappedInputStream( xStreamToWrap->getInputStream(), uno::UNO_QUERY ), + m_xWrappedComponent( xStreamToWrap, uno::UNO_QUERY ), + m_xWrappedTypeProv( xStreamToWrap, uno::UNO_QUERY ) +{ + OSL_ENSURE( m_xWrappedStream.is(), + "OutputStream::OutputStream: No stream to wrap!" ); + + OSL_ENSURE( m_xWrappedComponent.is(), + "OutputStream::OutputStream: No component to wrap!" ); + + OSL_ENSURE( m_xWrappedTypeProv.is(), + "OutputStream::OutputStream: No Type Provider!" ); + + // Use proxy factory service to create aggregatable proxy. + try + { + uno::Reference< reflection::XProxyFactory > xProxyFac( + xSMgr->createInstance( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.reflection.ProxyFactory" ) ) ), + uno::UNO_QUERY ); + if ( xProxyFac.is() ) + { + m_xAggProxy = xProxyFac->createProxy( m_xWrappedStream ); + } + } + catch ( uno::Exception const & ) + { + OSL_ENSURE( false, "OutputStream::OutputStream: Caught exception!" ); + } + + OSL_ENSURE( m_xAggProxy.is(), + "OutputStream::OutputStream: Wrapped stream cannot be aggregated!" ); + + if ( m_xAggProxy.is() ) + { + osl_incrementInterlockedCount( &m_refCount ); + { + // Solaris compiler problem: + // Extra block to enforce destruction of temporary object created + // in next statement _before_ osl_decrementInterlockedCount is + // called. Otherwise 'this' will destroy itself even before ctor + // is completed (See impl. of XInterface::release())! + + m_xAggProxy->setDelegator( + static_cast< cppu::OWeakObject * >( this ) ); + } + osl_decrementInterlockedCount( &m_refCount ); + } +} + +//========================================================================= +// virtual +Stream::~Stream() +{ + if ( m_xAggProxy.is() ) + m_xAggProxy->setDelegator( uno::Reference< uno::XInterface >() ); +} + +//========================================================================= +// +// uno::XInterface +// +//========================================================================= + +// virtual +uno::Any SAL_CALL Stream::queryInterface( const uno::Type& aType ) + throw ( uno::RuntimeException ) +{ + uno::Any aRet = StreamUNOBase::queryInterface( aType ); + + if ( aRet.hasValue() ) + return aRet; + + if ( m_xAggProxy.is() ) + return m_xAggProxy->queryAggregation( aType ); + else + return uno::Any(); +} + +//========================================================================= +// +// lang::XTypeProvider +// +//========================================================================= + +// virtual +uno::Sequence< uno::Type > SAL_CALL Stream::getTypes() + throw ( uno::RuntimeException ) +{ + return m_xWrappedTypeProv->getTypes(); +} + +//========================================================================= +// virtual +uno::Sequence< sal_Int8 > SAL_CALL Stream::getImplementationId() + throw ( uno::RuntimeException ) +{ + return m_xWrappedTypeProv->getImplementationId(); +} + +//========================================================================= +// +// io::XStream. +// +//========================================================================= + +// virtual +uno::Reference< io::XInputStream > SAL_CALL Stream::getInputStream() + throw( uno::RuntimeException ) +{ + return uno::Reference< io::XInputStream >( this ); +} + +//========================================================================= +// virtual +uno::Reference< io::XOutputStream > SAL_CALL Stream::getOutputStream() + throw( uno::RuntimeException ) +{ + return uno::Reference< io::XOutputStream >( this ); +} + +//========================================================================= +// +// io::XOutputStream. +// +//========================================================================= + +// virtual +void SAL_CALL Stream::writeBytes( const uno::Sequence< sal_Int8 >& aData ) + throw( io::NotConnectedException, + io::BufferSizeExceededException, + io::IOException, + uno::RuntimeException ) +{ + if ( m_xWrappedOutputStream.is() ) + { + m_xWrappedOutputStream->writeBytes( aData ); + commitChanges(); + } +} + +//========================================================================= +// virtual +void SAL_CALL Stream::flush() + throw( io::NotConnectedException, + io::BufferSizeExceededException, + io::IOException, + uno::RuntimeException ) +{ + if ( m_xWrappedOutputStream.is() ) + { + m_xWrappedOutputStream->flush(); + commitChanges(); + } +} + +//========================================================================= +// virtual +void SAL_CALL Stream::closeOutput() + throw( io::NotConnectedException, + io::IOException, + uno::RuntimeException ) +{ + if ( m_xWrappedOutputStream.is() ) + { + m_xWrappedOutputStream->closeOutput(); + commitChanges(); + } + + // Release parent storage. + // Now, that the stream is closed/disposed it is not needed any longer. + setParentStorage( uno::Reference< embed::XStorage >() ); +} + +//========================================================================= +// +// io::XTruncate. +// +//========================================================================= + +// virtual +void SAL_CALL Stream::truncate() + throw( io::IOException, + uno::RuntimeException ) +{ + if ( m_xWrappedTruncate.is() ) + { + m_xWrappedTruncate->truncate(); + commitChanges(); + } +} + +//========================================================================= +// +// io::XInputStream. +// +//========================================================================= + +// virtual +sal_Int32 SAL_CALL Stream::readBytes( uno::Sequence< sal_Int8 >& aData, + sal_Int32 nBytesToRead ) + throw( io::NotConnectedException, + io::BufferSizeExceededException, + io::IOException, + uno::RuntimeException ) +{ + return m_xWrappedInputStream->readBytes( aData, nBytesToRead ); +} + +//========================================================================= +// virtual +sal_Int32 SAL_CALL Stream::readSomeBytes( uno::Sequence< sal_Int8 >& aData, + sal_Int32 nMaxBytesToRead ) + throw( io::NotConnectedException, + io::BufferSizeExceededException, + io::IOException, + uno::RuntimeException ) +{ + return m_xWrappedInputStream->readSomeBytes( aData, nMaxBytesToRead ); +} + +//========================================================================= +// virtual +void SAL_CALL Stream::skipBytes( sal_Int32 nBytesToSkip ) + throw( io::NotConnectedException, + io::BufferSizeExceededException, + io::IOException, + uno::RuntimeException ) +{ + m_xWrappedInputStream->skipBytes( nBytesToSkip ); +} + +//========================================================================= +// virtual +sal_Int32 SAL_CALL Stream::available() + throw( io::NotConnectedException, + io::IOException, + uno::RuntimeException ) +{ + return m_xWrappedInputStream->available(); +} + +//========================================================================= +// virtual +void SAL_CALL Stream::closeInput() + throw( io::NotConnectedException, + io::IOException, + uno::RuntimeException ) +{ + m_xWrappedInputStream->closeInput(); +} + +//========================================================================= +// +// lang::XComponent +// +//========================================================================= + +// virtual +void SAL_CALL Stream::dispose() + throw ( uno::RuntimeException ) +{ + m_xWrappedComponent->dispose(); + + // Release parent storage. + // Now, that the stream is closed/disposed it is not needed any longer. + setParentStorage( uno::Reference< embed::XStorage >() ); +} + +//========================================================================= +// virtual +void SAL_CALL Stream::addEventListener( + const uno::Reference< lang::XEventListener >& xListener ) + throw ( uno::RuntimeException ) +{ + m_xWrappedComponent->addEventListener( xListener ); +} + +//========================================================================= +// virtual +void SAL_CALL Stream::removeEventListener( + const uno::Reference< lang::XEventListener >& aListener ) + throw ( uno::RuntimeException ) +{ + m_xWrappedComponent->removeEventListener( aListener ); +} + +//========================================================================= +// +// Non-UNO +// +//========================================================================= + +void Stream::commitChanges() + throw( io::IOException ) +{ + uno::Reference< embed::XTransactedObject > + xParentTA( getParentStorage(), uno::UNO_QUERY ); + OSL_ENSURE( xParentTA.is(), "No XTransactedObject interface!" ); + + if ( xParentTA.is() ) + { + try + { + xParentTA->commit(); + } + catch ( lang::WrappedTargetException const & ) + { + throw io::IOException(); // @@@ + } + } +} + diff --git a/ucb/source/ucp/tdoc/tdoc_stgelems.hxx b/ucb/source/ucp/tdoc/tdoc_stgelems.hxx new file mode 100644 index 000000000000..9afa15abf994 --- /dev/null +++ b/ucb/source/ucp/tdoc/tdoc_stgelems.hxx @@ -0,0 +1,542 @@ +/************************************************************************* + * + * 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 INCLUDED_TDOC_STGELEMS_HXX +#define INCLUDED_TDOC_STGELEMS_HXX + +#include <memory> + +#include "osl/mutex.hxx" +#include "rtl/ref.hxx" + +#include "cppuhelper/implbase2.hxx" +#include "cppuhelper/implbase5.hxx" + +#include "com/sun/star/embed/XStorage.hpp" +#include "com/sun/star/embed/XTransactedObject.hpp" +#include "com/sun/star/io/XOutputStream.hpp" +#include "com/sun/star/io/XStream.hpp" +#include "com/sun/star/io/XTruncate.hpp" +#include "com/sun/star/lang/XComponent.hpp" + +#include "tdoc_storage.hxx" + +namespace tdoc_ucp { + +struct MutexHolder +{ + osl::Mutex m_aMutex; +}; + +//======================================================================= + +class ParentStorageHolder : public MutexHolder +{ +public: + ParentStorageHolder( + const com::sun::star::uno::Reference< + com::sun::star::embed::XStorage > & xParentStorage, + const rtl::OUString & rUri ); + + bool isParentARootStorage() const + { return m_bParentIsRootStorage; } + com::sun::star::uno::Reference< com::sun::star::embed::XStorage > + getParentStorage() const + { return m_xParentStorage; } + void setParentStorage( const com::sun::star::uno::Reference< + com::sun::star::embed::XStorage > & xStg ) + { osl::MutexGuard aGuard( m_aMutex ); m_xParentStorage = xStg; } + +private: + com::sun::star::uno::Reference< + com::sun::star::embed::XStorage > m_xParentStorage; + bool m_bParentIsRootStorage; +}; + +//======================================================================= + +typedef + cppu::WeakImplHelper2< + com::sun::star::embed::XStorage, + com::sun::star::embed::XTransactedObject > StorageUNOBase; + +class Storage : public StorageUNOBase, public ParentStorageHolder +{ +public: + Storage( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory > & xSMgr, + const rtl::Reference< StorageElementFactory > & xFactory, + const rtl::OUString & rUri, + const com::sun::star::uno::Reference< + com::sun::star::embed::XStorage > & xParentStorage, + const com::sun::star::uno::Reference< + com::sun::star::embed::XStorage > & xStorageToWrap ); + virtual ~Storage(); + + bool isDocumentStorage() const { return m_bIsDocumentStorage; } + + // XInterface + virtual com::sun::star::uno::Any SAL_CALL queryInterface( + const com::sun::star::uno::Type& aType ) + throw ( com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL acquire() + throw (); + virtual void SAL_CALL release() + throw (); + + // XTypeProvider (implemnented by base, but needs to be overridden for + // delegating to aggregate) + virtual com::sun::star::uno::Sequence< com::sun::star::uno::Type > SAL_CALL + getTypes() + throw ( com::sun::star::uno::RuntimeException ); + virtual com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL + getImplementationId() + throw ( com::sun::star::uno::RuntimeException ); + + // XComponent ( one of XStorage bases ) + virtual void SAL_CALL + dispose() + throw ( com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + addEventListener( const com::sun::star::uno::Reference< + com::sun::star::lang::XEventListener > & xListener ) + throw ( com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + removeEventListener( const com::sun::star::uno::Reference< + com::sun::star::lang::XEventListener >& aListener ) + throw ( com::sun::star::uno::RuntimeException ); + + // XNameAccess ( one of XStorage bases ) + virtual com::sun::star::uno::Any SAL_CALL + getByName( const rtl::OUString& aName ) + throw ( com::sun::star::container::NoSuchElementException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException ); + virtual com::sun::star::uno::Sequence< rtl::OUString > SAL_CALL + getElementNames() + throw ( com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL + hasByName( const rtl::OUString& aName ) + throw ( com::sun::star::uno::RuntimeException ); + + // XElementAccess (base of XNameAccess) + virtual com::sun::star::uno::Type SAL_CALL + getElementType() + throw ( com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL + hasElements() + throw ( com::sun::star::uno::RuntimeException ); + + // XStorage + virtual void SAL_CALL + copyToStorage( const com::sun::star::uno::Reference< + com::sun::star::embed::XStorage >& xDest ) + throw ( com::sun::star::embed::InvalidStorageException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::io::IOException, + com::sun::star::embed::StorageWrappedTargetException, + com::sun::star::uno::RuntimeException ); + virtual com::sun::star::uno::Reference< com::sun::star::io::XStream > SAL_CALL + openStreamElement( const ::rtl::OUString& aStreamName, + sal_Int32 nOpenMode ) + throw ( com::sun::star::embed::InvalidStorageException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::packages::WrongPasswordException, + com::sun::star::io::IOException, + com::sun::star::embed::StorageWrappedTargetException, + com::sun::star::uno::RuntimeException ); + virtual com::sun::star::uno::Reference< com::sun::star::io::XStream > SAL_CALL + openEncryptedStreamElement( const ::rtl::OUString& aStreamName, + sal_Int32 nOpenMode, + const ::rtl::OUString& aPassword ) + throw ( com::sun::star::embed::InvalidStorageException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::packages::NoEncryptionException, + com::sun::star::packages::WrongPasswordException, + com::sun::star::io::IOException, + com::sun::star::embed::StorageWrappedTargetException, + com::sun::star::uno::RuntimeException ); + virtual com::sun::star::uno::Reference< com::sun::star::embed::XStorage > SAL_CALL + openStorageElement( const ::rtl::OUString& aStorName, + sal_Int32 nOpenMode ) + throw ( com::sun::star::embed::InvalidStorageException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::io::IOException, + com::sun::star::embed::StorageWrappedTargetException, + com::sun::star::uno::RuntimeException ); + virtual com::sun::star::uno::Reference< com::sun::star::io::XStream > SAL_CALL + cloneStreamElement( const ::rtl::OUString& aStreamName ) + throw ( com::sun::star::embed::InvalidStorageException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::packages::WrongPasswordException, + com::sun::star::io::IOException, + com::sun::star::embed::StorageWrappedTargetException, + com::sun::star::uno::RuntimeException ); + virtual com::sun::star::uno::Reference< com::sun::star::io::XStream > SAL_CALL + cloneEncryptedStreamElement( const ::rtl::OUString& aStreamName, + const ::rtl::OUString& aPassword ) + throw ( com::sun::star::embed::InvalidStorageException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::packages::NoEncryptionException, + com::sun::star::packages::WrongPasswordException, + com::sun::star::io::IOException, + com::sun::star::embed::StorageWrappedTargetException, + com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + copyLastCommitTo( const com::sun::star::uno::Reference< + com::sun::star::embed::XStorage >& xTargetStorage ) + throw ( com::sun::star::embed::InvalidStorageException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::io::IOException, + com::sun::star::embed::StorageWrappedTargetException, + com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + copyStorageElementLastCommitTo( const ::rtl::OUString& aStorName, + const com::sun::star::uno::Reference< + com::sun::star::embed::XStorage > & + xTargetStorage ) + throw ( com::sun::star::embed::InvalidStorageException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::io::IOException, + com::sun::star::embed::StorageWrappedTargetException, + com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL + isStreamElement( const ::rtl::OUString& aElementName ) + throw ( com::sun::star::container::NoSuchElementException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::embed::InvalidStorageException, + com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL + isStorageElement( const ::rtl::OUString& aElementName ) + throw ( com::sun::star::container::NoSuchElementException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::embed::InvalidStorageException, + com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + removeElement( const ::rtl::OUString& aElementName ) + throw ( com::sun::star::embed::InvalidStorageException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::container::NoSuchElementException, + com::sun::star::io::IOException, + com::sun::star::embed::StorageWrappedTargetException, + com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + renameElement( const ::rtl::OUString& aEleName, + const ::rtl::OUString& aNewName ) + throw ( com::sun::star::embed::InvalidStorageException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::container::NoSuchElementException, + com::sun::star::container::ElementExistException, + com::sun::star::io::IOException, + com::sun::star::embed::StorageWrappedTargetException, + com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + copyElementTo( const ::rtl::OUString& aElementName, + const com::sun::star::uno::Reference< + com::sun::star::embed::XStorage >& xDest, + const ::rtl::OUString& aNewName ) + throw ( com::sun::star::embed::InvalidStorageException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::container::NoSuchElementException, + com::sun::star::container::ElementExistException, + com::sun::star::io::IOException, + com::sun::star::embed::StorageWrappedTargetException, + com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + moveElementTo( const ::rtl::OUString& aElementName, + const com::sun::star::uno::Reference< + com::sun::star::embed::XStorage >& xDest, + const ::rtl::OUString& rNewName ) + throw ( com::sun::star::embed::InvalidStorageException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::container::NoSuchElementException, + com::sun::star::container::ElementExistException, + com::sun::star::io::IOException, + com::sun::star::embed::StorageWrappedTargetException, + com::sun::star::uno::RuntimeException ); + + // XTransactedObject + virtual void SAL_CALL commit() + throw ( com::sun::star::io::IOException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL revert() + throw ( com::sun::star::io::IOException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException ); + +private: + Storage( const rtl::Reference< Storage > & rFactory ); // n.i. + + rtl::Reference< StorageElementFactory > m_xFactory; + com::sun::star::uno::Reference< + com::sun::star::uno::XAggregation > m_xAggProxy; + com::sun::star::uno::Reference< + com::sun::star::embed::XStorage > m_xWrappedStorage; + com::sun::star::uno::Reference< + com::sun::star::embed::XTransactedObject > m_xWrappedTransObj; + com::sun::star::uno::Reference< + com::sun::star::lang::XComponent > m_xWrappedComponent; + com::sun::star::uno::Reference< + com::sun::star::lang::XTypeProvider > m_xWrappedTypeProv; + bool m_bIsDocumentStorage; + + StorageElementFactory::StorageMap::iterator m_aContainerIt; + + friend class StorageElementFactory; + friend class std::auto_ptr< Storage >; +}; + +//======================================================================= + +typedef + cppu::WeakImplHelper2< + com::sun::star::io::XOutputStream, + com::sun::star::lang::XComponent > OutputStreamUNOBase; + +class OutputStream : public OutputStreamUNOBase, public ParentStorageHolder +{ +public: + OutputStream( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory > & xSMgr, + const rtl::OUString & rUri, + const com::sun::star::uno::Reference< + com::sun::star::embed::XStorage > & xParentStorage, + const com::sun::star::uno::Reference< + com::sun::star::io::XOutputStream > & xStreamToWrap ); + virtual ~OutputStream(); + + // XInterface + virtual com::sun::star::uno::Any SAL_CALL + queryInterface( const com::sun::star::uno::Type& aType ) + throw ( com::sun::star::uno::RuntimeException ); + + // XTypeProvider (implemnented by base, but needs to be overridden for + // delegating to aggregate) + virtual com::sun::star::uno::Sequence< com::sun::star::uno::Type > SAL_CALL + getTypes() + throw ( com::sun::star::uno::RuntimeException ); + virtual com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL + getImplementationId() + throw ( com::sun::star::uno::RuntimeException ); + + // XOutputStream + virtual void SAL_CALL + writeBytes( const com::sun::star::uno::Sequence< sal_Int8 >& aData ) + throw ( com::sun::star::io::NotConnectedException, + com::sun::star::io::BufferSizeExceededException, + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + flush( ) + throw ( com::sun::star::io::NotConnectedException, + com::sun::star::io::BufferSizeExceededException, + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException ); + // Note: We need to intercept this one. + virtual void SAL_CALL + closeOutput( ) + throw ( com::sun::star::io::NotConnectedException, + com::sun::star::io::BufferSizeExceededException, + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException ); + + // XComponent + // Note: We need to intercept this one. + virtual void SAL_CALL + dispose() + throw ( com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + addEventListener( const com::sun::star::uno::Reference< + com::sun::star::lang::XEventListener >& xListener ) + throw ( com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + removeEventListener( const com::sun::star::uno::Reference< + com::sun::star::lang::XEventListener >& aListener ) + throw ( com::sun::star::uno::RuntimeException ); + +private: + com::sun::star::uno::Reference< + com::sun::star::uno::XAggregation > m_xAggProxy; + com::sun::star::uno::Reference< + com::sun::star::io::XOutputStream > m_xWrappedStream; + com::sun::star::uno::Reference< + com::sun::star::lang::XComponent > m_xWrappedComponent; + com::sun::star::uno::Reference< + com::sun::star::lang::XTypeProvider > m_xWrappedTypeProv; +}; + +//======================================================================= + +typedef cppu::WeakImplHelper5< com::sun::star::io::XStream, + com::sun::star::io::XOutputStream, + com::sun::star::io::XTruncate, + com::sun::star::io::XInputStream, + com::sun::star::lang::XComponent > + StreamUNOBase; + +class Stream : public StreamUNOBase, public ParentStorageHolder +{ +public: + Stream( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory > & xSMgr, + const rtl::OUString & rUri, + const com::sun::star::uno::Reference< + com::sun::star::embed::XStorage > & xParentStorage, + const com::sun::star::uno::Reference< + com::sun::star::io::XStream > & xStreamToWrap ); + + virtual ~Stream(); + + // XInterface + virtual com::sun::star::uno::Any SAL_CALL + queryInterface( const com::sun::star::uno::Type& aType ) + throw ( com::sun::star::uno::RuntimeException ); + + // XTypeProvider (implemnented by base, but needs to be overridden for + // delegating to aggregate) + virtual com::sun::star::uno::Sequence< com::sun::star::uno::Type > SAL_CALL + getTypes() + throw ( com::sun::star::uno::RuntimeException ); + virtual com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL + getImplementationId() + throw ( com::sun::star::uno::RuntimeException ); + + // XStream + virtual com::sun::star::uno::Reference< + com::sun::star::io::XInputStream > SAL_CALL + getInputStream() + throw( com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::uno::Reference< + com::sun::star::io::XOutputStream > SAL_CALL + getOutputStream() + throw( com::sun::star::uno::RuntimeException ); + + // XOutputStream + virtual void SAL_CALL + writeBytes( const com::sun::star::uno::Sequence< sal_Int8 >& aData ) + throw( com::sun::star::io::NotConnectedException, + com::sun::star::io::BufferSizeExceededException, + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL + flush() + throw( com::sun::star::io::NotConnectedException, + com::sun::star::io::BufferSizeExceededException, + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL + closeOutput() + throw( com::sun::star::io::NotConnectedException, + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException ); + + // XTruncate + virtual void SAL_CALL + truncate() + throw( com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException ); + + // XInputStream + virtual sal_Int32 SAL_CALL + readBytes( com::sun::star::uno::Sequence< sal_Int8 >& aData, + sal_Int32 nBytesToRead ) + throw( com::sun::star::io::NotConnectedException, + com::sun::star::io::BufferSizeExceededException, + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException ); + + virtual sal_Int32 SAL_CALL + readSomeBytes( com::sun::star::uno::Sequence< sal_Int8 >& aData, + sal_Int32 nMaxBytesToRead ) + throw( com::sun::star::io::NotConnectedException, + com::sun::star::io::BufferSizeExceededException, + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + skipBytes( sal_Int32 nBytesToSkip ) + throw( com::sun::star::io::NotConnectedException, + com::sun::star::io::BufferSizeExceededException, + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException ); + + virtual sal_Int32 SAL_CALL + available() + throw( com::sun::star::io::NotConnectedException, + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL + closeInput() + throw( com::sun::star::io::NotConnectedException, + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException ); + + // XComponent + // Note: We need to intercept this one. + virtual void SAL_CALL + dispose() + throw ( com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + addEventListener( const com::sun::star::uno::Reference< + com::sun::star::lang::XEventListener >& xListener ) + throw ( com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + removeEventListener( const com::sun::star::uno::Reference< + com::sun::star::lang::XEventListener >& aListener ) + throw ( com::sun::star::uno::RuntimeException ); + +private: + void commitChanges() + throw( com::sun::star::io::IOException ); + + com::sun::star::uno::Reference< + com::sun::star::uno::XAggregation > m_xAggProxy; + com::sun::star::uno::Reference< + com::sun::star::io::XStream > m_xWrappedStream; + com::sun::star::uno::Reference< + com::sun::star::io::XOutputStream > m_xWrappedOutputStream; + com::sun::star::uno::Reference< + com::sun::star::io::XTruncate > m_xWrappedTruncate; + com::sun::star::uno::Reference< + com::sun::star::io::XInputStream > m_xWrappedInputStream; + com::sun::star::uno::Reference< + com::sun::star::lang::XComponent > m_xWrappedComponent; + com::sun::star::uno::Reference< + com::sun::star::lang::XTypeProvider > m_xWrappedTypeProv; +}; + +} // namespace tdoc_ucp + +#endif /* !INCLUDED_TDOC_STGELEMS_HXX */ diff --git a/ucb/source/ucp/tdoc/tdoc_storage.cxx b/ucb/source/ucp/tdoc/tdoc_storage.cxx new file mode 100644 index 000000000000..8deb942900a8 --- /dev/null +++ b/ucb/source/ucp/tdoc/tdoc_storage.cxx @@ -0,0 +1,712 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + - remove root storage access workaround + + *************************************************************************/ + +#define ROOTSTORAGE_ACCESS_WORKAROUND 1 + +#include <memory> + +#include "com/sun/star/beans/XPropertySet.hpp" +#include "com/sun/star/embed/ElementModes.hpp" +#include "com/sun/star/lang/XSingleServiceFactory.hpp" + +#include "tdoc_uri.hxx" +#include "tdoc_docmgr.hxx" +#include "tdoc_stgelems.hxx" + +#include "tdoc_storage.hxx" + +using namespace com::sun::star; +using namespace tdoc_ucp; + + +//========================================================================= +//========================================================================= +// +// StorageElementFactory Implementation. +// +//========================================================================= +//========================================================================= + +StorageElementFactory::StorageElementFactory( + const uno::Reference< lang::XMultiServiceFactory > & xSMgr, + const rtl::Reference< OfficeDocumentsManager > & xDocsMgr ) +: m_xDocsMgr( xDocsMgr ), + m_xSMgr( xSMgr ) +{ +} + +//========================================================================= +StorageElementFactory::~StorageElementFactory() +{ + OSL_ENSURE( m_aMap.size() == 0, + "StorageElementFactory::~StorageElementFactory - Dangling storages!" ); +} + +//========================================================================= +uno::Reference< embed::XStorage > +StorageElementFactory::createTemporaryStorage() + throw ( uno::Exception, + uno::RuntimeException ) +{ + uno::Reference< embed::XStorage > xStorage; + uno::Reference< lang::XSingleServiceFactory > xStorageFac; + if ( m_xSMgr.is() ) + { + xStorageFac = uno::Reference< lang::XSingleServiceFactory >( + m_xSMgr->createInstance( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.embed.StorageFactory" ) ) ), + uno::UNO_QUERY ); + } + + OSL_ENSURE( xStorageFac.is(), "Can't create storage factory!" ); + if ( xStorageFac.is() ) + xStorage = uno::Reference< embed::XStorage >( + xStorageFac->createInstance(), + uno::UNO_QUERY ); + + if ( !xStorage.is() ) + throw uno::RuntimeException(); + + return xStorage; +} + +//========================================================================= +uno::Reference< embed::XStorage > +StorageElementFactory::createStorage( const rtl::OUString & rUri, + StorageAccessMode eMode ) + throw ( embed::InvalidStorageException, + lang::IllegalArgumentException, + io::IOException, + embed::StorageWrappedTargetException, + uno::RuntimeException ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + if ( ( eMode != READ ) && + ( eMode != READ_WRITE_NOCREATE ) && + ( eMode != READ_WRITE_CREATE ) ) + throw lang::IllegalArgumentException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "Invalid open mode!" ) ), + uno::Reference< uno::XInterface >(), + sal_Int16( 2 ) ); + + Uri aUri( rUri ); + if ( aUri.isRoot() ) + { + throw lang::IllegalArgumentException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "Root never has a storage!" ) ), + uno::Reference< uno::XInterface >(), + sal_Int16( 1 ) ); + } + + rtl::OUString aUriKey + ( ( rUri.getStr()[ rUri.getLength() - 1 ] == sal_Unicode( '/' ) ) + ? rUri.copy( 0, rUri.getLength() - 1 ) + : rUri ); + + StorageMap::iterator aIt ( m_aMap.begin() ); + StorageMap::iterator aEnd( m_aMap.end() ); + + while ( aIt != aEnd ) + { + if ( (*aIt).first.first == aUriKey ) + { + // URI matches. Now, check open mode. + bool bMatch = true; + switch ( eMode ) + { + case READ: + // No need to check; storage is at least readable. + bMatch = true; + break; + + case READ_WRITE_NOCREATE: + case READ_WRITE_CREATE: + // If found storage is writable, it can be used. + // If not, a new one must be created. + bMatch = (*aIt).first.second; + break; + } + + if ( bMatch ) + break; + } + ++aIt; + } + + if ( aIt == aEnd ) + { + uno::Reference< embed::XStorage > xParentStorage; + + // documents never have a parent storage. + if ( !aUri.isDocument() ) + { + xParentStorage = queryParentStorage( aUriKey, eMode ); + + if ( !xParentStorage.is() ) + { + // requested to create new storage, but failed? + OSL_ENSURE( eMode != READ_WRITE_CREATE, + "Unable to create parent storage!" ); + return xParentStorage; + } + } + + uno::Reference< embed::XStorage > xStorage + = queryStorage( xParentStorage, aUriKey, eMode ); + + if ( !xStorage.is() ) + { + // requested to create new storage, but failed? + OSL_ENSURE( eMode != READ_WRITE_CREATE, + "Unable to create storage!" ); + return xStorage; + } + + bool bWritable = ( ( eMode == READ_WRITE_NOCREATE ) + || ( eMode == READ_WRITE_CREATE ) ); + + std::auto_ptr< Storage > xElement( + new Storage( m_xSMgr, this, aUriKey, xParentStorage, xStorage ) ); + + aIt = m_aMap.insert( + StorageMap::value_type( + std::pair< rtl::OUString, bool >( aUriKey, bWritable ), + xElement.get() ) ).first; + + aIt->second->m_aContainerIt = aIt; + xElement.release(); + return aIt->second; + } + else if ( osl_incrementInterlockedCount( &aIt->second->m_refCount ) > 1 ) + { + rtl::Reference< Storage > xElement( aIt->second ); + osl_decrementInterlockedCount( &aIt->second->m_refCount ); + return aIt->second; + } + else + { + osl_decrementInterlockedCount( &aIt->second->m_refCount ); + aIt->second->m_aContainerIt = m_aMap.end(); + + uno::Reference< embed::XStorage > xParentStorage; + + // documents never have a parent storage. + if ( !aUri.isDocument() ) + { + xParentStorage = queryParentStorage( aUriKey, eMode ); + + if ( !xParentStorage.is() ) + { + // requested to create new storage, but failed? + OSL_ENSURE( eMode != READ_WRITE_CREATE, + "Unable to create parent storage!" ); + return xParentStorage; + } + } + + uno::Reference< embed::XStorage > xStorage + = queryStorage( xParentStorage, aUriKey, eMode ); + + if ( !xStorage.is() ) + { + // requested to create new storage, but failed? + OSL_ENSURE( eMode != READ_WRITE_CREATE, + "Unable to create storage!" ); + return xStorage; + } + + aIt->second + = new Storage( m_xSMgr, this, aUriKey, xParentStorage, xStorage ); + aIt->second->m_aContainerIt = aIt; + return aIt->second; + } +} + +//========================================================================= +uno::Reference< io::XInputStream > +StorageElementFactory::createInputStream( const rtl::OUString & rUri, + const rtl::OUString & rPassword ) + throw ( embed::InvalidStorageException, + lang::IllegalArgumentException, + io::IOException, + embed::StorageWrappedTargetException, + packages::WrongPasswordException, + uno::RuntimeException ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + uno::Reference< embed::XStorage > xParentStorage + = queryParentStorage( rUri, READ ); + + // Each stream must have a parent storage. + if ( !xParentStorage.is() ) + return uno::Reference< io::XInputStream >(); + + uno::Reference< io::XStream > xStream + = queryStream( xParentStorage, rUri, rPassword, READ, false ); + + if ( !xStream.is() ) + return uno::Reference< io::XInputStream >(); + + return xStream->getInputStream(); +} + +//========================================================================= +uno::Reference< io::XOutputStream > +StorageElementFactory::createOutputStream( const rtl::OUString & rUri, + const rtl::OUString & rPassword, + bool bTruncate ) + throw ( embed::InvalidStorageException, + lang::IllegalArgumentException, + io::IOException, + embed::StorageWrappedTargetException, + packages::WrongPasswordException, + uno::RuntimeException ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + uno::Reference< embed::XStorage > xParentStorage + = queryParentStorage( rUri, READ_WRITE_CREATE ); + + // Each stream must have a parent storage. + if ( !xParentStorage.is() ) + { + OSL_ENSURE( false, + "StorageElementFactory::createOutputStream - " + "Unable to create parent storage!" ); + return uno::Reference< io::XOutputStream >(); + } + + uno::Reference< io::XStream > xStream + = queryStream( + xParentStorage, rUri, rPassword, READ_WRITE_CREATE, bTruncate ); + + if ( !xStream.is() ) + { + OSL_ENSURE( false, + "StorageElementFactory::createOutputStream - " + "Unable to create stream!" ); + return uno::Reference< io::XOutputStream >(); + } + + // Note: We need a wrapper to hold a reference to the parent storage to + // ensure that nobody else owns it at the moment we want to commit + // our changes. (There can be only one writable instance at a time + // and even no writable instance if there is already another + // read-only instance!) + return uno::Reference< io::XOutputStream >( + new OutputStream( + m_xSMgr, rUri, xParentStorage, xStream->getOutputStream() ) ); +} + +//========================================================================= +uno::Reference< io::XStream > +StorageElementFactory::createStream( const rtl::OUString & rUri, + const rtl::OUString & rPassword, + bool bTruncate ) + throw ( embed::InvalidStorageException, + lang::IllegalArgumentException, + io::IOException, + embed::StorageWrappedTargetException, + packages::WrongPasswordException, + uno::RuntimeException ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + uno::Reference< embed::XStorage > xParentStorage + = queryParentStorage( rUri, READ_WRITE_CREATE ); + + // Each stream must have a parent storage. + if ( !xParentStorage.is() ) + { + OSL_ENSURE( false, + "StorageElementFactory::createStream - " + "Unable to create parent storage!" ); + return uno::Reference< io::XStream >(); + } + + uno::Reference< io::XStream > xStream + = queryStream( + xParentStorage, rUri, rPassword, READ_WRITE_NOCREATE, bTruncate ); + + if ( !xStream.is() ) + { + OSL_ENSURE( false, + "StorageElementFactory::createStream - " + "Unable to create stream!" ); + return uno::Reference< io::XStream >(); + } + + return uno::Reference< io::XStream >( + new Stream( m_xSMgr, rUri, xParentStorage, xStream ) ); +} + +//========================================================================= +void StorageElementFactory::releaseElement( Storage * pElement ) SAL_THROW( () ) +{ + OSL_ASSERT( pElement ); + osl::MutexGuard aGuard( m_aMutex ); + if ( pElement->m_aContainerIt != m_aMap.end() ) + m_aMap.erase( pElement->m_aContainerIt ); +} + +//========================================================================= +// +// Non-UNO interface +// +//========================================================================= + +uno::Reference< embed::XStorage > StorageElementFactory::queryParentStorage( + const rtl::OUString & rUri, StorageAccessMode eMode ) + throw ( embed::InvalidStorageException, + lang::IllegalArgumentException, + io::IOException, + embed::StorageWrappedTargetException, + uno::RuntimeException ) +{ + uno::Reference< embed::XStorage > xParentStorage; + + Uri aUri( rUri ); + Uri aParentUri( aUri.getParentUri() ); + if ( !aParentUri.isRoot() ) + { + xParentStorage = createStorage( aUri.getParentUri(), eMode ); + OSL_ENSURE( xParentStorage.is() + // requested to create new storage, but failed? + || ( eMode != READ_WRITE_CREATE ), + "StorageElementFactory::queryParentStorage - No storage!" ); + } + return xParentStorage; +} + +//========================================================================= +uno::Reference< embed::XStorage > StorageElementFactory::queryStorage( + const uno::Reference< embed::XStorage > & xParentStorage, + const rtl::OUString & rUri, + StorageAccessMode eMode ) + throw ( embed::InvalidStorageException, + lang::IllegalArgumentException, + io::IOException, + embed::StorageWrappedTargetException, + uno::RuntimeException ) +{ + uno::Reference< embed::XStorage > xStorage; + + Uri aUri( rUri ); + + if ( !xParentStorage.is() ) + { + // document storage + + xStorage = m_xDocsMgr->queryStorage( aUri.getDocumentId() ); + + if ( !xStorage.is() ) + { + if ( eMode == READ_WRITE_CREATE ) + throw lang::IllegalArgumentException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "Invalid open mode: document storages cannot be " + "created!" ) ), + uno::Reference< uno::XInterface >(), + sal_Int16( 2 ) ); + else + throw embed::InvalidStorageException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "Invalid document id!" ) ), + uno::Reference< uno::XInterface >() ); + } + + // match xStorage's open mode against requested open mode + + uno::Reference< beans::XPropertySet > xPropSet( + xStorage, uno::UNO_QUERY ); + OSL_ENSURE( xPropSet.is(), + "StorageElementFactory::queryStorage - " + "No XPropertySet interface!" ); + try + { + uno::Any aPropValue = xPropSet->getPropertyValue( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "OpenMode" ) ) ); + + sal_Int32 nOpenMode = 0; + if ( aPropValue >>= nOpenMode ) + { + switch ( eMode ) + { + case READ: + if ( !( nOpenMode & embed::ElementModes::READ ) ) + { + // document opened, but not readable. + throw embed::InvalidStorageException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "Storage is open, but not readable!" ) ), + uno::Reference< uno::XInterface >() ); + } + // storage okay + break; + + case READ_WRITE_NOCREATE: + case READ_WRITE_CREATE: + if ( !( nOpenMode & embed::ElementModes::WRITE ) ) + { + // document opened, but not writable. + throw embed::InvalidStorageException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "Storage is open, but not writable!" ) ), + uno::Reference< uno::XInterface >() ); + } + // storage okay + break; + } + } + else + { + OSL_ENSURE( + false, "Bug! Value of property OpenMode has wrong type!" ); + + throw uno::RuntimeException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "Bug! Value of property OpenMode has wrong type!" ) ), + uno::Reference< uno::XInterface >() ); + } + } + catch ( beans::UnknownPropertyException const & e ) + { + OSL_ENSURE( false, "Property OpenMode not supported!" ); + + throw embed::StorageWrappedTargetException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "Bug! Value of property OpenMode has wrong type!" ) ), + uno::Reference< uno::XInterface >(), + uno::makeAny( e ) ); + } + catch ( lang::WrappedTargetException const & e ) + { + OSL_ENSURE( false, "Caught WrappedTargetException!" ); + + throw embed::StorageWrappedTargetException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "WrappedTargetException during getPropertyValue!" ) ), + uno::Reference< uno::XInterface >(), + uno::makeAny( e ) ); + } + } + else + { + // sub storage + + const rtl::OUString & rName = aUri.getDecodedName(); + + if ( eMode == READ ) + { + try + { + sal_Int32 nOpenMode = embed::ElementModes::READ + | embed::ElementModes::NOCREATE; + xStorage + = xParentStorage->openStorageElement( rName, nOpenMode ); + } + catch ( io::IOException const & ) + { + // Another chance: Try to clone storage. + xStorage = createTemporaryStorage(); + xParentStorage->copyStorageElementLastCommitTo( rName, + xStorage ); + } + } + else + { + sal_Int32 nOpenMode = embed::ElementModes::READWRITE; + if ( eMode == READ_WRITE_NOCREATE ) + nOpenMode |= embed::ElementModes::NOCREATE; + + xStorage = xParentStorage->openStorageElement( rName, nOpenMode ); + } + } + + OSL_ENSURE( xStorage.is() || ( eMode != READ_WRITE_CREATE ), + "StorageElementFactory::queryStorage - No storage!" ); + return xStorage; +} + +//========================================================================= +uno::Reference< io::XStream > +StorageElementFactory::queryStream( + const uno::Reference< embed::XStorage > & xParentStorage, + const rtl::OUString & rUri, + const rtl::OUString & rPassword, + StorageAccessMode eMode, + bool bTruncate ) + throw ( embed::InvalidStorageException, + lang::IllegalArgumentException, + io::IOException, + embed::StorageWrappedTargetException, + packages::WrongPasswordException, + uno::RuntimeException ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + if ( !xParentStorage.is() ) + { + throw lang::IllegalArgumentException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "No parent storage!" ) ), + uno::Reference< uno::XInterface >(), + sal_Int16( 2 ) ); + } + + Uri aUri( rUri ); + if ( aUri.isRoot() ) + { + throw lang::IllegalArgumentException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "Root never is a stream!" ) ), + uno::Reference< uno::XInterface >(), + sal_Int16( 2 ) ); + } + else if ( aUri.isDocument() ) + { + throw lang::IllegalArgumentException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "A document never is a stream!" ) ), + uno::Reference< uno::XInterface >(), + sal_Int16( 2 ) ); + } + + sal_Int32 nOpenMode; + switch ( eMode ) + { + case READ: + nOpenMode = embed::ElementModes::READ + | embed::ElementModes::NOCREATE + | embed::ElementModes::SEEKABLE; + break; + + case READ_WRITE_NOCREATE: + nOpenMode = embed::ElementModes::READWRITE + | embed::ElementModes::NOCREATE + | embed::ElementModes::SEEKABLE; + + if ( bTruncate ) + nOpenMode |= embed::ElementModes::TRUNCATE; + + break; + + case READ_WRITE_CREATE: + nOpenMode = embed::ElementModes::READWRITE + | embed::ElementModes::SEEKABLE; + + if ( bTruncate ) + nOpenMode |= embed::ElementModes::TRUNCATE; + + break; + + default: + OSL_ENSURE( false, + "StorageElementFactory::queryStream : Unknown open mode!" ); + + throw embed::InvalidStorageException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "Unknown open mode!" ) ), + uno::Reference< uno::XInterface >() ); + } + + // No object re-usage mechanism; streams are seekable => not stateless. + + uno::Reference< io::XStream > xStream; + if ( rPassword.getLength() > 0 ) + { + if ( eMode == READ ) + { + try + { + xStream = xParentStorage->cloneEncryptedStreamElement( + aUri.getDecodedName(), + rPassword ); + } + catch ( packages::NoEncryptionException const & ) + { + xStream + = xParentStorage->cloneStreamElement( aUri.getDecodedName() ); + } + } + else + { + try + { + xStream = xParentStorage->openEncryptedStreamElement( + aUri.getDecodedName(), + nOpenMode, + rPassword ); + } + catch ( packages::NoEncryptionException const & ) + { + xStream + = xParentStorage->openStreamElement( aUri.getDecodedName(), + nOpenMode ); + } + } + } + else + { + if ( eMode == READ ) + { + xStream = xParentStorage->cloneStreamElement( aUri.getDecodedName() ); + } + else + { + xStream = xParentStorage->openStreamElement( aUri.getDecodedName(), + nOpenMode ); + } + } + + if ( !xStream.is() ) + { + throw embed::InvalidStorageException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "No stream!" ) ), + uno::Reference< uno::XInterface >() ); + } + + return xStream; +} diff --git a/ucb/source/ucp/tdoc/tdoc_storage.hxx b/ucb/source/ucp/tdoc/tdoc_storage.hxx new file mode 100644 index 000000000000..39a95a5a7fe8 --- /dev/null +++ b/ucb/source/ucp/tdoc/tdoc_storage.hxx @@ -0,0 +1,172 @@ +/************************************************************************* + * + * 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 INCLUDED_TDOC_STORAGE_HXX +#define INCLUDED_TDOC_STORAGE_HXX + +#include <map> + +#include "osl/mutex.hxx" +#include "rtl/ref.hxx" +#include "salhelper/simplereferenceobject.hxx" + +#include "com/sun/star/embed/XStorage.hpp" + +namespace tdoc_ucp { + + enum StorageAccessMode + { + READ, // Note: might be writable as well + READ_WRITE_NOCREATE, + READ_WRITE_CREATE + }; + + class Storage; + class OfficeDocumentsManager; + + class StorageElementFactory : public salhelper::SimpleReferenceObject + { + public: + StorageElementFactory( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory > & xSMgr, + const rtl::Reference< OfficeDocumentsManager > & xDocsMgr ); + ~StorageElementFactory(); + + com::sun::star::uno::Reference< com::sun::star::embed::XStorage > + createTemporaryStorage() + throw ( com::sun::star::uno::Exception, + com::sun::star::uno::RuntimeException ); + + com::sun::star::uno::Reference< com::sun::star::embed::XStorage > + createStorage( const rtl::OUString & rUri, StorageAccessMode eMode ) + throw ( com::sun::star::embed::InvalidStorageException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::io::IOException, + com::sun::star::embed::StorageWrappedTargetException, + com::sun::star::uno::RuntimeException ); + + com::sun::star::uno::Reference< com::sun::star::io::XInputStream > + createInputStream( const rtl::OUString & rUri, + const rtl::OUString & rPassword ) + throw ( com::sun::star::embed::InvalidStorageException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::io::IOException, + com::sun::star::embed::StorageWrappedTargetException, + com::sun::star::packages::WrongPasswordException, + com::sun::star::uno::RuntimeException ); + + com::sun::star::uno::Reference< com::sun::star::io::XOutputStream > + createOutputStream( const rtl::OUString & rUri, + const rtl::OUString & rPassword, + bool bTruncate ) + throw ( com::sun::star::embed::InvalidStorageException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::io::IOException, + com::sun::star::embed::StorageWrappedTargetException, + com::sun::star::packages::WrongPasswordException, + com::sun::star::uno::RuntimeException ); + + com::sun::star::uno::Reference< com::sun::star::io::XStream > + createStream( const rtl::OUString & rUri, + const rtl::OUString & rPassword, + bool bTruncate ) + throw ( com::sun::star::embed::InvalidStorageException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::io::IOException, + com::sun::star::embed::StorageWrappedTargetException, + com::sun::star::packages::WrongPasswordException, + com::sun::star::uno::RuntimeException ); + + private: + friend class Storage; + + void releaseElement( Storage * pElement ) SAL_THROW(()); + + com::sun::star::uno::Reference< com::sun::star::embed::XStorage > + queryParentStorage( const rtl::OUString & rUri, + StorageAccessMode eMode ) + throw ( com::sun::star::embed::InvalidStorageException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::io::IOException, + com::sun::star::embed::StorageWrappedTargetException, + com::sun::star::uno::RuntimeException ); + + com::sun::star::uno::Reference< com::sun::star::embed::XStorage > + queryStorage( const com::sun::star::uno::Reference< + com::sun::star::embed::XStorage > & xParentStorage, + const rtl::OUString & rUri, + StorageAccessMode eMode ) + throw ( com::sun::star::embed::InvalidStorageException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::io::IOException, + com::sun::star::embed::StorageWrappedTargetException, + com::sun::star::uno::RuntimeException ); + + com::sun::star::uno::Reference< com::sun::star::io::XStream > + queryStream( const com::sun::star::uno::Reference< + com::sun::star::embed::XStorage > & xParentStorage, + const rtl::OUString & rPassword, + const rtl::OUString & rUri, + StorageAccessMode eMode, + bool bTruncate /* ignored for read-only streams */ ) + throw ( com::sun::star::embed::InvalidStorageException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::io::IOException, + com::sun::star::embed::StorageWrappedTargetException, + com::sun::star::packages::WrongPasswordException, + com::sun::star::uno::RuntimeException ); + + struct ltstrbool + { + bool operator()( + const std::pair< rtl::OUString, bool > & s1, + const std::pair< rtl::OUString, bool > & s2 ) const + { + if ( s1.first < s2.first ) + return true; + else if ( s1.first == s2.first ) + return ( !s1.second && s2.second ); + else + return false; + } + }; + + // key: pair< storageuri, iswritable > + typedef std::map< + std::pair< rtl::OUString, bool >, Storage *, ltstrbool > StorageMap; + + StorageMap m_aMap; + osl::Mutex m_aMutex; + rtl::Reference< OfficeDocumentsManager > m_xDocsMgr; + com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory > m_xSMgr; + }; + +} // namespace tdoc_ucp + +#endif /* !INCLUDED_TDOC_STORAGE_HXX */ diff --git a/ucb/source/ucp/tdoc/tdoc_uri.cxx b/ucb/source/ucp/tdoc/tdoc_uri.cxx new file mode 100644 index 000000000000..712ced2d04f1 --- /dev/null +++ b/ucb/source/ucp/tdoc/tdoc_uri.cxx @@ -0,0 +1,135 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ + +#include "rtl/ustrbuf.hxx" +#include "../inc/urihelper.hxx" + +#include "tdoc_uri.hxx" + +using namespace tdoc_ucp; + +//========================================================================= +//========================================================================= +// +// Uri Implementation. +// +//========================================================================= +//========================================================================= + +void Uri::init() const +{ + // Already inited? + if ( m_eState == UNKNOWN ) + { + m_eState = INVALID; + + // Check for proper length: must be at least length of <sheme>:/ + if ( ( m_aUri.getLength() < TDOC_URL_SCHEME_LENGTH + 2 ) ) + { + // Invaild length (to short). + return; + } + + // Check for proper scheme. (Scheme is case insensitive.) + rtl::OUString aScheme + = m_aUri.copy( 0, TDOC_URL_SCHEME_LENGTH ).toAsciiLowerCase(); + if ( !aScheme.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( TDOC_URL_SCHEME ) ) ) + { + // Invaild scheme. + return; + } + + // Remember normalized scheme string. + m_aUri = m_aUri.replaceAt( 0, aScheme.getLength(), aScheme ); + + if ( m_aUri.getStr()[ TDOC_URL_SCHEME_LENGTH ] + != sal_Unicode( ':' ) ) + { + // Invaild (no ':' after <scheme>). + return; + } + + if ( m_aUri.getStr()[ TDOC_URL_SCHEME_LENGTH + 1 ] + != sal_Unicode( '/' ) ) + { + // Invaild (no '/' after <scheme>:). + return; + } + + m_aPath = m_aUri.copy( TDOC_URL_SCHEME_LENGTH + 1 ); + + // Note: There must be at least one slash; see above. + sal_Int32 nLastSlash = m_aUri.lastIndexOf( '/' ); + bool bTrailingSlash = false; + if ( nLastSlash == m_aUri.getLength() - 1 ) + { + // ignore trailing slash + bTrailingSlash = true; + nLastSlash = m_aUri.lastIndexOf( '/', nLastSlash ); + } + + if ( nLastSlash != -1 ) // -1 is valid for the root folder + { + m_aParentUri = m_aUri.copy( 0, nLastSlash + 1 ); + + if ( bTrailingSlash ) + m_aName = m_aUri.copy( nLastSlash + 1, + m_aUri.getLength() - nLastSlash - 2 ); + else + m_aName = m_aUri.copy( nLastSlash + 1 ); + + m_aDecodedName = ::ucb_impl::urihelper::decodeSegment( m_aName ); + + sal_Int32 nSlash = m_aPath.indexOf( '/', 1 ); + if ( nSlash == -1 ) + m_aDocId = m_aPath.copy( 1 ); + else + m_aDocId = m_aPath.copy( 1, nSlash - 1 ); + } + + if ( m_aDocId.getLength() > 0 ) + { + sal_Int32 nSlash = m_aPath.indexOf( '/', 1 ); + if ( nSlash != - 1 ) + m_aInternalPath = m_aPath.copy( nSlash ); + else + m_aInternalPath = rtl::OUString::createFromAscii( "/" ); + } + + m_eState = VALID; + } +} diff --git a/ucb/source/ucp/tdoc/tdoc_uri.hxx b/ucb/source/ucp/tdoc/tdoc_uri.hxx new file mode 100644 index 000000000000..5f251cc55bee --- /dev/null +++ b/ucb/source/ucp/tdoc/tdoc_uri.hxx @@ -0,0 +1,131 @@ +/************************************************************************* + * + * 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 INCLUDED_TDOC_URI_HXX +#define INCLUDED_TDOC_URI_HXX + +#include "rtl/ustring.hxx" + +namespace tdoc_ucp { + +//========================================================================= + +#define TDOC_URL_SCHEME "vnd.sun.star.tdoc" +#define TDOC_URL_SCHEME_LENGTH 17 + +//========================================================================= + +class Uri +{ + enum State { UNKNOWN, INVALID, VALID }; + + mutable ::rtl::OUString m_aUri; + mutable ::rtl::OUString m_aParentUri; + mutable ::rtl::OUString m_aPath; + mutable ::rtl::OUString m_aDocId; + mutable ::rtl::OUString m_aInternalPath; + mutable ::rtl::OUString m_aName; + mutable ::rtl::OUString m_aDecodedName; + mutable State m_eState; + +private: + void init() const; + +public: + Uri() : m_eState( UNKNOWN ) {} + Uri( const ::rtl::OUString & rUri ) + : m_aUri( rUri ), m_eState( UNKNOWN ) {} + + bool operator== ( const Uri & rOther ) const + { init(); return m_aUri == rOther.m_aUri; } + + bool operator!= ( const Uri & rOther ) const + { return !operator==( rOther ); } + + sal_Bool isValid() const + { init(); return m_eState == VALID; } + + const ::rtl::OUString & getUri() const + { init(); return m_aUri; } + + inline void setUri( const ::rtl::OUString & rUri ); + + const ::rtl::OUString & getParentUri() const + { init(); return m_aParentUri; } + + const ::rtl::OUString & getPath() const + { init(); return m_aPath; } + + const ::rtl::OUString & getDocumentId() const + { init(); return m_aDocId; } + + const ::rtl::OUString & getInternalPath() const + { init(); return m_aInternalPath; } + + const ::rtl::OUString & getName() const + { init(); return m_aName; } + + const ::rtl::OUString & getDecodedName() const + { init(); return m_aDecodedName; } + + inline sal_Bool isRoot() const; + + inline sal_Bool isDocument() const; + + inline sal_Bool isFolder() const; +}; + +inline void Uri::setUri( const ::rtl::OUString & rUri ) +{ + m_eState = UNKNOWN; + m_aUri = rUri; + m_aParentUri = m_aDocId = m_aInternalPath = m_aPath = m_aName + = m_aDecodedName = rtl::OUString(); +} + +inline sal_Bool Uri::isRoot() const +{ + init(); + return ( m_aPath.getLength() == 1 ); +} + +inline sal_Bool Uri::isDocument() const +{ + init(); + return ( ( m_aDocId.getLength() > 0 ) /* not root */ + && ( m_aPath.copy( m_aDocId.getLength() + 1 ).getLength() < 2 ) ); +} + +inline sal_Bool Uri::isFolder() const +{ + init(); + return ( m_aPath.lastIndexOf( '/' ) == m_aPath.getLength() - 1 ); +} + +} // namespace tdoc_ucp + +#endif /* !INCLUDED_TDOC_URI_HXX */ diff --git a/ucb/source/ucp/tdoc/ucptdoc.xml b/ucb/source/ucp/tdoc/ucptdoc.xml new file mode 100644 index 000000000000..b47249269470 --- /dev/null +++ b/ucb/source/ucp/tdoc/ucptdoc.xml @@ -0,0 +1,129 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE module-description PUBLIC "-//StarOffice//DTD ComponentDescription 1.0//EN" "module-description.dtd"> +<module-description xmlns:xlink="http://www.w3.org/1999/xlink"> + + <module-name> + ucptdoc + </module-name> + + <component-description> + <author> + Kai Sommerfeld + </author> + <name> + com.sun.star.comp.ucb.TransientDocumentsContentProvider + </name> + <description> + This component implements a Content Provider for the Universal Content Broker. + It provides access to the hierachical structure of the documents that are active + in a running OpenOffice.org process. + </description> + <loader-name> + com.sun.star.loader.SharedLibrary + </loader-name> + <language> + c++ + </language> + <status value="final"/> + <supported-service> + com.sun.star.ucb.TransientDocumentsContentProvider + </supported-service> + + <service-dependency> + com.sun.star.frame.GlobalEventBroadcaster + </service-dependency> + <service-dependency> + com.sun.star.reflection.ProxyFactory + </service-dependency> + <service-dependency> + com.sun.star.embed.StorageFactory + </service-dependency> + </component-description> + + <component-description> + <author> + Kai Sommerfeld + </author> + <name> + com.sun.star.comp.ucb.TransientDocumentsDocumentContentFactory + </name> + <description> + This component implements a factory for + 'com.sun.star.ucb.TransientDocumentsDocumentContent's. + </description> + <loader-name> + com.sun.star.loader.SharedLibrary + </loader-name> + <language> + c++ + </language> + <status value="final"/> + <supported-service> + com.sun.star.frame.TransientDocumentsDocumentContentFactory + </supported-service> + + <service-dependency> + com.sun.star.ucb.TransientDocumentsContentProvider + </service-dependency> + </component-description> + + <project-build-dependency> sal </project-build-dependency> + <project-build-dependency> salhelper </project-build-dependency> + <project-build-dependency> cppu </project-build-dependency> + <project-build-dependency> cppuhelper </project-build-dependency> + <project-build-dependency> ucbhelper </project-build-dependency> + + <runtime-module-dependency> sal3 </runtime-module-dependency> + <runtime-module-dependency> cppu3 </runtime-module-dependency> + <runtime-module-dependency> cppuhelper3$(COM) </runtime-module-dependency> + <runtime-module-dependency> ucbhelper4$(COM) </runtime-module-dependency> + + <type> com.sun.star.beans.Property </type> + <type> com.sun.star.beans.PropertyAttribute </type> + <type> com.sun.star.beans.PropertyValue </type> + <type> com.sun.star.beans.XPropertySet </type> + <type> com.sun.star.container.XEnumerationAccess </type> + <type> com.sun.star.container.XNameAccess </type> + <type> com.sun.star.document.XStorageBasedDocument </type> + <type> com.sun.star.document.XEventBroadcaster </type> + <type> com.sun.star.document.XEventListener </type> + <type> com.sun.star.embed.ElementModes </type> + <type> com.sun.star.embed.XStorage </type> + <type> com.sun.star.embed.XTransactedObject </type> + <type> com.sun.star.frame.XTransientDocumentsDocumentContentFactory </type> + <type> com.sun.star.io.XActiveDataSink </type> + <type> com.sun.star.io.XActiveDataStreamer </type> + <type> com.sun.star.io.XSeekable </type> + <type> com.sun.star.io.XTruncate </type> + <type> com.sun.star.lang.DisposedException </type> + <type> com.sun.star.lang.IllegalAccessException </type> + <type> com.sun.star.lang.XComponent </type> + <type> com.sun.star.lang.XMultiServiceFactory </type> + <type> com.sun.star.lang.XServiceInfo </type> + <type> com.sun.star.lang.XSingleServiceFactory </type> + <type> com.sun.star.reflection.XProxyFactory </type> + <type> com.sun.star.registry.XRegistryKey </type> + <type> com.sun.star.task.DocumentPasswordRequest </type> + <type> com.sun.star.task.XInteractionPassword </type> + <type> com.sun.star.sdbc.XRow </type> + <type> com.sun.star.ucb.CommandInfo </type> + <type> com.sun.star.ucb.ContentInfoAttribute </type> + <type> com.sun.star.ucb.InsertCommandArgument </type> + <type> com.sun.star.ucb.InteractiveBadTransferURLException </type> + <type> com.sun.star.ucb.MissingInputStreamException </type> + <type> com.sun.star.ucb.MissingPropertiesException </type> + <type> com.sun.star.ucb.NameClash </type> + <type> com.sun.star.ucb.NameClashException </type> + <type> com.sun.star.ucb.OpenCommandArgument2 </type> + <type> com.sun.star.ucb.OpenMode </type> + <type> com.sun.star.ucb.TransferInfo </type> + <type> com.sun.star.ucb.UnsupportedCommandException </type> + <type> com.sun.star.ucb.UnsupportedDataSinkException </type> + <type> com.sun.star.ucb.UnsupportedNameClashException </type> + <type> com.sun.star.ucb.UnsupportedOpenModeException </type> + <type> com.sun.star.ucb.XCommandInfo </type> + <type> com.sun.star.ucb.XContentCreator </type> + <type> com.sun.star.ucb.XPersistentPropertySet </type> + <type> com.sun.star.uno.XAggregation </type> + +</module-description> diff --git a/ucb/source/ucp/tdoc/ucptdoc1.component b/ucb/source/ucp/tdoc/ucptdoc1.component new file mode 100644 index 000000000000..8ba1471bd933 --- /dev/null +++ b/ucb/source/ucp/tdoc/ucptdoc1.component @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* 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. +* +**********************************************************************--> + +<component loader="com.sun.star.loader.SharedLibrary" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.ucb.TransientDocumentsContentProvider"> + <service name="com.sun.star.ucb.TransientDocumentsContentProvider"/> + </implementation> + <implementation name="com.sun.star.comp.ucb.TransientDocumentsDocumentContentFactory"> + <service name="com.sun.star.frame.TransientDocumentsDocumentContentFactory"/> + </implementation> +</component> diff --git a/ucb/source/ucp/webdav/ContentProperties.cxx b/ucb/source/ucp/webdav/ContentProperties.cxx new file mode 100644 index 000000000000..2285ad28a888 --- /dev/null +++ b/ucb/source/ucp/webdav/ContentProperties.cxx @@ -0,0 +1,573 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ +#include <osl/diagnose.h> +#include <com/sun/star/util/DateTime.hpp> +#include "NeonUri.hxx" +#include "DAVResource.hxx" +#include "DAVProperties.hxx" +#include "DateTimeHelper.hxx" +#include "webdavprovider.hxx" +#include "ContentProperties.hxx" + +using namespace com::sun::star; +using namespace webdav_ucp; + +/* +============================================================================= + + Property Mapping + +============================================================================= +HTTP (entity header) WebDAV (property) UCB (property) +============================================================================= + +Allow +Content-Encoding +Content-Language getcontentlanguage +Content-Length getcontentlength Size +Content-Location +Content-MD5 +Content-Range +Content-Type getcontenttype MediaType +Expires +Last-Modified getlastmodified DateModified + creationdate DateCreated + resourcetype IsFolder,IsDocument,ContentType + displayname +ETag (actually getetag +a response header ) + lockdiscovery + supportedlock + source + Title (always taken from URI) + +============================================================================= + +Important: HTTP headers will not be mapped to DAV properties; only to UCB + properties. (Content-Length,Content-Type,Last-Modified) +*/ + +//========================================================================= +//========================================================================= +// +// ContentProperties Implementation. +// +//========================================================================= +//========================================================================= + +// static member! +uno::Any ContentProperties::m_aEmptyAny; + +ContentProperties::ContentProperties( const DAVResource& rResource ) +: m_xProps( new PropertyValueMap ), + m_bTrailingSlash( false ) +{ + OSL_ENSURE( rResource.uri.getLength(), + "ContentProperties ctor - Empty resource URI!" ); + + // Title + try + { + NeonUri aURI( rResource.uri ); + m_aEscapedTitle = aURI.GetPathBaseName(); + + (*m_xProps)[ rtl::OUString::createFromAscii( "Title" ) ] + = PropertyValue( + uno::makeAny( aURI.GetPathBaseNameUnescaped() ), true ); + } + catch ( DAVException const & ) + { + (*m_xProps)[ rtl::OUString::createFromAscii( "Title" ) ] + = PropertyValue( + uno::makeAny( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "*** unknown ***" ) ) ), + true ); + } + + std::vector< DAVPropertyValue >::const_iterator it + = rResource.properties.begin(); + std::vector< DAVPropertyValue >::const_iterator end + = rResource.properties.end(); + + while ( it != end ) + { + addProperty( (*it) ); + ++it; + } + + if ( rResource.uri.getStr()[ rResource.uri.getLength() - 1 ] + == sal_Unicode( '/' ) ) + m_bTrailingSlash = sal_True; +} + +//========================================================================= +ContentProperties::ContentProperties( + const rtl::OUString & rTitle, sal_Bool bFolder ) +: m_xProps( new PropertyValueMap ), + m_bTrailingSlash( sal_False ) +{ + (*m_xProps)[ rtl::OUString::createFromAscii( "Title" ) ] + = PropertyValue( uno::makeAny( rTitle ), true ); + (*m_xProps)[ rtl::OUString::createFromAscii( "IsFolder" ) ] + = PropertyValue( uno::makeAny( bFolder ), true ); + (*m_xProps)[ rtl::OUString::createFromAscii( "IsDocument" ) ] + = PropertyValue( uno::makeAny( sal_Bool( !bFolder ) ), true ); +} + +//========================================================================= +ContentProperties::ContentProperties( const rtl::OUString & rTitle ) +: m_xProps( new PropertyValueMap ), + m_bTrailingSlash( sal_False ) +{ + (*m_xProps)[ rtl::OUString::createFromAscii( "Title" ) ] + = PropertyValue( uno::makeAny( rTitle ), true ); +} + +//========================================================================= +ContentProperties::ContentProperties( const ContentProperties & rOther ) +: m_aEscapedTitle( rOther.m_aEscapedTitle ), + m_xProps( rOther.m_xProps.get() + ? new PropertyValueMap( *rOther.m_xProps ) + : new PropertyValueMap ), + m_bTrailingSlash( rOther.m_bTrailingSlash ) +{ +} + +//========================================================================= +bool ContentProperties::contains( const rtl::OUString & rName ) const +{ + if ( get( rName ) ) + return true; + else + return false; +} + +//========================================================================= +const uno::Any & ContentProperties::getValue( + const rtl::OUString & rName ) const +{ + const PropertyValue * pProp = get( rName ); + if ( pProp ) + return pProp->value(); + else + return m_aEmptyAny; +} + +//========================================================================= +const PropertyValue * ContentProperties::get( + const rtl::OUString & rName ) const +{ + PropertyValueMap::const_iterator it = m_xProps->find( rName ); + const PropertyValueMap::const_iterator end = m_xProps->end(); + + if ( it == end ) + { + it = m_xProps->begin(); + while ( it != end ) + { + if ( (*it).first.equalsIgnoreAsciiCase( rName ) ) + return &(*it).second; + + ++it; + } + return 0; + } + else + return &(*it).second; +} + +//========================================================================= +// static +void ContentProperties::UCBNamesToDAVNames( + const uno::Sequence< beans::Property > & rProps, + std::vector< rtl::OUString > & propertyNames, + bool bIncludeUnmatched /* = true */ ) +{ + ////////////////////////////////////////////////////////////// + // Assemble list of DAV properties to obtain from server. + // Append DAV properties needed to obtain requested UCB props. + ////////////////////////////////////////////////////////////// + + // DAV UCB + // creationdate <- DateCreated + // getlastmodified <- DateModified + // getcontenttype <- MediaType + // getcontentlength <- Size + // resourcetype <- IsFolder, IsDocument, ContentType + // (taken from URI) <- Title + + sal_Bool bCreationDate = sal_False; + sal_Bool bLastModified = sal_False; + sal_Bool bContentType = sal_False; + sal_Bool bContentLength = sal_False; + sal_Bool bResourceType = sal_False; + + sal_Int32 nCount = rProps.getLength(); + for ( sal_Int32 n = 0; n < nCount; ++n ) + { + const beans::Property & rProp = rProps[ n ]; + + if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "Title" ) ) ) + { + // Title is always obtained from resource's URI. + continue; + } + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "DateCreated" ) ) + || + ( rProp.Name == DAVProperties::CREATIONDATE ) ) + { + if ( !bCreationDate ) + { + propertyNames.push_back( DAVProperties::CREATIONDATE ); + bCreationDate = sal_True; + } + } + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "DateModified" ) ) + || + ( rProp.Name == DAVProperties::GETLASTMODIFIED ) ) + { + if ( !bLastModified ) + { + propertyNames.push_back( + DAVProperties::GETLASTMODIFIED ); + bLastModified = sal_True; + } + } + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "MediaType" ) ) + || + ( rProp.Name == DAVProperties::GETCONTENTTYPE ) ) + { + if ( !bContentType ) + { + propertyNames.push_back( + DAVProperties::GETCONTENTTYPE ); + bContentType = sal_True; + } + } + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "Size" ) ) + || + ( rProp.Name == DAVProperties::GETCONTENTLENGTH ) ) + { + if ( !bContentLength ) + { + propertyNames.push_back( + DAVProperties::GETCONTENTLENGTH ); + bContentLength = sal_True; + } + } + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) + || + rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) + || + rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) + || + ( rProp.Name == DAVProperties::RESOURCETYPE ) ) + { + if ( !bResourceType ) + { + propertyNames.push_back( DAVProperties::RESOURCETYPE ); + bResourceType = sal_True; + } + } + else + { + if ( bIncludeUnmatched ) + propertyNames.push_back( rProp.Name ); + } + } +} + +//========================================================================= +// static +void ContentProperties::UCBNamesToHTTPNames( + const uno::Sequence< beans::Property > & rProps, + std::vector< rtl::OUString > & propertyNames, + bool bIncludeUnmatched /* = true */ ) +{ + ////////////////////////////////////////////////////////////// + // Assemble list of HTTP header names to obtain from server. + // Append HTTP headers needed to obtain requested UCB props. + ////////////////////////////////////////////////////////////// + + // HTTP UCB + // Last-Modified <- DateModified + // Content-Type <- MediaType + // Content-Length <- Size + + sal_Int32 nCount = rProps.getLength(); + for ( sal_Int32 n = 0; n < nCount; ++n ) + { + const beans::Property & rProp = rProps[ n ]; + + if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "DateModified" ) ) ) + { + propertyNames.push_back( + rtl::OUString::createFromAscii( "Last-Modified" ) ); + } + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "MediaType" ) ) ) + { + propertyNames.push_back( + rtl::OUString::createFromAscii( "Content-Type" ) ); + } + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "Size" ) ) ) + { + propertyNames.push_back( + rtl::OUString::createFromAscii( "Content-Length" ) ); + } + else + { + if ( bIncludeUnmatched ) + propertyNames.push_back( rProp.Name ); + } + } +} + +//========================================================================= +bool ContentProperties::containsAllNames( + const uno::Sequence< beans::Property >& rProps, + std::vector< rtl::OUString > & rNamesNotContained ) const +{ + rNamesNotContained.clear(); + + sal_Int32 nCount = rProps.getLength(); + for ( sal_Int32 n = 0; n < nCount; ++n ) + { + const rtl::OUString & rName = rProps[ n ].Name; + if ( !contains( rName ) ) + { + // Not found. + rNamesNotContained.push_back( rName ); + } + } + + return ( rNamesNotContained.size() == 0 ); +} + +//========================================================================= +void ContentProperties::addProperties( + const std::vector< rtl::OUString > & rProps, + const ContentProperties & rContentProps ) +{ + std::vector< rtl::OUString >::const_iterator it = rProps.begin(); + std::vector< rtl::OUString >::const_iterator end = rProps.end(); + + while ( it != end ) + { + const rtl::OUString & rName = (*it); + + if ( !contains( rName ) ) // ignore duplicates + { + const PropertyValue * pProp = rContentProps.get( rName ); + if ( pProp ) + { + // Add it. + addProperty( rName, pProp->value(), pProp->isCaseSensitive() ); + } + else + { + addProperty( rName, uno::Any(), false ); + } + } + ++it; + } +} + +//========================================================================= +void ContentProperties::addProperties( const ContentProperties & rProps ) +{ + PropertyValueMap::const_iterator it = rProps.m_xProps->begin(); + const PropertyValueMap::const_iterator end = rProps.m_xProps->end(); + + while ( it != end ) + { + addProperty( + (*it).first, (*it).second.value(), (*it).second.isCaseSensitive() ); + ++it; + } +} + +//========================================================================= +void ContentProperties::addProperties( + const std::vector< DAVPropertyValue > & rProps ) +{ + std::vector< DAVPropertyValue >::const_iterator it = rProps.begin(); + std::vector< DAVPropertyValue >::const_iterator end = rProps.end(); + + while ( it != end ) + { + addProperty( (*it) ); + ++it; + } +} + +//========================================================================= +void ContentProperties::addProperty( const DAVPropertyValue & rProp ) +{ + addProperty( rProp.Name, rProp.Value, rProp.IsCaseSensitive ); +} + +//========================================================================= +void ContentProperties::addProperty( const rtl::OUString & rName, + const com::sun::star::uno::Any & rValue, + bool bIsCaseSensitive ) +{ + if ( rName.equals( DAVProperties::CREATIONDATE ) ) + { + // Map DAV:creationdate to UCP:DateCreated + rtl::OUString aValue; + rValue >>= aValue; + util::DateTime aDate; + DateTimeHelper::convert( aValue, aDate ); + + (*m_xProps)[ rtl::OUString::createFromAscii( "DateCreated" ) ] + = PropertyValue( uno::makeAny( aDate ), true ); + } + // else if ( rName.equals( DAVProperties::DISPLAYNAME ) ) + // { + // } + // else if ( rName.equals( DAVProperties::GETCONTENTLANGUAGE ) ) + // { + // } + else if ( rName.equals( DAVProperties::GETCONTENTLENGTH ) ) + { + // Map DAV:getcontentlength to UCP:Size + rtl::OUString aValue; + rValue >>= aValue; + + (*m_xProps)[ rtl::OUString::createFromAscii( "Size" ) ] + = PropertyValue( uno::makeAny( aValue.toInt64() ), true ); + } + else if ( rName.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "Content-Length" ) ) ) + { + // Do NOT map Content-Lenght entity header to DAV:getcontentlength! + // Only DAV resources have this property. + + // Map Content-Length entity header to UCP:Size + rtl::OUString aValue; + rValue >>= aValue; + + (*m_xProps)[ rtl::OUString::createFromAscii( "Size" ) ] + = PropertyValue( uno::makeAny( aValue.toInt64() ), true ); + } + else if ( rName.equals( DAVProperties::GETCONTENTTYPE ) ) + { + // Map DAV:getcontenttype to UCP:MediaType (1:1) + (*m_xProps)[ rtl::OUString::createFromAscii( "MediaType" ) ] + = PropertyValue( rValue, true ); + } + else if ( rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Content-Type" ) ) ) + { + // Do NOT map Content-Type entity header to DAV:getcontenttype! + // Only DAV resources have this property. + + // Map DAV:getcontenttype to UCP:MediaType (1:1) + (*m_xProps)[ rtl::OUString::createFromAscii( "MediaType" ) ] + = PropertyValue( rValue, true ); + } + // else if ( rName.equals( DAVProperties::GETETAG ) ) + // { + // } + else if ( rName.equals( DAVProperties::GETLASTMODIFIED ) ) + { + // Map the DAV:getlastmodified entity header to UCP:DateModified + rtl::OUString aValue; + rValue >>= aValue; + util::DateTime aDate; + DateTimeHelper::convert( aValue, aDate ); + + (*m_xProps)[ rtl::OUString::createFromAscii( "DateModified" ) ] + = PropertyValue( uno::makeAny( aDate ), true ); + } + else if ( rName.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "Last-Modified" ) ) ) + { + // Do not map Last-Modified entity header to DAV:getlastmodified! + // Only DAV resources have this property. + + // Map the Last-Modified entity header to UCP:DateModified + rtl::OUString aValue; + rValue >>= aValue; + util::DateTime aDate; + DateTimeHelper::convert( aValue, aDate ); + + (*m_xProps)[ rtl::OUString::createFromAscii( "DateModified" ) ] + = PropertyValue( uno::makeAny( aDate ), true ); + } + // else if ( rName.equals( DAVProperties::LOCKDISCOVERY ) ) + // { + // } + else if ( rName.equals( DAVProperties::RESOURCETYPE ) ) + { + rtl::OUString aValue; + rValue >>= aValue; + + // Map DAV:resourceype to UCP:IsFolder, UCP:IsDocument, UCP:ContentType + sal_Bool bFolder = + aValue.equalsIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM( "collection" ) ); + + (*m_xProps)[ rtl::OUString::createFromAscii( "IsFolder" ) ] + = PropertyValue( uno::makeAny( bFolder ), true ); + (*m_xProps)[ rtl::OUString::createFromAscii( "IsDocument" ) ] + = PropertyValue( uno::makeAny( sal_Bool( !bFolder ) ), true ); + (*m_xProps)[ rtl::OUString::createFromAscii( "ContentType" ) ] + = PropertyValue( uno::makeAny( bFolder + ? rtl::OUString::createFromAscii( WEBDAV_COLLECTION_TYPE ) + : rtl::OUString::createFromAscii( WEBDAV_CONTENT_TYPE ) ), true ); + } + // else if ( rName.equals( DAVProperties::SOURCE ) ) + // { + // } + // else if ( rName.equals( DAVProperties::SUPPORTEDLOCK ) ) + // { + // } + + // Save property. + (*m_xProps)[ rName ] = PropertyValue( rValue, bIsCaseSensitive ); +} diff --git a/ucb/source/ucp/webdav/ContentProperties.hxx b/ucb/source/ucp/webdav/ContentProperties.hxx new file mode 100644 index 000000000000..7819698bf667 --- /dev/null +++ b/ucb/source/ucp/webdav/ContentProperties.hxx @@ -0,0 +1,197 @@ +/************************************************************************* + * + * 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 _WEBDAV_UCP_CONTENTPROPERTIES_HXX +#define _WEBDAV_UCP_CONTENTPROPERTIES_HXX + +#include <memory> +#include <vector> +#include <hash_map> +#include <rtl/ustring.hxx> +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/uno/Sequence.hxx> + +namespace com { namespace sun { namespace star { namespace beans { + struct Property; +} } } } + +namespace webdav_ucp +{ + +struct DAVResource; + +//========================================================================= + +struct equalString +{ + bool operator()( const rtl::OUString& s1, const rtl::OUString& s2 ) const + { + return !!( s1 == s2 ); + } +}; + +struct hashString +{ + size_t operator()( const rtl::OUString & rName ) const + { + return rName.hashCode(); + } +}; + +//========================================================================= +// +// PropertyValueMap. +// +//========================================================================= + +class PropertyValue +{ +private: + ::com::sun::star::uno::Any m_aValue; + bool m_bIsCaseSensitive; + +public: + PropertyValue() + : m_bIsCaseSensitive( true ) {} + + PropertyValue( const ::com::sun::star::uno::Any & rValue, + bool bIsCaseSensitive ) + : m_aValue( rValue), + m_bIsCaseSensitive( bIsCaseSensitive ) {} + + bool isCaseSensitive() const { return m_bIsCaseSensitive; } + const ::com::sun::star::uno::Any & value() const { return m_aValue; } + +}; + +typedef std::hash_map +< + rtl::OUString, + PropertyValue, + hashString, + equalString +> +PropertyValueMap; + +struct DAVResource; + +class ContentProperties +{ +public: + ContentProperties( const DAVResource& rResource ); + + // Mini props for transient contents. + ContentProperties( const rtl::OUString & rTitle, sal_Bool bFolder ); + + // Micro props for non-existing contents. + ContentProperties( const rtl::OUString & rTitle ); + + ContentProperties( const ContentProperties & rOther ); + + bool contains( const rtl::OUString & rName ) const; + + const com::sun::star::uno::Any & + getValue( const rtl::OUString & rName ) const; + + // Maps the UCB property names contained in rProps with their DAV property + // counterparts, if possible. All unmappable properties will be included + // unchanged in resulting vector unless bIncludeUnmatched is set to false. + // The vector filles by this method can directly be handed over to + // DAVResourceAccess::PROPFIND. The result from PROPFIND + // (vector< DAVResource >) can be used to create a ContentProperties + // instance which can map DAV properties back to UCB properties. + static void UCBNamesToDAVNames( const com::sun::star::uno::Sequence< + com::sun::star::beans::Property > & + rProps, + std::vector< rtl::OUString > & resources, + bool bIncludeUnmatched = true ); + + // Maps the UCB property names contained in rProps with their HTTP header + // counterparts, if possible. All unmappable properties will be included + // unchanged in resulting vector unless bIncludeUnmatched is set to false. + // The vector filles by this method can directly be handed over to + // DAVResourceAccess::HEAD. The result from HEAD (vector< DAVResource >) + // can be used to create a ContentProperties instance which can map header + // names back to UCB properties. + static void UCBNamesToHTTPNames( const com::sun::star::uno::Sequence< + com::sun::star::beans::Property > & + rProps, + std::vector< rtl::OUString > & resources, + bool bIncludeUnmatched = true ); + + // return true, if all properties contained in rProps are contained in + // this ContentProperties instance. Otherwiese, false will be returned. + // rNamesNotContained contain the missing names. + bool containsAllNames( + const com::sun::star::uno::Sequence< + com::sun::star::beans::Property >& rProps, + std::vector< rtl::OUString > & rNamesNotContained ) const; + + // adds all properties described by rProps that are actually contained in + // rContentProps to this instance. In case of duplicates the value + // already contained in this will left unchanged. + void addProperties( const std::vector< rtl::OUString > & rProps, + const ContentProperties & rContentProps ); + + // overwrites probably existing entries. + void addProperties( const ContentProperties & rProps ); + + // overwrites probably existing entries. + void addProperties( const std::vector< DAVPropertyValue > & rProps ); + + // overwrites probably existing entry. + void addProperty( const rtl::OUString & rName, + const com::sun::star::uno::Any & rValue, + bool bIsCaseSensitive ); + + // overwrites probably existing entry. + void addProperty( const DAVPropertyValue & rProp ); + + bool isTrailingSlash() const { return m_bTrailingSlash; } + + const rtl::OUString & getEscapedTitle() const { return m_aEscapedTitle; } + + // Not good to expose implementation details, but this is actually an + // internal class. + const std::auto_ptr< PropertyValueMap > & getProperties() const + { return m_xProps; } + +private: + ::rtl::OUString m_aEscapedTitle; // escaped Title + std::auto_ptr< PropertyValueMap > m_xProps; + bool m_bTrailingSlash; + + static com::sun::star::uno::Any m_aEmptyAny; + + ContentProperties & operator=( const ContentProperties & ); // n.i. + + const PropertyValue * get( const rtl::OUString & rName ) const; +}; + +} + +#endif /* !_WEBDAV_UCP_CONTENTPROPERTIES_HXX */ diff --git a/ucb/source/ucp/webdav/DAVAuthListener.hxx b/ucb/source/ucp/webdav/DAVAuthListener.hxx new file mode 100644 index 000000000000..71bed1c0a14d --- /dev/null +++ b/ucb/source/ucp/webdav/DAVAuthListener.hxx @@ -0,0 +1,52 @@ +/************************************************************************* + * + * 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 _DAVAUTHLISTENER_HXX_ +#define _DAVAUTHLISTENER_HXX_ + +#include <salhelper/simplereferenceobject.hxx> +#include <rtl/ustring.hxx> + +#include <com/sun/star/uno/XReference.hpp> +#include <com/sun/star/ucb/XCommandEnvironment.hpp> + +namespace webdav_ucp +{ + +class DAVAuthListener : public salhelper::SimpleReferenceObject +{ + public: + virtual int authenticate( + const ::rtl::OUString & inRealm, + const ::rtl::OUString & inHostName, + ::rtl::OUString & inoutUserName, + ::rtl::OUString & outPassWord, + sal_Bool bCanUseSystemCredentials ) = 0; +}; + +} // namespace webdav_ucp + +#endif // _DAVAUTHLISTENER_HXX_ diff --git a/ucb/source/ucp/webdav/DAVAuthListenerImpl.hxx b/ucb/source/ucp/webdav/DAVAuthListenerImpl.hxx new file mode 100644 index 000000000000..c0c9968613af --- /dev/null +++ b/ucb/source/ucp/webdav/DAVAuthListenerImpl.hxx @@ -0,0 +1,77 @@ +/************************************************************************* + * + * 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 _DAVAUTHLISTENERIMPL_HXX_ +#define _DAVAUTHLISTENERIMPL_HXX_ + +#include "DAVAuthListener.hxx" + + +namespace webdav_ucp +{ + +//========================================================================= + +//========================================================================= +//========================================================================= +// +// class DAVAuthListenerImpl. +// +//========================================================================= +//========================================================================= + + + class DAVAuthListener_Impl : public DAVAuthListener + { + public: + + DAVAuthListener_Impl( + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment>& xEnv, + const ::rtl::OUString & inURL ) + : m_xEnv( xEnv ), m_aURL( inURL ) + { + } + + virtual int authenticate( const ::rtl::OUString & inRealm, + const ::rtl::OUString & inHostName, + ::rtl::OUString & inoutUserName, + ::rtl::OUString & outPassWord, + sal_Bool bCanUseSystemCredentials ); + private: + + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > m_xEnv; + const rtl::OUString m_aURL; + + rtl::OUString m_aPrevPassword; + rtl::OUString m_aPrevUsername; + }; + +} + +#endif diff --git a/ucb/source/ucp/webdav/DAVException.hxx b/ucb/source/ucp/webdav/DAVException.hxx new file mode 100644 index 000000000000..c981eb404676 --- /dev/null +++ b/ucb/source/ucp/webdav/DAVException.hxx @@ -0,0 +1,166 @@ +/************************************************************************* + * + * 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 _DAVEXCEPTION_HXX_ +#define _DAVEXCEPTION_HXX_ + +#include <rtl/ustring.hxx> + +namespace webdav_ucp +{ + +///////////////////////////////////////////////////////////////////////////// +// HTTP/WebDAV status codes +///////////////////////////////////////////////////////////////////////////// + +const sal_uInt16 SC_NONE = 0; + +// 1xx (Informational - no errors) +const sal_uInt16 SC_CONTINUE = 100; +const sal_uInt16 SC_SWITCHING_PROTOCOLS = 101; +// DAV extensions +const sal_uInt16 SC_PROCESSING = 102; + +//2xx (Successful - no errors) +const sal_uInt16 SC_OK = 200; +const sal_uInt16 SC_CREATED = 201; +const sal_uInt16 SC_ACCEPTED = 202; +const sal_uInt16 SC_NON_AUTHORITATIVE_INFORMATION = 203; +const sal_uInt16 SC_NO_CONTENT = 204; +const sal_uInt16 SC_RESET_CONTENT = 205; +const sal_uInt16 SC_PARTIAL_CONTENT = 206; +// DAV extensions +const sal_uInt16 SC_MULTISTATUS = 207; + +//3xx (Redirection) +const sal_uInt16 SC_MULTIPLE_CHOICES = 300; +const sal_uInt16 SC_MOVED_PERMANENTLY = 301; +const sal_uInt16 SC_MOVED_TEMPORARILY = 302; +const sal_uInt16 SC_SEE_OTHER = 303; +const sal_uInt16 SC_NOT_MODIFIED = 304; +const sal_uInt16 SC_USE_PROXY = 305; +const sal_uInt16 SC_TEMPORARY_REDIRECT = 307; + +//4xx (Client error) +const sal_uInt16 SC_BAD_REQUEST = 400; +const sal_uInt16 SC_UNAUTHORIZED = 401; +const sal_uInt16 SC_PAYMENT_REQUIRED = 402; +const sal_uInt16 SC_FORBIDDEN = 403; +const sal_uInt16 SC_NOT_FOUND = 404; +const sal_uInt16 SC_METHOD_NOT_ALLOWED = 405; +const sal_uInt16 SC_NOT_ACCEPTABLE = 406; +const sal_uInt16 SC_PROXY_AUTHENTICATION_REQUIRED = 407; +const sal_uInt16 SC_REQUEST_TIMEOUT = 408; +const sal_uInt16 SC_CONFLICT = 409; +const sal_uInt16 SC_GONE = 410; +const sal_uInt16 SC_LENGTH_REQUIRED = 411; +const sal_uInt16 SC_PRECONDITION_FAILED = 412; +const sal_uInt16 SC_REQUEST_ENTITY_TOO_LARGE = 413; +const sal_uInt16 SC_REQUEST_URI_TOO_LONG = 414; +const sal_uInt16 SC_UNSUPPORTED_MEDIA_TYPE = 415; +const sal_uInt16 SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416; +const sal_uInt16 SC_EXPECTATION_FAILED = 417; +// DAV extensions +const sal_uInt16 SC_UNPROCESSABLE_ENTITY = 422; +const sal_uInt16 SC_LOCKED = 423; +const sal_uInt16 SC_FAILED_DEPENDENCY = 424; + +//5xx (Server error) +const sal_uInt16 SC_INTERNAL_SERVER_ERROR = 500; +const sal_uInt16 SC_NOT_IMPLEMENTED = 501; +const sal_uInt16 SC_BAD_GATEWAY = 502; +const sal_uInt16 SC_SERVICE_UNAVAILABLE = 503; +const sal_uInt16 SC_GATEWAY_TIMEOUT = 504; +const sal_uInt16 SC_HTTP_VERSION_NOT_SUPPORTED = 505; +// DAV extensions +const sal_uInt16 SC_INSUFFICIENT_STORAGE = 507; + +///////////////////////////////////////////////////////////////////////////// + +class DAVException +{ + public: + enum ExceptionCode { + DAV_HTTP_ERROR = 0, // Generic error, + // mData = server error message, + // mStatusCode = HTTP status code + DAV_HTTP_LOOKUP, // Name lookup failed, + // mData = server[:port] + DAV_HTTP_AUTH, // User authentication failed on server, + // mData = server[:port] + DAV_HTTP_AUTHPROXY, // User authentication failed on proxy, + // mData = proxy server[:port] + DAV_HTTP_CONNECT, // Could not connect to server, + // mData = server[:port] + DAV_HTTP_TIMEOUT, // Connection timed out + // mData = server[:port] + DAV_HTTP_FAILED, // The precondition failed + // mData = server[:port] + DAV_HTTP_RETRY, // Retry request + // mData = server[:port] + DAV_HTTP_REDIRECT, // Request was redirected, + // mData = new URL + DAV_SESSION_CREATE, // session creation error, + // mData = server[:port] + DAV_INVALID_ARG, // invalid argument + + DAV_LOCK_EXPIRED, // DAV lock expired + + DAV_NOT_LOCKED, // not locked + + DAV_LOCKED_SELF, // locked by this OOo session + + DAV_LOCKED // locked by third party + }; + + private: + ExceptionCode mExceptionCode; + rtl::OUString mData; + sal_uInt16 mStatusCode; + + public: + DAVException( ExceptionCode inExceptionCode ) : + mExceptionCode( inExceptionCode ), mStatusCode( SC_NONE ) {}; + DAVException( ExceptionCode inExceptionCode, + const rtl::OUString & rData ) : + mExceptionCode( inExceptionCode ), mData( rData ), + mStatusCode( SC_NONE ) {}; + DAVException( ExceptionCode inExceptionCode, + const rtl::OUString & rData, + sal_uInt16 nStatusCode ) : + mExceptionCode( inExceptionCode ), mData( rData ), + mStatusCode( nStatusCode ) {}; + ~DAVException( ) {}; + + const ExceptionCode & getError() const { return mExceptionCode; } + const rtl::OUString & getData() const { return mData; } + sal_uInt16 getStatus() const { return mStatusCode; } +}; + +} // namespace webdav_ucp + +#endif // _DAVEXCEPTION_HXX_ diff --git a/ucb/source/ucp/webdav/DAVProperties.cxx b/ucb/source/ucp/webdav/DAVProperties.cxx new file mode 100644 index 000000000000..1202fb75a59f --- /dev/null +++ b/ucb/source/ucp/webdav/DAVProperties.cxx @@ -0,0 +1,199 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +#include <string.h> +#include "DAVProperties.hxx" + +using namespace webdav_ucp; + +const ::rtl::OUString DAVProperties::CREATIONDATE = + ::rtl::OUString::createFromAscii( "DAV:creationdate" ); +const ::rtl::OUString DAVProperties::DISPLAYNAME = + ::rtl::OUString::createFromAscii( "DAV:displayname" ); +const ::rtl::OUString DAVProperties::GETCONTENTLANGUAGE = + ::rtl::OUString::createFromAscii( "DAV:getcontentlanguage" ); +const ::rtl::OUString DAVProperties::GETCONTENTLENGTH = + ::rtl::OUString::createFromAscii( "DAV:getcontentlength" ); +const ::rtl::OUString DAVProperties::GETCONTENTTYPE = + ::rtl::OUString::createFromAscii( "DAV:getcontenttype" ); +const ::rtl::OUString DAVProperties::GETETAG = + ::rtl::OUString::createFromAscii( "DAV:getetag" ); +const ::rtl::OUString DAVProperties::GETLASTMODIFIED = + ::rtl::OUString::createFromAscii( "DAV:getlastmodified" ); +const ::rtl::OUString DAVProperties::LOCKDISCOVERY = + ::rtl::OUString::createFromAscii( "DAV:lockdiscovery" ); +const ::rtl::OUString DAVProperties::RESOURCETYPE = + ::rtl::OUString::createFromAscii( "DAV:resourcetype" ); +const ::rtl::OUString DAVProperties::SOURCE = + ::rtl::OUString::createFromAscii( "DAV:source" ); +const ::rtl::OUString DAVProperties::SUPPORTEDLOCK = + ::rtl::OUString::createFromAscii( "DAV:supportedlock" ); + +const ::rtl::OUString DAVProperties::EXECUTABLE = + ::rtl::OUString::createFromAscii( + "http://apache.org/dav/props/executable" ); + +// ------------------------------------------------------------------- +// static +void DAVProperties::createNeonPropName( const rtl::OUString & rFullName, + NeonPropName & rName ) +{ + if ( rFullName.compareToAscii( RTL_CONSTASCII_STRINGPARAM( "DAV:" ) ) == 0 ) + { + rName.nspace = "DAV:"; + rName.name + = strdup( rtl::OUStringToOString( + rFullName.copy( RTL_CONSTASCII_LENGTH( "DAV:" ) ), + RTL_TEXTENCODING_UTF8 ) ); + } + else if ( rFullName.compareToAscii( RTL_CONSTASCII_STRINGPARAM( + "http://apache.org/dav/props/" ) ) == 0 ) + { + rName.nspace = "http://apache.org/dav/props/"; + rName.name + = strdup( rtl::OUStringToOString( + rFullName.copy( + RTL_CONSTASCII_LENGTH( + "http://apache.org/dav/props/" ) ), + RTL_TEXTENCODING_UTF8 ) ); + } + else if ( rFullName.compareToAscii( RTL_CONSTASCII_STRINGPARAM( + "http://ucb.openoffice.org/dav/props/" ) ) == 0 ) + { + rName.nspace = "http://ucb.openoffice.org/dav/props/"; + rName.name + = strdup( rtl::OUStringToOString( + rFullName.copy( + RTL_CONSTASCII_LENGTH( + "http://ucb.openoffice.org/dav/props/" ) ), + RTL_TEXTENCODING_UTF8 ) ); + } + else if ( rFullName.compareToAscii( RTL_CONSTASCII_STRINGPARAM( + "<prop:" ) ) == 0 ) + { + // Support for 3rd party namespaces/props + + rtl::OString aFullName + = rtl::OUStringToOString( rFullName, RTL_TEXTENCODING_UTF8 ); + + // Format: <prop:the_propname xmlns:prop="the_namespace"> + + sal_Int32 nStart = RTL_CONSTASCII_LENGTH( "<prop:" ); + sal_Int32 nLen = aFullName.indexOf( ' ' ) - nStart; + rName.name = strdup( aFullName.copy( nStart, nLen ) ); + + nStart = aFullName.indexOf( '=', nStart + nLen ) + 2; // after =" + nLen = aFullName.getLength() - RTL_CONSTASCII_LENGTH( "\">" ) - nStart; + rName.nspace = strdup( aFullName.copy( nStart, nLen ) ); + } + else + { + // Add our namespace to our own properties. + rName.nspace = "http://ucb.openoffice.org/dav/props/"; + rName.name + = strdup( rtl::OUStringToOString( rFullName, + RTL_TEXTENCODING_UTF8 ) ); + } +} + +// ------------------------------------------------------------------- +// static +void DAVProperties::createUCBPropName( const char * nspace, + const char * name, + rtl::OUString & rFullName ) +{ + rtl::OUString aNameSpace + = rtl::OStringToOUString( nspace, RTL_TEXTENCODING_UTF8 ); + rtl::OUString aName + = rtl::OStringToOUString( name, RTL_TEXTENCODING_UTF8 ); + + if ( !aNameSpace.getLength() ) + { + // Some servers send XML without proper namespaces. Assume "DAV:" + // in this case, if name is a well-known dav property name. + // Although this is not 100% correct, it solves many problems. + + if ( DAVProperties::RESOURCETYPE.matchIgnoreAsciiCase( aName, 4 ) || + DAVProperties::SUPPORTEDLOCK.matchIgnoreAsciiCase( aName, 4 ) || + DAVProperties::LOCKDISCOVERY.matchIgnoreAsciiCase( aName, 4 ) || + DAVProperties::CREATIONDATE.matchIgnoreAsciiCase( aName, 4 ) || + DAVProperties::DISPLAYNAME.matchIgnoreAsciiCase( aName, 4 ) || + DAVProperties::GETCONTENTLANGUAGE.matchIgnoreAsciiCase( aName, 4 ) || + DAVProperties::GETCONTENTLENGTH.matchIgnoreAsciiCase( aName, 4 ) || + DAVProperties::GETCONTENTTYPE.matchIgnoreAsciiCase( aName, 4 ) || + DAVProperties::GETETAG.matchIgnoreAsciiCase( aName, 4 ) || + DAVProperties::GETLASTMODIFIED.matchIgnoreAsciiCase( aName, 4 ) || + DAVProperties::SOURCE.matchIgnoreAsciiCase( aName, 4 ) ) + aNameSpace = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DAV:" ) ); + } + + // Note: Concatenating strings BEFORE comparing against known namespaces + // is important. See RFC 2815 ( 23.4.2 Meaning of Qualified Names ). + rFullName = aNameSpace; + rFullName += aName; + + if ( rFullName.compareToAscii( RTL_CONSTASCII_STRINGPARAM( + "DAV:" ) ) == 0 ) + { + // Okay, Just concat strings. + } + else if ( rFullName.compareToAscii( RTL_CONSTASCII_STRINGPARAM( + "http://apache.org/dav/props/" ) ) == 0 ) + { + // Okay, Just concat strings. + } + else if ( rFullName.compareToAscii( RTL_CONSTASCII_STRINGPARAM( + "http://ucb.openoffice.org/dav/props/" ) ) == 0 ) + { + // Remove namespace from our own properties. + rFullName = rFullName.copy( + RTL_CONSTASCII_LENGTH( + "http://ucb.openoffice.org/dav/props/" ) ); + } + else + { + // Create property name that encodes, namespace and name ( XML ). + rFullName = rtl::OUString::createFromAscii( "<prop:" ); + rFullName += aName; + rFullName += rtl::OUString::createFromAscii( " xmlns:prop=\"" ); + rFullName += aNameSpace; + rFullName += rtl::OUString::createFromAscii( "\">" ); + } +} + +// ------------------------------------------------------------------- +// static +bool DAVProperties::isUCBDeadProperty( const NeonPropName & rName ) +{ + return ( rName.nspace && + ( rtl_str_compareIgnoreAsciiCase( + rName.nspace, "http://ucb.openoffice.org/dav/props/" ) + == 0 ) ); +} diff --git a/ucb/source/ucp/webdav/DAVProperties.hxx b/ucb/source/ucp/webdav/DAVProperties.hxx new file mode 100644 index 000000000000..46effc84697c --- /dev/null +++ b/ucb/source/ucp/webdav/DAVProperties.hxx @@ -0,0 +1,62 @@ +/************************************************************************* + * + * 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 _DAVPROPERTIES_HXX_ +#define _DAVPROPERTIES_HXX_ + +#include <rtl/ustring.hxx> +#include "NeonTypes.hxx" + +namespace webdav_ucp +{ + +struct DAVProperties +{ + static const ::rtl::OUString CREATIONDATE; + static const ::rtl::OUString DISPLAYNAME; + static const ::rtl::OUString GETCONTENTLANGUAGE; + static const ::rtl::OUString GETCONTENTLENGTH; + static const ::rtl::OUString GETCONTENTTYPE; + static const ::rtl::OUString GETETAG; + static const ::rtl::OUString GETLASTMODIFIED; + static const ::rtl::OUString LOCKDISCOVERY; + static const ::rtl::OUString RESOURCETYPE; + static const ::rtl::OUString SOURCE; + static const ::rtl::OUString SUPPORTEDLOCK; + static const ::rtl::OUString EXECUTABLE; + + static void createNeonPropName( const rtl::OUString & rFullName, + NeonPropName & rName ); + static void createUCBPropName ( const char * nspace, + const char * name, + rtl::OUString & rFullName ); + + static bool isUCBDeadProperty( const NeonPropName & rName ); +}; + +} // namespace webdav_ucp + +#endif // _DAVPROPERTIES_HXX_ diff --git a/ucb/source/ucp/webdav/DAVRequestEnvironment.hxx b/ucb/source/ucp/webdav/DAVRequestEnvironment.hxx new file mode 100644 index 000000000000..96e3faaff62f --- /dev/null +++ b/ucb/source/ucp/webdav/DAVRequestEnvironment.hxx @@ -0,0 +1,62 @@ +/************************************************************************* + * + * 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 _DAVREQUESTENVIRONMENT_HXX_ +#define _DAVREQUESTENVIRONMENT_HXX_ + +#include <vector> +#include <rtl/ref.hxx> +#include "DAVAuthListener.hxx" + +namespace webdav_ucp +{ + typedef std::pair< rtl::OUString, rtl::OUString > DAVRequestHeader; + typedef std::vector< DAVRequestHeader > DAVRequestHeaders; + +struct DAVRequestEnvironment +{ + rtl::OUString m_aRequestURI; + rtl::Reference< DAVAuthListener > m_xAuthListener; +// rtl::Reference< DAVStatusListener > m_xStatusListener; +// rtl::Reference< DAVProgressListener > m_xStatusListener; + DAVRequestHeaders m_aRequestHeaders; + uno::Reference< ucb::XCommandEnvironment > m_xEnv; + +DAVRequestEnvironment( const rtl::OUString & rRequestURI, + const rtl::Reference< DAVAuthListener > & xListener, + const DAVRequestHeaders & rRequestHeaders, + const uno::Reference< ucb::XCommandEnvironment > & xEnv) + : m_aRequestURI( rRequestURI ), + m_xAuthListener( xListener ), + m_aRequestHeaders( rRequestHeaders ), + m_xEnv( xEnv ){} + + DAVRequestEnvironment() {} +}; + +} // namespace webdav_ucp + +#endif // _DAVREQUESTENVIRONMENT_HXX_ diff --git a/ucb/source/ucp/webdav/DAVResource.hxx b/ucb/source/ucp/webdav/DAVResource.hxx new file mode 100644 index 000000000000..4a14dc262443 --- /dev/null +++ b/ucb/source/ucp/webdav/DAVResource.hxx @@ -0,0 +1,67 @@ +/************************************************************************* + * + * 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 _DAVRESOURCE_HXX_ +#define _DAVRESOURCE_HXX_ + +#include <vector> + +#include "rtl/ustring.hxx" +#include "com/sun/star/uno/Any.hxx" + +namespace webdav_ucp +{ + +struct DAVPropertyValue +{ + rtl::OUString Name; + com::sun::star::uno::Any Value; + bool IsCaseSensitive; + + DAVPropertyValue() : IsCaseSensitive( true ) {} +}; + +struct DAVResource +{ + ::rtl::OUString uri; + std::vector< DAVPropertyValue > properties; + + DAVResource() {} + DAVResource( const ::rtl::OUString & inUri ) : uri( inUri ) {} +}; + +struct DAVResourceInfo +{ + ::rtl::OUString uri; + std::vector < ::rtl::OUString > properties; + + DAVResourceInfo( const ::rtl::OUString & inUri ) : uri( inUri ) {} +}; + +} // namespace webdav_ucp + +#endif // _DAVRESOURCE_HXX_ diff --git a/ucb/source/ucp/webdav/DAVResourceAccess.cxx b/ucb/source/ucp/webdav/DAVResourceAccess.cxx new file mode 100644 index 000000000000..e4617b7b9ea7 --- /dev/null +++ b/ucb/source/ucp/webdav/DAVResourceAccess.cxx @@ -0,0 +1,1218 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +#include "osl/diagnose.h" + +#include "com/sun/star/task/XInteractionAbort.hpp" +#include "com/sun/star/ucb/XWebDAVCommandEnvironment.hpp" + +#include "ucbhelper/simpleauthenticationrequest.hxx" +#include "comphelper/seekableinput.hxx" + +#include "DAVAuthListenerImpl.hxx" +#include "DAVResourceAccess.hxx" + +using namespace webdav_ucp; +using namespace com::sun::star; + +//========================================================================= +//========================================================================= +// +// DAVAuthListener_Impl Implementation. +// +//========================================================================= +//========================================================================= + +//========================================================================= +// virtual +int DAVAuthListener_Impl::authenticate( + const ::rtl::OUString & inRealm, + const ::rtl::OUString & inHostName, + ::rtl::OUString & inoutUserName, + ::rtl::OUString & outPassWord, + sal_Bool bCanUseSystemCredentials ) +{ + if ( m_xEnv.is() ) + { + uno::Reference< task::XInteractionHandler > xIH + = m_xEnv->getInteractionHandler(); + + if ( xIH.is() ) + { + // #102871# - Supply username and password from previous try. + // Password container service depends on this! + if ( inoutUserName.getLength() == 0 ) + inoutUserName = m_aPrevUsername; + + if ( outPassWord.getLength() == 0 ) + outPassWord = m_aPrevPassword; + + rtl::Reference< ucbhelper::SimpleAuthenticationRequest > xRequest + = new ucbhelper::SimpleAuthenticationRequest( + m_aURL, inHostName, inRealm, inoutUserName, + outPassWord, ::rtl::OUString(), + true /*bAllowPersistentStoring*/, + bCanUseSystemCredentials ); + xIH->handle( xRequest.get() ); + + rtl::Reference< ucbhelper::InteractionContinuation > xSelection + = xRequest->getSelection(); + + if ( xSelection.is() ) + { + // Handler handled the request. + uno::Reference< task::XInteractionAbort > xAbort( + xSelection.get(), uno::UNO_QUERY ); + if ( !xAbort.is() ) + { + const rtl::Reference< + ucbhelper::InteractionSupplyAuthentication > & xSupp + = xRequest->getAuthenticationSupplier(); + + sal_Bool bUseSystemCredentials = sal_False; + + if ( bCanUseSystemCredentials ) + bUseSystemCredentials + = xSupp->getUseSystemCredentials(); + + if ( bUseSystemCredentials ) + { + // This is the (strange) way to tell neon to use + // system credentials. + inoutUserName = rtl::OUString(); + outPassWord = rtl::OUString(); + } + else + { + inoutUserName = xSupp->getUserName(); + outPassWord = xSupp->getPassword(); + } + + // #102871# - Remember username and password. + m_aPrevUsername = inoutUserName; + m_aPrevPassword = outPassWord; + + // go on. + return 0; + } + } + } + } + // Abort. + return -1; +} + +//========================================================================= +//========================================================================= +// +// DAVResourceAccess Implementation. +// +//========================================================================= +//========================================================================= + +//========================================================================= +DAVResourceAccess::DAVResourceAccess( + const uno::Reference< lang::XMultiServiceFactory > & rSMgr, + rtl::Reference< DAVSessionFactory > const & rSessionFactory, + const rtl::OUString & rURL ) +: m_aURL( rURL ), + m_xSessionFactory( rSessionFactory ), + m_xSMgr( rSMgr ) +{ +} + +//========================================================================= +DAVResourceAccess::DAVResourceAccess( const DAVResourceAccess & rOther ) +: m_aURL( rOther.m_aURL ), + m_aPath( rOther.m_aPath ), + m_xSession( rOther.m_xSession ), + m_xSessionFactory( rOther.m_xSessionFactory ), + m_xSMgr( rOther.m_xSMgr ), + m_aRedirectURIs( rOther.m_aRedirectURIs ) +{ +} + +//========================================================================= +DAVResourceAccess & DAVResourceAccess::operator=( + const DAVResourceAccess & rOther ) +{ + m_aURL = rOther.m_aURL; + m_aPath = rOther.m_aPath; + m_xSession = rOther.m_xSession; + m_xSessionFactory = rOther.m_xSessionFactory; + m_xSMgr = rOther.m_xSMgr; + m_aRedirectURIs = rOther.m_aRedirectURIs; + + return *this; +} + +#if 0 // currently not used, but please don't remove code +//========================================================================= +void DAVResourceAccess::OPTIONS( + DAVCapabilities & rCapabilities, + const uno::Reference< ucb::XCommandEnvironment > & xEnv ) + throw( DAVException ) +{ + initialize(); + + bool bRetry; + int errorCount = 0; + do + { + bRetry = false; + try + { + DAVRequestHeaders aHeaders; + getUserRequestHeaders( xEnv, + getRequestURI(), + rtl::OUString::createFromAscii( + "OPTIONS" ), + aHeaders ); + + m_xSession->OPTIONS( getRequestURI(), + rCapabilities, + DAVRequestEnvironment( + getRequestURI(), + new DAVAuthListener_Impl( xEnv, m_aURL ), + aHeaders, xEnv) ); + } + catch ( DAVException & e ) + { + errorCount++; + bRetry = handleException( e, errorCount ); + if ( !bRetry ) + throw; + } + } + while ( bRetry ); +} +#endif + +//========================================================================= +void DAVResourceAccess::PROPFIND( + const Depth nDepth, + const std::vector< rtl::OUString > & rPropertyNames, + std::vector< DAVResource > & rResources, + const uno::Reference< ucb::XCommandEnvironment > & xEnv ) + throw( DAVException ) +{ + initialize(); + + int errorCount = 0; + bool bRetry; + do + { + bRetry = false; + try + { + DAVRequestHeaders aHeaders; + + getUserRequestHeaders( xEnv, + getRequestURI(), + rtl::OUString::createFromAscii( + "PROPFIND" ), + aHeaders ); + + m_xSession->PROPFIND( getRequestURI(), + nDepth, + rPropertyNames, + rResources, + DAVRequestEnvironment( + getRequestURI(), + new DAVAuthListener_Impl( xEnv, m_aURL ), + aHeaders, xEnv ) ); + } + catch ( DAVException & e ) + { + errorCount++; + bRetry = handleException( e, errorCount ); + if ( !bRetry ) + throw; + } + } + while ( bRetry ); +} + +//========================================================================= +void DAVResourceAccess::PROPFIND( + const Depth nDepth, + std::vector< DAVResourceInfo > & rResInfo, + const uno::Reference< ucb::XCommandEnvironment > & xEnv ) + throw( DAVException ) +{ + initialize(); + + int errorCount = 0; + bool bRetry; + do + { + bRetry = false; + try + { + DAVRequestHeaders aHeaders; + getUserRequestHeaders( xEnv, + getRequestURI(), + rtl::OUString::createFromAscii( + "PROPFIND" ), + aHeaders ); + + m_xSession->PROPFIND( getRequestURI(), + nDepth, + rResInfo, + DAVRequestEnvironment( + getRequestURI(), + new DAVAuthListener_Impl( xEnv, m_aURL ), + aHeaders, xEnv ) ) ; + } + catch ( DAVException & e ) + { + errorCount++; + bRetry = handleException( e, errorCount ); + if ( !bRetry ) + throw; + } + } + while ( bRetry ); +} + +//========================================================================= +void DAVResourceAccess::PROPPATCH( + const std::vector< ProppatchValue >& rValues, + const uno::Reference< ucb::XCommandEnvironment >& xEnv ) + throw( DAVException ) +{ + initialize(); + + int errorCount = 0; + bool bRetry; + do + { + bRetry = false; + try + { + DAVRequestHeaders aHeaders; + getUserRequestHeaders( xEnv, + getRequestURI(), + rtl::OUString::createFromAscii( + "PROPPATCH" ), + aHeaders ); + + m_xSession->PROPPATCH( getRequestURI(), + rValues, + DAVRequestEnvironment( + getRequestURI(), + new DAVAuthListener_Impl( xEnv, m_aURL ), + aHeaders, xEnv ) ); + } + catch ( DAVException & e ) + { + errorCount++; + bRetry = handleException( e, errorCount ); + if ( !bRetry ) + throw; + } + } + while ( bRetry ); +} + +//========================================================================= +void DAVResourceAccess::HEAD( + const std::vector< rtl::OUString > & rHeaderNames, + DAVResource & rResource, + const uno::Reference< ucb::XCommandEnvironment >& xEnv ) + throw( DAVException ) +{ + initialize(); + + int errorCount = 0; + bool bRetry; + do + { + bRetry = false; + try + { + DAVRequestHeaders aHeaders; + getUserRequestHeaders( xEnv, + getRequestURI(), + rtl::OUString::createFromAscii( "HEAD" ), + aHeaders ); + + m_xSession->HEAD( getRequestURI(), + rHeaderNames, + rResource, + DAVRequestEnvironment( + getRequestURI(), + new DAVAuthListener_Impl( xEnv, m_aURL ), + aHeaders, xEnv ) ); + } + catch ( DAVException & e ) + { + errorCount++; + bRetry = handleException( e, errorCount ); + if ( !bRetry ) + throw; + } + } + while ( bRetry ); +} + +//========================================================================= +uno::Reference< io::XInputStream > DAVResourceAccess::GET( + const uno::Reference< ucb::XCommandEnvironment > & xEnv ) + throw( DAVException ) +{ + initialize(); + + uno::Reference< io::XInputStream > xStream; + int errorCount = 0; + bool bRetry; + do + { + bRetry = false; + try + { + DAVRequestHeaders aHeaders; + getUserRequestHeaders( xEnv, + getRequestURI(), + rtl::OUString::createFromAscii( "GET" ), + aHeaders ); + + xStream = m_xSession->GET( getRequestURI(), + DAVRequestEnvironment( + getRequestURI(), + new DAVAuthListener_Impl( + xEnv, m_aURL ), + aHeaders, xEnv ) ); + } + catch ( DAVException & e ) + { + errorCount++; + bRetry = handleException( e, errorCount ); + if ( !bRetry ) + throw; + } + } + while ( bRetry ); + + return xStream; +} + +//========================================================================= +void DAVResourceAccess::GET( + uno::Reference< io::XOutputStream > & rStream, + const uno::Reference< ucb::XCommandEnvironment > & xEnv ) + throw( DAVException ) +{ + initialize(); + + int errorCount = 0; + bool bRetry; + do + { + bRetry = false; + try + { + DAVRequestHeaders aHeaders; + getUserRequestHeaders( xEnv, + getRequestURI(), + rtl::OUString::createFromAscii( "GET" ), + aHeaders ); + + m_xSession->GET( getRequestURI(), + rStream, + DAVRequestEnvironment( + getRequestURI(), + new DAVAuthListener_Impl( xEnv, m_aURL ), + aHeaders, xEnv ) ); + } + catch ( DAVException & e ) + { + errorCount++; + bRetry = handleException( e, errorCount ); + if ( !bRetry ) + throw; + } + } + while ( bRetry ); +} + +//========================================================================= +uno::Reference< io::XInputStream > DAVResourceAccess::GET( + const std::vector< rtl::OUString > & rHeaderNames, + DAVResource & rResource, + const uno::Reference< ucb::XCommandEnvironment > & xEnv ) + throw( DAVException ) +{ + initialize(); + + uno::Reference< io::XInputStream > xStream; + int errorCount = 0; + bool bRetry; + do + { + bRetry = false; + try + { + DAVRequestHeaders aHeaders; + getUserRequestHeaders( xEnv, + getRequestURI(), + rtl::OUString::createFromAscii( "GET" ), + aHeaders ); + + xStream = m_xSession->GET( getRequestURI(), + rHeaderNames, + rResource, + DAVRequestEnvironment( + getRequestURI(), + new DAVAuthListener_Impl( + xEnv, m_aURL ), + aHeaders, xEnv ) ); + } + catch ( DAVException & e ) + { + errorCount++; + bRetry = handleException( e, errorCount ); + if ( !bRetry ) + throw; + } + } + while ( bRetry ); + + return xStream; +} + +//========================================================================= +void DAVResourceAccess::GET( + uno::Reference< io::XOutputStream > & rStream, + const std::vector< rtl::OUString > & rHeaderNames, + DAVResource & rResource, + const uno::Reference< ucb::XCommandEnvironment > & xEnv ) + throw( DAVException ) +{ + initialize(); + + bool bRetry; + int errorCount = 0; + do + { + bRetry = false; + try + { + DAVRequestHeaders aHeaders; + getUserRequestHeaders( xEnv, + getRequestURI(), + rtl::OUString::createFromAscii( "GET" ), + aHeaders ); + + m_xSession->GET( getRequestURI(), + rStream, + rHeaderNames, + rResource, + DAVRequestEnvironment( + getRequestURI(), + new DAVAuthListener_Impl( xEnv, m_aURL ), + aHeaders, xEnv ) ); + } + catch ( DAVException & e ) + { + errorCount++; + bRetry = handleException( e, errorCount ); + if ( !bRetry ) + throw; + } + } + while ( bRetry ); +} + +//========================================================================= +void DAVResourceAccess::abort() + throw( DAVException ) +{ + // 17.11.09 (tkr): abort currently disabled caused by issue i106766 + // initialize(); + // m_xSession->abort(); + OSL_TRACE( "Not implemented. -> #i106766#" ); +} + +//========================================================================= +namespace { + + void resetInputStream( const uno::Reference< io::XInputStream > & rStream ) + throw( DAVException ) + { + try + { + uno::Reference< io::XSeekable > xSeekable( + rStream, uno::UNO_QUERY ); + if ( xSeekable.is() ) + { + xSeekable->seek( 0 ); + return; + } + } + catch ( lang::IllegalArgumentException const & ) + { + } + catch ( io::IOException const & ) + { + } + + throw DAVException( DAVException::DAV_INVALID_ARG ); + } + +} // namespace + +//========================================================================= +void DAVResourceAccess::PUT( + const uno::Reference< io::XInputStream > & rStream, + const uno::Reference< ucb::XCommandEnvironment > & xEnv ) + throw( DAVException ) +{ + initialize(); + + // Make stream seekable, if it not. Needed, if request must be retried. + uno::Reference< io::XInputStream > xSeekableStream + = comphelper::OSeekableInputWrapper::CheckSeekableCanWrap( + rStream, m_xSMgr ); + + int errorCount = 0; + bool bRetry = false; + do + { + if ( bRetry ) + resetInputStream( xSeekableStream ); + + bRetry = false; + try + { + DAVRequestHeaders aHeaders; + getUserRequestHeaders( xEnv, + getRequestURI(), + rtl::OUString::createFromAscii( "PUT" ), + aHeaders ); + + m_xSession->PUT( getRequestURI(), + xSeekableStream, + DAVRequestEnvironment( + getRequestURI(), + new DAVAuthListener_Impl( xEnv, m_aURL ), + aHeaders, xEnv ) ); + } + catch ( DAVException & e ) + { + errorCount++; + bRetry = handleException( e, errorCount ); + if ( !bRetry ) + throw; + } + } + while ( bRetry ); +} + +//========================================================================= +uno::Reference< io::XInputStream > DAVResourceAccess::POST( + const rtl::OUString & rContentType, + const rtl::OUString & rReferer, + const uno::Reference< io::XInputStream > & rInputStream, + const uno::Reference< ucb::XCommandEnvironment >& xEnv ) + throw ( DAVException ) +{ + initialize(); + + // Make stream seekable, if it not. Needed, if request must be retried. + uno::Reference< io::XInputStream > xSeekableStream + = comphelper::OSeekableInputWrapper::CheckSeekableCanWrap( + rInputStream, m_xSMgr ); + + uno::Reference< io::XInputStream > xStream; + int errorCount = 0; + bool bRetry = false; + do + { + if ( bRetry ) + { + resetInputStream( xSeekableStream ); + bRetry = false; + } + + try + { + DAVRequestHeaders aHeaders; + getUserRequestHeaders( xEnv, + getRequestURI(), + rtl::OUString::createFromAscii( "POST" ), + aHeaders ); + + xStream = m_xSession->POST( getRequestURI(), + rContentType, + rReferer, + xSeekableStream, + DAVRequestEnvironment( + getRequestURI(), + new DAVAuthListener_Impl( + xEnv, m_aURL ), + aHeaders, xEnv ) ); + } + catch ( DAVException & e ) + { + errorCount++; + bRetry = handleException( e, errorCount ); + if ( !bRetry ) + throw; + + if ( e.getError() == DAVException::DAV_HTTP_REDIRECT ) + { + // #i74980# - Upon POST redirect, do a GET. + return GET( xEnv ); + } + } + } + while ( bRetry ); + + return xStream; +} + +//========================================================================= +void DAVResourceAccess::POST( + const rtl::OUString & rContentType, + const rtl::OUString & rReferer, + const uno::Reference< io::XInputStream > & rInputStream, + uno::Reference< io::XOutputStream > & rOutputStream, + const uno::Reference< ucb::XCommandEnvironment >& xEnv ) + throw ( DAVException ) +{ + initialize(); + + // Make stream seekable, if it not. Needed, if request must be retried. + uno::Reference< io::XInputStream > xSeekableStream + = comphelper::OSeekableInputWrapper::CheckSeekableCanWrap( + rInputStream, m_xSMgr ); + + int errorCount = 0; + bool bRetry = false; + do + { + if ( bRetry ) + { + resetInputStream( xSeekableStream ); + bRetry = false; + } + + try + { + DAVRequestHeaders aHeaders; + getUserRequestHeaders( xEnv, + getRequestURI(), + rtl::OUString::createFromAscii( "POST" ), + aHeaders ); + + m_xSession->POST( getRequestURI(), + rContentType, + rReferer, + xSeekableStream, + rOutputStream, + DAVRequestEnvironment( + getRequestURI(), + new DAVAuthListener_Impl( xEnv, m_aURL ), + aHeaders, xEnv ) ); + } + catch ( DAVException & e ) + { + errorCount++; + bRetry = handleException( e, errorCount ); + if ( !bRetry ) + throw; + + if ( e.getError() == DAVException::DAV_HTTP_REDIRECT ) + { + // #i74980# - Upon POST redirect, do a GET. + GET( rOutputStream, xEnv ); + return; + } + } + } + while ( bRetry ); +} + +//========================================================================= +void DAVResourceAccess::MKCOL( + const uno::Reference< ucb::XCommandEnvironment > & xEnv ) + throw( DAVException ) +{ + initialize(); + + int errorCount = 0; + bool bRetry; + do + { + bRetry = false; + try + { + DAVRequestHeaders aHeaders; + getUserRequestHeaders( xEnv, + getRequestURI(), + rtl::OUString::createFromAscii( "MKCOL" ), + aHeaders ); + + m_xSession->MKCOL( getRequestURI(), + DAVRequestEnvironment( + getRequestURI(), + new DAVAuthListener_Impl( xEnv, m_aURL ), + aHeaders, xEnv ) ); + } + catch ( DAVException & e ) + { + errorCount++; + bRetry = handleException( e, errorCount ); + if ( !bRetry ) + throw; + } + } + while ( bRetry ); +} + +//========================================================================= +void DAVResourceAccess::COPY( + const ::rtl::OUString & rSourcePath, + const ::rtl::OUString & rDestinationURI, + sal_Bool bOverwrite, + const uno::Reference< ucb::XCommandEnvironment > & xEnv ) + throw( DAVException ) +{ + initialize(); + + int errorCount = 0; + bool bRetry; + do + { + bRetry = false; + try + { + DAVRequestHeaders aHeaders; + getUserRequestHeaders( xEnv, + getRequestURI(), + rtl::OUString::createFromAscii( "COPY" ), + aHeaders ); + + m_xSession->COPY( rSourcePath, + rDestinationURI, + DAVRequestEnvironment( + getRequestURI(), + new DAVAuthListener_Impl( xEnv, m_aURL ), + aHeaders, xEnv ), + bOverwrite ); + } + catch ( DAVException & e ) + { + errorCount++; + bRetry = handleException( e, errorCount ); + if ( !bRetry ) + throw; + } + } + while ( bRetry ); +} + +//========================================================================= +void DAVResourceAccess::MOVE( + const ::rtl::OUString & rSourcePath, + const ::rtl::OUString & rDestinationURI, + sal_Bool bOverwrite, + const uno::Reference< ucb::XCommandEnvironment > & xEnv ) + throw( DAVException ) +{ + initialize(); + + int errorCount = 0; + bool bRetry; + do + { + bRetry = false; + try + { + DAVRequestHeaders aHeaders; + getUserRequestHeaders( xEnv, + getRequestURI(), + rtl::OUString::createFromAscii( "MOVE" ), + aHeaders ); + + m_xSession->MOVE( rSourcePath, + rDestinationURI, + DAVRequestEnvironment( + getRequestURI(), + new DAVAuthListener_Impl( xEnv, m_aURL ), + aHeaders, xEnv ), + bOverwrite ); + } + catch ( DAVException & e ) + { + errorCount++; + bRetry = handleException( e, errorCount ); + if ( !bRetry ) + throw; + } + } + while ( bRetry ); +} + +//========================================================================= +void DAVResourceAccess::DESTROY( + const uno::Reference< ucb::XCommandEnvironment > & xEnv ) + throw( DAVException ) +{ + initialize(); + + int errorCount = 0; + bool bRetry; + do + { + bRetry = false; + try + { + DAVRequestHeaders aHeaders; + getUserRequestHeaders( xEnv, + getRequestURI(), + rtl::OUString::createFromAscii( + "DESTROY" ), + aHeaders ); + + m_xSession->DESTROY( getRequestURI(), + DAVRequestEnvironment( + getRequestURI(), + new DAVAuthListener_Impl( xEnv, m_aURL ), + aHeaders, xEnv ) ); + } + catch ( DAVException & e ) + { + errorCount++; + bRetry = handleException( e, errorCount ); + if ( !bRetry ) + throw; + } + } + while ( bRetry ); +} + +//========================================================================= +// set new lock. +void DAVResourceAccess::LOCK( + ucb::Lock & inLock, + const uno::Reference< ucb::XCommandEnvironment > & xEnv ) + throw ( DAVException ) +{ + initialize(); + + int errorCount = 0; + bool bRetry; + do + { + bRetry = false; + try + { + DAVRequestHeaders aHeaders; + getUserRequestHeaders( xEnv, + getRequestURI(), + rtl::OUString::createFromAscii( "LOCK" ), + aHeaders ); + + m_xSession->LOCK( getRequestURI(), + inLock, + DAVRequestEnvironment( + getRequestURI(), + new DAVAuthListener_Impl( xEnv, m_aURL ), + aHeaders, xEnv ) ); + } + catch ( DAVException & e ) + { + errorCount++; + bRetry = handleException( e, errorCount ); + if ( !bRetry ) + throw; + } + } + while ( bRetry ); +} + +#if 0 // currently not used, but please don't remove code +//========================================================================= +// refresh existing lock. +sal_Int64 DAVResourceAccess::LOCK( + sal_Int64 nTimeout, + const uno::Reference< ucb::XCommandEnvironment > & xEnv ) + throw ( DAVException ) +{ + initialize(); + + sal_Int64 nNewTimeout = 0; + int errorCount = 0; + bool bRetry; + do + { + bRetry = false; + try + { + DAVRequestHeaders aHeaders; + getUserRequestHeaders( xEnv, + getRequestURI(), + rtl::OUString::createFromAscii( "LOCK" ), + aHeaders ); + + nNewTimeout = m_xSession->LOCK( getRequestURI(), + nTimeout, + DAVRequestEnvironment( + getRequestURI(), + new DAVAuthListener_Impl( + xEnv, m_aURL ), + aHeaders, xEnv ) ); + } + catch ( DAVException & e ) + { + errorCount++; + bRetry = handleException( e, errorCount ); + if ( !bRetry ) + throw; + } + } + while ( bRetry ); + + return nNewTimeout; +} +#endif + +//========================================================================= +void DAVResourceAccess::UNLOCK( + const uno::Reference< ucb::XCommandEnvironment > & xEnv ) + throw ( DAVException ) +{ + initialize(); + + int errorCount = 0; + bool bRetry; + do + { + bRetry = false; + try + { + DAVRequestHeaders aHeaders; + getUserRequestHeaders( xEnv, + getRequestURI(), + rtl::OUString::createFromAscii( "UNLOCK" ), + aHeaders ); + + m_xSession->UNLOCK( getRequestURI(), + DAVRequestEnvironment( + getRequestURI(), + new DAVAuthListener_Impl( xEnv, m_aURL ), + aHeaders, xEnv ) ); + } + catch ( DAVException & e ) + { + errorCount++; + bRetry = handleException( e, errorCount ); + if ( !bRetry ) + throw; + } + } + while ( bRetry ); +} + +//========================================================================= +void DAVResourceAccess::setURL( const rtl::OUString & rNewURL ) + throw( DAVException ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + m_aURL = rNewURL; + m_aPath = rtl::OUString(); // Next initialize() will create new session. +} + +//========================================================================= +// init dav session and path +void DAVResourceAccess::initialize() + throw ( DAVException ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + if ( m_aPath.getLength() == 0 ) + { + NeonUri aURI( m_aURL ); + rtl::OUString aPath( aURI.GetPath() ); + + /* #134089# - Check URI */ + if ( !aPath.getLength() ) + throw DAVException( DAVException::DAV_INVALID_ARG ); + + /* #134089# - Check URI */ + if ( !aURI.GetHost().getLength() ) + throw DAVException( DAVException::DAV_INVALID_ARG ); + + if ( !m_xSession.is() || !m_xSession->CanUse( m_aURL ) ) + { + m_xSession.clear(); + + // create new webdav session + m_xSession + = m_xSessionFactory->createDAVSession( m_aURL, m_xSMgr ); + + if ( !m_xSession.is() ) + return; + } + + // Own URI is needed for redirect cycle detection. + m_aRedirectURIs.push_back( aURI ); + + // Success. + m_aPath = aPath; + + // Not only the path has to be encoded + m_aURL = aURI.GetURI(); + } +} + +//========================================================================= +const rtl::OUString & DAVResourceAccess::getRequestURI() const +{ + OSL_ENSURE( m_xSession.is(), + "DAVResourceAccess::getRequestURI - Not initialized!" ); + + // In case a proxy is used we have to use the absolute URI for a request. + if ( m_xSession->UsesProxy() ) + return m_aURL; + + return m_aPath; +} + +//========================================================================= +// static +void DAVResourceAccess::getUserRequestHeaders( + const uno::Reference< ucb::XCommandEnvironment > & xEnv, + const rtl::OUString & rURI, + const rtl::OUString & rMethod, + DAVRequestHeaders & rRequestHeaders ) +{ + if ( xEnv.is() ) + { + uno::Reference< ucb::XWebDAVCommandEnvironment > xDAVEnv( + xEnv, uno::UNO_QUERY ); + + if ( xDAVEnv.is() ) + { + uno::Sequence< beans::NamedValue > aRequestHeaders + = xDAVEnv->getUserRequestHeaders( rURI, rMethod ); + + for ( sal_Int32 n = 0; n < aRequestHeaders.getLength(); ++n ) + { + rtl::OUString aValue; + sal_Bool isString = aRequestHeaders[ n ].Value >>= aValue; + + if ( !isString ) + { + OSL_ENSURE( isString, + "DAVResourceAccess::getUserRequestHeaders :" + "Value is not a string! Ignoring..." ); + } + + rRequestHeaders.push_back( + DAVRequestHeader( aRequestHeaders[ n ].Name, aValue ) ); + } + } + } +} + +//========================================================================= +sal_Bool DAVResourceAccess::detectRedirectCycle( + const rtl::OUString& rRedirectURL ) + throw ( DAVException ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + NeonUri aUri( rRedirectURL ); + + std::vector< NeonUri >::const_iterator it = m_aRedirectURIs.begin(); + std::vector< NeonUri >::const_iterator end = m_aRedirectURIs.end(); + + while ( it != end ) + { + if ( aUri == (*it) ) + return sal_True; + + it++; + } + + return sal_False; +} + +//========================================================================= +void DAVResourceAccess::resetUri() +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + if ( m_aRedirectURIs.size() > 0 ) + { + std::vector< NeonUri >::const_iterator it = m_aRedirectURIs.begin(); + + NeonUri aUri( (*it) ); + m_aRedirectURIs.clear(); + setURL ( aUri.GetURI() ); + initialize(); + } +} + +//========================================================================= +sal_Bool DAVResourceAccess::handleException( DAVException & e, int errorCount ) + throw ( DAVException ) +{ + switch ( e.getError() ) + { + case DAVException::DAV_HTTP_REDIRECT: + if ( !detectRedirectCycle( e.getData() ) ) + { + // set new URL and path. + setURL( e.getData() ); + initialize(); + return sal_True; + } + return sal_False; + // --> tkr #67048# copy & paste images doesn't display. + // if we have a bad connection try again. Up to three times. + case DAVException::DAV_HTTP_ERROR: + // retry up to three times, if not a client-side error. + if ( ( e.getStatus() < 400 || e.getStatus() >= 500 ) && + errorCount < 3 ) + { + return sal_True; + } + return sal_False; + // <-- + // --> tkr: if connection has said retry then retry! + case DAVException::DAV_HTTP_RETRY: + return sal_True; + // <-- + default: + return sal_False; // Abort + } +} diff --git a/ucb/source/ucp/webdav/DAVResourceAccess.hxx b/ucb/source/ucp/webdav/DAVResourceAccess.hxx new file mode 100644 index 000000000000..53a98847078b --- /dev/null +++ b/ucb/source/ucp/webdav/DAVResourceAccess.hxx @@ -0,0 +1,251 @@ +/************************************************************************* + * + * 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 _DAVRESOURCEACCESS_HXX_ +#define _DAVRESOURCEACCESS_HXX_ + +#include <vector> +#include <rtl/ustring.hxx> +#include <rtl/ref.hxx> +#include <osl/mutex.hxx> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/ucb/Lock.hpp> +#include <com/sun/star/ucb/XCommandEnvironment.hpp> +#include "DAVAuthListener.hxx" +#include "DAVException.hxx" +#include "DAVSession.hxx" +#include "DAVResource.hxx" +#include "DAVTypes.hxx" +#include "NeonUri.hxx" + +namespace webdav_ucp +{ + +class DAVSessionFactory; + +class DAVResourceAccess +{ + osl::Mutex m_aMutex; + rtl::OUString m_aURL; + rtl::OUString m_aPath; + rtl::Reference< DAVSession > m_xSession; + rtl::Reference< DAVSessionFactory > m_xSessionFactory; + com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory > m_xSMgr; + std::vector< NeonUri > m_aRedirectURIs; + +public: + DAVResourceAccess() : m_xSessionFactory( 0 ) {} + DAVResourceAccess( const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory > & rSMgr, + rtl::Reference< + DAVSessionFactory > const & rSessionFactory, + const rtl::OUString & rURL ); + DAVResourceAccess( const DAVResourceAccess & rOther ); + + DAVResourceAccess & operator=( const DAVResourceAccess & rOther ); + + void setURL( const rtl::OUString & rNewURL ) + throw ( DAVException ); + + void resetUri(); + + const rtl::OUString & getURL() const { return m_aURL; } + + rtl::Reference< DAVSessionFactory > getSessionFactory() const + { return m_xSessionFactory; } + + // DAV methods + // + +#if 0 // currently not used, but please don't remove code + void + OPTIONS( DAVCapabilities & rCapabilities, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw ( DAVException ); +#endif + + // allprop & named + void + PROPFIND( const Depth nDepth, + const std::vector< rtl::OUString > & rPropertyNames, + std::vector< DAVResource > & rResources, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw ( DAVException ); + + // propnames + void + PROPFIND( const Depth nDepth, + std::vector< DAVResourceInfo > & rResInfo, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw ( DAVException ); + + void + PROPPATCH( const std::vector< ProppatchValue > & rValues, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment >& xEnv ) + throw ( DAVException ); + + void + HEAD( const std::vector< rtl::OUString > & rHeaderNames, // empty == 'all' + DAVResource & rResource, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment >& xEnv ) + throw ( DAVException ); + + com::sun::star::uno::Reference< com::sun::star::io::XInputStream > + GET( const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw ( DAVException ); + + void + GET( com::sun::star::uno::Reference< + com::sun::star::io::XOutputStream > & rStream, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw ( DAVException ); + + com::sun::star::uno::Reference< com::sun::star::io::XInputStream > + GET( const std::vector< rtl::OUString > & rHeaderNames, // empty == 'all' + DAVResource & rResource, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw ( DAVException ); + + void + GET( com::sun::star::uno::Reference< + com::sun::star::io::XOutputStream > & rStream, + const std::vector< rtl::OUString > & rHeaderNames, // empty == 'all' + DAVResource & rResource, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw ( DAVException ); + + void + PUT( const com::sun::star::uno::Reference< + com::sun::star::io::XInputStream > & rStream, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw ( DAVException ); + + com::sun::star::uno::Reference< com::sun::star::io::XInputStream > + POST( const rtl::OUString & rContentType, + const rtl::OUString & rReferer, + const com::sun::star::uno::Reference< + com::sun::star::io::XInputStream > & rInputStream, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment >& xEnv ) + throw ( DAVException ); + + void + POST( const rtl::OUString & rContentType, + const rtl::OUString & rReferer, + const com::sun::star::uno::Reference< + com::sun::star::io::XInputStream > & rInputStream, + com::sun::star::uno::Reference< + com::sun::star::io::XOutputStream > & rOutputStream, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment >& xEnv ) + throw ( DAVException ); + + void + MKCOL( const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw ( DAVException ); + + void + COPY( const ::rtl::OUString & rSourcePath, + const ::rtl::OUString & rDestinationURI, + sal_Bool bOverwrite, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw ( DAVException ); + + void + MOVE( const ::rtl::OUString & rSourcePath, + const ::rtl::OUString & rDestinationURI, + sal_Bool bOverwrite, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw ( DAVException ); + + void + DESTROY( const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw ( DAVException ); + + // set new lock. + void + LOCK( com::sun::star::ucb::Lock & inLock, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw( DAVException ); + +#if 0 // currently not used, but please don't remove code + // refresh existing lock. + sal_Int64 + LOCK( sal_Int64 nTimeout, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw ( DAVException ); +#endif + + void + UNLOCK( const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw ( DAVException ); + + void + abort() + throw ( DAVException ); + + // helper + static void + getUserRequestHeaders( + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv, + const rtl::OUString & rURI, + const rtl::OUString & rMethod, + DAVRequestHeaders & rRequestHeaders ); + +private: + const rtl::OUString & getRequestURI() const; + sal_Bool detectRedirectCycle( const rtl::OUString& rRedirectURL ) + throw ( DAVException ); + sal_Bool handleException( DAVException & e, int errorCount ) + throw ( DAVException ); + void initialize() + throw ( DAVException ); +}; + +} // namespace webdav_ucp + +#endif // _DAVRESOURCEACCESS_HXX_ diff --git a/ucb/source/ucp/webdav/DAVSession.hxx b/ucb/source/ucp/webdav/DAVSession.hxx new file mode 100644 index 000000000000..4ea24f372c12 --- /dev/null +++ b/ucb/source/ucp/webdav/DAVSession.hxx @@ -0,0 +1,219 @@ +/************************************************************************* + * + * 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 _DAVSESSION_HXX_ +#define _DAVSESSION_HXX_ + +#include <memory> +#include <rtl/ustring.hxx> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/io/XOutputStream.hpp> +#include "DAVException.hxx" +#include "DAVProperties.hxx" +#include "DAVResource.hxx" +#include "DAVSessionFactory.hxx" +#include "DAVTypes.hxx" +#include "DAVRequestEnvironment.hxx" + +namespace com { namespace sun { namespace star { namespace ucb { + struct Lock; +} } } } + +namespace webdav_ucp +{ + +class DAVAuthListener; + +class DAVSession +{ +public: + inline void acquire() SAL_THROW(()) + { + osl_incrementInterlockedCount( &m_nRefCount ); + } + + void release() SAL_THROW(()) + { + if ( osl_decrementInterlockedCount( &m_nRefCount ) == 0 ) + { + m_xFactory->releaseElement( this ); + delete this; + } + } + + virtual sal_Bool CanUse( const ::rtl::OUString & inPath ) = 0; + + virtual sal_Bool UsesProxy() = 0; + + // DAV methods + // + + virtual void OPTIONS( const ::rtl::OUString & inPath, + DAVCapabilities & outCapabilities, + const DAVRequestEnvironment & rEnv ) + throw( DAVException ) = 0; + + // allprop & named + virtual void PROPFIND( const ::rtl::OUString & inPath, + const Depth inDepth, + const std::vector< ::rtl::OUString > & inPropertyNames, + std::vector< DAVResource > & ioResources, + const DAVRequestEnvironment & rEnv ) + throw( DAVException ) = 0; + + // propnames + virtual void PROPFIND( const ::rtl::OUString & inPath, + const Depth inDepth, + std::vector< DAVResourceInfo > & ioResInfo, + const DAVRequestEnvironment & rEnv ) + throw( DAVException ) = 0; + + virtual void PROPPATCH( const ::rtl::OUString & inPath, + const std::vector< ProppatchValue > & inValues, + const DAVRequestEnvironment & rEnv ) + throw( DAVException ) = 0; + + virtual void HEAD( const ::rtl::OUString & inPath, + const std::vector< ::rtl::OUString > & inHeaderNames, + DAVResource & ioResource, + const DAVRequestEnvironment & rEnv ) + throw( DAVException ) = 0; + + virtual com::sun::star::uno::Reference< com::sun::star::io::XInputStream > + GET( const ::rtl::OUString & inPath, + const DAVRequestEnvironment & rEnv ) + throw( DAVException ) = 0; + + virtual void GET( const ::rtl::OUString & inPath, + com::sun::star::uno::Reference< + com::sun::star::io::XOutputStream >& o, + const DAVRequestEnvironment & rEnv ) + throw( DAVException ) = 0; + + virtual com::sun::star::uno::Reference< com::sun::star::io::XInputStream > + GET( const ::rtl::OUString & inPath, + const std::vector< ::rtl::OUString > & inHeaderNames, + DAVResource & ioResource, + const DAVRequestEnvironment & rEnv ) + throw( DAVException ) = 0; + + virtual void + GET( const ::rtl::OUString & inPath, + com::sun::star::uno::Reference< com::sun::star::io::XOutputStream >& o, + const std::vector< ::rtl::OUString > & inHeaderNames, + DAVResource & ioResource, + const DAVRequestEnvironment & rEnv ) + throw( DAVException ) = 0; + + virtual void PUT( const ::rtl::OUString & inPath, + const com::sun::star::uno::Reference< + com::sun::star::io::XInputStream >& s, + const DAVRequestEnvironment & rEnv ) + throw( DAVException ) = 0; + + virtual com::sun::star::uno::Reference< com::sun::star::io::XInputStream > + POST( const rtl::OUString & inPath, + const rtl::OUString & rContentType, + const rtl::OUString & rReferer, + const com::sun::star::uno::Reference< + com::sun::star::io::XInputStream > & inInputStream, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ) = 0; + + virtual void POST( const rtl::OUString & inPath, + const rtl::OUString & rContentType, + const rtl::OUString & rReferer, + const com::sun::star::uno::Reference< + com::sun::star::io::XInputStream > & inInputStream, + com::sun::star::uno::Reference< + com::sun::star::io::XOutputStream > & oOutputStream, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ) = 0; + + virtual void MKCOL( const ::rtl::OUString & inPath, + const DAVRequestEnvironment & rEnv ) + throw( DAVException ) = 0; + + virtual void COPY( const ::rtl::OUString & inSource, + const ::rtl::OUString & inDestination, + const DAVRequestEnvironment & rEnv, + sal_Bool inOverwrite = false ) + throw( DAVException ) = 0; + + virtual void MOVE( const ::rtl::OUString & inSource, + const ::rtl::OUString & inDestination, + const DAVRequestEnvironment & rEnv, + sal_Bool inOverwrite = false ) + throw( DAVException ) = 0; + + virtual void DESTROY( const ::rtl::OUString & inPath, + const DAVRequestEnvironment & rEnv ) + throw( DAVException ) = 0; + + // set new lock. + virtual void LOCK( const ::rtl::OUString & inPath, + com::sun::star::ucb::Lock & inLock, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ) = 0; + + // refresh existing lock. + virtual sal_Int64 LOCK( const ::rtl::OUString & inPath, + sal_Int64 nTimeout, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ) = 0; + + virtual void UNLOCK( const ::rtl::OUString & inPath, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ) = 0; + + virtual void abort() + throw( DAVException ) = 0; + +protected: + rtl::Reference< DAVSessionFactory > m_xFactory; + + DAVSession( rtl::Reference< DAVSessionFactory > const & rFactory ) + : m_xFactory( rFactory ), m_nRefCount( 0 ) {} + + virtual ~DAVSession() {} + +private: + DAVSessionFactory::Map::iterator m_aContainerIt; + oslInterlockedCount m_nRefCount; + + friend class DAVSessionFactory; +#if defined WNT && _MSC_VER < 1310 + friend struct std::auto_ptr< DAVSession >; + // work around compiler bug... +#else // WNT + friend class std::auto_ptr< DAVSession >; +#endif // WNT +}; + +} // namespace webdav_ucp + +#endif // _DAVSESSION_HXX_ diff --git a/ucb/source/ucp/webdav/DAVSessionFactory.cxx b/ucb/source/ucp/webdav/DAVSessionFactory.cxx new file mode 100644 index 000000000000..86d513f23fd6 --- /dev/null +++ b/ucb/source/ucp/webdav/DAVSessionFactory.cxx @@ -0,0 +1,106 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" +#include "DAVSessionFactory.hxx" +#include "NeonSession.hxx" +#include "NeonUri.hxx" +#include <com/sun/star/lang/XMultiServiceFactory.hpp> + +using namespace webdav_ucp; +using namespace com::sun::star; + +DAVSessionFactory::~DAVSessionFactory() +{ +} + +rtl::Reference< DAVSession > DAVSessionFactory::createDAVSession( + const ::rtl::OUString & inUri, + const uno::Reference< lang::XMultiServiceFactory > & rxSMgr ) + throw( DAVException ) +{ + m_xMSF = rxSMgr; + + osl::MutexGuard aGuard( m_aMutex ); + + if ( !m_xProxyDecider.get() ) + m_xProxyDecider.reset( new ucbhelper::InternetProxyDecider( rxSMgr ) ); + + Map::iterator aIt( m_aMap.begin() ); + Map::iterator aEnd( m_aMap.end() ); + + while ( aIt != aEnd ) + { + if ( (*aIt).second->CanUse( inUri ) ) + break; + + ++aIt; + } + + if ( aIt == aEnd ) + { + NeonUri aURI( inUri ); + + std::auto_ptr< DAVSession > xElement( + new NeonSession( this, inUri, *m_xProxyDecider.get() ) ); + + aIt = m_aMap.insert( Map::value_type( inUri, xElement.get() ) ).first; + aIt->second->m_aContainerIt = aIt; + xElement.release(); + return aIt->second; + } + else if ( osl_incrementInterlockedCount( &aIt->second->m_nRefCount ) > 1 ) + { + rtl::Reference< DAVSession > xElement( aIt->second ); + osl_decrementInterlockedCount( &aIt->second->m_nRefCount ); + return xElement; + } + else + { + osl_decrementInterlockedCount( &aIt->second->m_nRefCount ); + aIt->second->m_aContainerIt = m_aMap.end(); + + // If URL scheme is different from http or https we definitely + // have to use a proxy and therefore can optimize the getProxy + // call a little: + NeonUri aURI( inUri ); + + aIt->second = new NeonSession( this, inUri, *m_xProxyDecider.get() ); + aIt->second->m_aContainerIt = aIt; + return aIt->second; + } +} + +void DAVSessionFactory::releaseElement( DAVSession * pElement ) SAL_THROW(()) +{ + OSL_ASSERT( pElement ); + osl::MutexGuard aGuard( m_aMutex ); + if ( pElement->m_aContainerIt != m_aMap.end() ) + m_aMap.erase( pElement->m_aContainerIt ); +} + diff --git a/ucb/source/ucp/webdav/DAVSessionFactory.hxx b/ucb/source/ucp/webdav/DAVSessionFactory.hxx new file mode 100644 index 000000000000..eb1f22ace925 --- /dev/null +++ b/ucb/source/ucp/webdav/DAVSessionFactory.hxx @@ -0,0 +1,82 @@ +/************************************************************************* + * + * 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 _DAVSESSIONFACTORY_HXX_ +#define _DAVSESSIONFACTORY_HXX_ + +#ifdef min +#undef min // GNU libstdc++ <memory> includes <limit> which defines methods called min... +#endif +#include <map> +#include <memory> +#include <osl/mutex.hxx> +#include <salhelper/simplereferenceobject.hxx> +#include <rtl/ref.hxx> +#include <com/sun/star/uno/Reference.hxx> +#include <ucbhelper/proxydecider.hxx> +#include "DAVException.hxx" + +using namespace com::sun::star; + +namespace com { namespace sun { namespace star { namespace lang { + class XMultiServiceFactory; +} } } } + +namespace webdav_ucp +{ + +class DAVSession; + +class DAVSessionFactory : public salhelper::SimpleReferenceObject +{ +public: + ~DAVSessionFactory() SAL_THROW(()); + + rtl::Reference< DAVSession > + createDAVSession( const ::rtl::OUString & inUri, + const ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XMultiServiceFactory >& + rxSMgr ) + throw( DAVException ); + + ::uno::Reference< ::lang::XMultiServiceFactory > getServiceFactory() { return m_xMSF; } +private: + typedef std::map< rtl::OUString, DAVSession * > Map; + + Map m_aMap; + osl::Mutex m_aMutex; + std::auto_ptr< ucbhelper::InternetProxyDecider > m_xProxyDecider; + + ::uno::Reference< ::lang::XMultiServiceFactory > m_xMSF; + + void releaseElement( DAVSession * pElement ) SAL_THROW(()); + + friend class DAVSession; +}; + +} // namespace webdav_ucp + +#endif // _DAVSESSIONFACTORY_HXX_ diff --git a/ucb/source/ucp/webdav/DAVTypes.hxx b/ucb/source/ucp/webdav/DAVTypes.hxx new file mode 100644 index 000000000000..04da2fefed0c --- /dev/null +++ b/ucb/source/ucp/webdav/DAVTypes.hxx @@ -0,0 +1,85 @@ +/************************************************************************* + * + * 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 _DAVTYPES_HXX_ +#define _DAVTYPES_HXX_ + +#include <rtl/ustring.hxx> +#include <com/sun/star/uno/Any.hxx> + +namespace webdav_ucp +{ +/* RFC 2518 + +15.1 Class 1 + + A class 1 compliant resource MUST meet all "MUST" requirements in all + sections of this document. + + Class 1 compliant resources MUST return, at minimum, the value "1" in + the DAV header on all responses to the OPTIONS method. + +15.2 Class 2 + + A class 2 compliant resource MUST meet all class 1 requirements and + support the LOCK method, the supportedlock property, the + lockdiscovery property, the Time-Out response header and the Lock- + Token request header. A class "2" compliant resource SHOULD also + support the Time-Out request header and the owner XML element. + + Class 2 compliant resources MUST return, at minimum, the values "1" + and "2" in the DAV header on all responses to the OPTIONS method. +*/ + +struct DAVCapabilities +{ + bool class1; + bool class2; + bool executable; // supports "executable" property (introduced by mod_dav) + + DAVCapabilities() : class1( false ), class2( false ), executable( false ) {} +}; + +enum Depth { DAVZERO = 0, DAVONE = 1, DAVINFINITY = -1 }; + +enum ProppatchOperation { PROPSET = 0, PROPREMOVE = 1 }; + +struct ProppatchValue +{ + ProppatchOperation operation; + rtl::OUString name; + com::sun::star::uno::Any value; + + ProppatchValue( const ProppatchOperation o, + const rtl::OUString & n, + const com::sun::star::uno::Any & v ) + : operation( o ), name( n ), value( v ) {} +}; + +} // namespace webdav_ucp + +#endif // _DAVTYPES_HXX_ diff --git a/ucb/source/ucp/webdav/DateTimeHelper.cxx b/ucb/source/ucp/webdav/DateTimeHelper.cxx new file mode 100644 index 000000000000..41caac39f64b --- /dev/null +++ b/ucb/source/ucp/webdav/DateTimeHelper.cxx @@ -0,0 +1,270 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +#include <stdio.h> +#include <osl/time.h> +#include <com/sun/star/util/DateTime.hpp> +#include "DateTimeHelper.hxx" + +using namespace com::sun::star::util; +using namespace rtl; + +using namespace webdav_ucp; + +bool DateTimeHelper::ISO8601_To_DateTime (const OUString& s, + DateTime& dateTime) +{ + OString aDT (s.getStr(), s.getLength(), RTL_TEXTENCODING_ASCII_US); + + int year, month, day, hours, minutes, off_hours, off_minutes, fix; + double seconds; + + // 2001-01-01T12:30:00Z + int n = sscanf( aDT.getStr(), "%04d-%02d-%02dT%02d:%02d:%lfZ", + &year, &month, &day, &hours, &minutes, &seconds ); + if ( n == 6 ) + { + fix = 0; + } + else + { + // 2001-01-01T12:30:00+03:30 + n = sscanf( aDT.getStr(), "%04d-%02d-%02dT%02d:%02d:%lf+%02d:%02d", + &year, &month, &day, &hours, &minutes, &seconds, + &off_hours, &off_minutes ); + if ( n == 8 ) + { + fix = - off_hours * 3600 - off_minutes * 60; + } + else + { + // 2001-01-01T12:30:00-03:30 + n = sscanf( aDT.getStr(), "%04d-%02d-%02dT%02d:%02d:%lf-%02d:%02d", + &year, &month, &day, &hours, &minutes, &seconds, + &off_hours, &off_minutes ); + if ( n == 8 ) + { + fix = off_hours * 3600 + off_minutes * 60; + } + else + { + return false; + } + } + } + + // Convert to local time... + + oslDateTime aDateTime; + aDateTime.NanoSeconds = 0; + aDateTime.Seconds = sal::static_int_cast< sal_uInt16 >(seconds); // 0-59 + aDateTime.Minutes = sal::static_int_cast< sal_uInt16 >(minutes); // 0-59 + aDateTime.Hours = sal::static_int_cast< sal_uInt16 >(hours); // 0-23 + aDateTime.Day = sal::static_int_cast< sal_uInt16 >(day); // 1-31 + aDateTime.DayOfWeek = 0; // 0-6, 0 = Sunday + aDateTime.Month = sal::static_int_cast< sal_uInt16 >(month); // 1-12 + aDateTime.Year = sal::static_int_cast< sal_uInt16 >(year); + + TimeValue aTimeValue; + if ( osl_getTimeValueFromDateTime( &aDateTime, &aTimeValue ) ) + { + aTimeValue.Seconds += fix; + + if ( osl_getLocalTimeFromSystemTime( &aTimeValue, &aTimeValue ) ) + { + if ( osl_getDateTimeFromTimeValue( &aTimeValue, &aDateTime ) ) + { + dateTime.Year = aDateTime.Year; + dateTime.Month = aDateTime.Month; + dateTime.Day = aDateTime.Day; + dateTime.Hours = aDateTime.Hours; + dateTime.Minutes = aDateTime.Minutes; + dateTime.Seconds = aDateTime.Seconds; + + return true; + } + } + } + + return false; +} + +/* +sal_Int32 DateTimeHelper::convertDayToInt (const OUString& day) +{ + if (day.compareToAscii ("Sun") == 0) + return 0; + else if (day.compareToAscii ("Mon") == 0) + return 1; + else if (day.compareToAscii ("Tue") == 0) + return 2; + else if (day.compareToAscii ("Wed") == 0) + return 3; + else if (day.compareToAscii ("Thu") == 0) + return 4; + else if (day.compareToAscii ("Fri") == 0) + return 5; + else if (day.compareToAscii ("Sat") == 0) + return 6; + else + return -1; +} +*/ + +sal_Int32 DateTimeHelper::convertMonthToInt (const OUString& month) +{ + if (month.compareToAscii ("Jan") == 0) + return 1; + else if (month.compareToAscii ("Feb") == 0) + return 2; + else if (month.compareToAscii ("Mar") == 0) + return 3; + else if (month.compareToAscii ("Apr") == 0) + return 4; + else if (month.compareToAscii ("May") == 0) + return 5; + else if (month.compareToAscii ("Jun") == 0) + return 6; + else if (month.compareToAscii ("Jul") == 0) + return 7; + else if (month.compareToAscii ("Aug") == 0) + return 8; + else if (month.compareToAscii ("Sep") == 0) + return 9; + else if (month.compareToAscii ("Oct") == 0) + return 10; + else if (month.compareToAscii ("Nov") == 0) + return 11; + else if (month.compareToAscii ("Dec") == 0) + return 12; + else + return 0; +} + +bool DateTimeHelper::RFC2068_To_DateTime (const OUString& s, + DateTime& dateTime) +{ + int year; + int day; + int hours; + int minutes; + int seconds; + sal_Char string_month[3 + 1]; + sal_Char string_day[3 + 1]; + + sal_Int32 found = s.indexOf (','); + if (found != -1) + { + OString aDT (s.getStr(), s.getLength(), RTL_TEXTENCODING_ASCII_US); + + // RFC 1123 + found = sscanf (aDT.getStr(), "%3s, %2d %3s %4d %2d:%2d:%2d GMT", + string_day, &day, string_month, &year, &hours, &minutes, &seconds); + if (found != 7) + { + // RFC 1036 + found = sscanf (aDT.getStr(), "%3s, %2d-%3s-%2d %2d:%2d:%2d GMT", + string_day, &day, string_month, &year, &hours, &minutes, &seconds); + } + found = (found == 7) ? 1 : 0; + } + else + { + OString aDT (s.getStr(), s.getLength(), RTL_TEXTENCODING_ASCII_US); + + // ANSI C's asctime () format + found = sscanf (aDT.getStr(), "%3s %3s %d %2d:%2d:%2d %4d", + string_day, string_month, + &day, &hours, &minutes, &seconds, &year); + found = (found == 7) ? 1 : 0; + } + + if (found) + { + found = 0; + + int month = DateTimeHelper::convertMonthToInt ( + OUString::createFromAscii (string_month)); + if (month) + { + // Convert to local time... + + oslDateTime aDateTime; + aDateTime.NanoSeconds = 0; + aDateTime.Seconds = sal::static_int_cast< sal_uInt16 >(seconds); + // 0-59 + aDateTime.Minutes = sal::static_int_cast< sal_uInt16 >(minutes); + // 0-59 + aDateTime.Hours = sal::static_int_cast< sal_uInt16 >(hours); + // 0-23 + aDateTime.Day = sal::static_int_cast< sal_uInt16 >(day); + // 1-31 + aDateTime.DayOfWeek = 0; //dayofweek; // 0-6, 0 = Sunday + aDateTime.Month = sal::static_int_cast< sal_uInt16 >(month); + // 1-12 + aDateTime.Year = sal::static_int_cast< sal_uInt16 >(year); + + TimeValue aTimeValue; + if ( osl_getTimeValueFromDateTime( &aDateTime, + &aTimeValue ) ) + { + if ( osl_getLocalTimeFromSystemTime( &aTimeValue, + &aTimeValue ) ) + { + if ( osl_getDateTimeFromTimeValue( &aTimeValue, + &aDateTime ) ) + { + dateTime.Year = aDateTime.Year; + dateTime.Month = aDateTime.Month; + dateTime.Day = aDateTime.Day; + dateTime.Hours = aDateTime.Hours; + dateTime.Minutes = aDateTime.Minutes; + dateTime.Seconds = aDateTime.Seconds; + + found = 1; + } + } + } + } + } + + return (found) ? true : false; +} + +bool DateTimeHelper::convert (const OUString& s, DateTime& dateTime) +{ + if (ISO8601_To_DateTime (s, dateTime)) + return true; + else if (RFC2068_To_DateTime (s, dateTime)) + return true; + else + return false; +} + diff --git a/ucb/source/ucp/webdav/DateTimeHelper.hxx b/ucb/source/ucp/webdav/DateTimeHelper.hxx new file mode 100644 index 000000000000..c857457d0534 --- /dev/null +++ b/ucb/source/ucp/webdav/DateTimeHelper.hxx @@ -0,0 +1,63 @@ +/************************************************************************* + * + * 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 _WEBDAV_DATETIME_HELPER_HXX +#define _WEBDAV_DATETIME_HELPER_HXX + +#include <sal/types.h> + +namespace com { namespace sun { namespace star { namespace util { + struct DateTime; +} } } } + +namespace rtl { + class OUString; +} + +namespace webdav_ucp +{ + +class DateTimeHelper +{ +private: + static sal_Int32 convertMonthToInt (const ::rtl::OUString& ); + + static bool ISO8601_To_DateTime (const ::rtl::OUString&, + ::com::sun::star::util::DateTime& ); + + static bool RFC2068_To_DateTime (const ::rtl::OUString&, + ::com::sun::star::util::DateTime& ); + +public: + static bool convert (const ::rtl::OUString&, + ::com::sun::star::util::DateTime& ); +}; + +} // namespace webdav_ucp + +#endif + diff --git a/ucb/source/ucp/webdav/LinkSequence.cxx b/ucb/source/ucp/webdav/LinkSequence.cxx new file mode 100644 index 000000000000..39d8d9cecc38 --- /dev/null +++ b/ucb/source/ucp/webdav/LinkSequence.cxx @@ -0,0 +1,223 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +#include <string.h> +#include <ne_xml.h> + +#ifndef _LINKSEQUENCE_HXX_ +#include "LinkSequence.hxx" +#endif + +using namespace webdav_ucp; +using namespace com::sun::star; + +////////////////////////////////////////////////////////////////////////// + +struct LinkSequenceParseContext +{ + ucb::Link * pLink; + bool hasSource; + bool hasDestination; + + LinkSequenceParseContext() + : pLink( 0 ), hasSource( false ), hasDestination( false ) {} + ~LinkSequenceParseContext() { delete pLink; } +}; + +#define STATE_TOP (1) + +#define STATE_LINK (STATE_TOP) +#define STATE_DST (STATE_TOP + 1) +#define STATE_SRC (STATE_TOP + 2) + +////////////////////////////////////////////////////////////////////////// +extern "C" int LinkSequence_startelement_callback( + void *, + int parent, + const char * /*nspace*/, + const char *name, + const char ** ) +{ + if ( name != 0 ) + { + switch ( parent ) + { + case NE_XML_STATEROOT: + if ( strcmp( name, "link" ) == 0 ) + return STATE_LINK; + break; + + case STATE_LINK: + if ( strcmp( name, "dst" ) == 0 ) + return STATE_DST; + else if ( strcmp( name, "src" ) == 0 ) + return STATE_SRC; + break; + } + } + return NE_XML_DECLINE; +} + +////////////////////////////////////////////////////////////////////////// +extern "C" int LinkSequence_chardata_callback( + void *userdata, + int state, + const char *buf, + size_t len ) +{ + LinkSequenceParseContext * pCtx + = static_cast< LinkSequenceParseContext * >( userdata ); + if ( !pCtx->pLink ) + pCtx->pLink = new ucb::Link; + + switch ( state ) + { + case STATE_DST: + pCtx->pLink->Destination + = rtl::OUString( buf, len, RTL_TEXTENCODING_ASCII_US ); + pCtx->hasDestination = true; + break; + + case STATE_SRC: + pCtx->pLink->Source + = rtl::OUString( buf, len, RTL_TEXTENCODING_ASCII_US ); + pCtx->hasSource = true; + break; + } + return 0; // zero to continue, non-zero to abort parsing +} + +////////////////////////////////////////////////////////////////////////// +extern "C" int LinkSequence_endelement_callback( + void *userdata, + int state, + const char *, + const char * ) +{ + LinkSequenceParseContext * pCtx + = static_cast< LinkSequenceParseContext * >( userdata ); + if ( !pCtx->pLink ) + pCtx->pLink = new ucb::Link; + + switch ( state ) + { + case STATE_LINK: + if ( !pCtx->hasDestination || !pCtx->hasSource ) + return 1; // abort + break; + } + return 0; // zero to continue, non-zero to abort parsing +} + +////////////////////////////////////////////////////////////////////////// +// static +bool LinkSequence::createFromXML( const rtl::OString & rInData, + uno::Sequence< ucb::Link > & rOutData ) +{ + const sal_Int32 TOKEN_LENGTH = 7; // </link> + bool success = true; + + // rInData may contain multiple <link>...</link> tags. + sal_Int32 nCount = 0; + sal_Int32 nStart = 0; + sal_Int32 nEnd = rInData.indexOf( "</link>" ); + while ( nEnd > -1 ) + { + ne_xml_parser * parser = ne_xml_create(); + if ( !parser ) + { + success = false; + break; + } + + LinkSequenceParseContext aCtx; + ne_xml_push_handler( parser, + LinkSequence_startelement_callback, + LinkSequence_chardata_callback, + LinkSequence_endelement_callback, + &aCtx ); + + ne_xml_parse( parser, + rInData.getStr() + nStart, + nEnd - nStart + TOKEN_LENGTH ); + +#if NEON_VERSION >= 0x0250 + success = !ne_xml_failed( parser ); +#else + success = !!ne_xml_valid( parser ); +#endif + + ne_xml_destroy( parser ); + + if ( !success ) + break; + + if ( aCtx.pLink ) + { + nCount++; + if ( nCount > rOutData.getLength() ) + rOutData.realloc( rOutData.getLength() + 1 ); + + rOutData[ nCount - 1 ] = *aCtx.pLink; + } + + nStart = nEnd + TOKEN_LENGTH; + nEnd = rInData.indexOf( "</link>", nStart ); + } + + return success; +} + +////////////////////////////////////////////////////////////////////////// +// static +bool LinkSequence::toXML( const uno::Sequence< ucb::Link > & rInData, + rtl::OUString & rOutData ) +{ + // <link><src>value</src><dst>value</dst></link><link><src>.... + + sal_Int32 nCount = rInData.getLength(); + if ( nCount ) + { + rtl::OUString aPre( rtl::OUString::createFromAscii( "<link><src>" ) ); + rtl::OUString aMid( rtl::OUString::createFromAscii( "</src><dst>" ) ); + rtl::OUString aEnd( rtl::OUString::createFromAscii( "</dst></link>" ) ); + + for ( sal_Int32 n = 0; n < nCount; ++n ) + { + rOutData += aPre; + rOutData += rInData[ n ].Source; + rOutData += aMid; + rOutData += rInData[ n ].Destination; + rOutData += aEnd; + } + return true; + } + return false; +} diff --git a/ucb/source/ucp/webdav/LinkSequence.hxx b/ucb/source/ucp/webdav/LinkSequence.hxx new file mode 100644 index 000000000000..49bf883f1099 --- /dev/null +++ b/ucb/source/ucp/webdav/LinkSequence.hxx @@ -0,0 +1,51 @@ +/************************************************************************* + * + * 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 _LINKSEQUENCE_HXX_ +#define _LINKKSEQUENCE_HXX_ + +#include <rtl/string.hxx> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/ucb/Link.hpp> + +namespace webdav_ucp +{ + +class LinkSequence +{ +public: + static bool createFromXML( const rtl::OString & rInData, + com::sun::star::uno::Sequence< + com::sun::star::ucb::Link > & rOutData ); + static bool toXML( const com::sun::star::uno::Sequence< + com::sun::star::ucb::Link > & rInData, + rtl::OUString & rOutData ); +}; + +} + +#endif /* _LINKSEQUENCE_HXX_ */ diff --git a/ucb/source/ucp/webdav/LockEntrySequence.cxx b/ucb/source/ucp/webdav/LockEntrySequence.cxx new file mode 100644 index 000000000000..762170e7e057 --- /dev/null +++ b/ucb/source/ucp/webdav/LockEntrySequence.cxx @@ -0,0 +1,244 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +#include <string.h> +#include <ne_xml.h> +#include "LockEntrySequence.hxx" + +using namespace webdav_ucp; +using namespace com::sun::star; + +////////////////////////////////////////////////////////////////////////// + +struct LockEntrySequenceParseContext +{ + ucb::LockEntry * pEntry; + bool hasScope; + bool hasType; + + LockEntrySequenceParseContext() + : pEntry( 0 ), hasScope( false ), hasType( false ) {} + ~LockEntrySequenceParseContext() { delete pEntry; } +}; + +#define STATE_TOP (1) + +#define STATE_LOCKENTRY (STATE_TOP) +#define STATE_LOCKSCOPE (STATE_TOP + 1) +#define STATE_EXCLUSIVE (STATE_TOP + 2) +#define STATE_SHARED (STATE_TOP + 3) +#define STATE_LOCKTYPE (STATE_TOP + 4) +#define STATE_WRITE (STATE_TOP + 5) + +////////////////////////////////////////////////////////////////////////// +extern "C" int LockEntrySequence_startelement_callback( + void *, + int parent, + const char * /*nspace*/, + const char *name, + const char ** ) +{ + if ( name != 0 ) + { + switch ( parent ) + { + case NE_XML_STATEROOT: + if ( strcmp( name, "lockentry" ) == 0 ) + return STATE_LOCKENTRY; + break; + + case STATE_LOCKENTRY: + if ( strcmp( name, "lockscope" ) == 0 ) + return STATE_LOCKSCOPE; + else if ( strcmp( name, "locktype" ) == 0 ) + return STATE_LOCKTYPE; + +#define IIS_BUGS_WORKAROUND + +#ifdef IIS_BUGS_WORKAROUND + /* IIS (6) returns XML violating RFC 4918 + for DAV:supportedlock property value. + + <lockentry> + <write></write> + <shared></shared> + </lockentry> + <lockentry> + <write></write> + <exclusive></exclusive> + </lockentry> + + Bother... + */ + else if ( strcmp( name, "exclusive" ) == 0 ) + return STATE_EXCLUSIVE; + else if ( strcmp( name, "shared" ) == 0 ) + return STATE_SHARED; + else if ( strcmp( name, "write" ) == 0 ) + return STATE_WRITE; +#endif + break; + + case STATE_LOCKSCOPE: + if ( strcmp( name, "exclusive" ) == 0 ) + return STATE_EXCLUSIVE; + else if ( strcmp( name, "shared" ) == 0 ) + return STATE_SHARED; + break; + + case STATE_LOCKTYPE: + if ( strcmp( name, "write" ) == 0 ) + return STATE_WRITE; + break; + } + } + return NE_XML_DECLINE; +} + +////////////////////////////////////////////////////////////////////////// +extern "C" int LockEntrySequence_chardata_callback( + void *, + int, + const char *, + size_t ) +{ + return 0; // zero to continue, non-zero to abort parsing +} + +////////////////////////////////////////////////////////////////////////// +extern "C" int LockEntrySequence_endelement_callback( + void *userdata, + int state, + const char *, + const char * ) +{ + LockEntrySequenceParseContext * pCtx + = static_cast< LockEntrySequenceParseContext * >( userdata ); + if ( !pCtx->pEntry ) + pCtx->pEntry = new ucb::LockEntry; + + switch ( state ) + { + case STATE_EXCLUSIVE: + pCtx->pEntry->Scope = ucb::LockScope_EXCLUSIVE; + pCtx->hasScope = true; + break; + + case STATE_SHARED: + pCtx->pEntry->Scope = ucb::LockScope_SHARED; + pCtx->hasScope = true; + break; + + case STATE_WRITE: + pCtx->pEntry->Type = ucb::LockType_WRITE; + pCtx->hasType = true; + break; + + case STATE_LOCKSCOPE: + if ( !pCtx->hasScope ) + return 1; // abort + break; + + case STATE_LOCKTYPE: + if ( !pCtx->hasType ) + return 1; // abort + break; + + case STATE_LOCKENTRY: + if ( !pCtx->hasType || !pCtx->hasType ) + return 1; // abort + break; + + default: + break; + } + return 0; // zero to continue, non-zero to abort parsing +} + +////////////////////////////////////////////////////////////////////////// +// static +bool LockEntrySequence::createFromXML( const rtl::OString & rInData, + uno::Sequence< + ucb::LockEntry > & rOutData ) +{ + const sal_Int32 TOKEN_LENGTH = 12; // </lockentry> + bool success = true; + + // rInData may contain multiple <lockentry>...</lockentry> tags. + sal_Int32 nCount = 0; + sal_Int32 nStart = 0; + sal_Int32 nEnd = rInData.indexOf( "</lockentry>" ); + while ( nEnd > -1 ) + { + ne_xml_parser * parser = ne_xml_create(); + if ( !parser ) + { + success = false; + break; + } + + LockEntrySequenceParseContext aCtx; + ne_xml_push_handler( parser, + LockEntrySequence_startelement_callback, + LockEntrySequence_chardata_callback, + LockEntrySequence_endelement_callback, + &aCtx ); + + ne_xml_parse( parser, + rInData.getStr() + nStart, + nEnd - nStart + TOKEN_LENGTH ); + +#if NEON_VERSION >= 0x0250 + success = !ne_xml_failed( parser ); +#else + success = !!ne_xml_valid( parser ); +#endif + + ne_xml_destroy( parser ); + + if ( !success ) + break; + + if ( aCtx.pEntry ) + { + nCount++; + if ( nCount > rOutData.getLength() ) + rOutData.realloc( rOutData.getLength() + 2 ); + + rOutData[ nCount - 1 ] = *aCtx.pEntry; + } + + nStart = nEnd + TOKEN_LENGTH; + nEnd = rInData.indexOf( "</lockentry>", nStart ); + } + + rOutData.realloc( nCount ); + return success; +} diff --git a/ucb/source/ucp/webdav/LockEntrySequence.hxx b/ucb/source/ucp/webdav/LockEntrySequence.hxx new file mode 100644 index 000000000000..12c407100ecf --- /dev/null +++ b/ucb/source/ucp/webdav/LockEntrySequence.hxx @@ -0,0 +1,48 @@ +/************************************************************************* + * + * 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 _LOCKENTRYSEQUENCE_HXX_ +#define _LOCKENTRYSEQUENCE_HXX_ + +#include <rtl/string.hxx> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/ucb/LockEntry.hpp> + +namespace webdav_ucp +{ + +class LockEntrySequence +{ +public: + static bool createFromXML( const rtl::OString & rInData, + com::sun::star::uno::Sequence< + com::sun::star::ucb::LockEntry > & rOutData ); +}; + +} + +#endif /* _LOCKENTRYSEQUENCE_HXX_ */ diff --git a/ucb/source/ucp/webdav/LockSequence.cxx b/ucb/source/ucp/webdav/LockSequence.cxx new file mode 100644 index 000000000000..cd5f12708d58 --- /dev/null +++ b/ucb/source/ucp/webdav/LockSequence.cxx @@ -0,0 +1,351 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +#include <string.h> +#include <ne_xml.h> +#include "LockSequence.hxx" + +using namespace webdav_ucp; +using namespace com::sun::star; + +////////////////////////////////////////////////////////////////////////// + +struct LockSequenceParseContext +{ + ucb::Lock * pLock; + bool hasLockScope; + bool hasLockType; + bool hasDepth; + bool hasHREF; + bool hasTimeout; + + LockSequenceParseContext() + : pLock( 0 ), hasLockScope( false ), hasLockType( false ), + hasDepth( false ), hasHREF( false ), hasTimeout( false ) {} + + ~LockSequenceParseContext() { delete pLock; } +}; + +#define STATE_TOP (1) + +#define STATE_ACTIVELOCK (STATE_TOP) +#define STATE_LOCKSCOPE (STATE_TOP + 1) +#define STATE_LOCKTYPE (STATE_TOP + 2) +#define STATE_DEPTH (STATE_TOP + 3) +#define STATE_OWNER (STATE_TOP + 4) +#define STATE_TIMEOUT (STATE_TOP + 5) +#define STATE_LOCKTOKEN (STATE_TOP + 6) +#define STATE_EXCLUSIVE (STATE_TOP + 7) +#define STATE_SHARED (STATE_TOP + 8) +#define STATE_WRITE (STATE_TOP + 9) +#define STATE_HREF (STATE_TOP + 10) + +////////////////////////////////////////////////////////////////////////// +extern "C" int LockSequence_startelement_callback( + void *, + int parent, + const char * /*nspace*/, + const char *name, + const char ** ) +{ + if ( name != 0 ) + { + switch ( parent ) + { + case NE_XML_STATEROOT: + if ( strcmp( name, "activelock" ) == 0 ) + return STATE_ACTIVELOCK; + break; + + case STATE_ACTIVELOCK: + if ( strcmp( name, "lockscope" ) == 0 ) + return STATE_LOCKSCOPE; + else if ( strcmp( name, "locktype" ) == 0 ) + return STATE_LOCKTYPE; + else if ( strcmp( name, "depth" ) == 0 ) + return STATE_DEPTH; + else if ( strcmp( name, "owner" ) == 0 ) + return STATE_OWNER; + else if ( strcmp( name, "timeout" ) == 0 ) + return STATE_TIMEOUT; + else if ( strcmp( name, "locktoken" ) == 0 ) + return STATE_LOCKTOKEN; + break; + + case STATE_LOCKSCOPE: + if ( strcmp( name, "exclusive" ) == 0 ) + return STATE_EXCLUSIVE; + else if ( strcmp( name, "shared" ) == 0 ) + return STATE_SHARED; + break; + + case STATE_LOCKTYPE: + if ( strcmp( name, "write" ) == 0 ) + return STATE_WRITE; + break; + + case STATE_LOCKTOKEN: + if ( strcmp( name, "href" ) == 0 ) + return STATE_HREF; + break; + + case STATE_OWNER: + // owner elem contains ANY. Accept anything; no state change. + return STATE_OWNER; + } + } + return NE_XML_DECLINE; +} + +////////////////////////////////////////////////////////////////////////// +extern "C" int LockSequence_chardata_callback( + void *userdata, + int state, + const char *buf, + size_t len ) +{ + LockSequenceParseContext * pCtx + = static_cast< LockSequenceParseContext * >( userdata ); + if ( !pCtx->pLock ) + pCtx->pLock = new ucb::Lock; + + switch ( state ) + { + case STATE_DEPTH: + if ( rtl_str_compareIgnoreAsciiCase_WithLength( + buf, len, "0", 1 ) == 0 ) + { + pCtx->pLock->Depth = ucb::LockDepth_ZERO; + pCtx->hasDepth = true; + } + else if ( rtl_str_compareIgnoreAsciiCase_WithLength( + buf, len, "1", 1 ) == 0 ) + { + pCtx->pLock->Depth = ucb::LockDepth_ONE; + pCtx->hasDepth = true; + } + else if ( rtl_str_compareIgnoreAsciiCase_WithLength( + buf, len, "infinity", 8 ) == 0 ) + { + pCtx->pLock->Depth = ucb::LockDepth_INFINITY; + pCtx->hasDepth = true; + } + else + OSL_ENSURE( sal_False, + "LockSequence_chardata_callback - Unknown depth!" ); + break; + + case STATE_OWNER: + { + // collect raw XML data... (owner contains ANY) + rtl::OUString aValue; + pCtx->pLock->Owner >>= aValue; + aValue += rtl::OUString( buf, len, RTL_TEXTENCODING_ASCII_US ); + pCtx->pLock->Owner <<= aValue; + break; + } + + case STATE_TIMEOUT: + // + // RFC2518, RFC2616: + // + // TimeType = ("Second-" DAVTimeOutVal | "Infinite" | Other) + // DAVTimeOutVal = 1*digit + // Other = "Extend" field-value + // field-value = *( field-content | LWS ) + // field-content = <the OCTETs making up the field-value + // and consisting of either *TEXT or combinations + // of token, separators, and quoted-string> + + if ( rtl_str_compareIgnoreAsciiCase_WithLength( + buf, len, "Infinite", 8 ) == 0 ) + { + pCtx->pLock->Timeout = sal_Int64( -1 ); + pCtx->hasTimeout = true; + } + else if ( rtl_str_shortenedCompareIgnoreAsciiCase_WithLength( + buf, len, "Second-", 7, 7 ) == 0 ) + { + pCtx->pLock->Timeout + = rtl::OString( buf + 7, len - 7 ).toInt64(); + pCtx->hasTimeout = true; + } +// else if ( rtl_str_shortenedCompareIgnoreCase_WithLength( +// buf, len, "Extend", 6, 6 ) == 0 ) +// { +// @@@ +// } + else + { + pCtx->pLock->Timeout = sal_Int64( -1 ); + pCtx->hasTimeout = true; + OSL_ENSURE( sal_False, + "LockSequence_chardata_callback - Unknown timeout!" ); + } + break; + + case STATE_HREF: + { + // collect hrefs. + sal_Int32 nPos = pCtx->pLock->LockTokens.getLength(); + pCtx->pLock->LockTokens.realloc( nPos + 1 ); + pCtx->pLock->LockTokens[ nPos ] + = rtl::OUString( buf, len, RTL_TEXTENCODING_ASCII_US ); + pCtx->hasHREF = true; + break; + } + + } + return 0; // zero to continue, non-zero to abort parsing +} + +////////////////////////////////////////////////////////////////////////// +extern "C" int LockSequence_endelement_callback( + void *userdata, + int state, + const char *, + const char * ) +{ + LockSequenceParseContext * pCtx + = static_cast< LockSequenceParseContext * >( userdata ); + if ( !pCtx->pLock ) + pCtx->pLock = new ucb::Lock; + + switch ( state ) + { + case STATE_EXCLUSIVE: + pCtx->pLock->Scope = ucb::LockScope_EXCLUSIVE; + pCtx->hasLockScope = true; + break; + + case STATE_SHARED: + pCtx->pLock->Scope = ucb::LockScope_SHARED; + pCtx->hasLockScope = true; + break; + + case STATE_WRITE: + pCtx->pLock->Type = ucb::LockType_WRITE; + pCtx->hasLockType = true; + break; + + case STATE_DEPTH: + if ( !pCtx->hasDepth ) + return 1; // abort + break; + + case STATE_HREF: + if ( !pCtx->hasHREF ) + return 1; // abort + break; + + case STATE_TIMEOUT: + if ( !pCtx->hasTimeout ) + return 1; // abort + break; + + case STATE_LOCKSCOPE: + if ( !pCtx->hasLockScope ) + return 1; // abort + break; + + case STATE_LOCKTYPE: + if ( !pCtx->hasLockType ) + return 1; // abort + break; + + case STATE_ACTIVELOCK: + if ( !pCtx->hasLockType || !pCtx->hasLockType || !pCtx->hasDepth ) + return 1; // abort + break; + + default: + break; + } + return 0; // zero to continue, non-zero to abort parsing +} + +////////////////////////////////////////////////////////////////////////// +// static +bool LockSequence::createFromXML( const rtl::OString & rInData, + uno::Sequence< ucb::Lock > & rOutData ) +{ + const sal_Int32 TOKEN_LENGTH = 13; // </activelock> + bool success = true; + + // rInData may contain multiple <activelock>...</activelock> tags. + sal_Int32 nCount = 0; + sal_Int32 nStart = 0; + sal_Int32 nEnd = rInData.indexOf( "</activelock>" ); + while ( nEnd > -1 ) + { + ne_xml_parser * parser = ne_xml_create(); + if ( !parser ) + { + success = false; + break; + } + + LockSequenceParseContext aCtx; + ne_xml_push_handler( parser, + LockSequence_startelement_callback, + LockSequence_chardata_callback, + LockSequence_endelement_callback, + &aCtx ); + + ne_xml_parse( parser, + rInData.getStr() + nStart, + nEnd - nStart + TOKEN_LENGTH ); + +#if NEON_VERSION >= 0x0250 + success = !ne_xml_failed( parser ); +#else + success = !!ne_xml_valid( parser ); +#endif + + ne_xml_destroy( parser ); + + if ( !success ) + break; + + if ( aCtx.pLock ) + { + nCount++; + if ( nCount > rOutData.getLength() ) + rOutData.realloc( rOutData.getLength() + 1 ); + + rOutData[ nCount - 1 ] = *aCtx.pLock; + } + + nStart = nEnd + TOKEN_LENGTH; + nEnd = rInData.indexOf( "</activelock>", nStart ); + } + + return success; +} diff --git a/ucb/source/ucp/webdav/LockSequence.hxx b/ucb/source/ucp/webdav/LockSequence.hxx new file mode 100644 index 000000000000..85d4cdee77f5 --- /dev/null +++ b/ucb/source/ucp/webdav/LockSequence.hxx @@ -0,0 +1,48 @@ +/************************************************************************* + * + * 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 _LOCKSEQUENCE_HXX_ +#define _LOCKSEQUENCE_HXX_ + +#include <rtl/string.hxx> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/ucb/Lock.hpp> + +namespace webdav_ucp +{ + +class LockSequence +{ +public: + static bool createFromXML( const rtl::OString & rInData, + com::sun::star::uno::Sequence< + com::sun::star::ucb::Lock > & rOutData ); +}; + +} + +#endif /* _LOCKSEQUENCE_HXX_ */ diff --git a/ucb/source/ucp/webdav/NeonHeadRequest.cxx b/ucb/source/ucp/webdav/NeonHeadRequest.cxx new file mode 100644 index 000000000000..2880a86a727d --- /dev/null +++ b/ucb/source/ucp/webdav/NeonHeadRequest.cxx @@ -0,0 +1,200 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" +#include <osl/diagnose.h> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/beans/PropertyState.hpp> +#include "NeonHeadRequest.hxx" + +using namespace webdav_ucp; +using namespace com::sun::star; + +namespace { + +#if NEON_VERSION >= 0x0250 +void process_headers(ne_request *req, + DAVResource &rResource, + const std::vector< ::rtl::OUString > &rHeaderNames) +{ + void *cursor = NULL; + const char *name, *value; + + while ((cursor = ne_response_header_iterate(req, cursor, + &name, &value)) != NULL) { + rtl::OUString aHeaderName( rtl::OUString::createFromAscii( name ) ); + rtl::OUString aHeaderValue( rtl::OUString::createFromAscii( value ) ); + + // Note: Empty vector means that all headers are requested. + bool bIncludeIt = ( rHeaderNames.size() == 0 ); + + if ( !bIncludeIt ) + { + // Check whether this header was requested. + std::vector< ::rtl::OUString >::const_iterator it( + rHeaderNames.begin() ); + const std::vector< ::rtl::OUString >::const_iterator end( + rHeaderNames.end() ); + + while ( it != end ) + { + if ( (*it) == aHeaderName ) + break; + + ++it; + } + + if ( it != end ) + bIncludeIt = true; + } + + if ( bIncludeIt ) + { + // Create & set the PropertyValue + DAVPropertyValue thePropertyValue; + thePropertyValue.Name = aHeaderName; + thePropertyValue.IsCaseSensitive = false; + thePropertyValue.Value <<= aHeaderValue; + + // Add the newly created PropertyValue + rResource.properties.push_back( thePropertyValue ); + } + } +} +#else +struct NeonHeadRequestContext +{ + DAVResource * pResource; + const std::vector< ::rtl::OUString > * pHeaderNames; + + NeonHeadRequestContext( DAVResource * p, + const std::vector< ::rtl::OUString > * pHeaders ) + : pResource( p ), pHeaderNames( pHeaders ) {} +}; + +extern "C" void NHR_ResponseHeaderCatcher( void * userdata, + const char * value ) +{ + rtl::OUString aHeader( rtl::OUString::createFromAscii( value ) ); + sal_Int32 nPos = aHeader.indexOf( ':' ); + + if ( nPos != -1 ) + { + rtl::OUString aHeaderName( aHeader.copy( 0, nPos ) ); + + NeonHeadRequestContext * pCtx + = static_cast< NeonHeadRequestContext * >( userdata ); + + // Note: Empty vector means that all headers are requested. + bool bIncludeIt = ( pCtx->pHeaderNames->size() == 0 ); + + if ( !bIncludeIt ) + { + // Check whether this header was requested. + std::vector< ::rtl::OUString >::const_iterator it( + pCtx->pHeaderNames->begin() ); + const std::vector< ::rtl::OUString >::const_iterator end( + pCtx->pHeaderNames->end() ); + + while ( it != end ) + { + if ( (*it) == aHeaderName ) + break; + + ++it; + } + + if ( it != end ) + bIncludeIt = true; + } + + if ( bIncludeIt ) + { + // Create & set the PropertyValue + DAVPropertyValue thePropertyValue; + thePropertyValue.Name = aHeaderName; + thePropertyValue.IsCaseSensitive = false; + + if ( nPos < aHeader.getLength() ) + thePropertyValue.Value <<= aHeader.copy( nPos + 1 ).trim(); + + // Add the newly created PropertyValue + pCtx->pResource->properties.push_back( thePropertyValue ); + } + } +} +#endif + +} // namespace + +// ------------------------------------------------------------------- +// Constructor +// ------------------------------------------------------------------- + +NeonHeadRequest::NeonHeadRequest( HttpSession* inSession, + const rtl::OUString & inPath, + const std::vector< ::rtl::OUString > & + inHeaderNames, + DAVResource & ioResource, + int & nError ) +{ + ioResource.uri = inPath; + ioResource.properties.clear(); + + // Create and dispatch HEAD request. Install catcher for all response + // header fields. + ne_request * req = ne_request_create( inSession, + "HEAD", + rtl::OUStringToOString( + inPath, + RTL_TEXTENCODING_UTF8 ) ); + +#if NEON_VERSION < 0x0250 + NeonHeadRequestContext aCtx( &ioResource, &inHeaderNames ); + ne_add_response_header_catcher( req, NHR_ResponseHeaderCatcher, &aCtx ); +#endif + + nError = ne_request_dispatch( req ); + +#if NEON_VERSION >= 0x0250 + process_headers(req, ioResource, inHeaderNames); +#endif + + if ( nError == NE_OK && ne_get_status( req )->klass != 2 ) + nError = NE_ERROR; + + ne_request_destroy( req ); +} + +// ------------------------------------------------------------------- +// Destructor +// ------------------------------------------------------------------- +NeonHeadRequest::~NeonHeadRequest() +{ +} + diff --git a/ucb/source/ucp/webdav/NeonHeadRequest.hxx b/ucb/source/ucp/webdav/NeonHeadRequest.hxx new file mode 100644 index 000000000000..eb79ae7658c2 --- /dev/null +++ b/ucb/source/ucp/webdav/NeonHeadRequest.hxx @@ -0,0 +1,53 @@ +/************************************************************************* + * + * 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 _NEONHEADREQUEST_HXX_ +#define _NEONHEADREQUEST_HXX_ + +#include <vector> +#include "NeonTypes.hxx" +#include "DAVResource.hxx" + +namespace webdav_ucp +{ + +class NeonHeadRequest +{ +public: + // named / allprop + NeonHeadRequest( HttpSession* inSession, + const rtl::OUString & inPath, + const std::vector< ::rtl::OUString > & inHeaderNames, + DAVResource & ioResource, + int & nError ); + ~NeonHeadRequest(); +}; + +} // namespace webdav_ucp + +#endif // _NEONHEADREQUEST_HXX_ + diff --git a/ucb/source/ucp/webdav/NeonInputStream.cxx b/ucb/source/ucp/webdav/NeonInputStream.cxx new file mode 100644 index 000000000000..2e142af955c8 --- /dev/null +++ b/ucb/source/ucp/webdav/NeonInputStream.cxx @@ -0,0 +1,195 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" +#include "NeonInputStream.hxx" +#include <rtl/memory.h> + +using namespace cppu; +using namespace rtl; +using namespace com::sun::star::io; +using namespace com::sun::star::uno; +using namespace webdav_ucp; + + +// ------------------------------------------------------------------- +// Constructor +// ------------------------------------------------------------------- +NeonInputStream::NeonInputStream( void ) +: mLen( 0 ), + mPos( 0 ) +{ +} + +// ------------------------------------------------------------------- +// Destructor +// ------------------------------------------------------------------- +NeonInputStream::~NeonInputStream( void ) +{ +} + +// ------------------------------------------------------------------- +// AddToStream +// Allows the caller to add some data to the "end" of the stream +// ------------------------------------------------------------------- +void NeonInputStream::AddToStream( const char * inBuf, sal_Int32 inLen ) +{ + mInputBuffer.realloc( sal::static_int_cast<sal_Int32>(mLen) + inLen ); + rtl_copyMemory( mInputBuffer.getArray() + mLen, inBuf, inLen ); + mLen += inLen; +} + +// ------------------------------------------------------------------- +// queryInterface +// ------------------------------------------------------------------- +Any NeonInputStream::queryInterface( const Type &type ) + throw( RuntimeException ) +{ + Any aRet = ::cppu::queryInterface( type, + static_cast< XInputStream * >( this ), + static_cast< XSeekable * >( this ) ); + return aRet.hasValue() ? aRet : OWeakObject::queryInterface( type ); +} + +// ------------------------------------------------------------------- +// readBytes +// "Reads" the specified number of bytes from the stream +// ------------------------------------------------------------------- +sal_Int32 SAL_CALL NeonInputStream::readBytes( + ::com::sun::star::uno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead ) + throw( ::com::sun::star::io::NotConnectedException, + ::com::sun::star::io::BufferSizeExceededException, + ::com::sun::star::io::IOException, + ::com::sun::star::uno::RuntimeException ) +{ + // Work out how much we're actually going to write + sal_Int32 theBytes2Read = nBytesToRead; + sal_Int32 theBytesLeft = sal::static_int_cast<sal_Int32>(mLen - mPos); + if ( theBytes2Read > theBytesLeft ) + theBytes2Read = theBytesLeft; + + // Realloc buffer. + aData.realloc( theBytes2Read ); + + // Write the data + rtl_copyMemory( + aData.getArray(), mInputBuffer.getConstArray() + mPos, theBytes2Read ); + + // Update our stream position for next time + mPos += theBytes2Read; + + return theBytes2Read; +} + +// ------------------------------------------------------------------- +// readSomeBytes +// ------------------------------------------------------------------- +sal_Int32 SAL_CALL NeonInputStream::readSomeBytes( + ::com::sun::star::uno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead ) + throw( ::com::sun::star::io::NotConnectedException, + ::com::sun::star::io::BufferSizeExceededException, + ::com::sun::star::io::IOException, + ::com::sun::star::uno::RuntimeException ) +{ + // Warning: What should this be doing ? + return readBytes( aData, nMaxBytesToRead ); +} + +// ------------------------------------------------------------------- +// skipBytes +// Moves the current stream position forward +// ------------------------------------------------------------------- +void SAL_CALL NeonInputStream::skipBytes( sal_Int32 nBytesToSkip ) + throw( ::com::sun::star::io::NotConnectedException, + ::com::sun::star::io::BufferSizeExceededException, + ::com::sun::star::io::IOException, + ::com::sun::star::uno::RuntimeException ) +{ + mPos += nBytesToSkip; + if ( mPos >= mLen ) + mPos = mLen; +} + +// ------------------------------------------------------------------- +// available +// Returns the number of unread bytes currently remaining on the stream +// ------------------------------------------------------------------- +sal_Int32 SAL_CALL NeonInputStream::available( ) + throw( ::com::sun::star::io::NotConnectedException, + ::com::sun::star::io::IOException, + ::com::sun::star::uno::RuntimeException ) +{ + return sal::static_int_cast<sal_Int32>(mLen - mPos); +} + +// ------------------------------------------------------------------- +// closeInput +// ------------------------------------------------------------------- +void SAL_CALL NeonInputStream::closeInput( void ) + throw( ::com::sun::star::io::NotConnectedException, + ::com::sun::star::io::IOException, + ::com::sun::star::uno::RuntimeException ) +{ +} + +// ------------------------------------------------------------------- +// seek +// ------------------------------------------------------------------- +void SAL_CALL NeonInputStream::seek( sal_Int64 location ) + throw( ::com::sun::star::lang::IllegalArgumentException, + ::com::sun::star::io::IOException, + ::com::sun::star::uno::RuntimeException ) +{ + if ( location < 0 ) + throw ::com::sun::star::lang::IllegalArgumentException(); + + if ( location <= mLen ) + mPos = location; + else + throw ::com::sun::star::lang::IllegalArgumentException(); +} + +// ------------------------------------------------------------------- +// getPosition +// ------------------------------------------------------------------- +sal_Int64 SAL_CALL NeonInputStream::getPosition() + throw( ::com::sun::star::io::IOException, + ::com::sun::star::uno::RuntimeException ) +{ + return mPos; +} + +// ------------------------------------------------------------------- +// getLength +// ------------------------------------------------------------------- +sal_Int64 SAL_CALL NeonInputStream::getLength() + throw( ::com::sun::star::io::IOException, + ::com::sun::star::uno::RuntimeException ) +{ + return mLen; +} diff --git a/ucb/source/ucp/webdav/NeonInputStream.hxx b/ucb/source/ucp/webdav/NeonInputStream.hxx new file mode 100644 index 000000000000..55bf64b1bfcc --- /dev/null +++ b/ucb/source/ucp/webdav/NeonInputStream.hxx @@ -0,0 +1,124 @@ +/************************************************************************* + * + * 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 _NEONINPUTSTREAM_HXX_ +#define _NEONINPUTSTREAM_HXX_ + +#include <sal/types.h> +#include <rtl/ustring.hxx> +#include <cppuhelper/weak.hxx> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/io/XSeekable.hpp> + + +namespace webdav_ucp +{ + +// ------------------------------------------------------------------- +// NeonInputStream +// A simple XInputStream implementation provided specifically for use +// by the DAVSession::GET method. +// ------------------------------------------------------------------- +class NeonInputStream : public ::com::sun::star::io::XInputStream, + public ::com::sun::star::io::XSeekable, + public ::cppu::OWeakObject +{ + private: + com::sun::star::uno::Sequence< sal_Int8 > mInputBuffer; + sal_Int64 mLen; + sal_Int64 mPos; + + public: + NeonInputStream( void ); + virtual ~NeonInputStream(); + + // Add some data to the end of the stream + void AddToStream( const char * inBuf, sal_Int32 inLen ); + + // XInterface + virtual com::sun::star::uno::Any SAL_CALL queryInterface( + const ::com::sun::star::uno::Type & type ) + throw( ::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL acquire( void ) + throw () + { OWeakObject::acquire(); } + + virtual void SAL_CALL release( void ) + throw() + { OWeakObject::release(); } + + + // XInputStream + virtual sal_Int32 SAL_CALL readBytes( + ::com::sun::star::uno::Sequence< sal_Int8 > & aData, + sal_Int32 nBytesToRead ) + throw( ::com::sun::star::io::NotConnectedException, + ::com::sun::star::io::BufferSizeExceededException, + ::com::sun::star::io::IOException, + ::com::sun::star::uno::RuntimeException ); + + virtual sal_Int32 SAL_CALL readSomeBytes( + ::com::sun::star::uno::Sequence< sal_Int8 > & aData, + sal_Int32 nMaxBytesToRead ) + throw( ::com::sun::star::io::NotConnectedException, + ::com::sun::star::io::BufferSizeExceededException, + ::com::sun::star::io::IOException, + ::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip ) + throw( ::com::sun::star::io::NotConnectedException, + ::com::sun::star::io::BufferSizeExceededException, + ::com::sun::star::io::IOException, + ::com::sun::star::uno::RuntimeException ); + + virtual sal_Int32 SAL_CALL available( void ) + throw( ::com::sun::star::io::NotConnectedException, + ::com::sun::star::io::IOException, + ::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL closeInput( void ) + throw( ::com::sun::star::io::NotConnectedException, + ::com::sun::star::io::IOException, + ::com::sun::star::uno::RuntimeException ); + + // XSeekable + virtual void SAL_CALL seek( sal_Int64 location ) + throw( ::com::sun::star::lang::IllegalArgumentException, + ::com::sun::star::io::IOException, + ::com::sun::star::uno::RuntimeException ); + + virtual sal_Int64 SAL_CALL getPosition() + throw( ::com::sun::star::io::IOException, + ::com::sun::star::uno::RuntimeException ); + + virtual sal_Int64 SAL_CALL getLength() + throw( ::com::sun::star::io::IOException, + ::com::sun::star::uno::RuntimeException ); +}; + +} // namespace webdav_ucp +#endif // _NEONINPUTSTREAM_HXX_ diff --git a/ucb/source/ucp/webdav/NeonLockStore.cxx b/ucb/source/ucp/webdav/NeonLockStore.cxx new file mode 100644 index 000000000000..82510fcc9b71 --- /dev/null +++ b/ucb/source/ucp/webdav/NeonLockStore.cxx @@ -0,0 +1,245 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +#include <ne_locks.h> +#include <ne_uri.h> +#include "rtl/ustring.hxx" +#include "osl/time.h" +#include "osl/thread.hxx" +#include "NeonSession.hxx" +#include "NeonLockStore.hxx" + +using namespace webdav_ucp; + +namespace webdav_ucp { + +class TickerThread : public osl::Thread +{ + bool m_bFinish; + NeonLockStore & m_rLockStore; + +public: + + TickerThread( NeonLockStore & rLockStore ) + : osl::Thread(), m_bFinish( false ), m_rLockStore( rLockStore ) {} + + void finish() { m_bFinish = true; } + +protected: + + virtual void SAL_CALL run(); +}; + +} // namespace webdav_ucp + +// ------------------------------------------------------------------- +void TickerThread::run() +{ + OSL_TRACE( "TickerThread: start." ); + + // we have to go through the loop more often to be able to finish ~quickly + const int nNth = 25; + + int nCount = nNth; + while ( !m_bFinish ) + { + if ( nCount-- <= 0 ) + { + m_rLockStore.refreshLocks(); + nCount = nNth; + } + + TimeValue aTV; + aTV.Seconds = 0; + aTV.Nanosec = 1000000000 / nNth; + wait( aTV ); + } + + OSL_TRACE( "TickerThread: stop." ); +} + +// ------------------------------------------------------------------- +NeonLockStore::NeonLockStore() + : m_pNeonLockStore( ne_lockstore_create() ), + m_pTickerThread( 0 ) +{ + OSL_ENSURE( m_pNeonLockStore, "Unable to create neon lock store!" ); +} + +// ------------------------------------------------------------------- +NeonLockStore::~NeonLockStore() +{ + stopTicker(); + + // release active locks, if any. + OSL_ENSURE( m_aLockInfoMap.size() == 0, + "NeonLockStore::~NeonLockStore - Releasing active locks!" ); + + LockInfoMap::const_iterator it( m_aLockInfoMap.begin() ); + const LockInfoMap::const_iterator end( m_aLockInfoMap.end() ); + while ( it != end ) + { + NeonLock * pLock = (*it).first; + (*it).second.xSession->UNLOCK( pLock ); + + ne_lockstore_remove( m_pNeonLockStore, pLock ); + ne_lock_destroy( pLock ); + + ++it; + } + + ne_lockstore_destroy( m_pNeonLockStore ); +} + +// ------------------------------------------------------------------- +void NeonLockStore::startTicker() +{ + osl::MutexGuard aGuard( m_aMutex ); + + if ( !m_pTickerThread ) + { + m_pTickerThread = new TickerThread( *this ); + m_pTickerThread->create(); + } +} + +// ------------------------------------------------------------------- +void NeonLockStore::stopTicker() +{ + osl::MutexGuard aGuard( m_aMutex ); + + if ( m_pTickerThread ) + { + m_pTickerThread->finish(); + m_pTickerThread->join(); + delete m_pTickerThread; + m_pTickerThread = 0; + } +} + +// ------------------------------------------------------------------- +void NeonLockStore::registerSession( HttpSession * pHttpSession ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + ne_lockstore_register( m_pNeonLockStore, pHttpSession ); +} + +// ------------------------------------------------------------------- +NeonLock * NeonLockStore::findByUri( rtl::OUString const & rUri ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + ne_uri aUri; + ne_uri_parse( rtl::OUStringToOString( + rUri, RTL_TEXTENCODING_UTF8 ).getStr(), &aUri ); + return ne_lockstore_findbyuri( m_pNeonLockStore, &aUri ); +} + +// ------------------------------------------------------------------- +void NeonLockStore::addLock( NeonLock * pLock, + rtl::Reference< NeonSession > const & xSession, + sal_Int32 nLastChanceToSendRefreshRequest ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + ne_lockstore_add( m_pNeonLockStore, pLock ); + m_aLockInfoMap[ pLock ] + = LockInfo( xSession, nLastChanceToSendRefreshRequest ); + + startTicker(); +} + +// ------------------------------------------------------------------- +void NeonLockStore::updateLock( NeonLock * pLock, + sal_Int32 nLastChanceToSendRefreshRequest ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + LockInfoMap::iterator it( m_aLockInfoMap.find( pLock ) ); + OSL_ENSURE( it != m_aLockInfoMap.end(), + "NeonLockStore::updateLock: lock not found!" ); + + if ( it != m_aLockInfoMap.end() ) + { + (*it).second.nLastChanceToSendRefreshRequest + = nLastChanceToSendRefreshRequest; + } +} + +// ------------------------------------------------------------------- +void NeonLockStore::removeLock( NeonLock * pLock ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + m_aLockInfoMap.erase( pLock ); + ne_lockstore_remove( m_pNeonLockStore, pLock ); + + if ( m_aLockInfoMap.size() == 0 ) + stopTicker(); +} + +// ------------------------------------------------------------------- +void NeonLockStore::refreshLocks() +{ + osl::MutexGuard aGuard( m_aMutex ); + + LockInfoMap::iterator it( m_aLockInfoMap.begin() ); + const LockInfoMap::const_iterator end( m_aLockInfoMap.end() ); + while ( it != end ) + { + LockInfo & rInfo = (*it).second; + if ( rInfo.nLastChanceToSendRefreshRequest != -1 ) + { + // 30 seconds or less remaining until lock expires? + TimeValue t1; + osl_getSystemTime( &t1 ); + if ( rInfo.nLastChanceToSendRefreshRequest - 30 + <= sal_Int32( t1.Seconds ) ) + { + // refresh the lock. + sal_Int32 nlastChanceToSendRefreshRequest = -1; + if ( rInfo.xSession->LOCK( + (*it).first, + /* out param */ nlastChanceToSendRefreshRequest ) ) + { + rInfo.nLastChanceToSendRefreshRequest + = nlastChanceToSendRefreshRequest; + } + else + { + // refresh failed. stop auto-refresh. + rInfo.nLastChanceToSendRefreshRequest = -1; + } + } + } + ++it; + } +} diff --git a/ucb/source/ucp/webdav/NeonLockStore.hxx b/ucb/source/ucp/webdav/NeonLockStore.hxx new file mode 100644 index 000000000000..66f771f61901 --- /dev/null +++ b/ucb/source/ucp/webdav/NeonLockStore.hxx @@ -0,0 +1,102 @@ +/************************************************************************* + * + * 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 INCLUDED_NEONLOCKSTORE_HXX +#define INCLUDED_NEONLOCKSTORE_HXX + +#include <map> +#include "ne_locks.h" +#include "osl/mutex.hxx" +#include "rtl/ref.hxx" +#include "NeonTypes.hxx" + +namespace webdav_ucp +{ + +class TickerThread; +class NeonSession; + +struct ltptr +{ + bool operator()( const NeonLock * p1, const NeonLock * p2 ) const + { + return p1 < p2; + } +}; + +typedef struct _LockInfo +{ + rtl::Reference< NeonSession > xSession; + sal_Int32 nLastChanceToSendRefreshRequest; + + _LockInfo() + : nLastChanceToSendRefreshRequest( -1 ) {} + + _LockInfo( rtl::Reference< NeonSession > const & _xSession, + sal_Int32 _nLastChanceToSendRefreshRequest ) + : xSession( _xSession ), + nLastChanceToSendRefreshRequest( _nLastChanceToSendRefreshRequest ) {} + +} LockInfo; + +typedef std::map< NeonLock *, LockInfo, ltptr > LockInfoMap; + +class NeonLockStore +{ + osl::Mutex m_aMutex; + ne_lock_store * m_pNeonLockStore; + TickerThread * m_pTickerThread; + LockInfoMap m_aLockInfoMap; + +public: + NeonLockStore(); + ~NeonLockStore(); + + void registerSession( HttpSession * pHttpSession ); + + NeonLock * findByUri( rtl::OUString const & rUri ); + + void addLock( NeonLock * pLock, + rtl::Reference< NeonSession > const & xSession, + // time in seconds since Jan 1 1970 + // -1: infinite lock, no refresh + sal_Int32 nLastChanceToSendRefreshRequest ); + + void updateLock( NeonLock * pLock, + sal_Int32 nLastChanceToSendRefreshRequest ); + + void removeLock( NeonLock * pLock ); + + void refreshLocks(); + +private: + void startTicker(); + void stopTicker(); +}; + +} // namespace webdav_ucp + +#endif // INCLUDED_NEONLOCKSTORE_HXX diff --git a/ucb/source/ucp/webdav/NeonPropFindRequest.cxx b/ucb/source/ucp/webdav/NeonPropFindRequest.cxx new file mode 100644 index 000000000000..85b5ea0393e0 --- /dev/null +++ b/ucb/source/ucp/webdav/NeonPropFindRequest.cxx @@ -0,0 +1,345 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +#include "osl/diagnose.h" +#include "rtl/strbuf.hxx" +#include "NeonTypes.hxx" +#include "DAVException.hxx" +#include "DAVProperties.hxx" +#include "NeonPropFindRequest.hxx" +#include "LinkSequence.hxx" +#include "LockSequence.hxx" +#include "LockEntrySequence.hxx" +#include "UCBDeadPropertyValue.hxx" + +using namespace rtl; +using namespace com::sun::star::uno; +using namespace com::sun::star::ucb; +using namespace std; +using namespace webdav_ucp; + +// ------------------------------------------------------------------- +namespace +{ + // strip "DAV:" namespace from XML snippets to avoid + // parser error (undeclared namespace) later on. + rtl::OString stripDavNamespace( const rtl::OString & in ) + { + const rtl::OString inXML( in.toAsciiLowerCase() ); + + rtl::OStringBuffer buf; + sal_Int32 start = 0; + sal_Int32 end = inXML.indexOf( "dav:" ); + while ( end != -1 ) + { + if ( inXML[ end - 1 ] == '<' || + inXML[ end - 1 ] == '/' ) + { + // copy from original buffer - preserve case. + buf.append( in.copy( start, end - start ) ); + } + else + { + // copy from original buffer - preserve case. + buf.append( in.copy( start, end - start + 4 ) ); + } + start = end + 4; + end = inXML.indexOf( "dav:", start ); + } + buf.append( inXML.copy( start ) ); + + return rtl::OString( buf.makeStringAndClear() ); + } +} + +// ------------------------------------------------------------------- +extern "C" int NPFR_propfind_iter( void* userdata, + const NeonPropName* pname, + const char* value, + const HttpStatus* status ) +{ + /* + HTTP Response Status Classes: + + - 1: Informational - Request received, continuing process + + - 2: Success - The action was successfully received, + understood, and accepted + + - 3: Redirection - Further action must be taken in order to + complete the request + + - 4: Client Error - The request contains bad syntax or cannot + be fulfilled + + - 5: Server Error - The server failed to fulfill an apparently + valid request + */ + + if ( status->klass > 2 ) + return 0; // Error getting this property. Go on. + + // Create & set the PropertyValue + DAVPropertyValue thePropertyValue; + thePropertyValue.IsCaseSensitive = true; + + OSL_ENSURE( pname->nspace, "NPFR_propfind_iter - No namespace!" ); + + DAVProperties::createUCBPropName( pname->nspace, + pname->name, + thePropertyValue.Name ); + bool bHasValue = false; + if ( DAVProperties::isUCBDeadProperty( *pname ) ) + { + // DAV dead property added by WebDAV UCP? + if ( UCBDeadPropertyValue::createFromXML( + value, thePropertyValue.Value ) ) + { + OSL_ENSURE( thePropertyValue.Value.hasValue(), + "NPFR_propfind_iter - No value!" ); + bHasValue = true; + } + } + + if ( !bHasValue ) + { + if ( rtl_str_compareIgnoreAsciiCase( + pname->name, "resourcetype" ) == 0 ) + { + OString aValue( value ); + aValue = aValue.trim(); // #107358# remove leading/trailing spaces + if ( aValue.getLength() ) + { + aValue = stripDavNamespace( aValue ).toAsciiLowerCase(); + if ( aValue.compareTo( + RTL_CONSTASCII_STRINGPARAM( "<collection" ) ) == 0 ) + { + thePropertyValue.Value + <<= OUString::createFromAscii( "collection" ); + } + } + + if ( !thePropertyValue.Value.hasValue() ) + { + // Take over the value exactly as supplied by the server. + thePropertyValue.Value <<= OUString::createFromAscii( value ); + } + } + else if ( rtl_str_compareIgnoreAsciiCase( + pname->name, "supportedlock" ) == 0 ) + { + Sequence< LockEntry > aEntries; + LockEntrySequence::createFromXML( + stripDavNamespace( value ), aEntries ); + thePropertyValue.Value <<= aEntries; + } + else if ( rtl_str_compareIgnoreAsciiCase( + pname->name, "lockdiscovery" ) == 0 ) + { + Sequence< Lock > aLocks; + LockSequence::createFromXML( + stripDavNamespace( value ), aLocks ); + thePropertyValue.Value <<= aLocks; + } + else if ( rtl_str_compareIgnoreAsciiCase( pname->name, "source" ) == 0 ) + { + Sequence< Link > aLinks; + LinkSequence::createFromXML( + stripDavNamespace( value ), aLinks ); + thePropertyValue.Value <<= aLinks; + } + else + { + thePropertyValue.Value + <<= OStringToOUString( value, RTL_TEXTENCODING_UTF8 ); + } + } + + // Add the newly created PropertyValue + DAVResource* theResource = static_cast< DAVResource * >( userdata ); + theResource->properties.push_back( thePropertyValue ); + + return 0; // Go on. +} + +// ------------------------------------------------------------------- +extern "C" void NPFR_propfind_results( void* userdata, +#if NEON_VERSION >= 0x0260 + const ne_uri* uri, +#else + const char* href, +#endif + const NeonPropFindResultSet* set ) +{ + // @@@ href is not the uri! DAVResource ctor wants uri! + +#if NEON_VERSION >= 0x0260 + DAVResource theResource( + OStringToOUString( uri->path, RTL_TEXTENCODING_UTF8 ) ); +#else + DAVResource theResource( + OStringToOUString( href, RTL_TEXTENCODING_UTF8 ) ); +#endif + + ne_propset_iterate( set, NPFR_propfind_iter, &theResource ); + + // Add entry to resources list. + vector< DAVResource > * theResources + = static_cast< vector< DAVResource > * >( userdata ); + theResources->push_back( theResource ); +} +// ------------------------------------------------------------------- +extern "C" int NPFR_propnames_iter( void* userdata, + const NeonPropName* pname, + const char* /*value*/, + const HttpStatus* /*status*/ ) +{ + OUString aFullName; + DAVProperties::createUCBPropName( pname->nspace, + pname->name, + aFullName ); + + DAVResourceInfo* theResource = static_cast< DAVResourceInfo * >( userdata ); + theResource->properties.push_back( aFullName ); + return 0; +} + +// ------------------------------------------------------------------- +extern "C" void NPFR_propnames_results( void* userdata, +#if NEON_VERSION >= 0x0260 + const ne_uri* uri, +#else + const char* href, +#endif + const NeonPropFindResultSet* results ) +{ + // @@@ href is not the uri! DAVResourceInfo ctor wants uri! + // Create entry for the resource. +#if NEON_VERSION >= 0x0260 + DAVResourceInfo theResource( + OStringToOUString( uri->path, RTL_TEXTENCODING_UTF8 ) ); +#else + DAVResourceInfo theResource( + OStringToOUString( href, RTL_TEXTENCODING_UTF8 ) ); +#endif + + // Fill entry. + ne_propset_iterate( results, NPFR_propnames_iter, &theResource ); + + // Add entry to resources list. + vector< DAVResourceInfo > * theResources + = static_cast< vector< DAVResourceInfo > * >( userdata ); + theResources->push_back( theResource ); +} + +// ------------------------------------------------------------------- +// Constructor +// ------------------------------------------------------------------- + +NeonPropFindRequest::NeonPropFindRequest( HttpSession* inSession, + const char* inPath, + const Depth inDepth, + const vector< OUString >& inPropNames, + vector< DAVResource >& ioResources, + int & nError ) +{ + // Generate the list of properties we're looking for + int thePropCount = inPropNames.size(); + if ( thePropCount > 0 ) + { + NeonPropName* thePropNames = new NeonPropName[ thePropCount + 1 ]; + int theIndex; + + for ( theIndex = 0; theIndex < thePropCount; theIndex ++ ) + { + // Split fullname into namespace and name! + DAVProperties::createNeonPropName( + inPropNames[ theIndex ], thePropNames[ theIndex ] ); + } + thePropNames[ theIndex ].nspace = NULL; + thePropNames[ theIndex ].name = NULL; + + nError = ne_simple_propfind( inSession, + inPath, + inDepth, + thePropNames, + NPFR_propfind_results, + &ioResources ); + + for ( theIndex = 0; theIndex < thePropCount; theIndex ++ ) + free( (void *)thePropNames[ theIndex ].name ); + + delete [] thePropNames; + } + else + { + // ALLPROP + nError = ne_simple_propfind( inSession, + inPath, + inDepth, + NULL, // 0 == allprop + NPFR_propfind_results, + &ioResources ); + } + + // #87585# - Sometimes neon lies (because some servers lie). + if ( ( nError == NE_OK ) && ioResources.empty() ) + nError = NE_ERROR; +} + +// ------------------------------------------------------------------- +// Constructor +// - obtains property names +// ------------------------------------------------------------------- + +NeonPropFindRequest::NeonPropFindRequest( + HttpSession* inSession, + const char* inPath, + const Depth inDepth, + std::vector< DAVResourceInfo > & ioResInfo, + int & nError ) +{ + nError = ne_propnames( inSession, + inPath, + inDepth, + NPFR_propnames_results, + &ioResInfo ); + + // #87585# - Sometimes neon lies (because some servers lie). + if ( ( nError == NE_OK ) && ioResInfo.empty() ) + nError = NE_ERROR; +} + +// ------------------------------------------------------------------- +// Destructor +// ------------------------------------------------------------------- +NeonPropFindRequest::~NeonPropFindRequest( ) +{ +} diff --git a/ucb/source/ucp/webdav/NeonPropFindRequest.hxx b/ucb/source/ucp/webdav/NeonPropFindRequest.hxx new file mode 100644 index 000000000000..26e8793e2b96 --- /dev/null +++ b/ucb/source/ucp/webdav/NeonPropFindRequest.hxx @@ -0,0 +1,62 @@ +/************************************************************************* + * + * 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 _NEONPROPFINDREQUEST_HXX_ +#define _NEONPROPFINDREQUEST_HXX_ + +#include <vector> +#include <rtl/ustring.hxx> +#include "NeonTypes.hxx" +#include "DAVTypes.hxx" +#include "DAVResource.hxx" + +namespace webdav_ucp +{ + +class NeonPropFindRequest +{ +public: + // named / allprop + NeonPropFindRequest( HttpSession* inSession, + const char* inPath, + const Depth inDepth, + const std::vector< ::rtl::OUString > & inPropNames, + std::vector< DAVResource > & ioResources, + int & nError ); + // propnames + NeonPropFindRequest( HttpSession* inSession, + const char* inPath, + const Depth inDepth, + std::vector< DAVResourceInfo > & ioResInfo, + int & nError ); + + ~NeonPropFindRequest(); +}; + +} // namespace webdav_ucp + +#endif // _NEONPROPFINDREQUEST_HXX_ diff --git a/ucb/source/ucp/webdav/NeonSession.cxx b/ucb/source/ucp/webdav/NeonSession.cxx new file mode 100644 index 000000000000..254fae546940 --- /dev/null +++ b/ucb/source/ucp/webdav/NeonSession.cxx @@ -0,0 +1,2184 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +#include <hash_map> +#include <vector> +#include <string.h> +#include "osl/diagnose.h" +#include "osl/time.h" +#include <rtl/string.h> +#include <ne_socket.h> +#include <ne_auth.h> +#include <ne_redirect.h> +#include <ne_ssl.h> +#include <ne_compress.h> +#include "libxml/parser.h" +#include "rtl/ustrbuf.hxx" +#include "comphelper/sequence.hxx" +#include "ucbhelper/simplecertificatevalidationrequest.hxx" + +#include "DAVAuthListener.hxx" +#include "NeonTypes.hxx" +#include "NeonSession.hxx" +#include "NeonInputStream.hxx" +#include "NeonPropFindRequest.hxx" +#include "NeonHeadRequest.hxx" +#include "NeonUri.hxx" +#include "LinkSequence.hxx" +#include "UCBDeadPropertyValue.hxx" + +#include <com/sun/star/xml/crypto/XSecurityEnvironment.hpp> +#include <com/sun/star/security/XCertificate.hpp> +#include <com/sun/star/security/CertificateValidity.hpp> +#include <com/sun/star/security/CertificateContainerStatus.hpp> +#include <com/sun/star/security/CertificateContainer.hpp> +#include <com/sun/star/security/XCertificateContainer.hpp> +#include <com/sun/star/ucb/Lock.hpp> +#include <com/sun/star/xml/crypto/XSEInitializer.hpp> + +using namespace com::sun::star; +using namespace webdav_ucp; + +#define SEINITIALIZER_COMPONENT "com.sun.star.xml.crypto.SEInitializer" + +#ifndef EOL +# define EOL "\r\n" +#endif + +// ------------------------------------------------------------------- +// RequestData +// ------------------------------------------------------------------- + +struct RequestData +{ + // POST + rtl::OUString aContentType; + rtl::OUString aReferer; + + RequestData() {} + RequestData( const rtl::OUString & rContentType, + const rtl::OUString & rReferer ) + : aContentType( rContentType ), aReferer( rReferer ) {} +}; + +// ------------------------------------------------------------------- +// RequestDataMap +// ------------------------------------------------------------------- + +struct equalPtr +{ + bool operator()( const ne_request* p1, const ne_request* p2 ) const + { + return p1 == p2; + } +}; + +struct hashPtr +{ + size_t operator()( const ne_request* p ) const + { + return (size_t)p; + } +}; + +typedef std::hash_map +< + ne_request*, + RequestData, + hashPtr, + equalPtr +> +RequestDataMap; + +// ------------------------------------------------------------------- +// Helper fuction +// ------------------------------------------------------------------- +static sal_uInt16 makeStatusCode( const rtl::OUString & rStatusText ) +{ + // Extract status code from session error string. Unfortunately + // neon provides no direct access to the status code... + + if ( rStatusText.getLength() < 3 ) + { + OSL_ENSURE( + sal_False, "makeStatusCode - status text string to short!" ); + return 0; + } + + sal_Int32 nPos = rStatusText.indexOf( ' ' ); + if ( nPos == -1 ) + { + OSL_ENSURE( sal_False, "makeStatusCode - wrong status text format!" ); + return 0; + } + + return sal_uInt16( rStatusText.copy( 0, nPos ).toInt32() ); +} + +// ------------------------------------------------------------------- +struct NeonRequestContext +{ + uno::Reference< io::XOutputStream > xOutputStream; + rtl::Reference< NeonInputStream > xInputStream; + const std::vector< ::rtl::OUString > * pHeaderNames; + DAVResource * pResource; + + NeonRequestContext( uno::Reference< io::XOutputStream > & xOutStrm ) + : xOutputStream( xOutStrm ), xInputStream( 0 ), + pHeaderNames( 0 ), pResource( 0 ) {} + + NeonRequestContext( const rtl::Reference< NeonInputStream > & xInStrm ) + : xOutputStream( 0 ), xInputStream( xInStrm ), + pHeaderNames( 0 ), pResource( 0 ) {} + + NeonRequestContext( uno::Reference< io::XOutputStream > & xOutStrm, + const std::vector< ::rtl::OUString > & inHeaderNames, + DAVResource & ioResource ) + : xOutputStream( xOutStrm ), xInputStream( 0 ), + pHeaderNames( &inHeaderNames ), pResource( &ioResource ) {} + + NeonRequestContext( const rtl::Reference< NeonInputStream > & xInStrm, + const std::vector< ::rtl::OUString > & inHeaderNames, + DAVResource & ioResource ) + : xOutputStream( 0 ), xInputStream( xInStrm ), + pHeaderNames( &inHeaderNames ), pResource( &ioResource ) {} +}; + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +// +// Callback functions +// +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- + +// ------------------------------------------------------------------- +// ResponseBlockReader +// A simple Neon response_block_reader for use with an XInputStream +// ------------------------------------------------------------------- + +#if NEON_VERSION >= 0x0250 +extern "C" int NeonSession_ResponseBlockReader(void * inUserData, +#else +extern "C" void NeonSession_ResponseBlockReader(void * inUserData, +#endif + const char * inBuf, + size_t inLen ) +{ + // neon sometimes calls this function with (inLen == 0)... + if ( inLen > 0 ) + { + NeonRequestContext * pCtx + = static_cast< NeonRequestContext * >( inUserData ); + + rtl::Reference< NeonInputStream > xInputStream( + pCtx->xInputStream ); + + if ( xInputStream.is() ) + xInputStream->AddToStream( inBuf, inLen ); + } +#if NEON_VERSION >= 0x0250 + return 0; +#endif +} + +// ------------------------------------------------------------------- +// ResponseBlockWriter +// A simple Neon response_block_reader for use with an XOutputStream +// ------------------------------------------------------------------- + +#if NEON_VERSION >= 0x0250 +extern "C" int NeonSession_ResponseBlockWriter( void * inUserData, +#else +extern "C" void NeonSession_ResponseBlockWriter( void * inUserData, +#endif + const char * inBuf, + size_t inLen ) +{ + // neon calls this function with (inLen == 0)... + if ( inLen > 0 ) + { + NeonRequestContext * pCtx + = static_cast< NeonRequestContext * >( inUserData ); + uno::Reference< io::XOutputStream > xOutputStream + = pCtx->xOutputStream; + + if ( xOutputStream.is() ) + { + const uno::Sequence< sal_Int8 > aSeq( (sal_Int8 *)inBuf, inLen ); + xOutputStream->writeBytes( aSeq ); + } + } +#if NEON_VERSION >= 0x0250 + return 0; +#endif +} + +// ------------------------------------------------------------------- +extern "C" int NeonSession_NeonAuth( void * inUserData, +#ifdef NE_FEATURE_SSPI + const char * inAuthProtocol, +#endif + const char * inRealm, + int attempt, + char * inoutUserName, + char * inoutPassWord ) +{ +/* The callback used to request the username and password in the given + * realm. The username and password must be copied into the buffers + * which are both of size NE_ABUFSIZ. The 'attempt' parameter is zero + * on the first call to the callback, and increases by one each time + * an attempt to authenticate fails. + * + * The callback must return zero to indicate that authentication + * should be attempted with the username/password, or non-zero to + * cancel the request. (if non-zero, username and password are + * ignored.) */ + +#if 0 + // Give'em only a limited mumber of retries.. + if ( attempt > 9 ) + { + // abort + return -1; + } +#endif + + NeonSession * theSession = static_cast< NeonSession * >( inUserData ); + DAVAuthListener * pListener + = theSession->getRequestEnvironment().m_xAuthListener.get(); + if ( !pListener ) + { + // abort + return -1; + } + rtl::OUString theUserName; + rtl::OUString thePassWord; + + if ( attempt == 0 ) + { + // neon does not handle username supplied with request URI (for + // instance when doing FTP over proxy - last checked: 0.23.5 ) + + try + { + NeonUri uri( theSession->getRequestEnvironment().m_aRequestURI ); + rtl::OUString aUserInfo( uri.GetUserInfo() ); + if ( aUserInfo.getLength() ) + { + sal_Int32 nPos = aUserInfo.indexOf( '@' ); + if ( nPos == -1 ) + { + theUserName = aUserInfo; + } + else + { + theUserName = aUserInfo.copy( 0, nPos ); + thePassWord = aUserInfo.copy( nPos + 1 ); + } + } + } + catch ( DAVException const & ) + { + // abort + return -1; + } + } + else + { + // username buffer is prefilled with user name from last attempt. + theUserName = rtl::OUString::createFromAscii( inoutUserName ); + // @@@ Neon does not initialize password buffer (last checked: 0.22.0). + //thePassWord = rtl::OUString::createFromAscii( inoutPassWord ); + } + + bool bCanUseSystemCreds = false; + +#ifdef NE_FEATURE_SSPI + bCanUseSystemCreds + = (attempt == 0) && // avoid endless loops + ne_has_support( NE_FEATURE_SSPI ) && // Windows-only feature. + ( ( ne_strcasecmp( inAuthProtocol, "NTLM" ) == 0 ) || + ( ne_strcasecmp( inAuthProtocol, "Negotiate" ) == 0 ) ); +#endif + + int theRetVal = pListener->authenticate( + rtl::OUString::createFromAscii( inRealm ), + theSession->getHostName(), + theUserName, + thePassWord, + bCanUseSystemCreds); + + rtl::OString aUser( + rtl::OUStringToOString( theUserName, RTL_TEXTENCODING_UTF8 ) ); + if ( aUser.getLength() > ( NE_ABUFSIZ - 1 ) ) + { + OSL_ENSURE( + sal_False, "NeonSession_NeonAuth - username to long!" ); + return -1; + } + + rtl::OString aPass( + rtl::OUStringToOString( thePassWord, RTL_TEXTENCODING_UTF8 ) ); + if ( aPass.getLength() > ( NE_ABUFSIZ - 1 ) ) + { + OSL_ENSURE( + sal_False, "NeonSession_NeonAuth - password to long!" ); + return -1; + } + + strcpy( inoutUserName, // #100211# - checked + rtl::OUStringToOString( theUserName, RTL_TEXTENCODING_UTF8 ) ); + + strcpy( inoutPassWord, // #100211# - checked + rtl::OUStringToOString( thePassWord, RTL_TEXTENCODING_UTF8 ) ); + + return theRetVal; +} + +// ------------------------------------------------------------------- + +namespace { + // ------------------------------------------------------------------- + // Helper function + ::rtl::OUString GetHostnamePart( const ::rtl::OUString& _rRawString ) + { + ::rtl::OUString sPart; + ::rtl::OUString sPartId = ::rtl::OUString::createFromAscii( "CN=" ); + sal_Int32 nContStart = _rRawString.indexOf( sPartId ); + if ( nContStart != -1 ) + { + nContStart = nContStart + sPartId.getLength(); + sal_Int32 nContEnd + = _rRawString.indexOf( sal_Unicode( ',' ), nContStart ); + sPart = _rRawString.copy( nContStart, nContEnd - nContStart ); + } + return sPart; + } +} // namespace + +// ------------------------------------------------------------------- +extern "C" int NeonSession_CertificationNotify( void *userdata, + int failures, + const ne_ssl_certificate *cert ) +{ + OSL_ASSERT( cert ); + + NeonSession * pSession = static_cast< NeonSession * >( userdata ); + uno::Reference< security::XCertificateContainer > xCertificateContainer; + try + { + xCertificateContainer + = uno::Reference< security::XCertificateContainer >( + pSession->getMSF()->createInstance( + rtl::OUString::createFromAscii( + "com.sun.star.security.CertificateContainer" ) ), + uno::UNO_QUERY ); + } + catch ( uno::Exception const & ) + { + } + + if ( !xCertificateContainer.is() ) + return 1; + + failures = 0; + + char * dn = ne_ssl_readable_dname( ne_ssl_cert_subject( cert ) ); + rtl::OUString cert_subject( dn, strlen( dn ), RTL_TEXTENCODING_UTF8, 0 ); + + ne_free( dn ); + + security::CertificateContainerStatus certificateContainer( + xCertificateContainer->hasCertificate( + pSession->getHostName(), cert_subject ) ); + + if ( certificateContainer != security::CertificateContainerStatus_NOCERT ) + return + certificateContainer == security::CertificateContainerStatus_TRUSTED + ? 0 + : 1; + + uno::Reference< xml::crypto::XSEInitializer > xSEInitializer; + try + { + xSEInitializer = uno::Reference< xml::crypto::XSEInitializer >( + pSession->getMSF()->createInstance( + rtl::OUString::createFromAscii( SEINITIALIZER_COMPONENT ) ), + uno::UNO_QUERY ); + } + catch ( uno::Exception const & ) + { + } + + if ( !xSEInitializer.is() ) + return 1; + + uno::Reference< xml::crypto::XXMLSecurityContext > xSecurityContext( + xSEInitializer->createSecurityContext( rtl::OUString() ) ); + + uno::Reference< xml::crypto::XSecurityEnvironment > xSecurityEnv( + xSecurityContext->getSecurityEnvironment() ); + + //The end entity certificate + char * eeCertB64 = ne_ssl_cert_export( cert ); + + rtl::OString sEECertB64( eeCertB64 ); + + uno::Reference< security::XCertificate > xEECert( + xSecurityEnv->createCertificateFromAscii( + rtl::OStringToOUString( sEECertB64, RTL_TEXTENCODING_ASCII_US ) ) ); + + ne_free( eeCertB64 ); + eeCertB64 = 0; + + std::vector< uno::Reference< security::XCertificate > > vecCerts; + const ne_ssl_certificate * issuerCert = cert; + do + { + //get the intermediate certificate + //the returned value is const ! Therfore it does not need to be freed + //with ne_ssl_cert_free, which takes a non-const argument + issuerCert = ne_ssl_cert_signedby( issuerCert ); + if ( NULL == issuerCert ) + break; + + char * imCertB64 = ne_ssl_cert_export( issuerCert ); + rtl::OString sInterMediateCertB64( imCertB64 ); + ne_free( imCertB64 ); + + uno::Reference< security::XCertificate> xImCert( + xSecurityEnv->createCertificateFromAscii( + rtl::OStringToOUString( + sInterMediateCertB64, RTL_TEXTENCODING_ASCII_US ) ) ); + if ( xImCert.is() ) + vecCerts.push_back( xImCert ); + } + while ( 1 ); + + sal_Int64 certValidity = xSecurityEnv->verifyCertificate( xEECert, + ::comphelper::containerToSequence( vecCerts ) ); + + if ( pSession->isDomainMatch( + GetHostnamePart( xEECert.get()->getSubjectName() ) ) ) + { + // if host name matched with certificate then look if the + // certificate was ok + if( certValidity == security::CertificateValidity::VALID ) + return 0; + } + + const uno::Reference< ucb::XCommandEnvironment > xEnv( + pSession->getRequestEnvironment().m_xEnv ); + if ( xEnv.is() ) + { + failures = static_cast< int >( certValidity ); + + uno::Reference< task::XInteractionHandler > xIH( + xEnv->getInteractionHandler() ); + if ( xIH.is() ) + { + rtl::Reference< ucbhelper::SimpleCertificateValidationRequest > + xRequest( new ucbhelper::SimpleCertificateValidationRequest( + (sal_Int32)failures, xEECert, pSession->getHostName() ) ); + xIH->handle( xRequest.get() ); + + rtl::Reference< ucbhelper::InteractionContinuation > xSelection + = xRequest->getSelection(); + + if ( xSelection.is() ) + { + uno::Reference< task::XInteractionApprove > xApprove( + xSelection.get(), uno::UNO_QUERY ); + if ( xApprove.is() ) + { + xCertificateContainer->addCertificate( + pSession->getHostName(), cert_subject, sal_True ); + return 0; + } + else + { + // Don't trust cert + xCertificateContainer->addCertificate( + pSession->getHostName(), cert_subject, sal_False ); + return 1; + } + } + } + else + { + // Don't trust cert + xCertificateContainer->addCertificate( + pSession->getHostName(), cert_subject, sal_False ); + return 1; + } + } + return 1; +} + +// ------------------------------------------------------------------- +extern "C" void NeonSession_PreSendRequest( ne_request * req, + void * userdata, + ne_buffer * headers ) +{ + // userdata -> value returned by 'create' + + NeonSession * pSession = static_cast< NeonSession * >( userdata ); + if ( pSession ) + { + // If there is a proxy server in between, it shall never use + // cached data. We always want 'up-to-date' data. + ne_buffer_concat( headers, "Pragma: no-cache", EOL, NULL ); + // alternative, but understoud by HTTP 1.1 servers only: + // ne_buffer_concat( headers, "Cache-Control: max-age=0", EOL, NULL ); + + const RequestDataMap * pRequestData + = static_cast< const RequestDataMap* >( + pSession->getRequestData() ); + + RequestDataMap::const_iterator it = pRequestData->find( req ); + if ( it != pRequestData->end() ) + { + if ( (*it).second.aContentType.getLength() ) + { + char * pData = headers->data; + if ( strstr( pData, "Content-Type:" ) == NULL ) + { + rtl::OString aType + = rtl::OUStringToOString( (*it).second.aContentType, + RTL_TEXTENCODING_UTF8 ); + ne_buffer_concat( headers, "Content-Type: ", + aType.getStr(), EOL, NULL ); + } + } + + if ( (*it).second.aReferer.getLength() ) + { + char * pData = headers->data; + if ( strstr( pData, "Referer:" ) == NULL ) + { + rtl::OString aReferer + = rtl::OUStringToOString( (*it).second.aReferer, + RTL_TEXTENCODING_UTF8 ); + ne_buffer_concat( headers, "Referer: ", + aReferer.getStr(), EOL, NULL ); + } + } + } + + const DAVRequestHeaders & rHeaders + = pSession->getRequestEnvironment().m_aRequestHeaders; + + DAVRequestHeaders::const_iterator it1( rHeaders.begin() ); + const DAVRequestHeaders::const_iterator end1( rHeaders.end() ); + + while ( it1 != end1 ) + { + rtl::OString aHeader + = rtl::OUStringToOString( (*it1).first, + RTL_TEXTENCODING_UTF8 ); + rtl::OString aValue + = rtl::OUStringToOString( (*it1).second, + RTL_TEXTENCODING_UTF8 ); + ne_buffer_concat( headers, aHeader.getStr(), ": ", + aValue.getStr(), EOL, NULL ); + + ++it1; + } + } +} + +// ------------------------------------------------------------------- +// static members! +bool NeonSession::m_bGlobalsInited = false; +osl::Mutex NeonSession::m_aGlobalMutex; +NeonLockStore NeonSession::m_aNeonLockStore; + +// ------------------------------------------------------------------- +// Constructor +// ------------------------------------------------------------------- +NeonSession::NeonSession( + const rtl::Reference< DAVSessionFactory > & rSessionFactory, + const rtl::OUString& inUri, + const ucbhelper::InternetProxyDecider & rProxyDecider ) + throw ( DAVException ) +: DAVSession( rSessionFactory ), + m_pHttpSession( 0 ), + m_pRequestData( new RequestDataMap ), + m_rProxyDecider( rProxyDecider ) +{ + NeonUri theUri( inUri ); + m_aScheme = theUri.GetScheme(); + m_aHostName = theUri.GetHost(); + m_nPort = theUri.GetPort(); +} + +// ------------------------------------------------------------------- +// Destructor +// ------------------------------------------------------------------- +NeonSession::~NeonSession( ) +{ + if ( m_pHttpSession ) + { + ne_session_destroy( m_pHttpSession ); + m_pHttpSession = 0; + } + delete static_cast< RequestDataMap * >( m_pRequestData ); +} + +// ------------------------------------------------------------------- +void NeonSession::Init( const DAVRequestEnvironment & rEnv ) + throw ( DAVException ) +{ + osl::Guard< osl::Mutex > theGuard( m_aMutex ); + m_aEnv = rEnv; + Init(); +} + +// ------------------------------------------------------------------- +void NeonSession::Init() + throw ( DAVException ) +{ + osl::Guard< osl::Mutex > theGuard( m_aMutex ); + + bool bCreateNewSession = false; + + if ( m_pHttpSession == 0 ) + { + // Ensure that Neon sockets are initialized + + // --> tkr #151111# crashed if copy and pasted pictures from the internet + // ne_sock_init() was executed by two threads at the same time. + osl::Guard< osl::Mutex > theGlobalGuard( m_aGlobalMutex ); + // <-- + if ( !m_bGlobalsInited ) + { + if ( ne_sock_init() != 0 ) + throw DAVException( DAVException::DAV_SESSION_CREATE, + NeonUri::makeConnectionEndPointString( + m_aHostName, m_nPort ) ); + + // #122205# - libxml2 needs to be initialized once if used by + // multithreaded programs like OOo. + xmlInitParser(); +#if 0 + // for more debug flags see ne_utils.h; NE_DEBUGGING must be defined + // while compiling neon in order to actually activate neon debug + // output. + ne_debug_init( stderr, NE_DBG_FLUSH + | NE_DBG_HTTP + // | NE_DBG_HTTPBODY + // | NE_DBG_HTTPAUTH + // | NE_DBG_XML + // | NE_DBG_XMLPARSE + // | NE_DBG_LOCKS + ); +#endif + m_bGlobalsInited = true; + } + + const ucbhelper::InternetProxyServer & rProxyCfg = getProxySettings(); + + m_aProxyName = rProxyCfg.aName; + m_nProxyPort = rProxyCfg.nPort; + + // Not yet initialized. Create new session. + bCreateNewSession = true; + } + else + { + // #112271# Check whether proxy settings are still valid (They may + // change at any time). If not, create new Neon session. + + const ucbhelper::InternetProxyServer & rProxyCfg = getProxySettings(); + + if ( ( rProxyCfg.aName != m_aProxyName ) + || ( rProxyCfg.nPort != m_nProxyPort ) ) + { + m_aProxyName = rProxyCfg.aName; + m_nProxyPort = rProxyCfg.nPort; + + // new session needed, destroy old first + ne_session_destroy( m_pHttpSession ); + m_pHttpSession = 0; + bCreateNewSession = true; + } + } + + if ( bCreateNewSession ) + { + // @@@ For FTP over HTTP proxy inUserInfo is needed to be able to + // build the complete request URI (including user:pass), but + // currently (0.22.0) neon does not allow to pass the user info + // to the session + + m_pHttpSession = ne_session_create( + rtl::OUStringToOString( m_aScheme, + RTL_TEXTENCODING_UTF8 ).getStr(), + /* theUri.GetUserInfo(), + @@@ for FTP via HTTP proxy, but not supported by Neon */ + rtl::OUStringToOString( m_aHostName, + RTL_TEXTENCODING_UTF8 ).getStr(), + m_nPort ); + + if ( m_pHttpSession == 0 ) + throw DAVException( DAVException::DAV_SESSION_CREATE, + NeonUri::makeConnectionEndPointString( + m_aHostName, m_nPort ) ); + + // Register the session with the lock store + m_aNeonLockStore.registerSession( m_pHttpSession ); + + if ( m_aScheme.equalsIgnoreAsciiCase( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "https" ) ) ) ) + { + // Set a failure callback for certificate check + ne_ssl_set_verify( + m_pHttpSession, NeonSession_CertificationNotify, this); + } + + // Add hooks (i.e. for adding additional headers to the request) + +#if 0 + /* Hook called when a request is created. */ + //typedef void (*ne_create_request_fn)(ne_request *req, void *userdata, + // const char *method, const char *path); + + ne_hook_create_request( m_pHttpSession, create_req_hook_fn, this ); +#endif + + /* Hook called before the request is sent. 'header' is the raw HTTP + * header before the trailing CRLF is added: add in more here. */ + //typedef void (*ne_pre_send_fn)(ne_request *req, void *userdata, + // ne_buffer *header); + + ne_hook_pre_send( m_pHttpSession, NeonSession_PreSendRequest, this ); +#if 0 + /* Hook called after the request is sent. May return: + * NE_OK everything is okay + * NE_RETRY try sending the request again. + * anything else signifies an error, and the request is failed. The + * return code is passed back the _dispatch caller, so the session error + * must also be set appropriately (ne_set_error). + */ + //typedef int (*ne_post_send_fn)(ne_request *req, void *userdata, + // const ne_status *status); + + ne_hook_post_send( m_pHttpSession, post_send_req_hook_fn, this ); + + /* Hook called when the request is destroyed. */ + //typedef void (*ne_destroy_req_fn)(ne_request *req, void *userdata); + + ne_hook_destroy_request( m_pHttpSession, destroy_req_hook_fn, this ); + + /* Hook called when the session is destroyed. */ + //typedef void (*ne_destroy_sess_fn)(void *userdata); + + ne_hook_destroy_session( m_pHttpSession, destroy_sess_hook_fn, this ); +#endif + + if ( m_aProxyName.getLength() ) + { + ne_session_proxy( m_pHttpSession, + rtl::OUStringToOString( + m_aProxyName, + RTL_TEXTENCODING_UTF8 ).getStr(), + m_nProxyPort ); + } + + // Register for redirects. + ne_redirect_register( m_pHttpSession ); + + // authentication callbacks. + ne_add_server_auth( + m_pHttpSession, NE_AUTH_ALL, NeonSession_NeonAuth, this ); + ne_add_proxy_auth( + m_pHttpSession, NE_AUTH_ALL, NeonSession_NeonAuth, this ); + } +} + +// ------------------------------------------------------------------- +// virtual +sal_Bool NeonSession::CanUse( const rtl::OUString & inUri ) +{ + try + { + NeonUri theUri( inUri ); + if ( ( theUri.GetPort() == m_nPort ) && + ( theUri.GetHost() == m_aHostName ) && + ( theUri.GetScheme() == m_aScheme ) ) + return sal_True; + } + catch ( DAVException const & ) + { + return sal_False; + } + return sal_False; +} + +// ------------------------------------------------------------------- +// virtual +sal_Bool NeonSession::UsesProxy() +{ + Init(); + return ( m_aProxyName.getLength() > 0 ); +} + +// ------------------------------------------------------------------- +// OPTIONS +// ------------------------------------------------------------------- +void NeonSession::OPTIONS( const rtl::OUString & inPath, + DAVCapabilities & outCapabilities, + const DAVRequestEnvironment & rEnv ) + throw( DAVException ) +{ + osl::Guard< osl::Mutex > theGuard( m_aMutex ); + + Init( rEnv ); + + HttpServerCapabilities servercaps; + memset( &servercaps, 0, sizeof( servercaps ) ); + + int theRetVal = ne_options( m_pHttpSession, + rtl::OUStringToOString( + inPath, RTL_TEXTENCODING_UTF8 ), + &servercaps ); + + HandleError( theRetVal, inPath, rEnv ); + + outCapabilities.class1 = !!servercaps.dav_class1; + outCapabilities.class2 = !!servercaps.dav_class2; + outCapabilities.executable = !!servercaps.dav_executable; +} + +// ------------------------------------------------------------------- +// PROPFIND - allprop & named +// ------------------------------------------------------------------- +void NeonSession::PROPFIND( const rtl::OUString & inPath, + const Depth inDepth, + const std::vector< rtl::OUString > & inPropNames, + std::vector< DAVResource > & ioResources, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ) +{ + osl::Guard< osl::Mutex > theGuard( m_aMutex ); + + Init( rEnv ); + + int theRetVal = NE_OK; + NeonPropFindRequest theRequest( m_pHttpSession, + rtl::OUStringToOString( + inPath, RTL_TEXTENCODING_UTF8 ), + inDepth, + inPropNames, + ioResources, + theRetVal ); + + HandleError( theRetVal, inPath, rEnv ); +} + +// ------------------------------------------------------------------- +// PROPFIND - propnames +// ------------------------------------------------------------------- +void NeonSession::PROPFIND( const rtl::OUString & inPath, + const Depth inDepth, + std::vector< DAVResourceInfo > & ioResInfo, + const DAVRequestEnvironment & rEnv ) + throw( DAVException ) +{ + osl::Guard< osl::Mutex > theGuard( m_aMutex ); + + Init( rEnv ); + + int theRetVal = NE_OK; + NeonPropFindRequest theRequest( m_pHttpSession, + rtl::OUStringToOString( + inPath, RTL_TEXTENCODING_UTF8 ), + inDepth, + ioResInfo, + theRetVal ); + + HandleError( theRetVal, inPath, rEnv ); +} + +// ------------------------------------------------------------------- +// PROPPATCH +// ------------------------------------------------------------------- +void NeonSession::PROPPATCH( const rtl::OUString & inPath, + const std::vector< ProppatchValue > & inValues, + const DAVRequestEnvironment & rEnv ) + throw( DAVException ) +{ + /* @@@ Which standard live properties can be set by the client? + This is a known WebDAV RFC issue ( verified: 04/10/2001 ) + --> http://www.ics.uci.edu/pub/ietf/webdav/protocol/issues.html + + mod_dav implementation: + + creationdate r ( File System prop ) + displayname w + getcontentlanguage r ( #ifdef DAV_DISABLE_WRITEABLE_PROPS ) + getcontentlength r ( File System prop ) + getcontenttype r ( #ifdef DAV_DISABLE_WRITEABLE_PROPS ) + getetag r ( File System prop ) + getlastmodified r ( File System prop ) + lockdiscovery r + resourcetype r + source w + supportedlock r + executable w ( #ifndef WIN32 ) + + All dead properties are of course writable. + */ + + int theRetVal = NE_OK; + + int n; // for the "for" loop + + // Generate the list of properties we want to set. + int nPropCount = inValues.size(); + ne_proppatch_operation* pItems + = new ne_proppatch_operation[ nPropCount + 1 ]; + for ( n = 0; n < nPropCount; ++n ) + { + const ProppatchValue & rValue = inValues[ n ]; + + // Split fullname into namespace and name! + ne_propname * pName = new ne_propname; + DAVProperties::createNeonPropName( rValue.name, *pName ); + pItems[ n ].name = pName; + + if ( rValue.operation == PROPSET ) + { + pItems[ n ].type = ne_propset; + + rtl::OUString aStringValue; + if ( DAVProperties::isUCBDeadProperty( *pName ) ) + { + // DAV dead property added by WebDAV UCP? + if ( !UCBDeadPropertyValue::toXML( rValue.value, + aStringValue ) ) + { + // Error! + pItems[ n ].value = 0; + theRetVal = NE_ERROR; + nPropCount = n + 1; + break; + } + } + else if ( !( rValue.value >>= aStringValue ) ) + { + // complex properties... + if ( rValue.name == DAVProperties::SOURCE ) + { + uno::Sequence< ucb::Link > aLinks; + if ( rValue.value >>= aLinks ) + { + LinkSequence::toXML( aLinks, aStringValue ); + } + else + { + // Error! + pItems[ n ].value = 0; + theRetVal = NE_ERROR; + nPropCount = n + 1; + break; + } + } + else + { + OSL_ENSURE( sal_False, + "NeonSession::PROPPATCH - unsupported type!" ); + // Error! + pItems[ n ].value = 0; + theRetVal = NE_ERROR; + nPropCount = n + 1; + break; + } + } + pItems[ n ].value + = strdup( rtl::OUStringToOString( aStringValue, + RTL_TEXTENCODING_UTF8 ) ); + } + else + { + pItems[ n ].type = ne_propremove; + pItems[ n ].value = 0; + } + } + + if ( theRetVal == NE_OK ) + { + osl::Guard< osl::Mutex > theGuard( m_aMutex ); + + Init( rEnv ); + + pItems[ n ].name = 0; + + theRetVal = ne_proppatch( m_pHttpSession, + rtl::OUStringToOString( + inPath, RTL_TEXTENCODING_UTF8 ), + pItems ); + } + + for ( n = 0; n < nPropCount; ++n ) + { + free( (void *)pItems[ n ].name->name ); + delete pItems[ n ].name; + free( (void *)pItems[ n ].value ); + } + + delete [] pItems; + + HandleError( theRetVal, inPath, rEnv ); +} + +// ------------------------------------------------------------------- +// HEAD +// ------------------------------------------------------------------- +void NeonSession::HEAD( const ::rtl::OUString & inPath, + const std::vector< ::rtl::OUString > & inHeaderNames, + DAVResource & ioResource, + const DAVRequestEnvironment & rEnv ) + throw( DAVException ) +{ + osl::Guard< osl::Mutex > theGuard( m_aMutex ); + + Init( rEnv ); + + int theRetVal = NE_OK; + NeonHeadRequest theRequest( m_pHttpSession, + inPath, + inHeaderNames, + ioResource, + theRetVal ); + + HandleError( theRetVal, inPath, rEnv ); +} + +// ------------------------------------------------------------------- +// GET +// ------------------------------------------------------------------- +uno::Reference< io::XInputStream > +NeonSession::GET( const rtl::OUString & inPath, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ) +{ + osl::Guard< osl::Mutex > theGuard( m_aMutex ); + + Init( rEnv ); + + rtl::Reference< NeonInputStream > xInputStream( new NeonInputStream ); + NeonRequestContext aCtx( xInputStream ); + int theRetVal = GET( m_pHttpSession, + rtl::OUStringToOString( + inPath, RTL_TEXTENCODING_UTF8 ), + NeonSession_ResponseBlockReader, + false, + &aCtx ); + + HandleError( theRetVal, inPath, rEnv ); + + return uno::Reference< io::XInputStream >( xInputStream.get() ); +} + +// ------------------------------------------------------------------- +// GET +// ------------------------------------------------------------------- +void NeonSession::GET( const rtl::OUString & inPath, + uno::Reference< io::XOutputStream > & ioOutputStream, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ) +{ + osl::Guard< osl::Mutex > theGuard( m_aMutex ); + + Init( rEnv ); + + NeonRequestContext aCtx( ioOutputStream ); + int theRetVal = GET( m_pHttpSession, + rtl::OUStringToOString( + inPath, RTL_TEXTENCODING_UTF8 ), + NeonSession_ResponseBlockWriter, + false, + &aCtx ); + + HandleError( theRetVal, inPath, rEnv ); +} + +// ------------------------------------------------------------------- +// GET +// ------------------------------------------------------------------- +uno::Reference< io::XInputStream > +NeonSession::GET( const rtl::OUString & inPath, + const std::vector< ::rtl::OUString > & inHeaderNames, + DAVResource & ioResource, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ) +{ + osl::Guard< osl::Mutex > theGuard( m_aMutex ); + + Init( rEnv ); + + ioResource.uri = inPath; + ioResource.properties.clear(); + + rtl::Reference< NeonInputStream > xInputStream( new NeonInputStream ); + NeonRequestContext aCtx( xInputStream, inHeaderNames, ioResource ); + int theRetVal = GET( m_pHttpSession, + rtl::OUStringToOString( + inPath, RTL_TEXTENCODING_UTF8 ), + NeonSession_ResponseBlockReader, + true, + &aCtx ); + + HandleError( theRetVal, inPath, rEnv ); + + return uno::Reference< io::XInputStream >( xInputStream.get() ); +} + +// ------------------------------------------------------------------- +// GET +// ------------------------------------------------------------------- +void NeonSession::GET( const rtl::OUString & inPath, + uno::Reference< io::XOutputStream > & ioOutputStream, + const std::vector< ::rtl::OUString > & inHeaderNames, + DAVResource & ioResource, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ) +{ + osl::Guard< osl::Mutex > theGuard( m_aMutex ); + + Init( rEnv ); + + ioResource.uri = inPath; + ioResource.properties.clear(); + + NeonRequestContext aCtx( ioOutputStream, inHeaderNames, ioResource ); + int theRetVal = GET( m_pHttpSession, + rtl::OUStringToOString( + inPath, RTL_TEXTENCODING_UTF8 ), + NeonSession_ResponseBlockWriter, + true, + &aCtx ); + + HandleError( theRetVal, inPath, rEnv ); +} + +// ------------------------------------------------------------------- +// PUT +// ------------------------------------------------------------------- +void NeonSession::PUT( const rtl::OUString & inPath, + const uno::Reference< io::XInputStream > & inInputStream, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ) +{ + osl::Guard< osl::Mutex > theGuard( m_aMutex ); + + uno::Sequence< sal_Int8 > aDataToSend; + if ( !getDataFromInputStream( inInputStream, aDataToSend, false ) ) + throw DAVException( DAVException::DAV_INVALID_ARG ); + + Init( rEnv ); + + int theRetVal = PUT( m_pHttpSession, + rtl::OUStringToOString( + inPath, RTL_TEXTENCODING_UTF8 ), + reinterpret_cast< const char * >( + aDataToSend.getConstArray() ), + aDataToSend.getLength() ); + + HandleError( theRetVal, inPath, rEnv ); +} + +// ------------------------------------------------------------------- +// POST +// ------------------------------------------------------------------- +uno::Reference< io::XInputStream > +NeonSession::POST( const rtl::OUString & inPath, + const rtl::OUString & rContentType, + const rtl::OUString & rReferer, + const uno::Reference< io::XInputStream > & inInputStream, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ) +{ + osl::Guard< osl::Mutex > theGuard( m_aMutex ); + + uno::Sequence< sal_Int8 > aDataToSend; + if ( !getDataFromInputStream( inInputStream, aDataToSend, true ) ) + throw DAVException( DAVException::DAV_INVALID_ARG ); + + Init( rEnv ); + + rtl::Reference< NeonInputStream > xInputStream( new NeonInputStream ); + NeonRequestContext aCtx( xInputStream ); + int theRetVal = POST( m_pHttpSession, + rtl::OUStringToOString( + inPath, RTL_TEXTENCODING_UTF8 ), + reinterpret_cast< const char * >( + aDataToSend.getConstArray() ), + NeonSession_ResponseBlockReader, + &aCtx, + rContentType, + rReferer ); + + HandleError( theRetVal, inPath, rEnv ); + + return uno::Reference< io::XInputStream >( xInputStream.get() ); +} + +// ------------------------------------------------------------------- +// POST +// ------------------------------------------------------------------- +void NeonSession::POST( const rtl::OUString & inPath, + const rtl::OUString & rContentType, + const rtl::OUString & rReferer, + const uno::Reference< io::XInputStream > & inInputStream, + uno::Reference< io::XOutputStream > & oOutputStream, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ) +{ + osl::Guard< osl::Mutex > theGuard( m_aMutex ); + + uno::Sequence< sal_Int8 > aDataToSend; + if ( !getDataFromInputStream( inInputStream, aDataToSend, true ) ) + throw DAVException( DAVException::DAV_INVALID_ARG ); + + Init( rEnv ); + + NeonRequestContext aCtx( oOutputStream ); + int theRetVal = POST( m_pHttpSession, + rtl::OUStringToOString( + inPath, RTL_TEXTENCODING_UTF8 ), + reinterpret_cast< const char * >( + aDataToSend.getConstArray() ), + NeonSession_ResponseBlockWriter, + &aCtx, + rContentType, + rReferer ); + + HandleError( theRetVal, inPath, rEnv ); +} + +// ------------------------------------------------------------------- +// MKCOL +// ------------------------------------------------------------------- +void NeonSession::MKCOL( const rtl::OUString & inPath, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ) +{ + osl::Guard< osl::Mutex > theGuard( m_aMutex ); + + Init( rEnv ); + + int theRetVal = ne_mkcol( m_pHttpSession, + rtl::OUStringToOString( + inPath, RTL_TEXTENCODING_UTF8 ) ); + + HandleError( theRetVal, inPath, rEnv ); +} + +// ------------------------------------------------------------------- +// COPY +// ------------------------------------------------------------------- +void NeonSession::COPY( const rtl::OUString & inSourceURL, + const rtl::OUString & inDestinationURL, + const DAVRequestEnvironment & rEnv, + sal_Bool inOverWrite ) + throw ( DAVException ) +{ + osl::Guard< osl::Mutex > theGuard( m_aMutex ); + + Init( rEnv ); + + NeonUri theSourceUri( inSourceURL ); + NeonUri theDestinationUri( inDestinationURL ); + + int theRetVal = ne_copy( m_pHttpSession, + inOverWrite ? 1 : 0, + NE_DEPTH_INFINITE, + rtl::OUStringToOString( + theSourceUri.GetPath(), + RTL_TEXTENCODING_UTF8 ), + rtl::OUStringToOString( + theDestinationUri.GetPath(), + RTL_TEXTENCODING_UTF8 ) ); + + HandleError( theRetVal, inSourceURL, rEnv ); +} + +// ------------------------------------------------------------------- +// MOVE +// ------------------------------------------------------------------- +void NeonSession::MOVE( const rtl::OUString & inSourceURL, + const rtl::OUString & inDestinationURL, + const DAVRequestEnvironment & rEnv, + sal_Bool inOverWrite ) + throw ( DAVException ) +{ + osl::Guard< osl::Mutex > theGuard( m_aMutex ); + + Init( rEnv ); + + NeonUri theSourceUri( inSourceURL ); + NeonUri theDestinationUri( inDestinationURL ); + int theRetVal = ne_move( m_pHttpSession, + inOverWrite ? 1 : 0, + rtl::OUStringToOString( + theSourceUri.GetPath(), + RTL_TEXTENCODING_UTF8 ), + rtl::OUStringToOString( + theDestinationUri.GetPath(), + RTL_TEXTENCODING_UTF8 ) ); + + HandleError( theRetVal, inSourceURL, rEnv ); +} + +// ------------------------------------------------------------------- +// DESTROY +// ------------------------------------------------------------------- +void NeonSession::DESTROY( const rtl::OUString & inPath, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ) +{ + osl::Guard< osl::Mutex > theGuard( m_aMutex ); + + Init( rEnv ); + + int theRetVal = ne_delete( m_pHttpSession, + rtl::OUStringToOString( + inPath, RTL_TEXTENCODING_UTF8 ) ); + + HandleError( theRetVal, inPath, rEnv ); +} + +// ------------------------------------------------------------------- +namespace +{ + sal_Int32 lastChanceToSendRefreshRequest( TimeValue const & rStart, + int timeout ) + { + TimeValue aEnd; + osl_getSystemTime( &aEnd ); + + // Try to estimate a safe absolute time for sending the + // lock refresh request. + sal_Int32 lastChanceToSendRefreshRequest = -1; + if ( timeout != NE_TIMEOUT_INFINITE ) + { + sal_Int32 calltime = aEnd.Seconds - rStart.Seconds; + if ( calltime <= timeout ) + { + lastChanceToSendRefreshRequest + = aEnd.Seconds + timeout - calltime; + } + else + { + OSL_TRACE( "No chance to refresh lock before timeout!" ); + } + } + return lastChanceToSendRefreshRequest; + } + +} // namespace + +// ------------------------------------------------------------------- +// LOCK (set new lock) +// ------------------------------------------------------------------- +void NeonSession::LOCK( const ::rtl::OUString & inPath, + ucb::Lock & rLock, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ) +{ + osl::Guard< osl::Mutex > theGuard( m_aMutex ); + + Init( rEnv ); + + /* Create a depth zero, exclusive write lock, with default timeout + * (allowing a server to pick a default). token, owner and uri are + * unset. */ + NeonLock * theLock = ne_lock_create(); + + // Set the lock uri + ne_uri aUri; + ne_uri_parse( rtl::OUStringToOString( makeAbsoluteURL( inPath ), + RTL_TEXTENCODING_UTF8 ).getStr(), + &aUri ); + theLock->uri = aUri; + + // Set the lock depth + switch( rLock.Depth ) + { + case ucb::LockDepth_ZERO: + theLock->depth = NE_DEPTH_ZERO; + break; + case ucb::LockDepth_ONE: + theLock->depth = NE_DEPTH_ONE; + break; + case ucb::LockDepth_INFINITY: + theLock->depth = NE_DEPTH_INFINITE; + break; + default: + throw DAVException( DAVException::DAV_INVALID_ARG ); + } + + // Set the lock scope + switch ( rLock.Scope ) + { + case ucb::LockScope_EXCLUSIVE: + theLock->scope = ne_lockscope_exclusive; + break; + case ucb::LockScope_SHARED: + theLock->scope = ne_lockscope_shared; + break; + default: + throw DAVException( DAVException::DAV_INVALID_ARG ); + } + + // Set the lock timeout + theLock->timeout = (long)rLock.Timeout; + + // Set the lock owner + rtl::OUString aValue; + rLock.Owner >>= aValue; + theLock->owner = + ne_strdup( rtl::OUStringToOString( aValue, + RTL_TEXTENCODING_UTF8 ).getStr() ); + TimeValue startCall; + osl_getSystemTime( &startCall ); + + int theRetVal = ne_lock( m_pHttpSession, theLock ); + + if ( theRetVal == NE_OK ) + { + m_aNeonLockStore.addLock( theLock, + this, + lastChanceToSendRefreshRequest( + startCall, theLock->timeout ) ); + + uno::Sequence< rtl::OUString > aTokens( 1 ); + aTokens[ 0 ] = rtl::OUString::createFromAscii( theLock->token ); + rLock.LockTokens = aTokens; + + OSL_TRACE( "NeonSession::LOCK: created lock for %s. token: %s", + rtl::OUStringToOString( makeAbsoluteURL( inPath ), + RTL_TEXTENCODING_UTF8 ).getStr(), + theLock->token ); + } + else + { + ne_lock_destroy( theLock ); + + OSL_TRACE( "NeonSession::LOCK: obtaining lock for %s failed!", + rtl::OUStringToOString( makeAbsoluteURL( inPath ), + RTL_TEXTENCODING_UTF8 ).getStr() ); + } + + HandleError( theRetVal, inPath, rEnv ); +} + +// ------------------------------------------------------------------- +// LOCK (refresh existing lock) +// ------------------------------------------------------------------- +sal_Int64 NeonSession::LOCK( const ::rtl::OUString & inPath, + sal_Int64 nTimeout, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ) +{ + osl::Guard< osl::Mutex > theGuard( m_aMutex ); + + // Try to get the neon lock from lock store + NeonLock * theLock + = m_aNeonLockStore.findByUri( makeAbsoluteURL( inPath ) ); + if ( !theLock ) + throw DAVException( DAVException::DAV_NOT_LOCKED ); + + Init( rEnv ); + + // refresh existing lock. + theLock->timeout = static_cast< long >( nTimeout ); + + TimeValue startCall; + osl_getSystemTime( &startCall ); + + int theRetVal = ne_lock_refresh( m_pHttpSession, theLock ); + + if ( theRetVal == NE_OK ) + { + m_aNeonLockStore.updateLock( theLock, + lastChanceToSendRefreshRequest( + startCall, theLock->timeout ) ); + } + + HandleError( theRetVal, inPath, rEnv ); + + return theLock->timeout; +} + +// ------------------------------------------------------------------- +// LOCK (refresh existing lock) +// ------------------------------------------------------------------- +bool NeonSession::LOCK( NeonLock * pLock, + sal_Int32 & rlastChanceToSendRefreshRequest ) +{ + osl::Guard< osl::Mutex > theGuard( m_aMutex ); + +#if OSL_DEBUG_LEVEL > 0 + char * p = ne_uri_unparse( &(pLock->uri) ); + OSL_TRACE( "NeonSession::LOCK: Refreshing lock for %s.", p ); + ne_free( p ); +#endif + + // refresh existing lock. + + TimeValue startCall; + osl_getSystemTime( &startCall ); + + if ( ne_lock_refresh( m_pHttpSession, pLock ) == NE_OK ) + { + rlastChanceToSendRefreshRequest + = lastChanceToSendRefreshRequest( startCall, pLock->timeout ); + + OSL_TRACE( "Lock successfully refreshed." ); + return true; + } + else + { + OSL_TRACE( "Lock not refreshed!" ); + return false; + } +} + +// ------------------------------------------------------------------- +// UNLOCK +// ------------------------------------------------------------------- +void NeonSession::UNLOCK( const ::rtl::OUString & inPath, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ) +{ + osl::Guard< osl::Mutex > theGuard( m_aMutex ); + + // get the neon lock from lock store + NeonLock * theLock + = m_aNeonLockStore.findByUri( makeAbsoluteURL( inPath ) ); + if ( !theLock ) + throw DAVException( DAVException::DAV_NOT_LOCKED ); + + Init( rEnv ); + + int theRetVal = ne_unlock( m_pHttpSession, theLock ); + + if ( theRetVal == NE_OK ) + { + m_aNeonLockStore.removeLock( theLock ); + ne_lock_destroy( theLock ); + } + else + { + OSL_TRACE( "NeonSession::UNLOCK: unlocking of %s failed.", + rtl::OUStringToOString( makeAbsoluteURL( inPath ), + RTL_TEXTENCODING_UTF8 ).getStr() ); + } + + HandleError( theRetVal, inPath, rEnv ); +} + +// ------------------------------------------------------------------- +// UNLOCK +// ------------------------------------------------------------------- +bool NeonSession::UNLOCK( NeonLock * pLock ) +{ + osl::Guard< osl::Mutex > theGuard( m_aMutex ); + +#if OSL_DEBUG_LEVEL > 0 + char * p = ne_uri_unparse( &(pLock->uri) ); + OSL_TRACE( "NeonSession::UNLOCK: Unlocking %s.", p ); + ne_free( p ); +#endif + + if ( ne_unlock( m_pHttpSession, pLock ) == NE_OK ) + { + OSL_TRACE( "UNLOCK succeeded." ); + return true; + } + else + { + OSL_TRACE( "UNLOCK failed!" ); + return false; + } +} + +// ------------------------------------------------------------------- +void NeonSession::abort() + throw ( DAVException ) +{ + // 11.11.09 (tkr): The following code lines causing crashes if + // closing a ongoing connection. It turned out that this existing + // solution doesn't work in multi-threading environments. + // So I disabled them in 3.2. . Issue #73893# should fix it in OOo 3.3. + //if ( m_pHttpSession ) + // ne_close_connection( m_pHttpSession ); +} + +// ------------------------------------------------------------------- +const ucbhelper::InternetProxyServer & NeonSession::getProxySettings() const +{ + if ( m_aScheme.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "http" ) ) || + m_aScheme.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "https" ) ) ) + { + return m_rProxyDecider.getProxy( m_aScheme, + m_aHostName, + m_nPort ); + } + else + { + return m_rProxyDecider.getProxy( m_aScheme, + rtl::OUString() /* not used */, + -1 /* not used */ ); + } +} + +// ------------------------------------------------------------------- +namespace { + +bool containsLocktoken( const uno::Sequence< ucb::Lock > & rLocks, + const char * token ) +{ + for ( sal_Int32 n = 0; n < rLocks.getLength(); ++n ) + { + const uno::Sequence< rtl::OUString > & rTokens + = rLocks[ n ].LockTokens; + for ( sal_Int32 m = 0; m < rTokens.getLength(); ++m ) + { + if ( rTokens[ m ].equalsAscii( token ) ) + return true; + } + } + return false; +} + +} // namespace + +// ------------------------------------------------------------------- +bool NeonSession::removeExpiredLocktoken( const rtl::OUString & inURL, + const DAVRequestEnvironment & rEnv ) +{ + NeonLock * theLock = m_aNeonLockStore.findByUri( inURL ); + if ( !theLock ) + return false; + + // do a lockdiscovery to check whether this lock is still valid. + try + { + // @@@ Alternative: use ne_lock_discover() => less overhead + + std::vector< DAVResource > aResources; + std::vector< rtl::OUString > aPropNames; + aPropNames.push_back( DAVProperties::LOCKDISCOVERY ); + + PROPFIND( rEnv.m_aRequestURI, DAVZERO, aPropNames, aResources, rEnv ); + + if ( aResources.size() == 0 ) + return false; + + std::vector< DAVPropertyValue >::const_iterator it + = aResources[ 0 ].properties.begin(); + std::vector< DAVPropertyValue >::const_iterator end + = aResources[ 0 ].properties.end(); + + while ( it != end ) + { + if ( (*it).Name.equals( DAVProperties::LOCKDISCOVERY ) ) + { + uno::Sequence< ucb::Lock > aLocks; + if ( !( (*it).Value >>= aLocks ) ) + return false; + + if ( !containsLocktoken( aLocks, theLock->token ) ) + { + // expired! + break; + } + + // still valid. + return false; + } + ++it; + } + + // No lockdiscovery prop in propfind result / locktoken not found + // in propfind result -> not locked + OSL_TRACE( "NeonSession::removeExpiredLocktoken: Removing " + " expired lock token for %s. token: %s", + rtl::OUStringToOString( inURL, + RTL_TEXTENCODING_UTF8 ).getStr(), + theLock->token ); + + m_aNeonLockStore.removeLock( theLock ); + ne_lock_destroy( theLock ); + return true; + } + catch ( DAVException const & ) + { + } + return false; +} + +// ------------------------------------------------------------------- +// HandleError +// Common Error Handler +// ------------------------------------------------------------------- +void NeonSession::HandleError( int nError, + const rtl::OUString & inPath, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ) +{ + m_aEnv = DAVRequestEnvironment(); + + // Map error code to DAVException. + switch ( nError ) + { + case NE_OK: + return; + + case NE_ERROR: // Generic error + { + rtl::OUString aText = rtl::OUString::createFromAscii( + ne_get_error( m_pHttpSession ) ); + + sal_uInt16 code = makeStatusCode( aText ); + + if ( code == SC_LOCKED ) + { + if ( m_aNeonLockStore.findByUri( + makeAbsoluteURL( inPath ) ) == 0 ) + { + // locked by 3rd party + throw DAVException( DAVException::DAV_LOCKED ); + } + else + { + // locked by ourself + throw DAVException( DAVException::DAV_LOCKED_SELF ); + } + } + + // Special handling for 400 and 412 status codes, which may indicate + // that a lock previously obtained by us has been released meanwhile + // by the server. Unfortunately, RFC is not clear at this point, + // thus server implementations behave different... + else if ( code == SC_BAD_REQUEST || code == SC_PRECONDITION_FAILED ) + { + if ( removeExpiredLocktoken( makeAbsoluteURL( inPath ), rEnv ) ) + throw DAVException( DAVException::DAV_LOCK_EXPIRED ); + } + + throw DAVException( DAVException::DAV_HTTP_ERROR, aText, code ); + } + case NE_LOOKUP: // Name lookup failed. + throw DAVException( DAVException::DAV_HTTP_LOOKUP, + NeonUri::makeConnectionEndPointString( + m_aHostName, m_nPort ) ); + + case NE_AUTH: // User authentication failed on server + throw DAVException( DAVException::DAV_HTTP_AUTH, + NeonUri::makeConnectionEndPointString( + m_aHostName, m_nPort ) ); + + case NE_PROXYAUTH: // User authentication failed on proxy + throw DAVException( DAVException::DAV_HTTP_AUTHPROXY, + NeonUri::makeConnectionEndPointString( + m_aProxyName, m_nProxyPort ) ); + + case NE_CONNECT: // Could not connect to server + throw DAVException( DAVException::DAV_HTTP_CONNECT, + NeonUri::makeConnectionEndPointString( + m_aHostName, m_nPort ) ); + + case NE_TIMEOUT: // Connection timed out + throw DAVException( DAVException::DAV_HTTP_TIMEOUT, + NeonUri::makeConnectionEndPointString( + m_aHostName, m_nPort ) ); + + case NE_FAILED: // The precondition failed + throw DAVException( DAVException::DAV_HTTP_FAILED, + NeonUri::makeConnectionEndPointString( + m_aHostName, m_nPort ) ); + + case NE_RETRY: // Retry request (ne_end_request ONLY) + throw DAVException( DAVException::DAV_HTTP_RETRY, + NeonUri::makeConnectionEndPointString( + m_aHostName, m_nPort ) ); + + case NE_REDIRECT: + { + NeonUri aUri( ne_redirect_location( m_pHttpSession ) ); + throw DAVException( + DAVException::DAV_HTTP_REDIRECT, aUri.GetURI() ); + } + default: + { + OSL_TRACE( "NeonSession::HandleError : Unknown Neon error code!" ); + throw DAVException( DAVException::DAV_HTTP_ERROR, + rtl::OUString::createFromAscii( + ne_get_error( m_pHttpSession ) ) ); + } + } +} + +// ------------------------------------------------------------------- +namespace { + +void runResponseHeaderHandler( void * userdata, + const char * value ) +{ + rtl::OUString aHeader( rtl::OUString::createFromAscii( value ) ); + sal_Int32 nPos = aHeader.indexOf( ':' ); + + if ( nPos != -1 ) + { + rtl::OUString aHeaderName( aHeader.copy( 0, nPos ) ); + + NeonRequestContext * pCtx + = static_cast< NeonRequestContext * >( userdata ); + + // Note: Empty vector means that all headers are requested. + bool bIncludeIt = ( pCtx->pHeaderNames->size() == 0 ); + + if ( !bIncludeIt ) + { + // Check whether this header was requested. + std::vector< ::rtl::OUString >::const_iterator it( + pCtx->pHeaderNames->begin() ); + const std::vector< ::rtl::OUString >::const_iterator end( + pCtx->pHeaderNames->end() ); + + while ( it != end ) + { + // header names are case insensitive + if ( (*it).equalsIgnoreAsciiCase( aHeaderName ) ) + { + aHeaderName = (*it); + break; + } + ++it; + } + + if ( it != end ) + bIncludeIt = true; + } + + if ( bIncludeIt ) + { + // Create & set the PropertyValue + DAVPropertyValue thePropertyValue; + thePropertyValue.IsCaseSensitive = false; + thePropertyValue.Name = aHeaderName; + + if ( nPos < aHeader.getLength() ) + thePropertyValue.Value <<= aHeader.copy( nPos + 1 ).trim(); + + // Add the newly created PropertyValue + pCtx->pResource->properties.push_back( thePropertyValue ); + } + } +} + +} // namespace + +// ------------------------------------------------------------------- +// static +int NeonSession::GET( ne_session * sess, + const char * uri, + ne_block_reader reader, + bool getheaders, + void * userdata ) +{ + //struct get_context ctx; + ne_request * req = ne_request_create( sess, "GET", uri ); + int ret; + void *cursor = NULL; + const char *name, *value; + +#if NEON_VERSION < 0x0250 + if ( getheaders ) + ne_add_response_header_catcher( + req, runResponseHeaderHandler, userdata ); +#endif + ne_decompress * dc + = ne_decompress_reader( req, ne_accept_2xx, reader, userdata ); + + ret = ne_request_dispatch( req ); + +#if NEON_VERSION >= 0x0250 + if ( getheaders ) + { + while ( ( cursor = ne_response_header_iterate( + req, cursor, &name, &value ) ) != NULL ) + { + char buffer[8192]; + + ne_snprintf(buffer, sizeof buffer, "%s: %s", name, value); + runResponseHeaderHandler(userdata, buffer); + } + } +#endif + if ( ret == NE_OK && ne_get_status( req )->klass != 2 ) + ret = NE_ERROR; + + if ( dc != 0 ) + ne_decompress_destroy(dc); + + ne_request_destroy( req ); + return ret; +} + +// ------------------------------------------------------------------- +// static +int NeonSession::PUT( ne_session * sess, + const char * uri, + const char * buffer, + size_t size) +{ + ne_request * req = ne_request_create( sess, "PUT", uri ); + int ret; + + ne_lock_using_resource( req, uri, 0 ); + ne_lock_using_parent( req, uri ); + + ne_set_request_body_buffer( req, buffer, size ); + + ret = ne_request_dispatch( req ); + + if ( ret == NE_OK && ne_get_status( req )->klass != 2 ) + ret = NE_ERROR; + + ne_request_destroy( req ); + return ret; +} + +// ------------------------------------------------------------------- +int NeonSession::POST( ne_session * sess, + const char * uri, + const char * buffer, + ne_block_reader reader, + void * userdata, + const rtl::OUString & rContentType, + const rtl::OUString & rReferer ) +{ + ne_request * req = ne_request_create( sess, "POST", uri ); + //struct get_context ctx; + int ret; + + RequestDataMap * pData = 0; + + if ( rContentType.getLength() || rReferer.getLength() ) + { + // Remember contenttype and referer. Data will be added to HTTP request + // header in in 'PreSendRequest' callback. + pData = static_cast< RequestDataMap* >( m_pRequestData ); + (*pData)[ req ] = RequestData( rContentType, rReferer ); + } + + //ctx.total = -1; + //ctx.fd = fd; + //ctx.error = 0; + //ctx.session = sess; + + ///* Read the value of the Content-Length header into ctx.total */ + //ne_add_response_header_handler( req, "Content-Length", + // ne_handle_numeric_header, &ctx.total ); + + ne_add_response_body_reader( req, ne_accept_2xx, reader, userdata ); + + ne_set_request_body_buffer( req, buffer, strlen( buffer ) ); + + ret = ne_request_dispatch( req ); + + //if ( ctx.error ) + // ret = NE_ERROR; + //else + if ( ret == NE_OK && ne_get_status( req )->klass != 2 ) + ret = NE_ERROR; + + ne_request_destroy( req ); + + if ( pData ) + { + // Remove request data from session's list. + RequestDataMap::iterator it = pData->find( req ); + if ( it != pData->end() ) + pData->erase( it ); + } + + return ret; +} + +// ------------------------------------------------------------------- +// static +bool +NeonSession::getDataFromInputStream( + const uno::Reference< io::XInputStream > & xStream, + uno::Sequence< sal_Int8 > & rData, + bool bAppendTrailingZeroByte ) +{ + if ( xStream.is() ) + { + uno::Reference< io::XSeekable > xSeekable( xStream, uno::UNO_QUERY ); + if ( xSeekable.is() ) + { + try + { + sal_Int32 nSize + = sal::static_int_cast<sal_Int32>(xSeekable->getLength()); + sal_Int32 nRead + = xStream->readBytes( rData, nSize ); + + if ( nRead == nSize ) + { + if ( bAppendTrailingZeroByte ) + { + rData.realloc( nSize + 1 ); + rData[ nSize ] = sal_Int8( 0 ); + } + return true; + } + } + catch ( io::NotConnectedException const & ) + { + // readBytes + } + catch ( io::BufferSizeExceededException const & ) + { + // readBytes + } + catch ( io::IOException const & ) + { + // getLength, readBytes + } + } + else + { + try + { + uno::Sequence< sal_Int8 > aBuffer; + sal_Int32 nPos = 0; + + sal_Int32 nRead = xStream->readSomeBytes( aBuffer, 65536 ); + while ( nRead > 0 ) + { + if ( rData.getLength() < ( nPos + nRead ) ) + rData.realloc( nPos + nRead ); + + aBuffer.realloc( nRead ); + rtl_copyMemory( (void*)( rData.getArray() + nPos ), + (const void*)aBuffer.getConstArray(), + nRead ); + nPos += nRead; + + aBuffer.realloc( 0 ); + nRead = xStream->readSomeBytes( aBuffer, 65536 ); + } + + if ( bAppendTrailingZeroByte ) + { + rData.realloc( nPos + 1 ); + rData[ nPos ] = sal_Int8( 0 ); + } + return true; + } + catch ( io::NotConnectedException const & ) + { + // readBytes + } + catch ( io::BufferSizeExceededException const & ) + { + // readBytes + } + catch ( io::IOException const & ) + { + // readBytes + } + } + } + return false; +} + +// --------------------------------------------------------------------- +sal_Bool +NeonSession::isDomainMatch( rtl::OUString certHostName ) +{ + rtl::OUString hostName = getHostName(); + + if (hostName.equalsIgnoreAsciiCase( certHostName ) ) + return sal_True; + + if ( 0 == certHostName.indexOf( rtl::OUString::createFromAscii( "*" ) ) && + hostName.getLength() >= certHostName.getLength() ) + { + rtl::OUString cmpStr = certHostName.copy( 1 ); + + if ( hostName.matchIgnoreAsciiCase( + cmpStr, hostName.getLength() - cmpStr.getLength() ) ) + return sal_True; + } + return sal_False; +} + +// --------------------------------------------------------------------- +rtl::OUString NeonSession::makeAbsoluteURL( rtl::OUString const & rURL ) const +{ + try + { + // Is URL relative or already absolute? + if ( rURL[ 0 ] != sal_Unicode( '/' ) ) + { + // absolute. + return rtl::OUString( rURL ); + } + else + { + ne_uri aUri; + memset( &aUri, 0, sizeof( aUri ) ); + + ne_fill_server_uri( m_pHttpSession, &aUri ); + aUri.path + = ne_strdup( rtl::OUStringToOString( + rURL, RTL_TEXTENCODING_UTF8 ).getStr() ); + NeonUri aNeonUri( &aUri ); + ne_uri_free( &aUri ); + return aNeonUri.GetURI(); + } + } + catch ( DAVException const & ) + { + } + // error. + return rtl::OUString(); +} diff --git a/ucb/source/ucp/webdav/NeonSession.hxx b/ucb/source/ucp/webdav/NeonSession.hxx new file mode 100644 index 000000000000..65c2c25e4ec9 --- /dev/null +++ b/ucb/source/ucp/webdav/NeonSession.hxx @@ -0,0 +1,295 @@ +/************************************************************************* + * + * 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 _NEONSESSION_HXX_ +#define _NEONSESSION_HXX_ + +#include <vector> +#include <osl/mutex.hxx> +#include "DAVSession.hxx" +#include "NeonTypes.hxx" +#include "NeonLockStore.hxx" +#include <com/sun/star/lang/XMultiServiceFactory.hpp> + +namespace ucbhelper { class ProxyDecider; } + +namespace webdav_ucp +{ + +// ------------------------------------------------------------------- +// NeonSession +// A DAVSession implementation using the neon/expat library +// ------------------------------------------------------------------- + +class NeonSession : public DAVSession +{ +private: + osl::Mutex m_aMutex; + rtl::OUString m_aScheme; + rtl::OUString m_aHostName; + rtl::OUString m_aProxyName; + sal_Int32 m_nPort; + sal_Int32 m_nProxyPort; + HttpSession * m_pHttpSession; + void * m_pRequestData; + const ucbhelper::InternetProxyDecider & m_rProxyDecider; + + // @@@ This should really be per-request data. But Neon currently + // (0.23.5) has no interface for passing per-request user data. + // Theoretically, a NeonSession instance could handle multiple requests + // at a time --currently it doesn't. Thus this is not an issue at the + // moment. + DAVRequestEnvironment m_aEnv; + + static bool m_bGlobalsInited; + static osl::Mutex m_aGlobalMutex; + static NeonLockStore m_aNeonLockStore; + +protected: + virtual ~NeonSession(); + +public: + NeonSession( const rtl::Reference< DAVSessionFactory > & rSessionFactory, + const rtl::OUString& inUri, + const ucbhelper::InternetProxyDecider & rProxyDecider ) + throw ( DAVException ); + + // DAVSession methods + virtual sal_Bool CanUse( const ::rtl::OUString & inUri ); + + virtual sal_Bool UsesProxy(); + + const DAVRequestEnvironment & getRequestEnvironment() const + { return m_aEnv; } + + virtual void + OPTIONS( const ::rtl::OUString & inPath, + DAVCapabilities & outCapabilities, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ); + + // allprop & named + virtual void + PROPFIND( const ::rtl::OUString & inPath, + const Depth inDepth, + const std::vector< ::rtl::OUString > & inPropNames, + std::vector< DAVResource > & ioResources, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ); + + // propnames + virtual void + PROPFIND( const ::rtl::OUString & inPath, + const Depth inDepth, + std::vector< DAVResourceInfo >& ioResInfo, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ); + + virtual void + PROPPATCH( const ::rtl::OUString & inPath, + const std::vector< ProppatchValue > & inValues, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ); + + virtual void + HEAD( const ::rtl::OUString & inPath, + const std::vector< ::rtl::OUString > & inHeaderNames, + DAVResource & ioResource, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ); + + virtual com::sun::star::uno::Reference< com::sun::star::io::XInputStream > + GET( const ::rtl::OUString & inPath, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ); + + virtual void + GET( const ::rtl::OUString & inPath, + com::sun::star::uno::Reference< + com::sun::star::io::XOutputStream > & ioOutputStream, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ); + + virtual com::sun::star::uno::Reference< com::sun::star::io::XInputStream > + GET( const ::rtl::OUString & inPath, + const std::vector< ::rtl::OUString > & inHeaderNames, + DAVResource & ioResource, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ); + + virtual void + GET( const ::rtl::OUString & inPath, + com::sun::star::uno::Reference< + com::sun::star::io::XOutputStream > & ioOutputStream, + const std::vector< ::rtl::OUString > & inHeaderNames, + DAVResource & ioResource, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ); + + virtual void + PUT( const ::rtl::OUString & inPath, + const com::sun::star::uno::Reference< + com::sun::star::io::XInputStream > & inInputStream, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ); + + virtual com::sun::star::uno::Reference< com::sun::star::io::XInputStream > + POST( const rtl::OUString & inPath, + const rtl::OUString & rContentType, + const rtl::OUString & rReferer, + const com::sun::star::uno::Reference< + com::sun::star::io::XInputStream > & inInputStream, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ); + + virtual void + POST( const rtl::OUString & inPath, + const rtl::OUString & rContentType, + const rtl::OUString & rReferer, + const com::sun::star::uno::Reference< + com::sun::star::io::XInputStream > & inInputStream, + com::sun::star::uno::Reference< + com::sun::star::io::XOutputStream > & oOutputStream, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ); + + virtual void + MKCOL( const ::rtl::OUString & inPath, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ); + + virtual void + COPY( const ::rtl::OUString & inSourceURL, + const ::rtl::OUString & inDestinationURL, + const DAVRequestEnvironment & rEnv, + sal_Bool inOverWrite ) + throw ( DAVException ); + + virtual void + MOVE( const ::rtl::OUString & inSourceURL, + const ::rtl::OUString & inDestinationURL, + const DAVRequestEnvironment & rEnv, + sal_Bool inOverWrite ) + throw ( DAVException ); + + virtual void DESTROY( const ::rtl::OUString & inPath, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ); + + // set new lock. + virtual void LOCK( const ::rtl::OUString & inURL, + com::sun::star::ucb::Lock & inLock, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ); + + // refresh existing lock. + virtual sal_Int64 LOCK( const ::rtl::OUString & inURL, + sal_Int64 nTimeout, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ); + + virtual void UNLOCK( const ::rtl::OUString & inURL, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ); + + // helpers + virtual void abort() + throw ( DAVException ); + + const rtl::OUString & getHostName() const { return m_aHostName; } + + const ::uno::Reference< ::lang::XMultiServiceFactory > getMSF() + { return m_xFactory->getServiceFactory(); } + + const void * getRequestData() const { return m_pRequestData; } + + sal_Bool isDomainMatch( rtl::OUString certHostName ); + +private: + friend class NeonLockStore; + + void Init( void ) + throw ( DAVException ); + + void Init( const DAVRequestEnvironment & rEnv ) + throw ( DAVException ); + + // ret: true => retry request. + void HandleError( int nError, + const rtl::OUString & inPath, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ); + + const ucbhelper::InternetProxyServer & getProxySettings() const; + + bool removeExpiredLocktoken( const rtl::OUString & inURL, + const DAVRequestEnvironment & rEnv ); + + // refresh lock, called by NeonLockStore::refreshLocks + bool LOCK( NeonLock * pLock, + sal_Int32 & rlastChanceToSendRefreshRequest ); + + // unlock, called by NeonLockStore::~NeonLockStore + bool UNLOCK( NeonLock * pLock ); + + // low level GET implementation, used by public GET implementations + static int GET( ne_session * sess, + const char * uri, + ne_block_reader reader, + bool getheaders, + void * userdata ); + + // Buffer-based PUT implementation. Neon only has file descriptor- + // based API. + static int PUT( ne_session * sess, + const char * uri, + const char * buffer, + size_t size ); + + // Buffer-based POST implementation. Neon only has file descriptor- + // based API. + int POST( ne_session * sess, + const char * uri, + const char * buffer, + ne_block_reader reader, + void * userdata, + const rtl::OUString & rContentType, + const rtl::OUString & rReferer ); + + // Helper: XInputStream -> Sequence< sal_Int8 > + static bool getDataFromInputStream( + const com::sun::star::uno::Reference< + com::sun::star::io::XInputStream > & xStream, + com::sun::star::uno::Sequence< sal_Int8 > & rData, + bool bAppendTrailingZeroByte ); + + rtl::OUString makeAbsoluteURL( rtl::OUString const & rURL ) const; +}; + +} // namespace webdav_ucp + +#endif // _NEONSESSION_HXX_ diff --git a/ucb/source/ucp/webdav/NeonTypes.hxx b/ucb/source/ucp/webdav/NeonTypes.hxx new file mode 100644 index 000000000000..21902f352691 --- /dev/null +++ b/ucb/source/ucp/webdav/NeonTypes.hxx @@ -0,0 +1,46 @@ +/************************************************************************* + * + * 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 _NEONTYPES_HXX_ +#define _NEONTYPES_HXX_ + +#include <ne_session.h> +#include <ne_utils.h> +#include <ne_basic.h> +#include <ne_props.h> +#include <ne_locks.h> + +typedef ne_session HttpSession; +typedef ne_status HttpStatus; +typedef ne_server_capabilities HttpServerCapabilities; + +typedef ne_propname NeonPropName; +typedef ne_prop_result_set NeonPropFindResultSet; + +typedef struct ne_lock NeonLock; + +#endif // _NEONTYPES_HXX_ diff --git a/ucb/source/ucp/webdav/NeonUri.cxx b/ucb/source/ucp/webdav/NeonUri.cxx new file mode 100644 index 000000000000..774faa06b9dd --- /dev/null +++ b/ucb/source/ucp/webdav/NeonUri.cxx @@ -0,0 +1,358 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +#include <string.h> +#include <rtl/uri.hxx> +#include <rtl/ustring.hxx> +#include <rtl/ustrbuf.hxx> +#include "ne_alloc.h" +#include "NeonUri.hxx" +#include "DAVException.hxx" + +#include "../inc/urihelper.hxx" + +using namespace webdav_ucp; + +# if defined __SUNPRO_CC +// FIXME: not sure whether initializing a ne_uri statically is supposed to work +// the string fields of ne_uri are char*, not const char* +# pragma disable_warn +# endif + +#if defined __GNUC__ +#define GCC_VERSION (__GNUC__ * 10000 \ + + __GNUC_MINOR__ * 100 \ + + __GNUC_PATCHLEVEL__) +/* Diagnostics pragma was introduced with gcc-4.2.1 */ +#if GCC_VERSION > 40201 +#pragma GCC diagnostic ignored "-Wwrite-strings" +#endif +#endif + +namespace { + +const ne_uri g_sUriDefaultsHTTP = { "http", +#if NEON_VERSION >= 0x0260 + NULL, +#endif + NULL, + DEFAULT_HTTP_PORT, +#if NEON_VERSION >= 0x0260 + NULL, +#endif + NULL, + NULL }; +const ne_uri g_sUriDefaultsHTTPS = { "https", +#if NEON_VERSION >= 0x0260 + NULL, +#endif + NULL, + DEFAULT_HTTPS_PORT, +#if NEON_VERSION >= 0x0260 + NULL, +#endif + NULL, + NULL }; +const ne_uri g_sUriDefaultsFTP = { "ftp", +#if NEON_VERSION >= 0x0260 + NULL, +#endif + NULL, + DEFAULT_FTP_PORT, +#if NEON_VERSION >= 0x0260 + NULL, +#endif + NULL, + NULL }; +} // namespace + +# if defined __SUNPRO_CC +# pragma enable_warn +#endif + +// ------------------------------------------------------------------- +// Constructor +// ------------------------------------------------------------------- + +namespace { + +//TODO! rtl::OString::matchIgnoreAsciiCaseAsciiL() missing +inline bool matchIgnoreAsciiCase(rtl::OString const & rStr1, + sal_Char const * pStr2, + sal_Int32 nStr2Len) SAL_THROW(()) +{ + return + rtl_str_shortenedCompareIgnoreAsciiCase_WithLength( + rStr1.getStr(), rStr1.getLength(), pStr2, nStr2Len, nStr2Len) + == 0; +} + +} + +NeonUri::NeonUri( const ne_uri * inUri ) + throw ( DAVException ) +{ + if ( inUri == 0 ) + throw DAVException( DAVException::DAV_INVALID_ARG ); + + char * uri = ne_uri_unparse( inUri ); + + if ( uri == 0 ) + throw DAVException( DAVException::DAV_INVALID_ARG ); + + init( rtl::OString( uri ), inUri ); + ne_free( uri ); + + calculateURI(); +} + +NeonUri::NeonUri( const rtl::OUString & inUri ) + throw ( DAVException ) +{ + if ( inUri.getLength() <= 0 ) + throw DAVException( DAVException::DAV_INVALID_ARG ); + + // #i77023# + rtl::OUString aEscapedUri( ucb_impl::urihelper::encodeURI( inUri ) ); + + rtl::OString theInputUri( + aEscapedUri.getStr(), aEscapedUri.getLength(), RTL_TEXTENCODING_UTF8 ); + + ne_uri theUri; + if ( ne_uri_parse( theInputUri.getStr(), &theUri ) != 0 ) + { + ne_uri_free( &theUri ); + throw DAVException( DAVException::DAV_INVALID_ARG ); + } + + init( theInputUri, &theUri ); + ne_uri_free( &theUri ); + + calculateURI(); +} + +void NeonUri::init( const rtl::OString & rUri, const ne_uri * pUri ) +{ + // Complete URI. + const ne_uri * pUriDefs + = matchIgnoreAsciiCase( rUri, + RTL_CONSTASCII_STRINGPARAM( "ftp:" ) ) ? + &g_sUriDefaultsFTP : + matchIgnoreAsciiCase( rUri, + RTL_CONSTASCII_STRINGPARAM( "https:" ) ) ? + &g_sUriDefaultsHTTPS : + &g_sUriDefaultsHTTP; + + mScheme = rtl::OStringToOUString( + pUri->scheme ? pUri->scheme : pUriDefs->scheme, + RTL_TEXTENCODING_UTF8 ); + mUserInfo = rtl::OStringToOUString( +#if NEON_VERSION >= 0x0260 + pUri->userinfo ? pUri->userinfo : pUriDefs->userinfo, +#else + pUri->authinfo ? pUri->authinfo : pUriDefs->authinfo, +#endif + RTL_TEXTENCODING_UTF8 ); + mHostName = rtl::OStringToOUString( + pUri->host ? pUri->host : pUriDefs->host, + RTL_TEXTENCODING_UTF8 ); + mPort = pUri->port > 0 ? pUri->port : pUriDefs->port; + mPath = rtl::OStringToOUString( + pUri->path ? pUri->path : pUriDefs->path, + RTL_TEXTENCODING_UTF8 ); + +#if NEON_VERSION >= 0x0260 + if ( pUri->query ) + { + mPath += rtl::OUString::createFromAscii( "?" ); + mPath += rtl::OStringToOUString( + pUri->query, RTL_TEXTENCODING_UTF8 ); + } + + if ( pUri->fragment ) + { + mPath += rtl::OUString::createFromAscii( "#" ); + mPath += rtl::OStringToOUString( + pUri->fragment, RTL_TEXTENCODING_UTF8 ); + } +#endif +} + +// ------------------------------------------------------------------- +// Destructor +// ------------------------------------------------------------------- +NeonUri::~NeonUri( ) +{ +} + +void NeonUri::calculateURI () +{ + rtl::OUStringBuffer aBuf( mScheme ); + aBuf.appendAscii( "://" ); + if ( mUserInfo.getLength() > 0 ) + { + //TODO! differentiate between empty and missing userinfo + aBuf.append( mUserInfo ); + aBuf.appendAscii( "@" ); + } + // Is host a numeric IPv6 address? + if ( ( mHostName.indexOf( ':' ) != -1 ) && + ( mHostName[ 0 ] != sal_Unicode( '[' ) ) ) + { + aBuf.appendAscii( "[" ); + aBuf.append( mHostName ); + aBuf.appendAscii( "]" ); + } + else + { + aBuf.append( mHostName ); + } + + // append port, but only, if not default port. + bool bAppendPort = true; + switch ( mPort ) + { + case DEFAULT_HTTP_PORT: + bAppendPort + = !mScheme.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "http" ) ); + break; + + case DEFAULT_HTTPS_PORT: + bAppendPort + = !mScheme.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "https" ) ); + break; + + case DEFAULT_FTP_PORT: + bAppendPort + = !mScheme.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ftp" ) ); + break; + } + if ( bAppendPort ) + { + aBuf.appendAscii( ":" ); + aBuf.append( rtl::OUString::valueOf( mPort ) ); + } + aBuf.append( mPath ); + + mURI = aBuf.makeStringAndClear(); +} + +::rtl::OUString NeonUri::GetPathBaseName () const +{ + sal_Int32 nPos = mPath.lastIndexOf ('/'); + sal_Int32 nTrail = 0; + if (nPos == mPath.getLength () - 1) + { + // Trailing slash found. Skip. + nTrail = 1; + nPos = mPath.lastIndexOf ('/', nPos); + } + if (nPos != -1) + { + rtl::OUString aTemp( + mPath.copy (nPos + 1, mPath.getLength () - nPos - 1 - nTrail) ); + + // query, fragment present? + nPos = aTemp.indexOf( '?' ); + if ( nPos == -1 ) + nPos = aTemp.indexOf( '#' ); + + if ( nPos != -1 ) + aTemp = aTemp.copy( 0, nPos ); + + return aTemp; + } + else + return rtl::OUString::createFromAscii ("/"); +} + +bool NeonUri::operator== ( const NeonUri & rOther ) const +{ + return ( mURI == rOther.mURI ); +} + +::rtl::OUString NeonUri::GetPathBaseNameUnescaped () const +{ + return unescape( GetPathBaseName() ); +} + +void NeonUri::AppendPath (const rtl::OUString& rPath) +{ + if (mPath.lastIndexOf ('/') != mPath.getLength () - 1) + mPath += rtl::OUString::createFromAscii ("/"); + + mPath += rPath; + calculateURI (); +}; + +// static +rtl::OUString NeonUri::escapeSegment( const rtl::OUString& segment ) +{ + return rtl::Uri::encode( segment, + rtl_UriCharClassPchar, + rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8 ); +} + +// static +rtl::OUString NeonUri::unescape( const rtl::OUString& segment ) +{ + return rtl::Uri::decode( segment, + rtl_UriDecodeWithCharset, + RTL_TEXTENCODING_UTF8 ); +} + +// static +rtl::OUString NeonUri::makeConnectionEndPointString( + const rtl::OUString & rHostName, int nPort ) +{ + rtl::OUStringBuffer aBuf; + + // Is host a numeric IPv6 address? + if ( ( rHostName.indexOf( ':' ) != -1 ) && + ( rHostName[ 0 ] != sal_Unicode( '[' ) ) ) + { + aBuf.appendAscii( "[" ); + aBuf.append( rHostName ); + aBuf.appendAscii( "]" ); + } + else + { + aBuf.append( rHostName ); + } + + if ( ( nPort != DEFAULT_HTTP_PORT ) && ( nPort != DEFAULT_HTTPS_PORT ) ) + { + aBuf.appendAscii( ":" ); + aBuf.append( rtl::OUString::valueOf( sal_Int32( nPort ) ) ); + } + return aBuf.makeStringAndClear(); +} + diff --git a/ucb/source/ucp/webdav/NeonUri.hxx b/ucb/source/ucp/webdav/NeonUri.hxx new file mode 100644 index 000000000000..c83ca47d5a1c --- /dev/null +++ b/ucb/source/ucp/webdav/NeonUri.hxx @@ -0,0 +1,102 @@ +/************************************************************************* + * + * 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 _NEONURI_HXX_ +#define _NEONURI_HXX_ + +#include <ne_uri.h> +#include <rtl/ustring.hxx> +#include <DAVException.hxx> + +namespace webdav_ucp +{ + +#define DEFAULT_HTTP_PORT 80 +#define DEFAULT_HTTPS_PORT 443 +#define DEFAULT_FTP_PORT 21 + +// ------------------------------------------------------------------- +// NeonUri +// A URI implementation for use with the neon/expat library +// ------------------------------------------------------------------- +class NeonUri +{ + private: + ::rtl::OUString mURI; + ::rtl::OUString mScheme; + ::rtl::OUString mUserInfo; + ::rtl::OUString mHostName; + sal_Int32 mPort; + ::rtl::OUString mPath; + + void init( const rtl::OString & rUri, const ne_uri * pUri ); + void calculateURI (); + + public: + NeonUri( const ::rtl::OUString & inUri ) throw ( DAVException ); + NeonUri( const ne_uri * inUri ) throw ( DAVException ); + ~NeonUri( ); + + bool operator== ( const NeonUri & rOther ) const; + bool operator!= ( const NeonUri & rOther ) const + { return !operator==( rOther ); } + + const ::rtl::OUString & GetURI( void ) const + { return mURI; }; + const ::rtl::OUString & GetScheme( void ) const + { return mScheme; }; + const ::rtl::OUString & GetUserInfo( void ) const + { return mUserInfo; }; + const ::rtl::OUString & GetHost( void ) const + { return mHostName; }; + sal_Int32 GetPort( void ) const + { return mPort; }; + const ::rtl::OUString & GetPath( void ) const + { return mPath; }; + + ::rtl::OUString GetPathBaseName ( void ) const; + + ::rtl::OUString GetPathBaseNameUnescaped ( void ) const; + + void SetScheme (const ::rtl::OUString& scheme) + { mScheme = scheme; calculateURI (); }; + + void AppendPath (const ::rtl::OUString& rPath); + + static ::rtl::OUString escapeSegment( const ::rtl::OUString& segment ); + static ::rtl::OUString unescape( const ::rtl::OUString& string ); + + // "host:port", omit ":port" for port 80 and 443 + static rtl::OUString makeConnectionEndPointString( + const rtl::OUString & rHostName, + int nPort ); + rtl::OUString makeConnectionEndPointString() const + { return makeConnectionEndPointString( GetHost(), GetPort() ); } +}; + +} // namespace webdav_ucp + +#endif // _NEONURI_HXX_ diff --git a/ucb/source/ucp/webdav/PropertyMap.hxx b/ucb/source/ucp/webdav/PropertyMap.hxx new file mode 100644 index 000000000000..624187b1746e --- /dev/null +++ b/ucb/source/ucp/webdav/PropertyMap.hxx @@ -0,0 +1,65 @@ +/************************************************************************* + * + * 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 _WEBDAV_UCP_PROPERTYMAP_HXX +#define _WEBDAV_UCP_PROPERTYMAP_HXX + +#include <hash_set> +#include <com/sun/star/beans/Property.hpp> + +namespace webdav_ucp { + +//========================================================================= + +struct equalPropertyName +{ + bool operator()( const ::com::sun::star::beans::Property & p1, + const ::com::sun::star::beans::Property & p2 ) const + { + return !!( p1.Name == p2.Name ); + } +}; + +struct hashPropertyName +{ + size_t operator()( const ::com::sun::star::beans::Property & p ) const + { + return p.Name.hashCode(); + } +}; + +typedef std::hash_set +< + ::com::sun::star::beans::Property, + hashPropertyName, + equalPropertyName +> +PropertyMap; + +} + +#endif diff --git a/ucb/source/ucp/webdav/UCBDeadPropertyValue.cxx b/ucb/source/ucp/webdav/UCBDeadPropertyValue.cxx new file mode 100644 index 000000000000..1ce4c70e6b21 --- /dev/null +++ b/ucb/source/ucp/webdav/UCBDeadPropertyValue.cxx @@ -0,0 +1,547 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +#include <string.h> +#include <ne_xml.h> +#include <osl/diagnose.h> +#include <rtl/ustrbuf.hxx> +#include "UCBDeadPropertyValue.hxx" + +using namespace webdav_ucp; +using namespace com::sun::star; + +////////////////////////////////////////////////////////////////////////// + +struct UCBDeadPropertyValueParseContext +{ + rtl::OUString * pType; + rtl::OUString * pValue; + + UCBDeadPropertyValueParseContext() : pType( 0 ), pValue( 0 ) {} + ~UCBDeadPropertyValueParseContext() { delete pType; delete pValue; } +}; + +// static +const rtl::OUString UCBDeadPropertyValue::aTypeString + = rtl::OUString::createFromAscii( "string" ); +const rtl::OUString UCBDeadPropertyValue::aTypeLong + = rtl::OUString::createFromAscii( "long" ); +const rtl::OUString UCBDeadPropertyValue::aTypeShort + = rtl::OUString::createFromAscii( "short" ); +const rtl::OUString UCBDeadPropertyValue::aTypeBoolean + = rtl::OUString::createFromAscii( "boolean" ); +const rtl::OUString UCBDeadPropertyValue::aTypeChar + = rtl::OUString::createFromAscii( "char" ); +const rtl::OUString UCBDeadPropertyValue::aTypeByte + = rtl::OUString::createFromAscii( "byte" ); +const rtl::OUString UCBDeadPropertyValue::aTypeHyper + = rtl::OUString::createFromAscii( "hyper" ); +const rtl::OUString UCBDeadPropertyValue::aTypeFloat + = rtl::OUString::createFromAscii( "float" ); +const rtl::OUString UCBDeadPropertyValue::aTypeDouble + = rtl::OUString::createFromAscii( "double" ); + +// static +const rtl::OUString UCBDeadPropertyValue::aXMLPre + = rtl::OUString::createFromAscii( "<ucbprop><type>" ); +const rtl::OUString UCBDeadPropertyValue::aXMLMid + = rtl::OUString::createFromAscii( "</type><value>" ); +const rtl::OUString UCBDeadPropertyValue::aXMLEnd + = rtl::OUString::createFromAscii( "</value></ucbprop>" ); + +#define STATE_TOP (1) + +#define STATE_UCBPROP (STATE_TOP) +#define STATE_TYPE (STATE_TOP + 1) +#define STATE_VALUE (STATE_TOP + 2) + +////////////////////////////////////////////////////////////////////////// +extern "C" int UCBDeadPropertyValue_startelement_callback( + void *, + int parent, + const char * /*nspace*/, + const char *name, + const char ** ) +{ + if ( name != 0 ) + { + switch ( parent ) + { + case NE_XML_STATEROOT: + if ( strcmp( name, "ucbprop" ) == 0 ) + return STATE_UCBPROP; + break; + + case STATE_UCBPROP: + if ( strcmp( name, "type" ) == 0 ) + return STATE_TYPE; + else if ( strcmp( name, "value" ) == 0 ) + return STATE_VALUE; + break; + } + } + return NE_XML_DECLINE; +} + +////////////////////////////////////////////////////////////////////////// +extern "C" int UCBDeadPropertyValue_chardata_callback( + void *userdata, + int state, + const char *buf, + size_t len ) +{ + UCBDeadPropertyValueParseContext * pCtx + = static_cast< UCBDeadPropertyValueParseContext * >( userdata ); + + switch ( state ) + { + case STATE_TYPE: + OSL_ENSURE( !pCtx->pType, + "UCBDeadPropertyValue_endelement_callback - " + "Type already set!" ); + pCtx->pType + = new rtl::OUString( buf, len, RTL_TEXTENCODING_ASCII_US ); + break; + + case STATE_VALUE: + OSL_ENSURE( !pCtx->pValue, + "UCBDeadPropertyValue_endelement_callback - " + "Value already set!" ); + pCtx->pValue + = new rtl::OUString( buf, len, RTL_TEXTENCODING_ASCII_US ); + break; + } + return 0; // zero to continue, non-zero to abort parsing +} + +////////////////////////////////////////////////////////////////////////// +extern "C" int UCBDeadPropertyValue_endelement_callback( + void *userdata, + int state, + const char *, + const char * ) +{ + UCBDeadPropertyValueParseContext * pCtx + = static_cast< UCBDeadPropertyValueParseContext * >( userdata ); + + switch ( state ) + { + case STATE_TYPE: + if ( !pCtx->pType ) + return 1; // abort + break; + + case STATE_VALUE: + if ( !pCtx->pValue ) + return 1; // abort + break; + + case STATE_UCBPROP: + if ( !pCtx->pType || ! pCtx->pValue ) + return 1; // abort + break; + } + return 0; // zero to continue, non-zero to abort parsing +} + +////////////////////////////////////////////////////////////////////////// +static rtl::OUString encodeValue( const rtl::OUString & rValue ) +{ + // Note: I do not use the usual & + < + > encoding, because + // I want to prevent any XML parser from trying to 'understand' + // the value. This caused problems: + // + // Example: + // - Unencoded property value: x<z + // PROPPATCH: + // - Encoded property value: x<z + // - UCBDeadPropertyValue::toXML result: + // <ucbprop><type>string</type><value>x<z</value></ucbprop> + // PROPFIND: + // - parser replaces < by > ==> error (not well formed) + + rtl::OUStringBuffer aResult; + const sal_Unicode * pValue = rValue.getStr(); + + sal_Int32 nCount = rValue.getLength(); + for ( sal_Int32 n = 0; n < nCount; ++n ) + { + const sal_Unicode c = pValue[ n ]; + + if ( '%' == c ) + aResult.appendAscii( "%per;" ); + else if ( '<' == c ) + aResult.appendAscii( "%lt;" ); + else if ( '>' == c ) + aResult.appendAscii( "%gt;" ); + else + aResult.append( c ); + } + return rtl::OUString( aResult ); +} + +////////////////////////////////////////////////////////////////////////// +static rtl::OUString decodeValue( const rtl::OUString & rValue ) +{ + rtl::OUStringBuffer aResult; + const sal_Unicode * pValue = rValue.getStr(); + + sal_Int32 nPos = 0; + sal_Int32 nEnd = rValue.getLength(); + + while ( nPos < nEnd ) + { + sal_Unicode c = pValue[ nPos ]; + + if ( '%' == c ) + { + nPos++; + + if ( nPos == nEnd ) + { + OSL_ENSURE( sal_False, + "UCBDeadPropertyValue::decodeValue - syntax error!" ); + return rtl::OUString(); + } + + c = pValue[ nPos ]; + + if ( 'p' == c ) + { + // %per; + + if ( nPos > nEnd - 4 ) + { + OSL_ENSURE( sal_False, + "UCBDeadPropertyValue::decodeValue - syntax error!" ); + return rtl::OUString(); + } + + if ( ( 'e' == pValue[ nPos + 1 ] ) + && + ( 'r' == pValue[ nPos + 2 ] ) + && + ( ';' == pValue[ nPos + 3 ] ) ) + { + aResult.append( sal_Unicode( '%' ) ); + nPos += 3; + } + else + { + OSL_ENSURE( sal_False, + "UCBDeadPropertyValue::decodeValue - syntax error!" ); + return rtl::OUString(); + } + } + else if ( 'l' == c ) + { + // %lt; + + if ( nPos > nEnd - 3 ) + { + OSL_ENSURE( sal_False, + "UCBDeadPropertyValue::decodeValue - syntax error!" ); + return rtl::OUString(); + } + + if ( ( 't' == pValue[ nPos + 1 ] ) + && + ( ';' == pValue[ nPos + 2 ] ) ) + { + aResult.append( sal_Unicode( '<' ) ); + nPos += 2; + } + else + { + OSL_ENSURE( sal_False, + "UCBDeadPropertyValue::decodeValue - syntax error!" ); + return rtl::OUString(); + } + } + else if ( 'g' == c ) + { + // %gt; + + if ( nPos > nEnd - 3 ) + { + OSL_ENSURE( sal_False, + "UCBDeadPropertyValue::decodeValue - syntax error!" ); + return rtl::OUString(); + } + + if ( ( 't' == pValue[ nPos + 1 ] ) + && + ( ';' == pValue[ nPos + 2 ] ) ) + { + aResult.append( sal_Unicode( '>' ) ); + nPos += 2; + } + else + { + OSL_ENSURE( sal_False, + "UCBDeadPropertyValue::decodeValue - syntax error!" ); + return rtl::OUString(); + } + } + else + { + OSL_ENSURE( sal_False, + "UCBDeadPropertyValue::decodeValue - syntax error!" ); + return rtl::OUString(); + } + } + else + aResult.append( c ); + + nPos++; + } + + return rtl::OUString( aResult ); +} + +////////////////////////////////////////////////////////////////////////// +// static +bool UCBDeadPropertyValue::supportsType( const uno::Type & rType ) +{ + if ( ( rType != getCppuType( static_cast< const rtl::OUString * >( 0 ) ) ) + && + ( rType != getCppuType( static_cast< const sal_Int32 * >( 0 ) ) ) + && + ( rType != getCppuType( static_cast< const sal_Int16 * >( 0 ) ) ) + && + ( rType != getCppuBooleanType() ) + && + ( rType != getCppuCharType() ) + && + ( rType != getCppuType( static_cast< const sal_Int8 * >( 0 ) ) ) + && + ( rType != getCppuType( static_cast< const sal_Int64 * >( 0 ) ) ) + && + ( rType != getCppuType( static_cast< const float * >( 0 ) ) ) + && + ( rType != getCppuType( static_cast< const double * >( 0 ) ) ) ) + { + return false; + } + + return true; +} + +////////////////////////////////////////////////////////////////////////// +// static +bool UCBDeadPropertyValue::createFromXML( const rtl::OString & rInData, + uno::Any & rOutData ) +{ + bool success = false; + + ne_xml_parser * parser = ne_xml_create(); + if ( parser ) + { + UCBDeadPropertyValueParseContext aCtx; + ne_xml_push_handler( parser, + UCBDeadPropertyValue_startelement_callback, + UCBDeadPropertyValue_chardata_callback, + UCBDeadPropertyValue_endelement_callback, + &aCtx ); + + ne_xml_parse( parser, rInData.getStr(), rInData.getLength() ); + +#if NEON_VERSION >= 0x0250 + success = !ne_xml_failed( parser ); +#else + success = !!ne_xml_valid( parser ); +#endif + + ne_xml_destroy( parser ); + + if ( success ) + { + if ( aCtx.pType && aCtx.pValue ) + { + // Decode aCtx.pValue! It may contain XML reserved chars. + rtl::OUString aStringValue = decodeValue( *aCtx.pValue ); + if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeString ) ) + { + rOutData <<= aStringValue; + } + else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeLong ) ) + { + rOutData <<= aStringValue.toInt32(); + } + else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeShort ) ) + { + rOutData <<= sal_Int16( aStringValue.toInt32() ); + } + else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeBoolean ) ) + { + if ( aStringValue.equalsIgnoreAsciiCase( + rtl::OUString::createFromAscii( "true" ) ) ) + rOutData <<= sal_Bool( sal_True ); + else + rOutData <<= sal_Bool( sal_False ); + } + else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeChar ) ) + { + rOutData <<= aStringValue.toChar(); + } + else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeByte ) ) + { + rOutData <<= sal_Int8( aStringValue.toChar() ); + } + else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeHyper ) ) + { + rOutData <<= aStringValue.toInt64(); + } + else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeFloat ) ) + { + rOutData <<= aStringValue.toFloat(); + } + else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeDouble ) ) + { + rOutData <<= aStringValue.toDouble(); + } + else + { + OSL_ENSURE( sal_False, + "UCBDeadPropertyValue::createFromXML - " + "Unsupported property type!" ); + success = false; + } + } + else + success = false; + } + } + + return success; +} + +////////////////////////////////////////////////////////////////////////// +// static +bool UCBDeadPropertyValue::toXML( const uno::Any & rInData, + rtl::OUString & rOutData ) +{ + // <ucbprop><type>the_type</type><value>the_value</value></ucbprop> + + // Check property type. Extract type and value as string. + + const uno::Type& rType = rInData.getValueType(); + rtl::OUString aStringValue; + rtl::OUString aStringType; + + if ( rType == getCppuType( static_cast< const rtl::OUString * >( 0 ) ) ) + { + // string + rInData >>= aStringValue; + aStringType = aTypeString; + } + else if ( rType == getCppuType( static_cast< const sal_Int32 * >( 0 ) ) ) + { + // long + sal_Int32 nValue = 0; + rInData >>= nValue; + aStringValue = rtl::OUString::valueOf( nValue ); + aStringType = aTypeLong; + } + else if ( rType == getCppuType( static_cast< const sal_Int16 * >( 0 ) ) ) + { + // short + sal_Int32 nValue = 0; + rInData >>= nValue; + aStringValue = rtl::OUString::valueOf( nValue ); + aStringType = aTypeShort; + } + else if ( rType == getCppuBooleanType() ) + { + // boolean + sal_Bool bValue = false; + rInData >>= bValue; + aStringValue = rtl::OUString::valueOf( bValue ); + aStringType = aTypeBoolean; + } + else if ( rType == getCppuCharType() ) + { + // char + sal_Unicode cValue = 0; + rInData >>= cValue; + aStringValue = rtl::OUString::valueOf( cValue ); + aStringType = aTypeChar; + } + else if ( rType == getCppuType( static_cast< const sal_Int8 * >( 0 ) ) ) + { + // byte + sal_Int8 nValue = 0; + rInData >>= nValue; + aStringValue = rtl::OUString::valueOf( sal_Unicode( nValue ) ); + aStringType = aTypeByte; + } + else if ( rType == getCppuType( static_cast< const sal_Int64 * >( 0 ) ) ) + { + // hyper + sal_Int64 nValue = 0; + rInData >>= nValue; + aStringValue = rtl::OUString::valueOf( nValue ); + aStringType = aTypeHyper; + } + else if ( rType == getCppuType( static_cast< const float * >( 0 ) ) ) + { + // float + float nValue = 0; + rInData >>= nValue; + aStringValue = rtl::OUString::valueOf( nValue ); + aStringType = aTypeFloat; + } + else if ( rType == getCppuType( static_cast< const double * >( 0 ) ) ) + { + // double + double nValue = 0; + rInData >>= nValue; + aStringValue = rtl::OUString::valueOf( nValue ); + aStringType = aTypeDouble; + } + else + { + OSL_ENSURE( sal_False, + "UCBDeadPropertyValue::toXML - " + "Unsupported property type!" ); + return false; + } + + // Encode value! It must not contain XML reserved chars! + aStringValue = encodeValue( aStringValue ); + + rOutData = aXMLPre; + rOutData += aStringType; + rOutData += aXMLMid; + rOutData += aStringValue; + rOutData += aXMLEnd; + + return true; +} diff --git a/ucb/source/ucp/webdav/UCBDeadPropertyValue.hxx b/ucb/source/ucp/webdav/UCBDeadPropertyValue.hxx new file mode 100644 index 000000000000..69dc5d3c80bf --- /dev/null +++ b/ucb/source/ucp/webdav/UCBDeadPropertyValue.hxx @@ -0,0 +1,65 @@ +/************************************************************************* + * + * 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 _UCBDEADPROPERTYVALUE_HXX_ +#define _UCBDEADPROPERTYVALUE_HXX_ + +#include <rtl/string.hxx> +#include <com/sun/star/uno/Any.hxx> + +namespace webdav_ucp +{ + +class UCBDeadPropertyValue +{ +private: + static const rtl::OUString aTypeString; + static const rtl::OUString aTypeLong; + static const rtl::OUString aTypeShort; + static const rtl::OUString aTypeBoolean; + static const rtl::OUString aTypeChar; + static const rtl::OUString aTypeByte; + static const rtl::OUString aTypeHyper; + static const rtl::OUString aTypeFloat; + static const rtl::OUString aTypeDouble; + + static const rtl::OUString aXMLPre; + static const rtl::OUString aXMLMid; + static const rtl::OUString aXMLEnd; + +public: + static bool supportsType( const com::sun::star::uno::Type & rType ); + + static bool createFromXML( const rtl::OString & rInData, + com::sun::star::uno::Any & rOutData ); + static bool toXML( const com::sun::star::uno::Any & rInData, + rtl::OUString & rOutData ); +}; + +} + +#endif /* _UCBDEADPROPERTYVALUE_HXX_ */ diff --git a/ucb/source/ucp/webdav/makefile.mk b/ucb/source/ucp/webdav/makefile.mk new file mode 100644 index 000000000000..162d58266406 --- /dev/null +++ b/ucb/source/ucp/webdav/makefile.mk @@ -0,0 +1,168 @@ +#************************************************************************* +# +# 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. +# +#************************************************************************* + +# UCP Version - Increase, if UCP libraray becomes incompatible. +UCP_VERSION=1 + +# Name for the UCP. Will become part of the library name (See below). +UCP_NAME=dav + +# Relative path to project root. +PRJ = ..$/..$/.. + +# Project Name. +PRJNAME=ucb + +TARGET=ucp$(UCP_NAME) + +ENABLE_EXCEPTIONS=TRUE +USE_DEFFILE=TRUE +NO_BSYMBOLIC=TRUE + +# --- Settings --------------------------------------------------------- + +.INCLUDE: settings.mk +.IF "$(L10N_framework)"=="" + +.IF "$(DISABLE_NEON)" == "TRUE" + +@all: + @echo "neon disabled...." + +.ELSE + +NEONINCDIR=external$/neon + +.IF "$(SYSTEM_NEON)" != "YES" +.INCLUDE: $(SOLARINCDIR)$/$(NEONINCDIR)$/version.mk +.ENDIF + +CFLAGS+= -DNEON_VERSION=0x$(NEON_VERSION) + +.IF "$(SYSTEM_NEON)" == "YES" +CFLAGS+= $(NEON_CFLAGS) +.ELSE +CFLAGS+= -I$(SOLARINCDIR)$/$(NEONINCDIR) +.ENDIF + +.IF "$(SYSTEM_LIBXML)" == "YES" +CFLAGS+= $(LIBXML_CFLAGS) +.ELSE +LIBXMLINCDIR=external$/libxml +CFLAGS+= -I$(SOLARINCDIR)$/$(LIBXMLINCDIR) +.ENDIF + +.IF "$(SYSTEM_OPENSSL)" == "YES" +CFLAGS+= $(OPENSSL_CFLAGS) +.ENDIF + +# --- General ----------------------------------------------------- + +SLOFILES=\ + $(SLO)$/webdavservices.obj \ + $(SLO)$/webdavprovider.obj \ + $(SLO)$/webdavcontent.obj \ + $(SLO)$/webdavcontentcaps.obj \ + $(SLO)$/webdavresultset.obj \ + $(SLO)$/webdavdatasupplier.obj \ + $(SLO)$/ContentProperties.obj \ + $(SLO)$/DAVProperties.obj \ + $(SLO)$/DAVSessionFactory.obj \ + $(SLO)$/DAVResourceAccess.obj \ + $(SLO)$/NeonUri.obj \ + $(SLO)$/NeonInputStream.obj \ + $(SLO)$/NeonPropFindRequest.obj \ + $(SLO)$/NeonHeadRequest.obj \ + $(SLO)$/NeonSession.obj \ + $(SLO)$/NeonLockStore.obj \ + $(SLO)$/DateTimeHelper.obj \ + $(SLO)$/LinkSequence.obj \ + $(SLO)$/LockSequence.obj \ + $(SLO)$/LockEntrySequence.obj \ + $(SLO)$/UCBDeadPropertyValue.obj + +LIB1TARGET=$(SLB)$/_$(TARGET).lib +LIB1OBJFILES=$(SLOFILES) + +# --- Shared-Library --------------------------------------------------- + +SHL1TARGET=$(TARGET)$(UCP_VERSION) +SHL1IMPLIB=i$(TARGET) + +SHL1VERSIONMAP=$(SOLARENV)/src/component.map + +SHL1STDLIBS=\ + $(CPPUHELPERLIB) \ + $(CPPULIB) \ + $(SALLIB) \ + $(SALHELPERLIB) \ + $(UCBHELPERLIB) \ + $(COMPHELPERLIB) \ + $(NEON3RDLIB) \ + $(LIBXML2LIB) + +.IF "$(GUI)"=="WNT" +SHL1STDLIBS+= $(WSOCK32LIB) +.IF "$(WINDOWS_VISTA_PSDK)" != "" +SHL1STDLIBS+= $(WS2_32LIB) +.ENDIF +SHL1STDLIBS+= $(OPENSSLLIB) +.ELSE # WNT +.IF "$(OS)"=="SOLARIS" +SHL1STDLIBS+= -lnsl -lsocket -ldl +.ENDIF # SOLARIS +.IF "$(OS)"=="OS2" +SHL1STDLIBS+= pthread.lib libz.lib +.ENDIF # OS2 +.IF "$(SYSTEM_OPENSSL)"=="YES" +SHL1STDLIBS+= $(OPENSSLLIB) +.ELSE +SHL1STDLIBS+= $(OPENSSLLIBST) +.ENDIF +.ENDIF # WNT + +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +SHL1LIBS=$(LIB1TARGET) + +# --- Def-File --------------------------------------------------------- + +DEF1NAME=$(SHL1TARGET) + +.ENDIF #"$(DISABLE_NEON)" == "TRUE" + +.ENDIF # L10N_framework +# --- Targets ---------------------------------------------------------- + +.INCLUDE: target.mk + +ALLTAR : $(MISC)/ucpdav1.component + +$(MISC)/ucpdav1.component .ERRREMOVE : $(SOLARENV)/bin/createcomponent.xslt \ + ucpdav1.component + $(XSLTPROC) --nonet --stringparam uri \ + '$(COMPONENTPREFIX_BASIS_NATIVE)$(SHL1TARGETN:f)' -o $@ \ + $(SOLARENV)/bin/createcomponent.xslt ucpdav1.component diff --git a/ucb/source/ucp/webdav/ucpdav.xml b/ucb/source/ucp/webdav/ucpdav.xml new file mode 100644 index 000000000000..ccb993b3138c --- /dev/null +++ b/ucb/source/ucp/webdav/ucpdav.xml @@ -0,0 +1,109 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE module-description PUBLIC "-//StarOffice//DTD ComponentDescription 1.0//EN" "module-description.dtd"> +<module-description xmlns:xlink="http://www.w3.org/1999/xlink"> + + <module-name> + ucpdav + </module-name> + + <component-description> + <author> + Kai Sommerfeld + </author> + <name> + com.sun.star.comp.ucb.WebDAVContentProvider + </name> + <description> + This component implements a Content Provider for the Universal + Content Broker. It provides access to contents stored on an HTTP/WebDAV + server. + </description> + <loader-name> + com.sun.star.loader.SharedLibrary + </loader-name> + <language> + c++ + </language> + <status value="final"/> + <supported-service> + com.sun.star.ucb.WebDAVContentProvider + </supported-service> + </component-description> + + <project-build-dependency> external </project-build-dependency> + <project-build-dependency> sal </project-build-dependency> + <project-build-dependency> cppu </project-build-dependency> + <project-build-dependency> cppuhelper </project-build-dependency> + <project-build-dependency> ucbhelper </project-build-dependency> + + <runtime-module-dependency> sal3 </runtime-module-dependency> + <runtime-module-dependency> cppu3 </runtime-module-dependency> + <runtime-module-dependency> cppuhelper3$(COM) </runtime-module-dependency> + <runtime-module-dependency> ucbhelper4$(COM) </runtime-module-dependency> + + <type> com.sun.star.beans.PropertyAttribute </type> + <type> com.sun.star.beans.PropertyValue </type> + <type> com.sun.star.beans.XPropertiesChangeNotifier </type> + <type> com.sun.star.beans.XPropertyAccess </type> + <type> com.sun.star.beans.XPropertyContainer </type> + <type> com.sun.star.beans.XPropertySetInfoChangeNotifier </type> + <type> com.sun.star.container.XChild </type> + <type> com.sun.star.io.XActiveDataSink </type> + <type> com.sun.star.io.XInputStream </type> + <type> com.sun.star.io.XOutputStream </type> + <type> com.sun.star.io.XSeekable </type> + <type> com.sun.star.lang.IllegalAccessException </type> + <type> com.sun.star.lang.XComponent </type> + <type> com.sun.star.lang.XMultiServiceFactory </type> + <type> com.sun.star.lang.XServiceInfo </type> + <type> com.sun.star.lang.XSingleServiceFactory </type> + <type> com.sun.star.lang.XTypeProvider </type> + <type> com.sun.star.registry.XRegistryKey </type> + <type> com.sun.star.sdbc.XCloseable </type> + <type> com.sun.star.sdbc.XColumnLocate </type> + <type> com.sun.star.sdbc.XResultSetMetaDataSupplier </type> + <type> com.sun.star.sdbc.XRow </type> + <type> com.sun.star.task.InteractionClassification </type> + <type> com.sun.star.task.XInteractionAbort </type> + <type> com.sun.star.task.XInteractionReply </type> + <type> com.sun.star.ucb.AuthenticationRequest </type> + <type> com.sun.star.ucb.CommandFailedException </type> + <type> com.sun.star.ucb.ContentCreationException </type> + <type> com.sun.star.ucb.ContentInfoAttribute </type> + <type> com.sun.star.ucb.InsertCommandArgument </type> + <type> com.sun.star.ucb.InteractiveAugmentedIOException </type> + <type> com.sun.star.ucb.InteractiveBadTransferURLException </type> + <type> com.sun.star.ucb.InteractiveNetworkConnectException </type> + <type> com.sun.star.ucb.InteractiveNetworkGeneralException </type> + <type> com.sun.star.ucb.InteractiveNetworkReadException </type> + <type> com.sun.star.ucb.InteractiveNetworkResolveNameException </type> + <type> com.sun.star.ucb.InteractiveNetworkWriteException </type> + <type> com.sun.star.ucb.Link </type> + <type> com.sun.star.ucb.Lock </type> + <type> com.sun.star.ucb.MissingInputStreamException </type> + <type> com.sun.star.ucb.MissingPropertiesException </type> + <type> com.sun.star.ucb.NameClash </type> + <type> com.sun.star.ucb.NameClashException </type> + <type> com.sun.star.ucb.OpenCommandArgument2 </type> + <type> com.sun.star.ucb.OpenMode </type> + <type> com.sun.star.ucb.PostCommandArgument2 </type> + <type> com.sun.star.ucb.RememberAuthentication </type> + <type> com.sun.star.ucb.ResultSetException </type> + <type> com.sun.star.ucb.TransferInfo </type> + <type> com.sun.star.ucb.XCommandEnvironment </type> + <type> com.sun.star.ucb.UnsupportedCommandException </type> + <type> com.sun.star.ucb.UnsupportedDataSinkException </type> + <type> com.sun.star.ucb.UnsupportedNameClashException </type> + <type> com.sun.star.ucb.UnsupportedOpenModeException </type> + <type> com.sun.star.ucb.XCommandInfo </type> + <type> com.sun.star.ucb.XCommandInfoChangeNotifier </type> + <type> com.sun.star.ucb.XCommandProcessor </type> + <type> com.sun.star.ucb.XContentAccess </type> + <type> com.sun.star.ucb.XContentCreator </type> + <type> com.sun.star.ucb.XContentProvider </type> + <type> com.sun.star.ucb.XDynamicResultSet </type> + <type> com.sun.star.ucb.XInteractionSupplyAuthentication </type> + <type> com.sun.star.ucb.XPersistentPropertySet </type> + <type> com.sun.star.uno.XAggregation </type> + <type> com.sun.star.util.DateTime </type> +</module-description> diff --git a/ucb/source/ucp/webdav/ucpdav1.component b/ucb/source/ucp/webdav/ucpdav1.component new file mode 100644 index 000000000000..4e18b566e1a4 --- /dev/null +++ b/ucb/source/ucp/webdav/ucpdav1.component @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* 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. +* +**********************************************************************--> + +<component loader="com.sun.star.loader.SharedLibrary" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.WebDAVContentProvider"> + <service name="com.sun.star.ucb.WebDAVContentProvider"/> + </implementation> +</component> diff --git a/ucb/source/ucp/webdav/webdavcontent.cxx b/ucb/source/ucp/webdav/webdavcontent.cxx new file mode 100644 index 000000000000..26b2a044e7b6 --- /dev/null +++ b/ucb/source/ucp/webdav/webdavcontent.cxx @@ -0,0 +1,3247 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ + +#include <osl/diagnose.h> +#include "osl/doublecheckedlocking.h" +#include <rtl/uri.hxx> +#include <rtl/ustrbuf.hxx> +#include <ucbhelper/contentidentifier.hxx> +#include <ucbhelper/propertyvalueset.hxx> +#include <ucbhelper/simpleinteractionrequest.hxx> +#include <ucbhelper/cancelcommandexecution.hxx> + +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/beans/PropertySetInfoChange.hpp> +#include <com/sun/star/beans/PropertySetInfoChangeEvent.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/io/XActiveDataSink.hpp> +#include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/lang/IllegalAccessException.hpp> +#include <com/sun/star/task/PasswordContainerInteractionHandler.hpp> +#include <com/sun/star/ucb/CommandEnvironment.hpp> +#include <com/sun/star/ucb/CommandFailedException.hpp> +#include <com/sun/star/ucb/ContentInfoAttribute.hpp> +#include <com/sun/star/ucb/InsertCommandArgument.hpp> +#include <com/sun/star/ucb/InteractiveBadTransferURLException.hpp> +#include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp> +#include "com/sun/star/ucb/InteractiveLockingLockedException.hpp" +#include "com/sun/star/ucb/InteractiveLockingLockExpiredException.hpp" +#include "com/sun/star/ucb/InteractiveLockingNotLockedException.hpp" +#include <com/sun/star/ucb/InteractiveNetworkConnectException.hpp> +#include <com/sun/star/ucb/InteractiveNetworkGeneralException.hpp> +#include <com/sun/star/ucb/InteractiveNetworkReadException.hpp> +#include <com/sun/star/ucb/InteractiveNetworkResolveNameException.hpp> +#include <com/sun/star/ucb/InteractiveNetworkWriteException.hpp> +#include <com/sun/star/ucb/MissingInputStreamException.hpp> +#include <com/sun/star/ucb/MissingPropertiesException.hpp> +#include <com/sun/star/ucb/NameClash.hpp> +#include <com/sun/star/ucb/NameClashException.hpp> +#include <com/sun/star/ucb/OpenCommandArgument2.hpp> +#include <com/sun/star/ucb/OpenMode.hpp> +#include <com/sun/star/ucb/PostCommandArgument2.hpp> +#include <com/sun/star/ucb/TransferInfo.hpp> +#include <com/sun/star/ucb/UnsupportedCommandException.hpp> +#include <com/sun/star/ucb/UnsupportedDataSinkException.hpp> +#include <com/sun/star/ucb/UnsupportedNameClashException.hpp> +#include <com/sun/star/ucb/UnsupportedOpenModeException.hpp> +#include <com/sun/star/ucb/XCommandInfo.hpp> +#include <com/sun/star/ucb/XPersistentPropertySet.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> + +#include "webdavcontent.hxx" +#include "webdavprovider.hxx" +#include "webdavresultset.hxx" +#include "ContentProperties.hxx" +#include "NeonUri.hxx" +#include "UCBDeadPropertyValue.hxx" + +using namespace com::sun::star; +using namespace webdav_ucp; + +//========================================================================= +//========================================================================= +// +// Content Implementation. +// +//========================================================================= +//========================================================================= + +//========================================================================= +// ctr for content on an existing webdav resource +Content::Content( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + ContentProvider* pProvider, + const uno::Reference< ucb::XContentIdentifier >& Identifier, + rtl::Reference< DAVSessionFactory > const & rSessionFactory ) + throw ( ucb::ContentCreationException ) +: ContentImplHelper( rxSMgr, pProvider, Identifier ), + m_eResourceType( UNKNOWN ), + m_pProvider( pProvider ), + m_bTransient( false ), + m_bCollection( false ), + m_bDidGetOrHead( false ) +{ + try + { + m_xResAccess.reset( new DAVResourceAccess( + rxSMgr, + rSessionFactory, + Identifier->getContentIdentifier() ) ); + + NeonUri aURI( Identifier->getContentIdentifier() ); + m_aEscapedTitle = aURI.GetPathBaseName(); + } + catch ( DAVException const & ) + { + throw ucb::ContentCreationException(); + } +} + +//========================================================================= +// ctr for content on an non-existing webdav resource +Content::Content( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + ContentProvider* pProvider, + const uno::Reference< ucb::XContentIdentifier >& Identifier, + rtl::Reference< DAVSessionFactory > const & rSessionFactory, + sal_Bool isCollection ) + throw ( ucb::ContentCreationException ) +: ContentImplHelper( rxSMgr, pProvider, Identifier ), + m_eResourceType( UNKNOWN ), + m_pProvider( pProvider ), + m_bTransient( true ), + m_bCollection( isCollection ), + m_bDidGetOrHead( false ) +{ + try + { + m_xResAccess.reset( new DAVResourceAccess( + rxSMgr, rSessionFactory, Identifier->getContentIdentifier() ) ); + } + catch ( DAVException const & ) + { + throw ucb::ContentCreationException(); + } + + // Do not set m_aEscapedTitle here! Content::insert relays on this!!! +} + +//========================================================================= +// virtual +Content::~Content() +{ +} + +//========================================================================= +// +// XInterface methods. +// +//========================================================================= + +// virtual +void SAL_CALL Content::acquire() + throw( ) +{ + ContentImplHelper::acquire(); +} + +//========================================================================= +// virtual +void SAL_CALL Content::release() + throw( ) +{ + ContentImplHelper::release(); +} + +//========================================================================= +// virtual +uno::Any SAL_CALL Content::queryInterface( const uno::Type & rType ) + throw ( uno::RuntimeException ) +{ + // Note: isFolder may require network activities! So call it only + // if it is really necessary!!! + uno::Any aRet = cppu::queryInterface( + rType, + static_cast< ucb::XContentCreator * >( this ) ); + if ( aRet.hasValue() ) + { + try + { + uno::Reference< beans::XPropertySet > const xProps( + m_xSMgr, uno::UNO_QUERY_THROW ); + uno::Reference< uno::XComponentContext > xCtx; + xCtx.set( xProps->getPropertyValue( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ) ) ), + uno::UNO_QUERY_THROW ); + + uno::Reference< task::XInteractionHandler > xIH( + task::PasswordContainerInteractionHandler::create( xCtx ) ); + + // Supply a command env to isFolder() that contains an interaction + // handler that uses the password container service to obtain + // credentials without displaying a password gui. + + uno::Reference< ucb::XCommandEnvironment > xCmdEnv( + ucb::CommandEnvironment::create( + xCtx, + xIH, + uno::Reference< ucb::XProgressHandler >() ) ); + + return isFolder( xCmdEnv ) ? aRet : uno::Any(); + } + catch ( uno::RuntimeException const & ) + { + throw; + } + catch ( uno::Exception const & ) + { + return uno::Any(); + } + } + return aRet.hasValue() ? aRet : ContentImplHelper::queryInterface( rType ); +} + +//========================================================================= +// +// XTypeProvider methods. +// +//========================================================================= + +XTYPEPROVIDER_COMMON_IMPL( Content ); + +//========================================================================= +// virtual +uno::Sequence< uno::Type > SAL_CALL Content::getTypes() + throw( uno::RuntimeException ) +{ + sal_Bool bFolder = sal_False; + try + { + bFolder + = isFolder( uno::Reference< ucb::XCommandEnvironment >() ); + } + catch ( uno::RuntimeException const & ) + { + throw; + } + catch ( uno::Exception const & ) + { + } + + cppu::OTypeCollection * pCollection = 0; + + if ( bFolder ) + { + static cppu::OTypeCollection* pFolderTypes = 0; + + pCollection = pFolderTypes; + if ( !pCollection ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + + pCollection = pFolderTypes; + if ( !pCollection ) + { + static cppu::OTypeCollection aCollection( + CPPU_TYPE_REF( lang::XTypeProvider ), + CPPU_TYPE_REF( lang::XServiceInfo ), + CPPU_TYPE_REF( lang::XComponent ), + CPPU_TYPE_REF( ucb::XContent ), + CPPU_TYPE_REF( ucb::XCommandProcessor ), + CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ), + CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ), + CPPU_TYPE_REF( beans::XPropertyContainer ), + CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ), + CPPU_TYPE_REF( container::XChild ), + CPPU_TYPE_REF( ucb::XContentCreator ) ); // !! + pCollection = &aCollection; + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + pFolderTypes = pCollection; + } + } + else { + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + } + } + else + { + static cppu::OTypeCollection* pDocumentTypes = 0; + + pCollection = pDocumentTypes; + if ( !pCollection ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + + pCollection = pDocumentTypes; + if ( !pCollection ) + { + static cppu::OTypeCollection aCollection( + CPPU_TYPE_REF( lang::XTypeProvider ), + CPPU_TYPE_REF( lang::XServiceInfo ), + CPPU_TYPE_REF( lang::XComponent ), + CPPU_TYPE_REF( ucb::XContent ), + CPPU_TYPE_REF( ucb::XCommandProcessor ), + CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ), + CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ), + CPPU_TYPE_REF( beans::XPropertyContainer ), + CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ), + CPPU_TYPE_REF( container::XChild ) ); + pCollection = &aCollection; + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + pDocumentTypes = pCollection; + } + } + else { + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + } + } + + return (*pCollection).getTypes(); +} + +//========================================================================= +// +// XServiceInfo methods. +// +//========================================================================= + +// virtual +rtl::OUString SAL_CALL Content::getImplementationName() + throw( uno::RuntimeException ) +{ + return rtl::OUString::createFromAscii( + "com.sun.star.comp.ucb.WebDAVContent" ); +} + +//========================================================================= +// virtual +uno::Sequence< rtl::OUString > SAL_CALL Content::getSupportedServiceNames() + throw( uno::RuntimeException ) +{ + uno::Sequence< rtl::OUString > aSNS( 1 ); + aSNS.getArray()[ 0 ] + = rtl::OUString::createFromAscii( WEBDAV_CONTENT_SERVICE_NAME ); + return aSNS; +} + +//========================================================================= +// +// XContent methods. +// +//========================================================================= + +// virtual +rtl::OUString SAL_CALL Content::getContentType() + throw( uno::RuntimeException ) +{ + sal_Bool bFolder = sal_False; + try + { + bFolder + = isFolder( uno::Reference< ucb::XCommandEnvironment >() ); + } + catch ( uno::RuntimeException const & ) + { + throw; + } + catch ( uno::Exception const & ) + { + } + + if ( bFolder ) + return rtl::OUString::createFromAscii( WEBDAV_COLLECTION_TYPE ); + + return rtl::OUString::createFromAscii( WEBDAV_CONTENT_TYPE ); +} + +//========================================================================= +// +// XCommandProcessor methods. +// +//========================================================================= + +// virtual +uno::Any SAL_CALL Content::execute( + const ucb::Command& aCommand, + sal_Int32 /*CommandId*/, + const uno::Reference< ucb::XCommandEnvironment >& Environment ) + throw( uno::Exception, + ucb::CommandAbortedException, + uno::RuntimeException ) +{ + OSL_TRACE( ">>>>> Content::execute: start: command: %s, env: %s", + rtl::OUStringToOString( aCommand.Name, + RTL_TEXTENCODING_UTF8 ).getStr(), + Environment.is() ? "present" : "missing" ); + + uno::Any aRet; + + if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "getPropertyValues" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // getPropertyValues + ////////////////////////////////////////////////////////////////// + + uno::Sequence< beans::Property > Properties; + if ( !( aCommand.Argument >>= Properties ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Wrong argument type!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + aRet <<= getPropertyValues( Properties, Environment ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "setPropertyValues" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // setPropertyValues + ////////////////////////////////////////////////////////////////// + + uno::Sequence< beans::PropertyValue > aProperties; + if ( !( aCommand.Argument >>= aProperties ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Wrong argument type!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + if ( !aProperties.getLength() ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "No properties!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + aRet <<= setPropertyValues( aProperties, Environment ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "getPropertySetInfo" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // getPropertySetInfo + ////////////////////////////////////////////////////////////////// + + // Note: Implemented by base class. + aRet <<= getPropertySetInfo( Environment, + sal_False /* don't cache data */ ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "getCommandInfo" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // getCommandInfo + ////////////////////////////////////////////////////////////////// + + // Note: Implemented by base class. + aRet <<= getCommandInfo( Environment, sal_False ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "open" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // open + ////////////////////////////////////////////////////////////////// + + ucb::OpenCommandArgument2 aOpenCommand; + if ( !( aCommand.Argument >>= aOpenCommand ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Wrong argument type!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + aRet = open( aOpenCommand, Environment ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "insert" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // insert + ////////////////////////////////////////////////////////////////// + + ucb::InsertCommandArgument arg; + if ( !( aCommand.Argument >>= arg ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Wrong argument type!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + insert( arg.Data, arg.ReplaceExisting, Environment ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "delete" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // delete + ////////////////////////////////////////////////////////////////// + + sal_Bool bDeletePhysical = sal_False; + aCommand.Argument >>= bDeletePhysical; + +// KSO: Ignore parameter and destroy the content, if you don't support +// putting objects into trashcan. ( Since we do not have a trash can +// service yet (src603), you actually have no other choice. ) +// if ( bDeletePhysical ) +// { + try + { + std::auto_ptr< DAVResourceAccess > xResAccess; + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) ); + } + xResAccess->DESTROY( Environment ); + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) ); + } + } + catch ( DAVException const & e ) + { + cancelCommandExecution( e, Environment, sal_True ); + // Unreachable + } +// } + + // Propagate destruction. + destroy( bDeletePhysical ); + + // Remove own and all children's Additional Core Properties. + removeAdditionalPropertySet( sal_True ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "transfer" ) ) + && isFolder( Environment ) ) + { + ////////////////////////////////////////////////////////////////// + // transfer + // ( Not available at documents ) + ////////////////////////////////////////////////////////////////// + + ucb::TransferInfo transferArgs; + if ( !( aCommand.Argument >>= transferArgs ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Wrong argument type!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + transfer( transferArgs, Environment ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "post" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // post + ////////////////////////////////////////////////////////////////// + + ucb::PostCommandArgument2 aArg; + if ( !( aCommand.Argument >>= aArg ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Wrong argument type!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + post( aArg, Environment ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "lock" ) ) && + supportsExclusiveWriteLock( Environment ) ) + { + ////////////////////////////////////////////////////////////////// + // lock + ////////////////////////////////////////////////////////////////// + + lock( Environment ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "unlock" ) ) && + supportsExclusiveWriteLock( Environment ) ) + { + ////////////////////////////////////////////////////////////////// + // unlock + ////////////////////////////////////////////////////////////////// + + unlock( Environment ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "createNewContent" ) ) && + isFolder( Environment ) ) + { + ////////////////////////////////////////////////////////////////// + // createNewContent + ////////////////////////////////////////////////////////////////// + + ucb::ContentInfo aArg; + if ( !( aCommand.Argument >>= aArg ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Wrong argument type!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + aRet = uno::makeAny( createNewContent( aArg ) ); + } + else + { + ////////////////////////////////////////////////////////////////// + // Unsupported command + ////////////////////////////////////////////////////////////////// + + ucbhelper::cancelCommandExecution( + uno::makeAny( ucb::UnsupportedCommandException( + aCommand.Name, + static_cast< cppu::OWeakObject * >( this ) ) ), + Environment ); + // Unreachable + } + + OSL_TRACE( "<<<<< Content::execute: end: command: %s", + rtl::OUStringToOString( aCommand.Name, + RTL_TEXTENCODING_UTF8 ).getStr() ); + + return aRet; +} + +//========================================================================= +// virtual +void SAL_CALL Content::abort( sal_Int32 /*CommandId*/ ) + throw( uno::RuntimeException ) +{ + try + { + std::auto_ptr< DAVResourceAccess > xResAccess; + { + osl::MutexGuard aGuard( m_aMutex ); + xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) ); + } + xResAccess->abort(); + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) ); + } + } + catch ( DAVException const & ) + { + // abort failed! + } +} + +//========================================================================= +// +// XPropertyContainer methods. +// +//========================================================================= + +// virtual +void SAL_CALL Content::addProperty( const rtl::OUString& Name, + sal_Int16 Attributes, + const uno::Any& DefaultValue ) + throw( beans::PropertyExistException, + beans::IllegalTypeException, + lang::IllegalArgumentException, + uno::RuntimeException ) +{ +// if ( m_bTransient ) +// @@@ ??? + + if ( !Name.getLength() ) + throw lang::IllegalArgumentException(); + + // Check property type. + if ( !UCBDeadPropertyValue::supportsType( DefaultValue.getValueType() ) ) + { + OSL_ENSURE( sal_False, + "Content::addProperty - Unsupported property type!" ); + throw beans::IllegalTypeException(); + } + + ////////////////////////////////////////////////////////////////////// + // Make sure a property with the requested name does not already + // exist in dynamic and static(!) properties. + ////////////////////////////////////////////////////////////////////// + + // @@@ Need real command environment here, but where to get it from? + // XPropertyContainer interface should be replaced by + // XCommandProcessor commands! + uno::Reference< ucb::XCommandEnvironment > xEnv; + + // Note: This requires network access! + if ( getPropertySetInfo( xEnv, sal_False /* don't cache data */ ) + ->hasPropertyByName( Name ) ) + { + // Property does already exist. + throw beans::PropertyExistException(); + } + + ////////////////////////////////////////////////////////////////////// + // Add a new dynamic property. + ////////////////////////////////////////////////////////////////////// + + ProppatchValue aValue( PROPSET, Name, DefaultValue ); + + std::vector< ProppatchValue > aProppatchValues; + aProppatchValues.push_back( aValue ); + + try + { + // Set property value at server. + std::auto_ptr< DAVResourceAccess > xResAccess; + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) ); + } + xResAccess->PROPPATCH( aProppatchValues, xEnv ); + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) ); + } + + // Notify propertyset info change listeners. + beans::PropertySetInfoChangeEvent evt( + static_cast< cppu::OWeakObject * >( this ), + Name, + -1, // No handle available + beans::PropertySetInfoChange::PROPERTY_INSERTED ); + notifyPropertySetInfoChange( evt ); + } + catch ( DAVException const & e ) + { + if ( e.getStatus() == SC_FORBIDDEN ) + { + // Support for setting arbitrary dead properties is optional! + + // Store property locally. + ContentImplHelper::addProperty( + Name, Attributes, DefaultValue ); + } + else + { + if ( shouldAccessNetworkAfterException( e ) ) + { + try + { + const ResourceType & rType = getResourceType( xEnv ); + switch ( rType ) + { + case UNKNOWN: + case DAV: + throw lang::IllegalArgumentException(); + + case FTP: + case NON_DAV: + // Store property locally. + ContentImplHelper::addProperty( Name, + Attributes, + DefaultValue ); + break; + + default: + OSL_ENSURE( sal_False, + "Content::addProperty - " + "Unsupported resource type!" ); + break; + } + } + catch ( uno::Exception const & ) + { + OSL_ENSURE( sal_False, + "Content::addProperty - " + "Unable to determine resource type!" ); + } + } + else + { + OSL_ENSURE( sal_False, + "Content::addProperty - " + "Unable to determine resource type!" ); + } + } + } +} + +//========================================================================= +// virtual +void SAL_CALL Content::removeProperty( const rtl::OUString& Name ) + throw( beans::UnknownPropertyException, + beans::NotRemoveableException, + uno::RuntimeException ) +{ + // @@@ Need real command environment here, but where to get it from? + // XPropertyContainer interface should be replaced by + // XCommandProcessor commands! + uno::Reference< ucb::XCommandEnvironment > xEnv; + +#if 0 + // @@@ REMOVEABLE z.Z. nicht richtig an der PropSetInfo gesetzt!!! + try + { + beans::Property aProp + = getPropertySetInfo( xEnv, sal_False /* don't cache data */ ) + ->getPropertyByName( Name ); + + if ( !( aProp.Attributes & beans::PropertyAttribute::REMOVEABLE ) ) + { + // Not removeable! + throw beans::NotRemoveableException(); + } + } + catch ( beans::UnknownPropertyException const & ) + { + //OSL_ENSURE( sal_False, "removeProperty - Unknown property!" ); + throw; + } +#endif + + ////////////////////////////////////////////////////////////////////// + // Try to remove property from server. + ////////////////////////////////////////////////////////////////////// + + try + { + std::vector< ProppatchValue > aProppatchValues; + ProppatchValue aValue( PROPREMOVE, Name, uno::Any() ); + aProppatchValues.push_back( aValue ); + + // Remove property value from server. + std::auto_ptr< DAVResourceAccess > xResAccess; + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) ); + } + xResAccess->PROPPATCH( aProppatchValues, xEnv ); + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) ); + } + + // Notify propertyset info change listeners. + beans::PropertySetInfoChangeEvent evt( + static_cast< cppu::OWeakObject * >( this ), + Name, + -1, // No handle available + beans::PropertySetInfoChange::PROPERTY_REMOVED ); + notifyPropertySetInfoChange( evt ); + } + catch ( DAVException const & e ) + { + if ( e.getStatus() == SC_FORBIDDEN ) + { + // Support for setting arbitrary dead properties is optional! + + // Try to remove property from local store. + ContentImplHelper::removeProperty( Name ); + } + else + { + if ( shouldAccessNetworkAfterException( e ) ) + { + try + { + const ResourceType & rType = getResourceType( xEnv ); + switch ( rType ) + { + case UNKNOWN: + case DAV: + throw beans::UnknownPropertyException(); + + case FTP: + case NON_DAV: + // Try to remove property from local store. + ContentImplHelper::removeProperty( Name ); + break; + + default: + OSL_ENSURE( sal_False, + "Content::removeProperty - " + "Unsupported resource type!" ); + break; + } + } + catch ( uno::Exception const & ) + { + OSL_ENSURE( sal_False, + "Content::removeProperty - " + "Unable to determine resource type!" ); + } + } + else + { + OSL_ENSURE( sal_False, + "Content::removeProperty - " + "Unable to determine resource type!" ); +// throw beans::UnknownPropertyException(); + } + } + } +} + +//========================================================================= +// +// XContentCreator methods. +// +//========================================================================= + +// virtual +uno::Sequence< ucb::ContentInfo > SAL_CALL +Content::queryCreatableContentsInfo() + throw( uno::RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + uno::Sequence< ucb::ContentInfo > aSeq( 2 ); + + // document. + aSeq.getArray()[ 0 ].Type + = rtl::OUString::createFromAscii( WEBDAV_CONTENT_TYPE ); + aSeq.getArray()[ 0 ].Attributes + = ucb::ContentInfoAttribute::INSERT_WITH_INPUTSTREAM + | ucb::ContentInfoAttribute::KIND_DOCUMENT; + + beans::Property aProp; + m_pProvider->getProperty( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ), aProp ); + + uno::Sequence< beans::Property > aDocProps( 1 ); + aDocProps.getArray()[ 0 ] = aProp; + aSeq.getArray()[ 0 ].Properties = aDocProps; + + // folder. + aSeq.getArray()[ 1 ].Type + = rtl::OUString::createFromAscii( WEBDAV_COLLECTION_TYPE ); + aSeq.getArray()[ 1 ].Attributes + = ucb::ContentInfoAttribute::KIND_FOLDER; + + uno::Sequence< beans::Property > aFolderProps( 1 ); + aFolderProps.getArray()[ 0 ] = aProp; + aSeq.getArray()[ 1 ].Properties = aFolderProps; + return aSeq; +} + +//========================================================================= +// virtual +uno::Reference< ucb::XContent > SAL_CALL +Content::createNewContent( const ucb::ContentInfo& Info ) + throw( uno::RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + if ( !Info.Type.getLength() ) + return uno::Reference< ucb::XContent >(); + + if ( ( !Info.Type.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( WEBDAV_COLLECTION_TYPE ) ) ) + && + ( !Info.Type.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( WEBDAV_CONTENT_TYPE ) ) ) ) + return uno::Reference< ucb::XContent >(); + + rtl::OUString aURL = m_xIdentifier->getContentIdentifier(); + + OSL_ENSURE( aURL.getLength() > 0, + "WebdavContent::createNewContent - empty identifier!" ); + + if ( ( aURL.lastIndexOf( '/' ) + 1 ) != aURL.getLength() ) + aURL += rtl::OUString::createFromAscii( "/" ); + + sal_Bool isCollection; + if ( Info.Type.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( WEBDAV_COLLECTION_TYPE ) ) ) + { + aURL += rtl::OUString::createFromAscii( "New_Collection" ); + isCollection = sal_True; + } + else + { + aURL += rtl::OUString::createFromAscii( "New_Content" ); + isCollection = sal_False; + } + + uno::Reference< ucb::XContentIdentifier > xId( + new ::ucbhelper::ContentIdentifier( m_xSMgr, aURL ) ); + + // create the local content + try + { + return new ::webdav_ucp::Content( m_xSMgr, + m_pProvider, + xId, + m_xResAccess->getSessionFactory(), + isCollection ); + } + catch ( ucb::ContentCreationException & ) + { + return uno::Reference< ucb::XContent >(); + } +} + +//========================================================================= +// virtual +rtl::OUString Content::getParentURL() +{ + // <scheme>:// -> "" + // <scheme>://foo -> "" + // <scheme>://foo/ -> "" + // <scheme>://foo/bar -> <scheme>://foo/ + // <scheme>://foo/bar/ -> <scheme>://foo/ + // <scheme>://foo/bar/abc -> <scheme>://foo/bar/ + + rtl::OUString aURL = m_xIdentifier->getContentIdentifier(); + + sal_Int32 nPos = aURL.lastIndexOf( '/' ); + if ( nPos == ( aURL.getLength() - 1 ) ) + { + // Trailing slash found. Skip. + nPos = aURL.lastIndexOf( '/', nPos ); + } + + sal_Int32 nPos1 = aURL.lastIndexOf( '/', nPos ); + if ( nPos1 != -1 ) + nPos1 = aURL.lastIndexOf( '/', nPos1 ); + + if ( nPos1 == -1 ) + return rtl::OUString(); + + return rtl::OUString( aURL.copy( 0, nPos + 1 ) ); +} + +//========================================================================= +// +// Non-interface methods. +// +//========================================================================= + +// static +uno::Reference< sdbc::XRow > Content::getPropertyValues( + const uno::Reference< lang::XMultiServiceFactory >& rSMgr, + const uno::Sequence< beans::Property >& rProperties, + const ContentProperties& rData, + const rtl::Reference< ::ucbhelper::ContentProviderImplHelper >& rProvider, + const rtl::OUString& rContentId ) +{ + // Note: Empty sequence means "get values of all supported properties". + + rtl::Reference< ::ucbhelper::PropertyValueSet > xRow + = new ::ucbhelper::PropertyValueSet( rSMgr ); + + sal_Int32 nCount = rProperties.getLength(); + if ( nCount ) + { + uno::Reference< beans::XPropertySet > xAdditionalPropSet; + sal_Bool bTriedToGetAdditonalPropSet = sal_False; + + const beans::Property* pProps = rProperties.getConstArray(); + for ( sal_Int32 n = 0; n < nCount; ++n ) + { + const beans::Property& rProp = pProps[ n ]; + + // Process standard UCB, DAV and HTTP properties. + const uno::Any & rValue = rData.getValue( rProp.Name ); + if ( rValue.hasValue() ) + { + xRow->appendObject( rProp, rValue ); + } + else + { + // Process local Additional Properties. + if ( !bTriedToGetAdditonalPropSet && !xAdditionalPropSet.is() ) + { + xAdditionalPropSet + = uno::Reference< beans::XPropertySet >( + rProvider->getAdditionalPropertySet( rContentId, + sal_False ), + uno::UNO_QUERY ); + bTriedToGetAdditonalPropSet = sal_True; + } + + if ( !xAdditionalPropSet.is() || + !xRow->appendPropertySetValue( + xAdditionalPropSet, rProp ) ) + { + // Append empty entry. + xRow->appendVoid( rProp ); + } + } + } + } + else + { + // Append all standard UCB, DAV and HTTP properties. + + const std::auto_ptr< PropertyValueMap > & xProps = rData.getProperties(); + + PropertyValueMap::const_iterator it = xProps->begin(); + PropertyValueMap::const_iterator end = xProps->end(); + + ContentProvider * pProvider + = static_cast< ContentProvider * >( rProvider.get() ); + beans::Property aProp; + + while ( it != end ) + { + if ( pProvider->getProperty( (*it).first, aProp ) ) + xRow->appendObject( aProp, (*it).second.value() ); + + ++it; + } + + // Append all local Additional Properties. + uno::Reference< beans::XPropertySet > xSet( + rProvider->getAdditionalPropertySet( rContentId, sal_False ), + uno::UNO_QUERY ); + xRow->appendPropertySet( xSet ); + } + + return uno::Reference< sdbc::XRow >( xRow.get() ); +} + +//========================================================================= +uno::Reference< sdbc::XRow > Content::getPropertyValues( + const uno::Sequence< beans::Property >& rProperties, + const uno::Reference< ucb::XCommandEnvironment >& xEnv ) + throw ( uno::Exception ) +{ + std::auto_ptr< ContentProperties > xProps; + std::auto_ptr< ContentProperties > xCachedProps; + std::auto_ptr< DAVResourceAccess > xResAccess; + rtl::OUString aEscapedTitle; + bool bHasAll = false; + uno::Reference< lang::XMultiServiceFactory > xSMgr; + uno::Reference< ucb::XContentIdentifier > xIdentifier; + rtl::Reference< ::ucbhelper::ContentProviderImplHelper > xProvider; + + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + aEscapedTitle = NeonUri::unescape( m_aEscapedTitle ); + xSMgr.set( m_xSMgr ); + xIdentifier.set( m_xIdentifier ); + xProvider.set( m_xProvider.get() ); + xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) ); + + // First, ask cache... + if ( m_xCachedProps.get() ) + { + xCachedProps.reset( new ContentProperties( *m_xCachedProps.get() ) ); + + std::vector< rtl::OUString > aMissingProps; + if ( xCachedProps->containsAllNames( rProperties, aMissingProps ) ) + { + // All properties are already in cache! No server access needed. + bHasAll = true; + } + + // use the cached ContentProperties instance + xProps.reset( new ContentProperties( *xCachedProps.get() ) ); + } + } + + if ( !m_bTransient && !bHasAll ) + { + ///////////////////////////////////////////////////////////////////// + // Obtain values from server... + ///////////////////////////////////////////////////////////////////// + + // First, identify whether resource is DAV or not + const ResourceType & rType = getResourceType( xEnv, xResAccess ); + + bool bNetworkAccessAllowed = true; + + if ( DAV == rType ) + { + // cache lookup... getResourceType may fill the props cache via + // PROPFIND! + if ( m_xCachedProps.get() ) + { + xCachedProps.reset( + new ContentProperties( *m_xCachedProps.get() ) ); + + std::vector< rtl::OUString > aMissingProps; + if ( xCachedProps->containsAllNames( + rProperties, aMissingProps ) ) + { + // All properties are already in cache! No server access + // needed. + bHasAll = true; + } + + // use the cached ContentProperties instance + xProps.reset( new ContentProperties( *xCachedProps.get() ) ); + } + + if ( !bHasAll ) + { + // Only DAV resources support PROPFIND + std::vector< rtl::OUString > aPropNames; + + uno::Sequence< beans::Property > aProperties( + rProperties.getLength() ); + + if ( m_aFailedPropNames.size() > 0 ) + { + sal_Int32 nProps = 0; + sal_Int32 nCount = rProperties.getLength(); + for ( sal_Int32 n = 0; n < nCount; ++n ) + { + const rtl::OUString & rName = rProperties[ n ].Name; + + std::vector< rtl::OUString >::const_iterator it + = m_aFailedPropNames.begin(); + std::vector< rtl::OUString >::const_iterator end + = m_aFailedPropNames.end(); + + while ( it != end ) + { + if ( *it == rName ) + break; + + ++it; + } + + if ( it == end ) + { + aProperties[ nProps ] = rProperties[ n ]; + nProps++; + } + } + + aProperties.realloc( nProps ); + } + else + { + aProperties = rProperties; + } + + if ( aProperties.getLength() > 0 ) + ContentProperties::UCBNamesToDAVNames( + aProperties, aPropNames ); + + if ( aPropNames.size() > 0 ) + { + std::vector< DAVResource > resources; + try + { + xResAccess->PROPFIND( + DAVZERO, aPropNames, resources, xEnv ); + + if ( 1 == resources.size() ) + { + if ( xProps.get()) + xProps->addProperties( + aPropNames, + ContentProperties( resources[ 0 ] )); + else + xProps.reset( + new ContentProperties( resources[ 0 ] ) ); + } + } + catch ( DAVException const & e ) + { + bNetworkAccessAllowed + = shouldAccessNetworkAfterException( e ); + + if ( !bNetworkAccessAllowed ) + { + cancelCommandExecution( e, xEnv ); + // unreachable + } + } + } + } + } + + if ( bNetworkAccessAllowed ) + { + // All properties obtained already? + std::vector< rtl::OUString > aMissingProps; + if ( !( xProps.get() + && xProps->containsAllNames( + rProperties, aMissingProps ) ) + && !m_bDidGetOrHead ) + { + // Possibly the missing props can be obtained using a HEAD + // request. + + std::vector< rtl::OUString > aHeaderNames; + ContentProperties::UCBNamesToHTTPNames( + rProperties, + aHeaderNames, + true /* bIncludeUnmatched */ ); + + if ( aHeaderNames.size() > 0 ) + { + try + { + DAVResource resource; + xResAccess->HEAD( aHeaderNames, resource, xEnv ); + m_bDidGetOrHead = true; + + if ( xProps.get() ) + xProps->addProperties( + aMissingProps, + ContentProperties( resource ) ); + else + xProps.reset ( new ContentProperties( resource ) ); + + if ( m_eResourceType == NON_DAV ) + xProps->addProperties( aMissingProps, + ContentProperties( + aEscapedTitle, + false ) ); + } + catch ( DAVException const & e ) + { + bNetworkAccessAllowed + = shouldAccessNetworkAfterException( e ); + + if ( !bNetworkAccessAllowed ) + { + cancelCommandExecution( e, xEnv ); + // unreachable + } + } + } + } + } + + // might trigger HTTP redirect. + // Therefore, title must be updated here. + NeonUri aUri( xResAccess->getURL() ); + aEscapedTitle = aUri.GetPathBaseName(); + + if ( UNKNOWN == rType ) + { + xProps.reset( new ContentProperties( aEscapedTitle ) ); + } + + // For DAV resources we only know the Title, for non-DAV + // resources we additionally know that it is a document. + if ( DAV == rType ) + { + //xProps.reset( + // new ContentProperties( aEscapedTitle ) ); + xProps->addProperty( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ), + uno::makeAny( aEscapedTitle ), + true ); + } + else + { + if ( !xProps.get() ) + xProps.reset( new ContentProperties( aEscapedTitle, false ) ); + else + xProps->addProperty( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ), + uno::makeAny( aEscapedTitle ), + true ); + + xProps->addProperty( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ), + uno::makeAny( false ), + true ); + xProps->addProperty( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsDocument" ) ), + uno::makeAny( true ), + true ); + } + } + else + { + // No server access for just created (not yet committed) objects. + // Only a minimal set of properties supported at this stage. + if (m_bTransient) + xProps.reset( new ContentProperties( aEscapedTitle, + m_bCollection ) ); + } + + sal_Int32 nCount = rProperties.getLength(); + for ( sal_Int32 n = 0; n < nCount; ++n ) + { + const rtl::OUString rName = rProperties[ n ].Name; + if ( rName.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "BaseURI" ) ) ) + { + // Add BaseURI property, if requested. + xProps->addProperty( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "BaseURI" ) ), + uno::makeAny( getBaseURI( xResAccess ) ), + true ); + } + else if ( rName.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "CreatableContentsInfo" ) ) ) + { + // Add CreatableContentsInfo property, if requested. + sal_Bool bFolder = sal_False; + xProps->getValue( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ) ) + >>= bFolder; + xProps->addProperty( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "CreatableContentsInfo" ) ), + uno::makeAny( bFolder + ? queryCreatableContentsInfo() + : uno::Sequence< ucb::ContentInfo >() ), + true ); + } + } + + uno::Reference< sdbc::XRow > xResultRow + = getPropertyValues( xSMgr, + rProperties, + *xProps, + xProvider, + xIdentifier->getContentIdentifier() ); + + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + if ( !m_xCachedProps.get() ) + m_xCachedProps.reset( new ContentProperties( *xProps.get() ) ); + else + m_xCachedProps->addProperties( *xProps.get() ); + + m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) ); + m_aEscapedTitle = aEscapedTitle; + } + + return xResultRow; +} + +//========================================================================= +uno::Sequence< uno::Any > Content::setPropertyValues( + const uno::Sequence< beans::PropertyValue >& rValues, + const uno::Reference< ucb::XCommandEnvironment >& xEnv ) + throw ( uno::Exception ) +{ + uno::Reference< lang::XMultiServiceFactory > xSMgr; + uno::Reference< ucb::XContentIdentifier > xIdentifier; + rtl::Reference< ContentProvider > xProvider; + sal_Bool bTransient; + std::auto_ptr< DAVResourceAccess > xResAccess; + + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + xProvider.set( m_pProvider ); + xIdentifier.set( m_xIdentifier ); + bTransient = m_bTransient; + xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) ); + xSMgr.set( m_xSMgr ); + } + + uno::Sequence< uno::Any > aRet( rValues.getLength() ); + uno::Sequence< beans::PropertyChangeEvent > aChanges( rValues.getLength() ); + sal_Int32 nChanged = 0; + + beans::PropertyChangeEvent aEvent; + aEvent.Source = static_cast< cppu::OWeakObject * >( this ); + aEvent.Further = sal_False; + // aEvent.PropertyName = + aEvent.PropertyHandle = -1; + // aEvent.OldValue = + // aEvent.NewValue = + + std::vector< ProppatchValue > aProppatchValues; + std::vector< sal_Int32 > aProppatchPropsPositions; + + uno::Reference< ucb::XPersistentPropertySet > xAdditionalPropSet; + sal_Bool bTriedToGetAdditonalPropSet = sal_False; + + sal_Bool bExchange = sal_False; + rtl::OUString aNewTitle; + rtl::OUString aOldTitle; + sal_Int32 nTitlePos = -1; + + uno::Reference< beans::XPropertySetInfo > xInfo; + + const beans::PropertyValue* pValues = rValues.getConstArray(); + sal_Int32 nCount = rValues.getLength(); + for ( sal_Int32 n = 0; n < nCount; ++n ) + { + const beans::PropertyValue& rValue = pValues[ n ]; + const rtl::OUString & rName = rValue.Name; + + beans::Property aTmpProp; + xProvider->getProperty( rName, aTmpProp ); + + if ( aTmpProp.Attributes & beans::PropertyAttribute::READONLY ) + { + // Read-only property! + aRet[ n ] <<= lang::IllegalAccessException( + rtl::OUString::createFromAscii( + "Property is read-only!" ), + static_cast< cppu::OWeakObject * >( this ) ); + continue; + } + + ////////////////////////////////////////////////////////////////// + // Mandatory props. + ////////////////////////////////////////////////////////////////// + + if ( rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) ) + { + // Read-only property! + aRet[ n ] <<= lang::IllegalAccessException( + rtl::OUString::createFromAscii( + "Property is read-only!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + else if ( rName.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) ) + { + // Read-only property! + aRet[ n ] <<= lang::IllegalAccessException( + rtl::OUString::createFromAscii( + "Property is read-only!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + else if ( rName.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) ) + { + // Read-only property! + aRet[ n ] <<= lang::IllegalAccessException( + rtl::OUString::createFromAscii( + "Property is read-only!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + else if ( rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Title" ) ) ) + { + rtl::OUString aNewValue; + if ( rValue.Value >>= aNewValue ) + { + // No empty titles! + if ( aNewValue.getLength() > 0 ) + { + try + { + NeonUri aURI( xIdentifier->getContentIdentifier() ); + aOldTitle = aURI.GetPathBaseNameUnescaped(); + + if ( aNewValue != aOldTitle ) + { + // modified title -> modified URL -> exchange ! + if ( !bTransient ) + bExchange = sal_True; + + // new value will be set later... + aNewTitle = aNewValue; + + // remember position within sequence of values (for + // error handling). + nTitlePos = n; + } + } + catch ( DAVException const & ) + { + aRet[ n ] <<= lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Invalid content identifier!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ); + } + } + else + { + aRet[ n ] <<= lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Empty title not allowed!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ); + } + } + else + { + aRet[ n ] <<= beans::IllegalTypeException( + rtl::OUString::createFromAscii( + "Property value has wrong type!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + } + else + { + ////////////////////////////////////////////////////////////// + // Optional props. + ////////////////////////////////////////////////////////////// + + if ( !xInfo.is() ) + xInfo = getPropertySetInfo( xEnv, + sal_False /* don't cache data */ ); + + if ( !xInfo->hasPropertyByName( rName ) ) + { + // Check, whether property exists. Skip otherwise. + // PROPPATCH::set would add the property automatically, which + // is not allowed for "setPropertyValues" command! + aRet[ n ] <<= beans::UnknownPropertyException( + rtl::OUString::createFromAscii( + "Property is unknown!" ), + static_cast< cppu::OWeakObject * >( this ) ); + continue; + } + + if ( rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Size" ) ) ) + { + // Read-only property! + aRet[ n ] <<= lang::IllegalAccessException( + rtl::OUString::createFromAscii( + "Property is read-only!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + else if ( rName.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "DateCreated" ) ) ) + { + // Read-only property! + aRet[ n ] <<= lang::IllegalAccessException( + rtl::OUString::createFromAscii( + "Property is read-only!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + else if ( rName.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "DateModified" ) ) ) + { + // Read-only property! + aRet[ n ] <<= lang::IllegalAccessException( + rtl::OUString::createFromAscii( + "Property is read-only!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + else if ( rName.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "MediaType" ) ) ) + { + // Read-only property! + // (but could be writable, if 'getcontenttype' would be) + aRet[ n ] <<= lang::IllegalAccessException( + rtl::OUString::createFromAscii( + "Property is read-only!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + if ( rName.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "CreatableContentsInfo" ) ) ) + { + // Read-only property! + aRet[ n ] <<= lang::IllegalAccessException( + rtl::OUString::createFromAscii( + "Property is read-only!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + else + { + if ( getResourceType( xEnv, xResAccess ) == DAV ) + { + // Property value will be set on server. + ProppatchValue aValue( PROPSET, rName, rValue.Value ); + aProppatchValues.push_back( aValue ); + + // remember position within sequence of values (for + // error handling). + aProppatchPropsPositions.push_back( n ); + } + else + { + // Property value will be stored in local property store. + if ( !bTriedToGetAdditonalPropSet && + !xAdditionalPropSet.is() ) + { + xAdditionalPropSet + = getAdditionalPropertySet( sal_False ); + bTriedToGetAdditonalPropSet = sal_True; + } + + if ( xAdditionalPropSet.is() ) + { + try + { + uno::Any aOldValue + = xAdditionalPropSet->getPropertyValue( rName ); + if ( aOldValue != rValue.Value ) + { + xAdditionalPropSet->setPropertyValue( + rName, rValue.Value ); + + aEvent.PropertyName = rName; + aEvent.OldValue = aOldValue; + aEvent.NewValue = rValue.Value; + + aChanges.getArray()[ nChanged ] = aEvent; + nChanged++; + } + } + catch ( beans::UnknownPropertyException const & e ) + { + aRet[ n ] <<= e; + } + catch ( lang::WrappedTargetException const & e ) + { + aRet[ n ] <<= e; + } + catch ( beans::PropertyVetoException const & e ) + { + aRet[ n ] <<= e; + } + catch ( lang::IllegalArgumentException const & e ) + { + aRet[ n ] <<= e; + } + } + else + { + aRet[ n ] <<= uno::Exception( + rtl::OUString::createFromAscii( + "No property set for storing the value!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + } + } + } + } // for + + if ( !bTransient && aProppatchValues.size() ) + { + try + { + // Set property values at server. + xResAccess->PROPPATCH( aProppatchValues, xEnv ); + + std::vector< ProppatchValue >::const_iterator it + = aProppatchValues.begin(); + std::vector< ProppatchValue >::const_iterator end + = aProppatchValues.end(); + + while ( it != end ) + { + aEvent.PropertyName = (*it).name; + aEvent.OldValue = uno::Any(); // @@@ to expensive to obtain! + aEvent.NewValue = (*it).value; + + aChanges.getArray()[ nChanged ] = aEvent; + nChanged++; + + ++it; + } + } + catch ( DAVException const & e ) + { +// OSL_ENSURE( sal_False, +// "Content::setPropertyValues - PROPPATCH failed!" ); + +#if 1 + cancelCommandExecution( e, xEnv ); + // unreachable +#else + // Note: PROPPATCH either sets ALL property values OR NOTHING. + + std::vector< sal_Int32 >::const_iterator it + = aProppatchPropsPositions.begin(); + std::vector< sal_Int32 >::const_iterator end + = aProppatchPropsPositions.end(); + + while ( it != end ) + { + // Set error. + aRet[ (*it) ] <<= MapDAVException( e, sal_True ); + ++it; + } +#endif + } + } + + if ( bExchange ) + { + // Assemble new content identifier... + + rtl::OUString aNewURL = getParentURL(); + if ( aNewURL.lastIndexOf( '/' ) != ( aNewURL.getLength() - 1 ) ) + aNewURL += rtl::OUString::createFromAscii( "/" ); + + aNewURL += NeonUri::escapeSegment( aNewTitle ); + + uno::Reference< ucb::XContentIdentifier > xNewId + = new ::ucbhelper::ContentIdentifier( xSMgr, aNewURL ); + uno::Reference< ucb::XContentIdentifier > xOldId = xIdentifier; + + try + { + NeonUri sourceURI( xOldId->getContentIdentifier() ); + NeonUri targetURI( xNewId->getContentIdentifier() ); + targetURI.SetScheme( sourceURI.GetScheme() ); + + xResAccess->MOVE( + sourceURI.GetPath(), targetURI.GetURI(), sal_False, xEnv ); + // @@@ Should check for resources that could not be moved + // (due to source access or target overwrite) and send + // this information through the interaction handler. + + // @@@ Existing content should be checked to see if it needs + // to be deleted at the source + + // @@@ Existing content should be checked to see if it has + // been overwritten at the target + + if ( exchangeIdentity( xNewId ) ) + { + xResAccess->setURL( aNewURL ); + +// DAV resources store all additional props on server! +// // Adapt Additional Core Properties. +// renameAdditionalPropertySet( xOldId->getContentIdentifier(), +// xNewId->getContentIdentifier(), +// sal_True ); + } + else + { + // Do not set new title! + aNewTitle = rtl::OUString(); + + // Set error . + aRet[ nTitlePos ] <<= uno::Exception( + rtl::OUString::createFromAscii( "Exchange failed!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + } + catch ( DAVException const & e ) + { + // Do not set new title! + aNewTitle = rtl::OUString(); + + // Set error . + aRet[ nTitlePos ] <<= MapDAVException( e, sal_True ); + } + } + + if ( aNewTitle.getLength() ) + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + aEvent.PropertyName = rtl::OUString::createFromAscii( "Title" ); + aEvent.OldValue = uno::makeAny( aOldTitle ); + aEvent.NewValue = uno::makeAny( aNewTitle ); + + m_aEscapedTitle = NeonUri::escapeSegment( aNewTitle ); + + aChanges.getArray()[ nChanged ] = aEvent; + nChanged++; + } + + if ( nChanged > 0 ) + { + aChanges.realloc( nChanged ); + notifyPropertiesChange( aChanges ); + } + + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) ); + } + + return aRet; +} + +//========================================================================= +uno::Any Content::open( + const ucb::OpenCommandArgument2 & rArg, + const uno::Reference< ucb::XCommandEnvironment > & xEnv ) + throw( uno::Exception ) +{ + uno::Any aRet; + + sal_Bool bOpenFolder = ( ( rArg.Mode == ucb::OpenMode::ALL ) || + ( rArg.Mode == ucb::OpenMode::FOLDERS ) || + ( rArg.Mode == ucb::OpenMode::DOCUMENTS ) ); + if ( bOpenFolder ) + { + if ( isFolder( xEnv ) ) + { + // Open collection. + + uno::Reference< ucb::XDynamicResultSet > xSet + = new DynamicResultSet( m_xSMgr, this, rArg, xEnv ); + aRet <<= xSet; + } + else + { + // Error: Not a folder! + + rtl::OUStringBuffer aMsg; + if ( getResourceType( xEnv ) == FTP ) + { + // #114653# + aMsg.appendAscii( "FTP over HTTP proxy: resource cannot " + "be opened as folder! Wrong Open Mode!" ); + } + else + { + aMsg.appendAscii( "Non-folder resource cannot be " + "opened as folder! Wrong Open Mode!" ); + } + + ucbhelper::cancelCommandExecution( + uno::makeAny( + lang::IllegalArgumentException( + aMsg.makeStringAndClear(), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + xEnv ); + // Unreachable + } + } + + if ( rArg.Sink.is() ) + { + // Open document. + + if ( ( rArg.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_NONE ) || + ( rArg.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE ) ) + { + // Currently(?) unsupported. + ucbhelper::cancelCommandExecution( + uno::makeAny( + ucb::UnsupportedOpenModeException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + sal_Int16( rArg.Mode ) ) ), + xEnv ); + // Unreachable + } + + rtl::OUString aURL = m_xIdentifier->getContentIdentifier(); + uno::Reference< io::XOutputStream > xOut + = uno::Reference< io::XOutputStream >( rArg.Sink, uno::UNO_QUERY ); + if ( xOut.is() ) + { + // PUSH: write data + try + { + std::auto_ptr< DAVResourceAccess > xResAccess; + + { + osl::MutexGuard aGuard( m_aMutex ); + + xResAccess.reset( + new DAVResourceAccess( *m_xResAccess.get() ) ); + } + + DAVResource aResource; + std::vector< rtl::OUString > aHeaders; + + xResAccess->GET( xOut, aHeaders, aResource, xEnv ); + m_bDidGetOrHead = true; + + { + osl::MutexGuard aGuard( m_aMutex ); + + // cache headers. + if ( !m_xCachedProps.get()) + m_xCachedProps.reset( + new ContentProperties( aResource ) ); + else + m_xCachedProps->addProperties( aResource ); + + m_xResAccess.reset( + new DAVResourceAccess( *xResAccess.get() ) ); + } + } + catch ( DAVException const & e ) + { + cancelCommandExecution( e, xEnv ); + // Unreachable + } + } + else + { + uno::Reference< io::XActiveDataSink > xDataSink + = uno::Reference< io::XActiveDataSink >( rArg.Sink, + uno::UNO_QUERY ); + if ( xDataSink.is() ) + { + // PULL: wait for client read + try + { + std::auto_ptr< DAVResourceAccess > xResAccess; + { + osl::MutexGuard aGuard( m_aMutex ); + + xResAccess.reset( + new DAVResourceAccess( *m_xResAccess.get() ) ); + } + + // fill inputsream sync; return if all data present + DAVResource aResource; + std::vector< rtl::OUString > aHeaders; + + uno::Reference< io::XInputStream > xIn + = xResAccess->GET( aHeaders, aResource, xEnv ); + m_bDidGetOrHead = true; + + { + osl::MutexGuard aGuard( m_aMutex ); + + // cache headers. + if ( !m_xCachedProps.get()) + m_xCachedProps.reset( + new ContentProperties( aResource ) ); + else + m_xCachedProps->addProperties( + aResource.properties ); + + m_xResAccess.reset( + new DAVResourceAccess( *xResAccess.get() ) ); + } + + xDataSink->setInputStream( xIn ); + } + catch ( DAVException const & e ) + { + cancelCommandExecution( e, xEnv ); + // Unreachable + } + } + else + { + // Note: aOpenCommand.Sink may contain an XStream + // implementation. Support for this type of + // sink is optional... + ucbhelper::cancelCommandExecution( + uno::makeAny( + ucb::UnsupportedDataSinkException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + rArg.Sink ) ), + xEnv ); + // Unreachable + } + } + } + + return aRet; +} + +//========================================================================= +void Content::post( + const ucb::PostCommandArgument2 & rArg, + const uno::Reference< ucb::XCommandEnvironment > & xEnv ) + throw( uno::Exception ) +{ + uno::Reference< io::XActiveDataSink > xSink( rArg.Sink, uno::UNO_QUERY ); + if ( xSink.is() ) + { + try + { + std::auto_ptr< DAVResourceAccess > xResAccess; + { + osl::MutexGuard aGuard( m_aMutex ); + xResAccess.reset( + new DAVResourceAccess( *m_xResAccess.get() ) ); + } + + uno::Reference< io::XInputStream > xResult + = xResAccess->POST( rArg.MediaType, + rArg.Referer, + rArg.Source, + xEnv ); + + { + osl::MutexGuard aGuard( m_aMutex ); + m_xResAccess.reset( + new DAVResourceAccess( *xResAccess.get() ) ); + } + + xSink->setInputStream( xResult ); + } + catch ( DAVException const & e ) + { + cancelCommandExecution( e, xEnv, sal_True ); + // Unreachable + } + } + else + { + uno::Reference< io::XOutputStream > xResult( rArg.Sink, uno::UNO_QUERY ); + if ( xResult.is() ) + { + try + { + std::auto_ptr< DAVResourceAccess > xResAccess; + { + osl::MutexGuard aGuard( m_aMutex ); + xResAccess.reset( + new DAVResourceAccess( *m_xResAccess.get() ) ); + } + + xResAccess->POST( rArg.MediaType, + rArg.Referer, + rArg.Source, + xResult, + xEnv ); + + { + osl::MutexGuard aGuard( m_aMutex ); + m_xResAccess.reset( + new DAVResourceAccess( *xResAccess.get() ) ); + } + } + catch ( DAVException const & e ) + { + cancelCommandExecution( e, xEnv, sal_True ); + // Unreachable + } + } + else + { + ucbhelper::cancelCommandExecution( + uno::makeAny( + ucb::UnsupportedDataSinkException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + rArg.Sink ) ), + xEnv ); + // Unreachable + } + } +} + +//========================================================================= +void Content::queryChildren( ContentRefList& rChildren ) +{ + // Obtain a list with a snapshot of all currently instanciated contents + // from provider and extract the contents which are direct children + // of this content. + + ::ucbhelper::ContentRefList aAllContents; + m_xProvider->queryExistingContents( aAllContents ); + + rtl::OUString aURL = m_xIdentifier->getContentIdentifier(); + sal_Int32 nURLPos = aURL.lastIndexOf( '/' ); + + if ( nURLPos != ( aURL.getLength() - 1 ) ) + { + // No trailing slash found. Append. + aURL += rtl::OUString::createFromAscii( "/" ); + } + + sal_Int32 nLen = aURL.getLength(); + + ::ucbhelper::ContentRefList::const_iterator it = aAllContents.begin(); + ::ucbhelper::ContentRefList::const_iterator end = aAllContents.end(); + + while ( it != end ) + { + ::ucbhelper::ContentImplHelperRef xChild = (*it); + rtl::OUString aChildURL + = xChild->getIdentifier()->getContentIdentifier(); + + // Is aURL a prefix of aChildURL? + if ( ( aChildURL.getLength() > nLen ) && + ( aChildURL.compareTo( aURL, nLen ) == 0 ) ) + { + sal_Int32 nPos = nLen; + nPos = aChildURL.indexOf( '/', nPos ); + + if ( ( nPos == -1 ) || + ( nPos == ( aChildURL.getLength() - 1 ) ) ) + { + // No further slashes / only a final slash. It's a child! + rChildren.push_back( + ::webdav_ucp::Content::ContentRef( + static_cast< ::webdav_ucp::Content * >( + xChild.get() ) ) ); + } + } + ++it; + } +} + +//========================================================================= +void Content::insert( + const uno::Reference< io::XInputStream > & xInputStream, + sal_Bool bReplaceExisting, + const uno::Reference< ucb::XCommandEnvironment >& Environment ) + throw( uno::Exception ) +{ + sal_Bool bTransient, bCollection; + rtl::OUString aEscapedTitle; + std::auto_ptr< DAVResourceAccess > xResAccess; + + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + bTransient = m_bTransient; + bCollection = m_bCollection; + aEscapedTitle = m_aEscapedTitle; + xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) ); + } + + // Check, if all required properties are present. + + if ( aEscapedTitle.getLength() == 0 ) + { + OSL_ENSURE( sal_False, "Content::insert - Title missing!" ); + + uno::Sequence< rtl::OUString > aProps( 1 ); + aProps[ 0 ] = rtl::OUString::createFromAscii( "Title" ); + ucbhelper::cancelCommandExecution( + uno::makeAny( ucb::MissingPropertiesException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + aProps ) ), + Environment ); + // Unreachable + } + + if ( !bReplaceExisting ) + { + /* [RFC 2616] - HTTP + + The PUT method requests that the enclosed entity be stored under the + supplied Request-URI. If the Request-URI refers to an already + existing resource, the enclosed entity SHOULD be considered as a + modified version of the one residing on the origin server. + */ + + /* [RFC 2518] - WebDAV + + MKCOL creates a new collection resource at the location specified by + the Request-URI. If the resource identified by the Request-URI is + non-null then the MKCOL MUST fail. + */ + + // ==> Complain on PUT, continue on MKCOL. + if ( !bTransient || ( bTransient && !bCollection ) ) + { + ucb::UnsupportedNameClashException aEx( + rtl::OUString::createFromAscii( + "Unable to write without overwrite!" ), + static_cast< cppu::OWeakObject * >( this ), + ucb::NameClash::ERROR ); + + uno::Reference< task::XInteractionHandler > xIH; + + if ( Environment.is() ) + xIH = Environment->getInteractionHandler(); + + if ( xIH.is() ) + { + uno::Any aExAsAny( uno::makeAny( aEx ) ); + + rtl::Reference< ucbhelper::SimpleInteractionRequest > xRequest + = new ucbhelper::SimpleInteractionRequest( + aExAsAny, + ucbhelper::CONTINUATION_APPROVE + | ucbhelper::CONTINUATION_DISAPPROVE ); + xIH->handle( xRequest.get() ); + + const sal_Int32 nResp = xRequest->getResponse(); + + switch ( nResp ) + { + case ucbhelper::CONTINUATION_UNKNOWN: + // Not handled; throw. + throw aEx; +// break; + + case ucbhelper::CONTINUATION_APPROVE: + // Continue -> Overwrite. + bReplaceExisting = sal_True; + break; + + case ucbhelper::CONTINUATION_DISAPPROVE: + // Abort. + throw ucb::CommandFailedException( + rtl::OUString(), + uno::Reference< uno::XInterface >(), + aExAsAny ); +// break; + + default: + OSL_ENSURE( sal_False, + "Content::insert - " + "Unknown interaction selection!" ); + throw ucb::CommandFailedException( + rtl::OUString::createFromAscii( + "Unknown interaction selection!" ), + uno::Reference< uno::XInterface >(), + aExAsAny ); +// break; + } + } + else + { + // No IH; throw. + throw aEx; + } + } + } + + if ( bTransient ) + { + // Assemble new content identifier... + rtl::OUString aURL = getParentURL(); + if ( aURL.lastIndexOf( '/' ) != ( aURL.getLength() - 1 ) ) + aURL += rtl::OUString::createFromAscii( "/" ); + + aURL += aEscapedTitle; + + try + { + xResAccess->setURL( aURL ); + + if ( bCollection ) + xResAccess->MKCOL( Environment ); + else + xResAccess->PUT( xInputStream, Environment ); + } + catch ( DAVException const & except ) + { + if ( bCollection ) + { + if ( except.getStatus() == SC_METHOD_NOT_ALLOWED ) + { + // [RFC 2518] - WebDAV + // 405 (Method Not Allowed) - MKCOL can only be + // executed on a deleted/non-existent resource. + + if ( bReplaceExisting ) + { + // Destroy old resource. + try + { + xResAccess->DESTROY( Environment ); + } + catch ( DAVException const & e ) + { + cancelCommandExecution( e, Environment, sal_True ); + // Unreachable + } + + // Insert (recursion!). + insert( xInputStream, bReplaceExisting, Environment ); + + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + m_xResAccess.reset( + new DAVResourceAccess( *xResAccess.get() ) ); + } + + // Success! + return; + } + else + { + rtl::OUString aTitle; + try + { + NeonUri aURI( aURL ); + aTitle = aURI.GetPathBaseNameUnescaped(); + } + catch ( DAVException const & ) + { + } + + ucbhelper::cancelCommandExecution( + uno::makeAny( + ucb::NameClashException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + task::InteractionClassification_ERROR, + aTitle ) ), + Environment ); + // Unreachable + } + } + } + + cancelCommandExecution( except, Environment, sal_True ); + // Unreachable + } + + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + m_xIdentifier + = new ::ucbhelper::ContentIdentifier( m_xSMgr, aURL ); + } + + inserted(); + + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + m_bTransient = sal_False; + } + } + else + { + if ( !xInputStream.is() ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( + ucb::MissingInputStreamException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ) ) ), + Environment ); + // Unreachable + } + + try + { + xResAccess->PUT( xInputStream, Environment ); + } + catch ( DAVException const & e ) + { + cancelCommandExecution( e, Environment, sal_True ); + // Unreachable + } + } + + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) ); + } +} + +//========================================================================= +void Content::transfer( + const ucb::TransferInfo & rArgs, + const uno::Reference< ucb::XCommandEnvironment >& Environment ) + throw( uno::Exception ) +{ + uno::Reference< lang::XMultiServiceFactory > xSMgr; + uno::Reference< ucb::XContentIdentifier > xIdentifier; + uno::Reference< ucb::XContentProvider > xProvider; + std::auto_ptr< DAVResourceAccess > xResAccess; + + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + xSMgr.set( m_xSMgr ); + xIdentifier.set( m_xIdentifier ); + xProvider.set( m_xProvider.get() ); + xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) ); + } + + rtl::OUString aTargetURI; + try + { + NeonUri sourceURI( rArgs.SourceURL ); + NeonUri targetURI( xIdentifier->getContentIdentifier() ); + aTargetURI = targetURI.GetPathBaseNameUnescaped(); + + // Check source's and target's URL scheme + // + const rtl::OUString aScheme = sourceURI.GetScheme().toAsciiLowerCase(); + if ( aScheme.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( WEBDAV_URL_SCHEME ) ) ) + { + sourceURI.SetScheme( + rtl::OUString::createFromAscii( HTTP_URL_SCHEME ) ); + } + else if ( aScheme.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( DAV_URL_SCHEME ) ) ) + { + sourceURI.SetScheme( + rtl::OUString::createFromAscii( HTTP_URL_SCHEME ) ); + } + else if ( aScheme.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( DAVS_URL_SCHEME ) ) ) + { + sourceURI.SetScheme( + rtl::OUString::createFromAscii( HTTPS_URL_SCHEME ) ); + } + else + { + if ( !aScheme.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( HTTP_URL_SCHEME ) ) && + !aScheme.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( HTTPS_URL_SCHEME ) ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( + ucb::InteractiveBadTransferURLException( + rtl::OUString::createFromAscii( + "Unsupported URL scheme!" ), + static_cast< cppu::OWeakObject * >( this ) ) ), + Environment ); + // Unreachable + } + } + + if ( targetURI.GetScheme().toAsciiLowerCase().equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( WEBDAV_URL_SCHEME ) ) ) + targetURI.SetScheme( + rtl::OUString::createFromAscii( HTTP_URL_SCHEME ) ); + else if ( targetURI.GetScheme().toAsciiLowerCase().equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( DAV_URL_SCHEME ) ) ) + targetURI.SetScheme( + rtl::OUString::createFromAscii( HTTP_URL_SCHEME ) ); + + // @@@ This implementation of 'transfer' only works + // if the source and target are located at same host. + // (Neon does not support cross-server copy/move) + + // Check for same host + // + if ( sourceURI.GetHost().getLength() && + ( sourceURI.GetHost() != targetURI.GetHost() ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( ucb::InteractiveBadTransferURLException( + rtl::OUString::createFromAscii( + "Different hosts!" ), + static_cast< cppu::OWeakObject * >( this ) ) ), + Environment ); + // Unreachable + } + + rtl::OUString aTitle = rArgs.NewTitle; + + if ( !aTitle.getLength() ) + aTitle = sourceURI.GetPathBaseNameUnescaped(); + + if ( aTitle.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "/" ) ) ) + { + // kso: ??? + aTitle = rtl::OUString(); + } + + targetURI.AppendPath( aTitle ); + + rtl::OUString aTargetURL = xIdentifier->getContentIdentifier(); + if ( ( aTargetURL.lastIndexOf( '/' ) + 1 ) + != aTargetURL.getLength() ) + aTargetURL += rtl::OUString::createFromAscii( "/" ); + + aTargetURL += aTitle; + + uno::Reference< ucb::XContentIdentifier > xTargetId + = new ::ucbhelper::ContentIdentifier( xSMgr, aTargetURL ); + + DAVResourceAccess aSourceAccess( xSMgr, + xResAccess->getSessionFactory(), + sourceURI.GetURI() ); + + if ( rArgs.MoveData == sal_True ) + { + uno::Reference< ucb::XContentIdentifier > xId + = new ::ucbhelper::ContentIdentifier( xSMgr, rArgs.SourceURL ); + + // Note: The static cast is okay here, because its sure that + // xProvider is always the WebDAVContentProvider. + rtl::Reference< Content > xSource + = static_cast< Content * >( + xProvider->queryContent( xId ).get() ); + + // [RFC 2518] - WebDAV + // If a resource exists at the destination and the Overwrite + // header is "T" then prior to performing the move the server + // MUST perform a DELETE with "Depth: infinity" on the + // destination resource. If the Overwrite header is set to + // "F" then the operation will fail. + + aSourceAccess.MOVE( sourceURI.GetPath(), + targetURI.GetURI(), + rArgs.NameClash + == ucb::NameClash::OVERWRITE, + Environment ); + + if ( xSource.is() ) + { + // Propagate destruction to listeners. + xSource->destroy( sal_True ); + } + +// DAV resources store all additional props on server! +// // Rename own and all children's Additional Core Properties. +// renameAdditionalPropertySet( xId->getContentIdentifier(), +// xTargetId->getContentIdentifier(), +// sal_True ); + } + else + { + // [RFC 2518] - WebDAV + // If a resource exists at the destination and the Overwrite + // header is "T" then prior to performing the copy the server + // MUST perform a DELETE with "Depth: infinity" on the + // destination resource. If the Overwrite header is set to + // "F" then the operation will fail. + + aSourceAccess.COPY( sourceURI.GetPath(), + targetURI.GetURI(), + rArgs.NameClash + == ucb::NameClash::OVERWRITE, + Environment ); + +// DAV resources store all additional props on server! +// // Copy own and all children's Additional Core Properties. +// copyAdditionalPropertySet( xId->getContentIdentifier(), +// xTargetId->getContentIdentifier(), +// sal_True ); + } + + // Note: The static cast is okay here, because its sure that + // xProvider is always the WebDAVContentProvider. + rtl::Reference< Content > xTarget + = static_cast< Content * >( + xProvider->queryContent( xTargetId ).get() ); + + // Announce transfered content in its new folder. + xTarget->inserted(); + } + catch ( ucb::IllegalIdentifierException const & ) + { + // queryContent + } + catch ( DAVException const & e ) + { + // [RFC 2518] - WebDAV + // 412 (Precondition Failed) - The server was unable to maintain + // the liveness of the properties listed in the propertybehavior + // XML element or the Overwrite header is "F" and the state of + // the destination resource is non-null. + + if ( e.getStatus() == SC_PRECONDITION_FAILED ) + { + switch ( rArgs.NameClash ) + { + case ucb::NameClash::ERROR: + { + ucbhelper::cancelCommandExecution( + uno::makeAny( + ucb::NameClashException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + task::InteractionClassification_ERROR, + aTargetURI ) ), + Environment ); + // Unreachable + } + + case ucb::NameClash::OVERWRITE: + break; + + case ucb::NameClash::KEEP: // deprecated + case ucb::NameClash::RENAME: + case ucb::NameClash::ASK: + default: + { + ucbhelper::cancelCommandExecution( + uno::makeAny( + ucb::UnsupportedNameClashException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + rArgs.NameClash ) ), + Environment ); + // Unreachable + } + } + } + + cancelCommandExecution( e, Environment, sal_True ); + // Unreachable + } + + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) ); + } +} + +//========================================================================= +void Content::destroy( sal_Bool bDeletePhysical ) + throw( uno::Exception ) +{ + // @@@ take care about bDeletePhysical -> trashcan support + rtl::OUString aURL = m_xIdentifier->getContentIdentifier(); + + uno::Reference< ucb::XContent > xThis = this; + + deleted(); + + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + // Process instanciated children... + + ::webdav_ucp::Content::ContentRefList aChildren; + queryChildren( aChildren ); + + ContentRefList::const_iterator it = aChildren.begin(); + ContentRefList::const_iterator end = aChildren.end(); + + while ( it != end ) + { + (*it)->destroy( bDeletePhysical ); + ++it; + } +} + +//========================================================================= +bool Content::supportsExclusiveWriteLock( + const uno::Reference< ucb::XCommandEnvironment >& Environment ) +{ + if ( getResourceType( Environment ) == DAV ) + { + if ( m_xCachedProps.get() ) + { + uno::Sequence< ucb::LockEntry > aSupportedLocks; + if ( m_xCachedProps->getValue( DAVProperties::SUPPORTEDLOCK ) + >>= aSupportedLocks ) + { + for ( sal_Int32 n = 0; n < aSupportedLocks.getLength(); ++n ) + { + if ( aSupportedLocks[ n ].Scope + == ucb::LockScope_EXCLUSIVE && + aSupportedLocks[ n ].Type + == ucb::LockType_WRITE ) + return true; + } + } + } + } + return false; +} + +//========================================================================= +void Content::lock( + const uno::Reference< ucb::XCommandEnvironment >& Environment ) + throw( uno::Exception ) +{ + try + { + std::auto_ptr< DAVResourceAccess > xResAccess; + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) ); + } + + uno::Any aOwnerAny; + aOwnerAny + <<= rtl::OUString::createFromAscii( "http://ucb.openoffice.org" ); + + ucb::Lock aLock( + ucb::LockScope_EXCLUSIVE, + ucb::LockType_WRITE, + ucb::LockDepth_ZERO, + aOwnerAny, + 180, // lock timeout in secs + //-1, // infinite lock + uno::Sequence< ::rtl::OUString >() ); + + xResAccess->LOCK( aLock, Environment ); + + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) ); + } + } + catch ( DAVException const & e ) + { + cancelCommandExecution( e, Environment, sal_False ); + // Unreachable + } +} + +//========================================================================= +void Content::unlock( + const uno::Reference< ucb::XCommandEnvironment >& Environment ) + throw( uno::Exception ) +{ + try + { + std::auto_ptr< DAVResourceAccess > xResAccess; + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) ); + } + + xResAccess->UNLOCK( Environment ); + + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) ); + } + } + catch ( DAVException const & e ) + { + cancelCommandExecution( e, Environment, sal_False ); + // Unreachable + } +} + +//========================================================================= +sal_Bool Content::exchangeIdentity( + const uno::Reference< ucb::XContentIdentifier >& xNewId ) +{ + if ( !xNewId.is() ) + return sal_False; + + osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); + + uno::Reference< ucb::XContent > xThis = this; + + // Already persistent? + if ( m_bTransient ) + { + OSL_ENSURE( sal_False, "Content::exchangeIdentity - Not persistent!" ); + return sal_False; + } + + // Exchange own identitity. + + // Fail, if a content with given id already exists. +// if ( !hasData( xNewId ) ) + { + rtl::OUString aOldURL = m_xIdentifier->getContentIdentifier(); + + aGuard.clear(); + if ( exchange( xNewId ) ) + { + // Process instanciated children... + + ContentRefList aChildren; + queryChildren( aChildren ); + + ContentRefList::const_iterator it = aChildren.begin(); + ContentRefList::const_iterator end = aChildren.end(); + + while ( it != end ) + { + ContentRef xChild = (*it); + + // Create new content identifier for the child... + uno::Reference< ucb::XContentIdentifier > + xOldChildId = xChild->getIdentifier(); + rtl::OUString aOldChildURL + = xOldChildId->getContentIdentifier(); + rtl::OUString aNewChildURL + = aOldChildURL.replaceAt( + 0, + aOldURL.getLength(), + xNewId->getContentIdentifier() ); + uno::Reference< ucb::XContentIdentifier > xNewChildId + = new ::ucbhelper::ContentIdentifier( + m_xSMgr, aNewChildURL ); + + if ( !xChild->exchangeIdentity( xNewChildId ) ) + return sal_False; + + ++it; + } + return sal_True; + } + } + + OSL_ENSURE( sal_False, + "Content::exchangeIdentity - " + "Panic! Cannot exchange identity!" ); + return sal_False; +} + +//========================================================================= +sal_Bool Content::isFolder( + const uno::Reference< ucb::XCommandEnvironment >& xEnv ) + throw( uno::Exception ) +{ + { + osl::MutexGuard aGuard( m_aMutex ); + + if ( m_bTransient ) + return m_bCollection; + } + + uno::Sequence< beans::Property > aProperties( 1 ); + aProperties[ 0 ].Name = rtl::OUString::createFromAscii( "IsFolder" ); + aProperties[ 0 ].Handle = -1; + uno::Reference< sdbc::XRow > xRow( getPropertyValues( aProperties, xEnv ) ); + if ( xRow.is() ) + { + try + { + return xRow->getBoolean( 1 ); + } + catch ( sdbc::SQLException const & ) + { + } + } + + return sal_False; +} + +//========================================================================= +uno::Any Content::MapDAVException( const DAVException & e, sal_Bool bWrite ) +{ + // Map DAVException... + uno::Any aException; + + switch ( e.getStatus() ) + { + case SC_NOT_FOUND: + { + uno::Sequence< uno::Any > aArgs( 1 ); + aArgs[ 0 ] <<= beans::PropertyValue( + rtl::OUString::createFromAscii("Uri"), -1, + uno::makeAny(m_xIdentifier->getContentIdentifier()), + beans::PropertyState_DIRECT_VALUE); + + aException <<= + ucb::InteractiveAugmentedIOException( + rtl::OUString::createFromAscii( "Not found!" ), + static_cast< cppu::OWeakObject * >( this ), + task::InteractionClassification_ERROR, + ucb::IOErrorCode_NOT_EXISTING, + aArgs ); + return aException; + } + default: + break; + } + + switch ( e.getError() ) + { + case DAVException::DAV_HTTP_ERROR: + { + if ( bWrite ) + aException <<= + ucb::InteractiveNetworkWriteException( + e.getData(), + static_cast< cppu::OWeakObject * >( this ), + task::InteractionClassification_ERROR, + e.getData() ); + else + aException <<= + ucb::InteractiveNetworkReadException( + e.getData(), + static_cast< cppu::OWeakObject * >( this ), + task::InteractionClassification_ERROR, + e.getData() ); + break; + } + + case DAVException::DAV_HTTP_LOOKUP: + aException <<= + ucb::InteractiveNetworkResolveNameException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + task::InteractionClassification_ERROR, + e.getData() ); + break; + +// @@@ No matching InteractiveNetwork*Exception +// case DAVException::DAV_HTTP_AUTH: +// break; + +// @@@ No matching InteractiveNetwork*Exception +// case DAVException::DAV_HTTP_AUTHPROXY: +// break; + + case DAVException::DAV_HTTP_CONNECT: + aException <<= + ucb::InteractiveNetworkConnectException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + task::InteractionClassification_ERROR, + e.getData() ); + break; + +// @@@ No matching InteractiveNetwork*Exception +// case DAVException::DAV_HTTP_TIMEOUT: +// break; + +// @@@ No matching InteractiveNetwork*Exception +// case DAVException::DAV_HTTP_REDIRECT: +// break; + +// @@@ No matching InteractiveNetwork*Exception +// case DAVException::DAV_SESSION_CREATE: +// break; + + case DAVException::DAV_INVALID_ARG: + aException <<= + lang::IllegalArgumentException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + -1 ); + break; + + case DAVException::DAV_LOCKED: +#if 1 + aException <<= + ucb::InteractiveLockingLockedException( + rtl::OUString::createFromAscii( "Locked!" ), + static_cast< cppu::OWeakObject * >( this ), + task::InteractionClassification_ERROR, + m_xIdentifier->getContentIdentifier(), + sal_True ); +#else + { + uno::Sequence< uno::Any > aArgs( 1 ); + aArgs[ 0 ] <<= beans::PropertyValue( + rtl::OUString::createFromAscii("Uri"), -1, + uno::makeAny(m_xIdentifier->getContentIdentifier()), + beans::PropertyState_DIRECT_VALUE); + + aException <<= + ucb::InteractiveAugmentedIOException( + rtl::OUString::createFromAscii( "Locked!" ), + static_cast< cppu::OWeakObject * >( this ), + task::InteractionClassification_ERROR, + ucb::IOErrorCode_LOCKING_VIOLATION, + aArgs ); + } +#endif + break; + + case DAVException::DAV_LOCKED_SELF: + aException <<= + ucb::InteractiveLockingLockedException( + rtl::OUString::createFromAscii( "Locked (self)!" ), + static_cast< cppu::OWeakObject * >( this ), + task::InteractionClassification_ERROR, + m_xIdentifier->getContentIdentifier(), + sal_True ); + break; + + case DAVException::DAV_NOT_LOCKED: + aException <<= + ucb::InteractiveLockingNotLockedException( + rtl::OUString::createFromAscii( "Not locked!" ), + static_cast< cppu::OWeakObject * >( this ), + task::InteractionClassification_ERROR, + m_xIdentifier->getContentIdentifier() ); + break; + + case DAVException::DAV_LOCK_EXPIRED: + aException <<= + ucb::InteractiveLockingLockExpiredException( + rtl::OUString::createFromAscii( "Lock expired!" ), + static_cast< cppu::OWeakObject * >( this ), + task::InteractionClassification_ERROR, + m_xIdentifier->getContentIdentifier() ); + break; + + default: + aException <<= + ucb::InteractiveNetworkGeneralException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + task::InteractionClassification_ERROR ); + break; + } + + return aException; +} + +//========================================================================= +// static +bool Content::shouldAccessNetworkAfterException( const DAVException & e ) +{ + if ( ( e.getStatus() == SC_NOT_FOUND ) || + ( e.getError() == DAVException::DAV_HTTP_LOOKUP ) || + ( e.getError() == DAVException::DAV_HTTP_CONNECT ) || + ( e.getError() == DAVException::DAV_HTTP_AUTH ) || + ( e.getError() == DAVException::DAV_HTTP_AUTHPROXY ) ) + return false; + + return true; +} + +//========================================================================= +void Content::cancelCommandExecution( + const DAVException & e, + const uno::Reference< ucb::XCommandEnvironment > & xEnv, + sal_Bool bWrite /* = sal_False */ ) + throw ( uno::Exception ) +{ + ucbhelper::cancelCommandExecution( MapDAVException( e, bWrite ), xEnv ); + // Unreachable +} + +//========================================================================= +const rtl::OUString +Content::getBaseURI( const std::auto_ptr< DAVResourceAccess > & rResAccess ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + // First, try to obtain value of response header "Content-Location". + if ( m_xCachedProps.get() ) + { + rtl::OUString aLocation; + m_xCachedProps->getValue( rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "Content-Location" ) ) ) >>= aLocation; + if ( aLocation.getLength() ) + { + try + { + // Do not use m_xIdentifier->getContentIdentifier() because it + // for example does not reflect redirects applied to requests + // done using the original URI but m_xResAccess' URI does. + return rtl::Uri::convertRelToAbs( rResAccess->getURL(), + aLocation ); + } + catch ( rtl::MalformedUriException const & ) + { + } + } + } + + return rtl::OUString( rResAccess->getURL() ); +} + +//========================================================================= +const Content::ResourceType & Content::getResourceType( + const uno::Reference< ucb::XCommandEnvironment >& xEnv, + const std::auto_ptr< DAVResourceAccess > & rResAccess ) + throw ( uno::Exception ) +{ + if ( m_eResourceType == UNKNOWN ) + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + ResourceType eResourceType; + eResourceType = m_eResourceType; + + const rtl::OUString & rURL = rResAccess->getURL(); + const rtl::OUString aScheme( + rURL.copy( 0, rURL.indexOf( ':' ) ).toAsciiLowerCase() ); + + if ( aScheme.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( FTP_URL_SCHEME ) ) ) + { + eResourceType = FTP; + } + else + { + try + { + // Try to fetch some frequently used property value, e.g. those + // used when loading documents... along with identifying whether + // this is a DAV resource. + std::vector< DAVResource > resources; + std::vector< rtl::OUString > aPropNames; + uno::Sequence< beans::Property > aProperties( 5 ); + aProperties[ 0 ].Name + = rtl::OUString::createFromAscii( "IsFolder" ); + aProperties[ 1 ].Name + = rtl::OUString::createFromAscii( "IsDocument" ); + aProperties[ 2 ].Name + = rtl::OUString::createFromAscii( "IsReadOnly" ); + aProperties[ 3 ].Name + = rtl::OUString::createFromAscii( "MediaType" ); + aProperties[ 4 ].Name + = DAVProperties::SUPPORTEDLOCK; + + ContentProperties::UCBNamesToDAVNames( + aProperties, aPropNames ); + + rResAccess->PROPFIND( + DAVZERO, aPropNames, resources, xEnv ); + + if ( resources.size() == 1 ) + { + m_xCachedProps.reset( + new ContentProperties( resources[ 0 ] ) ); + m_xCachedProps->containsAllNames( + aProperties, m_aFailedPropNames ); + } + + eResourceType = DAV; + } + catch ( DAVException const & e ) + { + rResAccess->resetUri(); + + if ( e.getStatus() == SC_METHOD_NOT_ALLOWED ) + { + // Status SC_METHOD_NOT_ALLOWED is a safe indicator that the + // resource is NON_DAV + eResourceType = NON_DAV; + } + } + } + m_eResourceType = eResourceType; + } + return m_eResourceType; +} + +//========================================================================= +const Content::ResourceType & Content::getResourceType( + const uno::Reference< ucb::XCommandEnvironment >& xEnv ) + throw ( uno::Exception ) +{ + return getResourceType( xEnv, m_xResAccess ); +} diff --git a/ucb/source/ucp/webdav/webdavcontent.hxx b/ucb/source/ucp/webdav/webdavcontent.hxx new file mode 100644 index 000000000000..0568b2bfbb54 --- /dev/null +++ b/ucb/source/ucp/webdav/webdavcontent.hxx @@ -0,0 +1,299 @@ +/************************************************************************* + * + * 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 _WEBDAV_UCP_CONTENT_HXX +#define _WEBDAV_UCP_CONTENT_HXX + +#include <memory> +#include <list> +#include <rtl/ref.hxx> +#include <com/sun/star/ucb/ContentCreationException.hpp> +#include <com/sun/star/ucb/XContentCreator.hpp> +#include <ucbhelper/contenthelper.hxx> +#include "DAVResourceAccess.hxx" +#include "PropertyMap.hxx" + +namespace com { namespace sun { namespace star { namespace beans { + struct Property; + struct PropertyValue; +} } } } + +namespace com { namespace sun { namespace star { namespace io { + class XInputStream; +} } } } + +namespace com { namespace sun { namespace star { namespace sdbc { + class XRow; +} } } } + +namespace com { namespace sun { namespace star { namespace ucb { + struct OpenCommandArgument2; + struct PostCommandArgument2; + struct TransferInfo; +} } } } + +namespace webdav_ucp +{ + +//========================================================================= + +// UNO service name for the content. +#define WEBDAV_CONTENT_SERVICE_NAME "com.sun.star.ucb.WebDAVContent" + +//========================================================================= + +class ContentProvider; +class ContentProperties; + +class Content : public ::ucbhelper::ContentImplHelper, + public com::sun::star::ucb::XContentCreator +{ + enum ResourceType + { + UNKNOWN, + FTP, + NON_DAV, + DAV + }; + + std::auto_ptr< DAVResourceAccess > m_xResAccess; + std::auto_ptr< ContentProperties > m_xCachedProps; // locally cached props + rtl::OUString m_aEscapedTitle; + ResourceType m_eResourceType; + ContentProvider* m_pProvider; // No need for a ref, base class holds object + bool m_bTransient; + bool m_bCollection; + bool m_bDidGetOrHead; + std::vector< rtl::OUString > m_aFailedPropNames; + +private: + virtual com::sun::star::uno::Sequence< com::sun::star::beans::Property > + getProperties( const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv ); + virtual com::sun::star::uno::Sequence< com::sun::star::ucb::CommandInfo > + getCommands( const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv ); + virtual ::rtl::OUString getParentURL(); + + sal_Bool isFolder( const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment >& xEnv ) + throw ( ::com::sun::star::uno::Exception ); + + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRow > + getPropertyValues( const ::com::sun::star::uno::Sequence< + ::com::sun::star::beans::Property >& rProperties, + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment >& xEnv ) + throw ( ::com::sun::star::uno::Exception ); + + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > + setPropertyValues( const ::com::sun::star::uno::Sequence< + ::com::sun::star::beans::PropertyValue >& rValues, + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment >& xEnv ) + throw ( ::com::sun::star::uno::Exception ); + + typedef rtl::Reference< Content > ContentRef; + typedef std::list< ContentRef > ContentRefList; + void queryChildren( ContentRefList& rChildren); + + sal_Bool + exchangeIdentity( const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XContentIdentifier >& xNewId ); + + const rtl::OUString + getBaseURI( const std::auto_ptr< DAVResourceAccess > & rResAccess ); + + const ResourceType & + getResourceType( const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment >& xEnv ) + throw ( ::com::sun::star::uno::Exception ); + + const ResourceType & + getResourceType( const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment >& xEnv, + const std::auto_ptr< DAVResourceAccess > & rResAccess ) + throw ( ::com::sun::star::uno::Exception ); + + // Command "open" + com::sun::star::uno::Any open( + const com::sun::star::ucb::OpenCommandArgument2 & rArg, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw( ::com::sun::star::uno::Exception ); + + // Command "post" + void post( const com::sun::star::ucb::PostCommandArgument2 & rArg, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw( ::com::sun::star::uno::Exception ); + + // Command "insert" + void insert( const ::com::sun::star::uno::Reference< + ::com::sun::star::io::XInputStream > & xInputStream, + sal_Bool bReplaceExisting, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment >& Environment ) + throw( ::com::sun::star::uno::Exception ); + + // Command "transfer" + void transfer( const ::com::sun::star::ucb::TransferInfo & rArgs, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment >& Environment ) + throw( ::com::sun::star::uno::Exception ); + + // Command "delete" + void destroy( sal_Bool bDeletePhysical ) + throw( ::com::sun::star::uno::Exception ); + + // Command "lock" + void lock( const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment >& Environment ) + throw( ::com::sun::star::uno::Exception ); + + // Command "unlock" + void unlock( const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment >& Environment ) + throw( ::com::sun::star::uno::Exception ); + + ::com::sun::star::uno::Any MapDAVException( const DAVException & e, + sal_Bool bWrite ); + void cancelCommandExecution( + const DAVException & e, + const ::com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv, + sal_Bool bWrite = sal_False ) + throw( ::com::sun::star::uno::Exception ); + + static bool shouldAccessNetworkAfterException( const DAVException & e ); + + bool supportsExclusiveWriteLock( + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment >& Environment ); + +public: + Content( const ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + ContentProvider* pProvider, + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XContentIdentifier >& Identifier, + rtl::Reference< DAVSessionFactory > const & rSessionFactory ) + throw ( ::com::sun::star::ucb::ContentCreationException ); + Content( const ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + ContentProvider* pProvider, + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XContentIdentifier >& Identifier, + rtl::Reference< DAVSessionFactory > const & rSessionFactory, + sal_Bool isCollection ) + throw ( ::com::sun::star::ucb::ContentCreationException ); + virtual ~Content(); + + // XInterface + XINTERFACE_DECL() + + // XTypeProvider + XTYPEPROVIDER_DECL() + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL + getImplementationName() + throw( ::com::sun::star::uno::RuntimeException ); + + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL + getSupportedServiceNames() + throw( ::com::sun::star::uno::RuntimeException ); + + // XContent + virtual rtl::OUString SAL_CALL + getContentType() + throw( com::sun::star::uno::RuntimeException ); + + // XCommandProcessor + virtual com::sun::star::uno::Any SAL_CALL + execute( const com::sun::star::ucb::Command& aCommand, + sal_Int32 CommandId, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment >& Environment ) + throw( com::sun::star::uno::Exception, + com::sun::star::ucb::CommandAbortedException, + com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + abort( sal_Int32 CommandId ) + throw( com::sun::star::uno::RuntimeException ); + + // XPropertyContainer + virtual void SAL_CALL + addProperty( const rtl::OUString& Name, + sal_Int16 Attributes, + const com::sun::star::uno::Any& DefaultValue ) + throw( com::sun::star::beans::PropertyExistException, + com::sun::star::beans::IllegalTypeException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL + removeProperty( const rtl::OUString& Name ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::beans::NotRemoveableException, + com::sun::star::uno::RuntimeException ); + + ////////////////////////////////////////////////////////////////////// + // Additional interfaces + ////////////////////////////////////////////////////////////////////// + + // XContentCreator + virtual com::sun::star::uno::Sequence< + com::sun::star::ucb::ContentInfo > SAL_CALL + queryCreatableContentsInfo() + throw( com::sun::star::uno::RuntimeException ); + virtual com::sun::star::uno::Reference< + com::sun::star::ucb::XContent > SAL_CALL + createNewContent( const com::sun::star::ucb::ContentInfo& Info ) + throw( com::sun::star::uno::RuntimeException ); + + ////////////////////////////////////////////////////////////////////// + // Non-interface methods. + ////////////////////////////////////////////////////////////////////// + + DAVResourceAccess & getResourceAccess() { return *m_xResAccess; } + + // Called from resultset data supplier. + static ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRow > + getPropertyValues( const ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XMultiServiceFactory >& rSMgr, + const ::com::sun::star::uno::Sequence< + ::com::sun::star::beans::Property >& rProperties, + const ContentProperties& rData, + const rtl::Reference< + ::ucbhelper::ContentProviderImplHelper >& rProvider, + const ::rtl::OUString& rContentId ); +}; + +} + +#endif diff --git a/ucb/source/ucp/webdav/webdavcontentcaps.cxx b/ucb/source/ucp/webdav/webdavcontentcaps.cxx new file mode 100644 index 000000000000..145c256010f9 --- /dev/null +++ b/ucb/source/ucp/webdav/webdavcontentcaps.cxx @@ -0,0 +1,672 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ + +#include <set> +#include <com/sun/star/beans/Property.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/ucb/CommandInfo.hpp> +#include <com/sun/star/ucb/ContentInfo.hpp> +#include <com/sun/star/ucb/OpenCommandArgument2.hpp> +#include <com/sun/star/ucb/InsertCommandArgument.hpp> +#include <com/sun/star/ucb/PostCommandArgument2.hpp> +#include <com/sun/star/ucb/TransferInfo.hpp> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/util/DateTime.hpp> +#include <com/sun/star/ucb/Link.hpp> +#include <com/sun/star/ucb/Lock.hpp> +#include <com/sun/star/ucb/LockEntry.hpp> +#include "webdavcontent.hxx" +#include "webdavprovider.hxx" +#include "DAVSession.hxx" +#include "ContentProperties.hxx" + +using namespace com::sun::star; +using namespace webdav_ucp; + +//========================================================================= +// +// ContentProvider implementation. +// +//========================================================================= + +bool ContentProvider::getProperty( + const rtl::OUString & rPropName, beans::Property & rProp, bool bStrict ) +{ + if ( !m_pProps ) + { + osl::MutexGuard aGuard( m_aMutex ); + if ( !m_pProps ) + { + m_pProps = new PropertyMap; + + ////////////////////////////////////////////////////////////// + // Fill map of known properties... + ////////////////////////////////////////////////////////////// + + // Mandatory UCB properties. + m_pProps->insert( + beans::Property( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "ContentType" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ) ); + + m_pProps->insert( + beans::Property( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "IsDocument" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ) ); + + m_pProps->insert( + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ) ); + + m_pProps->insert( + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND ) ); + + // Optional UCB properties. + + m_pProps->insert( + beans::Property( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "DateCreated" ) ), + -1, + getCppuType( static_cast< const util::DateTime * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ) ); + + m_pProps->insert( + beans::Property( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "DateModified" ) ), + -1, + getCppuType( static_cast< const util::DateTime * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ) ); + + m_pProps->insert( + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ) ); + + m_pProps->insert( + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Size" ) ), + -1, + getCppuType( static_cast< const sal_Int64 * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ) ); + + m_pProps->insert( + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "BaseURI" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ) ); + + m_pProps->insert( + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "CreatableContentsInfo" ) ), + -1, + getCppuType( static_cast< + const uno::Sequence< ucb::ContentInfo > * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ) ); + + // Standard DAV properties. + + m_pProps->insert( + beans::Property( + DAVProperties::CREATIONDATE, + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ) ); + + m_pProps->insert( + beans::Property( + DAVProperties::DISPLAYNAME, + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND ) ); + + m_pProps->insert( + beans::Property( + DAVProperties::GETCONTENTLANGUAGE, + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ) ); + + m_pProps->insert( + beans::Property( + DAVProperties::GETCONTENTLENGTH, + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ) ); + + m_pProps->insert( + beans::Property( + DAVProperties::GETCONTENTTYPE , + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ) ); + + m_pProps->insert( + beans::Property( + DAVProperties::GETETAG, + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ) ); + + m_pProps->insert( + beans::Property( + DAVProperties::GETLASTMODIFIED, + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ) ); + + m_pProps->insert( + beans::Property( + DAVProperties::LOCKDISCOVERY, + -1, + getCppuType( static_cast< + const uno::Sequence< ucb::Lock > * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ) ); + + m_pProps->insert( + beans::Property( + DAVProperties::RESOURCETYPE, + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ) ); + + m_pProps->insert( + beans::Property( + DAVProperties::SOURCE, + -1, + getCppuType( static_cast< + const uno::Sequence< ucb::Link > * >( 0 ) ), + beans::PropertyAttribute::BOUND ) ); + + m_pProps->insert( + beans::Property( + DAVProperties::SUPPORTEDLOCK, + -1, + getCppuType( static_cast< + const uno::Sequence< + ucb::LockEntry > * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ) ); + + m_pProps->insert( + beans::Property( + DAVProperties::EXECUTABLE, + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND ) ); + } + } + + ////////////////////////////////////////////////////////////// + // Lookup property. + ////////////////////////////////////////////////////////////// + + beans::Property aProp; + aProp.Name = rPropName; + const PropertyMap::const_iterator it = m_pProps->find( aProp ); + if ( it != m_pProps->end() ) + { + rProp = (*it); + } + else + { + if ( bStrict ) + return false; + + // All unknown props are treated as: + rProp = beans::Property( + rPropName, + - 1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND ); + } + + return true; +} + +//========================================================================= +// +// Content implementation. +// +//========================================================================= + +// virtual +uno::Sequence< beans::Property > Content::getProperties( + const uno::Reference< ucb::XCommandEnvironment > & xEnv ) +{ + sal_Bool bTransient; + std::auto_ptr< DAVResourceAccess > xResAccess; + std::auto_ptr< ContentProperties > xCachedProps; + rtl::Reference< ContentProvider > xProvider; + + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + bTransient = m_bTransient; + xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) ); + if ( m_xCachedProps.get() ) + xCachedProps.reset( + new ContentProperties( *m_xCachedProps.get() ) ); + xProvider.set( m_pProvider ); + } + + typedef std::set< rtl::OUString > StringSet; + StringSet aPropSet; + + // No server access for just created (not yet committed) objects. + // Only a minimal set of properties supported at this stage. + if ( !bTransient ) + { + // Obtain all properties supported for this resource from server. + try + { + std::vector< DAVResourceInfo > props; + xResAccess->PROPFIND( DAVZERO, props, xEnv ); + + // Note: vector always contains exactly one resource info, because + // we used a depth of DAVZERO for PROPFIND. + aPropSet.insert( (*props.begin()).properties.begin(), + (*props.begin()).properties.end() ); + } + catch ( DAVException const & ) + { + } + } + + // Add DAV properties, map DAV properties to UCB properties. + sal_Bool bHasCreationDate = sal_False; // creationdate <-> DateCreated + sal_Bool bHasGetLastModified = sal_False; // getlastmodified <-> DateModified + sal_Bool bHasGetContentType = sal_False; // getcontenttype <-> MediaType + sal_Bool bHasGetContentLength = sal_False; // getcontentlength <-> Size + + sal_Bool bHasContentType = sal_False; + sal_Bool bHasIsDocument = sal_False; + sal_Bool bHasIsFolder = sal_False; + sal_Bool bHasTitle = sal_False; + sal_Bool bHasBaseURI = sal_False; + sal_Bool bHasDateCreated = sal_False; + sal_Bool bHasDateModified = sal_False; + sal_Bool bHasMediaType = sal_False; + sal_Bool bHasSize = sal_False; + sal_Bool bHasCreatableInfos = sal_False; + + { + std::set< rtl::OUString >::const_iterator it = aPropSet.begin(); + std::set< rtl::OUString >::const_iterator end = aPropSet.end(); + while ( it != end ) + { + if ( !bHasCreationDate && + ( (*it) == DAVProperties::CREATIONDATE ) ) + { + bHasCreationDate = sal_True; + } + else if ( !bHasGetLastModified && + ( (*it) == DAVProperties::GETLASTMODIFIED ) ) + { + bHasGetLastModified = sal_True; + } + else if ( !bHasGetContentType && + ( (*it) == DAVProperties::GETCONTENTTYPE ) ) + { + bHasGetContentType = sal_True; + } + else if ( !bHasGetContentLength && + ( (*it) == DAVProperties::GETCONTENTLENGTH ) ) + { + bHasGetContentLength = sal_True; + } + else if ( !bHasContentType && + (*it).equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) ) + { + bHasContentType = sal_True; + } + else if ( !bHasIsDocument && + (*it).equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) ) + { + bHasIsDocument = sal_True; + } + else if ( !bHasIsFolder && + (*it).equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) ) + { + bHasIsFolder = sal_True; + } + else if ( !bHasTitle && + (*it).equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "Title" ) ) ) + { + bHasTitle = sal_True; + } + else if ( !bHasBaseURI && + (*it).equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "BaseURI" ) ) ) + { + bHasBaseURI = sal_True; + } + else if ( !bHasDateCreated && + (*it).equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "DateCreated" ) ) ) + { + bHasDateCreated = sal_True; + } + else if ( !bHasDateModified && + (*it).equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "DateModified" ) ) ) + { + bHasDateModified = sal_True; + } + else if ( !bHasMediaType && + (*it).equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "MediaType" ) ) ) + { + bHasMediaType = sal_True; + } + else if ( !bHasSize && + (*it).equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "Size" ) ) ) + { + bHasSize = sal_True; + } + else if ( !bHasCreatableInfos && + (*it).equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( + "CreatableContentsInfo" ) ) ) + { + bHasCreatableInfos = sal_True; + } + it++; + } + } + + // Add mandatory properties. + if ( !bHasContentType ) + aPropSet.insert( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ContentType" ) ) ); + + if ( !bHasIsDocument ) + aPropSet.insert( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsDocument" ) ) ); + + if ( !bHasIsFolder ) + aPropSet.insert( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ) ); + + if ( !bHasTitle ) + { + // Always present since it can be calculated from content's URI. + aPropSet.insert( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ) ); + } + + // Add optional properties. + + if ( !bHasBaseURI ) + { + // Always present since it can be calculated from content's URI. + aPropSet.insert( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "BaseURI" ) ) ); + } + + if ( !bHasDateCreated && bHasCreationDate ) + aPropSet.insert( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DateCreated" ) ) ); + + if ( !bHasDateModified && bHasGetLastModified ) + aPropSet.insert( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DateModified" ) ) ); + + if ( !bHasMediaType && bHasGetContentType ) + aPropSet.insert( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ) ); + + if ( !bHasSize && bHasGetContentLength ) + aPropSet.insert( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Size" ) ) ); + + if ( !bHasCreatableInfos ) + aPropSet.insert( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "CreatableContentsInfo" ) ) ); + + // Add cached properties, if present and still missing. + if ( xCachedProps.get() ) + { + const std::set< rtl::OUString >::const_iterator set_end + = aPropSet.end(); + + const std::auto_ptr< PropertyValueMap > & xProps + = xCachedProps->getProperties(); + + PropertyValueMap::const_iterator map_it = xProps->begin(); + const PropertyValueMap::const_iterator map_end = xProps->end(); + + while ( map_it != map_end ) + { + if ( aPropSet.find( (*map_it).first ) == set_end ) + aPropSet.insert( (*map_it).first ); + + ++map_it; + } + } + + // std::set -> uno::Sequence + sal_Int32 nCount = aPropSet.size(); + uno::Sequence< beans::Property > aProperties( nCount ); + + std::set< rtl::OUString >::const_iterator it = aPropSet.begin(); + beans::Property aProp; + + for ( sal_Int32 n = 0; n < nCount; ++n, ++it ) + { + xProvider->getProperty( (*it), aProp ); + aProperties[ n ] = aProp; + } + + return aProperties; +} + +//========================================================================= +// virtual +uno::Sequence< ucb::CommandInfo > Content::getCommands( + const uno::Reference< ucb::XCommandEnvironment > & xEnv ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + uno::Sequence< ucb::CommandInfo > aCmdInfo( 8 ); + + /////////////////////////////////////////////////////////////// + // Mandatory commands + /////////////////////////////////////////////////////////////// + + aCmdInfo[ 0 ] = + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getCommandInfo" ) ), + -1, + getCppuVoidType() ); + aCmdInfo[ 1 ] = + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertySetInfo" ) ), + -1, + getCppuVoidType() ); + aCmdInfo[ 2 ] = + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertyValues" ) ), + -1, + getCppuType( static_cast< + uno::Sequence< beans::Property > * >( 0 ) ) ); + aCmdInfo[ 3 ] = + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ), + -1, + getCppuType( static_cast< + uno::Sequence< beans::PropertyValue > * >( 0 ) ) ); + + /////////////////////////////////////////////////////////////// + // Optional standard commands + /////////////////////////////////////////////////////////////// + + aCmdInfo[ 4 ] = + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "delete" ) ), + -1, + getCppuBooleanType() ); + aCmdInfo[ 5 ] = + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "insert" ) ), + -1, + getCppuType( static_cast< + ucb::InsertCommandArgument * >( 0 ) ) ); + aCmdInfo[ 6 ] = + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "open" ) ), + -1, + getCppuType( static_cast< + ucb::OpenCommandArgument2 * >( 0 ) ) ); + + /////////////////////////////////////////////////////////////// + // New commands + /////////////////////////////////////////////////////////////// + + aCmdInfo[ 7 ] = + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "post" ) ), + -1, + getCppuType( static_cast< + ucb::PostCommandArgument2 * >( 0 ) ) ); + + sal_Bool bFolder = sal_False; + + try + { + bFolder = isFolder( xEnv ); + } + catch ( uno::Exception const & ) + { + return aCmdInfo; + } + + sal_Bool bSupportsLocking = supportsExclusiveWriteLock( xEnv ); + + sal_Int32 nPos = aCmdInfo.getLength(); + sal_Int32 nMoreCmds = ( bFolder ? 2 : 0 ) + ( bSupportsLocking ? 2 : 0 ); + if ( nMoreCmds ) + aCmdInfo.realloc( nPos + nMoreCmds ); + else + return aCmdInfo; + + if ( bFolder ) + { + /////////////////////////////////////////////////////////////// + // Optional standard commands + /////////////////////////////////////////////////////////////// + + aCmdInfo[ nPos ] = + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "transfer" ) ), + -1, + getCppuType( static_cast< ucb::TransferInfo * >( 0 ) ) ); + nPos++; + aCmdInfo[ nPos ] = + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "createNewContent" ) ), + -1, + getCppuType( static_cast< ucb::ContentInfo * >( 0 ) ) ); + nPos++; + } + else + { + // no document-only commands at the moment. + } + + if ( bSupportsLocking ) + { + aCmdInfo[ nPos ] = + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "lock" ) ), + -1, + getCppuVoidType() ); + nPos++; + aCmdInfo[ nPos ] = + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "unlock" ) ), + -1, + getCppuVoidType() ); + nPos++; + } + return aCmdInfo; +} diff --git a/ucb/source/ucp/webdav/webdavdatasupplier.cxx b/ucb/source/ucp/webdav/webdavdatasupplier.cxx new file mode 100644 index 000000000000..8d2683939f0d --- /dev/null +++ b/ucb/source/ucp/webdav/webdavdatasupplier.cxx @@ -0,0 +1,512 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ +#include <osl/diagnose.h> +#include <com/sun/star/ucb/OpenMode.hpp> +#include <ucbhelper/contentidentifier.hxx> +#include <ucbhelper/providerhelper.hxx> +#include "webdavdatasupplier.hxx" +#include "webdavcontent.hxx" +#include "ContentProperties.hxx" +#ifndef _WEBDAV_SESSION_HXX +#include "DAVSession.hxx" +#endif +#include "NeonUri.hxx" + +using namespace com::sun::star; +using namespace webdav_ucp; + +namespace webdav_ucp +{ + +//========================================================================= +// +// struct ResultListEntry. +// +//========================================================================= + +struct ResultListEntry +{ + rtl::OUString aId; + uno::Reference< ucb::XContentIdentifier > xId; + uno::Reference< ucb::XContent > xContent; + uno::Reference< sdbc::XRow > xRow; + const ContentProperties* pData; + + ResultListEntry( const ContentProperties* pEntry ) : pData( pEntry ) {}; + ~ResultListEntry() { delete pData; } +}; + +//========================================================================= +// +// ResultList. +// +//========================================================================= + +typedef std::vector< ResultListEntry* > ResultList; + +//========================================================================= +// +// struct DataSupplier_Impl. +// +//========================================================================= + +struct DataSupplier_Impl +{ + osl::Mutex m_aMutex; + ResultList m_aResults; + rtl::Reference< Content > m_xContent; + uno::Reference< lang::XMultiServiceFactory > m_xSMgr; + sal_Int32 m_nOpenMode; + sal_Bool m_bCountFinal; + sal_Bool m_bThrowException; + + DataSupplier_Impl( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + const rtl::Reference< Content >& rContent, + sal_Int32 nOpenMode ) + : m_xContent( rContent ), m_xSMgr( rxSMgr ), m_nOpenMode( nOpenMode ), + m_bCountFinal( sal_False ), m_bThrowException( sal_False ) {} + ~DataSupplier_Impl(); +}; + +//========================================================================= +DataSupplier_Impl::~DataSupplier_Impl() +{ + ResultList::const_iterator it = m_aResults.begin(); + ResultList::const_iterator end = m_aResults.end(); + + while ( it != end ) + { + delete (*it); + it++; + } +} + +} + +//========================================================================= +//========================================================================= +// +// DataSupplier Implementation. +// +//========================================================================= +//========================================================================= + +DataSupplier::DataSupplier( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + const rtl::Reference< Content >& rContent, + sal_Int32 nOpenMode ) +: m_pImpl( new DataSupplier_Impl( rxSMgr, rContent, nOpenMode ) ) +{ +} + +//========================================================================= +// virtual +DataSupplier::~DataSupplier() +{ + delete m_pImpl; +} + +//========================================================================= +// virtual +rtl::OUString DataSupplier::queryContentIdentifierString( sal_uInt32 nIndex ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( nIndex < m_pImpl->m_aResults.size() ) + { + rtl::OUString aId = m_pImpl->m_aResults[ nIndex ]->aId; + if ( aId.getLength() ) + { + // Already cached. + return aId; + } + } + + if ( getResult( nIndex ) ) + { + rtl::OUString aId = m_pImpl->m_xContent->getResourceAccess().getURL(); + + const ContentProperties& props + = *( m_pImpl->m_aResults[ nIndex ]->pData ); + + if ( ( aId.lastIndexOf( '/' ) + 1 ) != aId.getLength() ) + aId += rtl::OUString::createFromAscii( "/" ); + + aId += props.getEscapedTitle(); + + if ( props.isTrailingSlash() ) + aId += rtl::OUString::createFromAscii( "/" ); + + m_pImpl->m_aResults[ nIndex ]->aId = aId; + return aId; + } + return rtl::OUString(); +} + +//========================================================================= +// virtual +uno::Reference< ucb::XContentIdentifier > +DataSupplier::queryContentIdentifier( sal_uInt32 nIndex ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( nIndex < m_pImpl->m_aResults.size() ) + { + uno::Reference< ucb::XContentIdentifier > xId + = m_pImpl->m_aResults[ nIndex ]->xId; + if ( xId.is() ) + { + // Already cached. + return xId; + } + } + + rtl::OUString aId = queryContentIdentifierString( nIndex ); + if ( aId.getLength() ) + { + uno::Reference< ucb::XContentIdentifier > xId + = new ::ucbhelper::ContentIdentifier( aId ); + m_pImpl->m_aResults[ nIndex ]->xId = xId; + return xId; + } + return uno::Reference< ucb::XContentIdentifier >(); +} + +//========================================================================= +// virtual +uno::Reference< ucb::XContent > +DataSupplier::queryContent( sal_uInt32 nIndex ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( nIndex < m_pImpl->m_aResults.size() ) + { + uno::Reference< ucb::XContent > xContent + = m_pImpl->m_aResults[ nIndex ]->xContent; + if ( xContent.is() ) + { + // Already cached. + return xContent; + } + } + + uno::Reference< ucb::XContentIdentifier > xId + = queryContentIdentifier( nIndex ); + if ( xId.is() ) + { + try + { + uno::Reference< ucb::XContent > xContent + = m_pImpl->m_xContent->getProvider()->queryContent( xId ); + m_pImpl->m_aResults[ nIndex ]->xContent = xContent; + return xContent; + + } + catch ( ucb::IllegalIdentifierException& ) + { + } + } + return uno::Reference< ucb::XContent >(); +} + +//========================================================================= +// virtual +sal_Bool DataSupplier::getResult( sal_uInt32 nIndex ) +{ + osl::ClearableGuard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( m_pImpl->m_aResults.size() > nIndex ) + { + // Result already present. + return sal_True; + } + + // Obtain values... + if ( getData() ) + { + if ( m_pImpl->m_aResults.size() > nIndex ) + { + // Result already present. + return sal_True; + } + } + + return sal_False; +} + +//========================================================================= +// virtual +sal_uInt32 DataSupplier::totalCount() +{ + // Obtain values... + getData(); + + return m_pImpl->m_aResults.size(); +} + +//========================================================================= +// virtual +sal_uInt32 DataSupplier::currentCount() +{ + return m_pImpl->m_aResults.size(); +} + +//========================================================================= +// virtual +sal_Bool DataSupplier::isCountFinal() +{ + return m_pImpl->m_bCountFinal; +} + +//========================================================================= +// virtual +uno::Reference< sdbc::XRow > DataSupplier::queryPropertyValues( + sal_uInt32 nIndex ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( nIndex < m_pImpl->m_aResults.size() ) + { + uno::Reference< sdbc::XRow > xRow = m_pImpl->m_aResults[ nIndex ]->xRow; + if ( xRow.is() ) + { + // Already cached. + return xRow; + } + } + + if ( getResult( nIndex ) ) + { + uno::Reference< sdbc::XRow > xRow + = Content::getPropertyValues( + m_pImpl->m_xSMgr, + getResultSet()->getProperties(), + *(m_pImpl->m_aResults[ nIndex ]->pData), + rtl::Reference< ::ucbhelper::ContentProviderImplHelper >( + m_pImpl->m_xContent->getProvider().get() ), + queryContentIdentifierString( nIndex ) ); + m_pImpl->m_aResults[ nIndex ]->xRow = xRow; + return xRow; + } + + return uno::Reference< sdbc::XRow >(); +} + +//========================================================================= +// virtual +void DataSupplier::releasePropertyValues( sal_uInt32 nIndex ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( nIndex < m_pImpl->m_aResults.size() ) + m_pImpl->m_aResults[ nIndex ]->xRow = uno::Reference< sdbc::XRow >(); +} + +//========================================================================= +// virtual +void DataSupplier::close() +{ +} + +//========================================================================= +// virtual +void DataSupplier::validate() + throw( ucb::ResultSetException ) +{ + if ( m_pImpl->m_bThrowException ) + throw ucb::ResultSetException(); +} + +//========================================================================= +sal_Bool DataSupplier::getData() +{ + osl::ClearableGuard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( !m_pImpl->m_bCountFinal ) + { + std::vector< rtl::OUString > propertyNames; + ContentProperties::UCBNamesToDAVNames( + getResultSet()->getProperties(), propertyNames ); + + // Append "resourcetype", if not already present. It's value is + // needed to get a valid ContentProperties::pIsFolder value, which + // is needed for OpenMode handling. + + std::vector< rtl::OUString >::const_iterator it + = propertyNames.begin(); + std::vector< rtl::OUString >::const_iterator end + = propertyNames.end(); + + while ( it != end ) + { + if ( (*it).equals( DAVProperties::RESOURCETYPE ) ) + break; + + it++; + } + + if ( it == end ) + propertyNames.push_back( DAVProperties::RESOURCETYPE ); + + std::vector< DAVResource > resources; + try + { + // propfind depth 1, get property values for parent AND for each + // child + m_pImpl->m_xContent->getResourceAccess() + .PROPFIND( DAVONE, + propertyNames, + resources, + getResultSet()->getEnvironment() ); + } + catch ( DAVException & ) + { +// OSL_ENSURE( sal_False, "PROPFIND : DAVException" ); + m_pImpl->m_bThrowException = sal_True; + } + + if ( !m_pImpl->m_bThrowException ) + { + try + { + NeonUri aURI( + m_pImpl->m_xContent->getResourceAccess().getURL() ); + rtl::OUString aPath = aURI.GetPath(); + + if ( aPath.getStr()[ aPath.getLength() - 1 ] + == sal_Unicode( '/' ) ) + aPath = aPath.copy( 0, aPath.getLength() - 1 ); + + aPath = NeonUri::unescape( aPath ); + bool bFoundParent = false; + + for ( sal_uInt32 n = 0; n < resources.size(); ++n ) + { + const DAVResource & rRes = resources[ n ]; + + // Filter parent, which is contained somewhere(!) in + // the vector. + if ( !bFoundParent ) + { + try + { + NeonUri aCurrURI( rRes.uri ); + rtl::OUString aCurrPath = aCurrURI.GetPath(); + if ( aCurrPath.getStr()[ + aCurrPath.getLength() - 1 ] + == sal_Unicode( '/' ) ) + aCurrPath + = aCurrPath.copy( + 0, + aCurrPath.getLength() - 1 ); + + aCurrPath = NeonUri::unescape( aCurrPath ); + if ( aPath == aCurrPath ) + { + bFoundParent = true; + continue; + } + } + catch ( DAVException const & ) + { + // do nothing, ignore error. continue. + } + } + + ContentProperties* pContentProperties + = new ContentProperties( rRes ); + + // Check resource against open mode. + switch ( m_pImpl->m_nOpenMode ) + { + case ucb::OpenMode::FOLDERS: + { + sal_Bool bFolder = sal_False; + + const uno::Any & rValue + = pContentProperties->getValue( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "IsFolder" ) ) ); + rValue >>= bFolder; + + if ( !bFolder ) + continue; + + break; + } + + case ucb::OpenMode::DOCUMENTS: + { + sal_Bool bDocument = sal_False; + + const uno::Any & rValue + = pContentProperties->getValue( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "IsDocument" ) ) ); + rValue >>= bDocument; + + if ( !bDocument ) + continue; + + break; + } + + case ucb::OpenMode::ALL: + default: + break; + } + + m_pImpl->m_aResults.push_back( + new ResultListEntry( pContentProperties ) ); + } + } + catch ( DAVException const & ) + { + } + } + + m_pImpl->m_bCountFinal = sal_True; + + // Callback possible, because listeners may be informed! + aGuard.clear(); + getResultSet()->rowCountFinal(); + } + return !m_pImpl->m_bThrowException; +} + diff --git a/ucb/source/ucp/webdav/webdavdatasupplier.hxx b/ucb/source/ucp/webdav/webdavdatasupplier.hxx new file mode 100644 index 000000000000..b28263df0201 --- /dev/null +++ b/ucb/source/ucp/webdav/webdavdatasupplier.hxx @@ -0,0 +1,82 @@ +/************************************************************************* + * + * 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 _WEBDAV_UCP_DATASUPPLIER_HXX +#define _WEBDAV_UCP_DATASUPPLIER_HXX + +#include <vector> +#include <rtl/ref.hxx> +#include <ucbhelper/resultset.hxx> + +namespace webdav_ucp { + +struct DataSupplier_Impl; +class Content; +struct DAVResource; +class ContentProperties; + +class DataSupplier : public ucbhelper::ResultSetDataSupplier +{ + DataSupplier_Impl* m_pImpl; + +private: + sal_Bool getData(); + +public: + DataSupplier( const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + const rtl::Reference< Content >& rContent, + sal_Int32 nOpenMode); + + virtual ~DataSupplier(); + + virtual rtl::OUString queryContentIdentifierString( sal_uInt32 nIndex ); + virtual com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier > + queryContentIdentifier( sal_uInt32 nIndex ); + virtual com::sun::star::uno::Reference< com::sun::star::ucb::XContent > + queryContent( sal_uInt32 nIndex ); + + virtual sal_Bool getResult( sal_uInt32 nIndex ); + + virtual sal_uInt32 totalCount(); + virtual sal_uInt32 currentCount(); + virtual sal_Bool isCountFinal(); + + virtual com::sun::star::uno::Reference< com::sun::star::sdbc::XRow > + queryPropertyValues( sal_uInt32 nIndex ); + virtual void releasePropertyValues( sal_uInt32 nIndex ); + + virtual void close(); + + virtual void validate() + throw( com::sun::star::ucb::ResultSetException ); +}; + +} + +#endif diff --git a/ucb/source/ucp/webdav/webdavprovider.cxx b/ucb/source/ucp/webdav/webdavprovider.cxx new file mode 100644 index 000000000000..cc9c69a15e25 --- /dev/null +++ b/ucb/source/ucp/webdav/webdavprovider.cxx @@ -0,0 +1,232 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ +#include <ucbhelper/contentidentifier.hxx> +#include "webdavprovider.hxx" +#include "webdavcontent.hxx" + +#include "osl/mutex.hxx" + +using namespace com::sun::star; +using namespace webdav_ucp; + +//========================================================================= +//========================================================================= +// +// ContentProvider Implementation. +// +//========================================================================= +//========================================================================= + +ContentProvider::ContentProvider( + const uno::Reference< lang::XMultiServiceFactory >& rSMgr ) +: ::ucbhelper::ContentProviderImplHelper( rSMgr ), + m_xDAVSessionFactory( new DAVSessionFactory() ), + m_pProps( 0 ) +{ +} + +//========================================================================= +// virtual +ContentProvider::~ContentProvider() +{ + delete m_pProps; +} + +//========================================================================= +// +// XInterface methods. +// +//========================================================================= + +XINTERFACE_IMPL_3( ContentProvider, + lang::XTypeProvider, + lang::XServiceInfo, + ucb::XContentProvider ); + +//========================================================================= +// +// XTypeProvider methods. +// +//========================================================================= + +XTYPEPROVIDER_IMPL_3( ContentProvider, + lang::XTypeProvider, + lang::XServiceInfo, + ucb::XContentProvider ); + +//========================================================================= +// +// XServiceInfo methods. +// +//========================================================================= + +XSERVICEINFO_IMPL_1( ContentProvider, + rtl::OUString::createFromAscii( + "com.sun.star.comp.WebDAVContentProvider" ), + rtl::OUString::createFromAscii( + WEBDAV_CONTENT_PROVIDER_SERVICE_NAME ) ); + +//========================================================================= +// +// Service factory implementation. +// +//========================================================================= + +ONE_INSTANCE_SERVICE_FACTORY_IMPL( ContentProvider ); + +//========================================================================= +// +// XContentProvider methods. +// +//========================================================================= + +// virtual +uno::Reference< ucb::XContent > SAL_CALL +ContentProvider::queryContent( + const uno::Reference< + ucb::XContentIdentifier >& Identifier ) + throw( ucb::IllegalIdentifierException, + uno::RuntimeException ) +{ + // Check URL scheme... + + const rtl::OUString aScheme + = Identifier->getContentProviderScheme().toAsciiLowerCase(); + if ( !aScheme.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( HTTP_URL_SCHEME ) ) && + !aScheme.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( HTTPS_URL_SCHEME ) ) && + !aScheme.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( WEBDAV_URL_SCHEME ) ) && + !aScheme.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( DAV_URL_SCHEME ) ) && + !aScheme.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( DAVS_URL_SCHEME ) ) && + !aScheme.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( FTP_URL_SCHEME ) ) ) + throw ucb::IllegalIdentifierException(); + + // Normalize URL and create new Id, if nessacary. + rtl::OUString aURL = Identifier->getContentIdentifier(); + + // At least: <scheme> + "://" + if ( aURL.getLength() < ( aScheme.getLength() + 3 ) ) + throw ucb::IllegalIdentifierException(); + + if ( ( aURL.getStr()[ aScheme.getLength() ] != sal_Unicode( ':' ) ) || + ( aURL.getStr()[ aScheme.getLength() + 1 ] != sal_Unicode( '/' ) ) || + ( aURL.getStr()[ aScheme.getLength() + 2 ] != sal_Unicode( '/' ) ) ) + throw ucb::IllegalIdentifierException(); + + uno::Reference< ucb::XContentIdentifier > xCanonicId; + + bool bNewId = false; + if ( aScheme.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( WEBDAV_URL_SCHEME ) ) ) + { + aURL = aURL.replaceAt( 0, + WEBDAV_URL_SCHEME_LENGTH, + rtl::OUString::createFromAscii( + HTTP_URL_SCHEME ) ); + bNewId = true; + } + else if ( aScheme.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( DAV_URL_SCHEME ) ) ) + { + aURL = aURL.replaceAt( 0, + DAV_URL_SCHEME_LENGTH, + rtl::OUString::createFromAscii( + HTTP_URL_SCHEME ) ); + bNewId = true; + } + else if ( aScheme.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( DAVS_URL_SCHEME ) ) ) + { + aURL = aURL.replaceAt( 0, + DAVS_URL_SCHEME_LENGTH, + rtl::OUString::createFromAscii( + HTTPS_URL_SCHEME ) ); + bNewId = true; + } + + sal_Int32 nPos = aURL.lastIndexOf( '/' ); + if ( nPos != aURL.getLength() - 1 ) + { + // Find second slash in URL. + nPos = aURL.indexOf( '/', aURL.indexOf( '/' ) + 1 ); + if ( nPos == -1 ) + throw ucb::IllegalIdentifierException(); + + nPos = aURL.indexOf( '/', nPos + 1 ); + if ( nPos == -1 ) + { + aURL += rtl::OUString::createFromAscii( "/" ); + bNewId = true; + } + } + + if ( bNewId ) + xCanonicId = new ::ucbhelper::ContentIdentifier( m_xSMgr, aURL ); + else + xCanonicId = Identifier; + + osl::MutexGuard aGuard( m_aMutex ); + + // Check, if a content with given id already exists... + uno::Reference< ucb::XContent > xContent + = queryExistingContent( xCanonicId ).get(); + if ( xContent.is() ) + return xContent; + + // Create a new content. + + try + { + xContent = new ::webdav_ucp::Content( + m_xSMgr, this, xCanonicId, m_xDAVSessionFactory ); + registerNewContent( xContent ); + } + catch ( ucb::ContentCreationException const & ) + { + throw ucb::IllegalIdentifierException(); + } + + if ( !xContent->getIdentifier().is() ) + throw ucb::IllegalIdentifierException(); + + return xContent; +} + diff --git a/ucb/source/ucp/webdav/webdavprovider.hxx b/ucb/source/ucp/webdav/webdavprovider.hxx new file mode 100644 index 000000000000..286f2e474c16 --- /dev/null +++ b/ucb/source/ucp/webdav/webdavprovider.hxx @@ -0,0 +1,124 @@ +/************************************************************************* + * + * 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 _WEBDAV_UCP_PROVIDER_HXX +#define _WEBDAV_UCP_PROVIDER_HXX + +#include <rtl/ref.hxx> +#include <com/sun/star/beans/Property.hpp> +#include "DAVSessionFactory.hxx" +#include <ucbhelper/providerhelper.hxx> +#include "PropertyMap.hxx" + +namespace webdav_ucp { + +//========================================================================= + +// UNO service name for the provider. This name will be used by the UCB to +// create instances of the provider. +#define WEBDAV_CONTENT_PROVIDER_SERVICE_NAME \ + "com.sun.star.ucb.WebDAVContentProvider" +#define WEBDAV_CONTENT_PROVIDER_SERVICE_NAME_LENGTH 38 + +// URL scheme. This is the scheme the provider will be able to create +// contents for. The UCB will select the provider ( i.e. in order to create +// contents ) according to this scheme. +#define WEBDAV_URL_SCHEME \ + "vnd.sun.star.webdav" +#define WEBDAV_URL_SCHEME_LENGTH 19 + +#define HTTP_URL_SCHEME "http" +#define HTTP_URL_SCHEME_LENGTH 4 + +#define HTTPS_URL_SCHEME "https" +#define HTTPS_URL_SCHEME_LENGTH 5 + +#define DAV_URL_SCHEME "dav" +#define DAV_URL_SCHEME_LENGTH 3 + +#define DAVS_URL_SCHEME "davs" +#define DAVS_URL_SCHEME_LENGTH 4 + + + +#define FTP_URL_SCHEME "ftp" + +#define HTTP_CONTENT_TYPE \ + "application/" HTTP_URL_SCHEME "-content" + +#define WEBDAV_CONTENT_TYPE HTTP_CONTENT_TYPE +#define WEBDAV_COLLECTION_TYPE \ + "application/" WEBDAV_URL_SCHEME "-collection" + +//========================================================================= + +class ContentProvider : public ::ucbhelper::ContentProviderImplHelper +{ + rtl::Reference< DAVSessionFactory > m_xDAVSessionFactory; + PropertyMap * m_pProps; + +public: + ContentProvider( const ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XMultiServiceFactory >& rSMgr ); + virtual ~ContentProvider(); + + // XInterface + XINTERFACE_DECL() + + // XTypeProvider + XTYPEPROVIDER_DECL() + + // XServiceInfo + XSERVICEINFO_DECL() + + // XContentProvider + virtual ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XContent > SAL_CALL + queryContent( const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XContentIdentifier >& Identifier ) + throw( ::com::sun::star::ucb::IllegalIdentifierException, + ::com::sun::star::uno::RuntimeException ); + + ////////////////////////////////////////////////////////////////////// + // Additional interfaces + ////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////// + // Non-interface methods. + ////////////////////////////////////////////////////////////////////// + + rtl::Reference< DAVSessionFactory > getDAVSessionFactory() + { return m_xDAVSessionFactory; } + + bool getProperty( const ::rtl::OUString & rPropName, + ::com::sun::star::beans::Property & rProp, + bool bStrict = false ); +}; + +} + +#endif diff --git a/ucb/source/ucp/webdav/webdavresultset.cxx b/ucb/source/ucp/webdav/webdavresultset.cxx new file mode 100644 index 000000000000..cf4cc88fd12f --- /dev/null +++ b/ucb/source/ucp/webdav/webdavresultset.cxx @@ -0,0 +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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + - This implementation is not a dynamic result set!!! It only implements + the necessary interfaces, but never recognizes/notifies changes!!! + + *************************************************************************/ +#include "webdavresultset.hxx" +#ifndef _WEBDAV_SESSION_HXX +#include "DAVSession.hxx" +#endif + +using namespace com::sun::star; +using namespace webdav_ucp; + +//========================================================================= +//========================================================================= +// +// DynamicResultSet Implementation. +// +//========================================================================= +//========================================================================= + +DynamicResultSet::DynamicResultSet( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + const rtl::Reference< Content >& rxContent, + const ucb::OpenCommandArgument2& rCommand, + const uno::Reference< ucb::XCommandEnvironment >& rxEnv ) +: ResultSetImplHelper( rxSMgr, rCommand ), + m_xContent( rxContent ), + m_xEnv( rxEnv ) +{ +} + +//========================================================================= +// +// Non-interface methods. +// +//========================================================================= + +void DynamicResultSet::initStatic() +{ + m_xResultSet1 + = new ::ucbhelper::ResultSet( m_xSMgr, + m_aCommand.Properties, + new DataSupplier( m_xSMgr, + m_xContent, + m_aCommand.Mode ), + m_xEnv ); +} + +//========================================================================= +void DynamicResultSet::initDynamic() +{ + m_xResultSet1 + = new ::ucbhelper::ResultSet( m_xSMgr, + m_aCommand.Properties, + new DataSupplier( m_xSMgr, + m_xContent, + m_aCommand.Mode ), + m_xEnv ); + m_xResultSet2 = m_xResultSet1; +} + diff --git a/ucb/source/ucp/webdav/webdavresultset.hxx b/ucb/source/ucp/webdav/webdavresultset.hxx new file mode 100644 index 000000000000..a438cc208e09 --- /dev/null +++ b/ucb/source/ucp/webdav/webdavresultset.hxx @@ -0,0 +1,59 @@ +/************************************************************************* + * + * 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 _WEBDAV_UCP_RESULTSET_HXX +#define _WEBDAV_UCP_RESULTSET_HXX + +#include <rtl/ref.hxx> +#include <ucbhelper/resultsethelper.hxx> +#include "webdavcontent.hxx" +#include "webdavdatasupplier.hxx" + +namespace webdav_ucp { + +class DynamicResultSet : public ::ucbhelper::ResultSetImplHelper +{ + rtl::Reference< Content > m_xContent; + com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > m_xEnv; + +private: + virtual void initStatic(); + virtual void initDynamic(); + +public: + DynamicResultSet( const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + const rtl::Reference< Content >& rxContent, + const com::sun::star::ucb::OpenCommandArgument2& rCommand, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment >& rxEnv ); +}; + +} + +#endif diff --git a/ucb/source/ucp/webdav/webdavservices.cxx b/ucb/source/ucp/webdav/webdavservices.cxx new file mode 100644 index 000000000000..7a38636e9dc7 --- /dev/null +++ b/ucb/source/ucp/webdav/webdavservices.cxx @@ -0,0 +1,76 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <com/sun/star/registry/XRegistryKey.hpp> +#include "webdavprovider.hxx" + +using namespace com::sun::star; + +//========================================================================= +extern "C" void SAL_CALL component_getImplementationEnvironment( + const sal_Char ** ppEnvTypeName, uno_Environment ** /*ppEnv*/ ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + +//========================================================================= +extern "C" void * SAL_CALL component_getFactory( + const sal_Char * pImplName, void * pServiceManager, void * /*pRegistryKey*/ ) +{ + void * pRet = 0; + + uno::Reference< lang::XMultiServiceFactory > xSMgr( + reinterpret_cast< lang::XMultiServiceFactory * >( + pServiceManager ) ); + uno::Reference< lang::XSingleServiceFactory > xFactory; + + ////////////////////////////////////////////////////////////////////// + // WebDAV Content Provider. + ////////////////////////////////////////////////////////////////////// + + if ( ::webdav_ucp::ContentProvider::getImplementationName_Static(). + compareToAscii( pImplName ) == 0 ) + { + xFactory = ::webdav_ucp::ContentProvider::createServiceFactory( xSMgr ); + } + + ////////////////////////////////////////////////////////////////////// + + if ( xFactory.is() ) + { + xFactory->acquire(); + pRet = xFactory.get(); + } + + return pRet; +} + + diff --git a/ucb/test/com/sun/star/comp/ucb/GlobalTransfer_Test.java b/ucb/test/com/sun/star/comp/ucb/GlobalTransfer_Test.java new file mode 100644 index 000000000000..72670bc314dd --- /dev/null +++ b/ucb/test/com/sun/star/comp/ucb/GlobalTransfer_Test.java @@ -0,0 +1,214 @@ +/************************************************************************* + * + * 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 com.sun.star.comp.ucb; + +import complexlib.ComplexTestCase; +import com.sun.star.lang.IllegalArgumentException; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.task.XInteractionAbort; +import com.sun.star.task.XInteractionHandler; +import com.sun.star.task.XInteractionRequest; +import com.sun.star.task.XInteractionContinuation; +import com.sun.star.ucb.Command; +import com.sun.star.ucb.GlobalTransferCommandArgument; +import com.sun.star.ucb.NameClash; +import com.sun.star.ucb.NameClashResolveRequest; +import com.sun.star.ucb.TransferCommandOperation; +import com.sun.star.ucb.XCommandEnvironment; +import com.sun.star.ucb.XCommandProcessor; +import com.sun.star.ucb.XInteractionReplaceExistingData; +import com.sun.star.ucb.XInteractionSupplyName; +import com.sun.star.ucb.XProgressHandler; +import com.sun.star.uno.AnyConverter; +import com.sun.star.uno.UnoRuntime; +import java.io.PrintWriter; + +public final class GlobalTransfer_Test extends ComplexTestCase { + + static private final String fileName + = "testcase-do-not-remove.sxw"; + static private final String httpSourceDir + = "http://so-berlin/~webdav/"; + static private final String httpTargetDir + = "http://so-berlin/~webdav/"; + static private final String fileSourceDir + = "file:///d:/temp/source/"; + static private final String fileTargetDir + = "file:///d:/temp/"; + + public String getTestObjectName() { + return getClass().getName(); + } + + public String[] getTestMethodNames() { + return new String[] { "testNameClashASK" }; + } + + public void testNameClashASK() throws Exception { + Object oObj = null; + try { + XMultiServiceFactory xMSF = (XMultiServiceFactory)param.getMSF(); + oObj + = xMSF.createInstance( "com.sun.star.ucb.UniversalContentBroker" ); + } + catch(com.sun.star.uno.Exception e) { + e.printStackTrace((PrintWriter)log); + + // After this exception the test has failed and cannot continue. + failed( "Cannot create service instance: com.sun.star.ucb." + + "UniversalContentBroker. message:" + e.getMessage() ); + return; + } + + if ( oObj == null ) { + failed( "Cannot create service instance: com.sun.star.ucb." + + "UniversalContentBroker"); + return; + } + + XCommandProcessor xCmdProc + = (XCommandProcessor)UnoRuntime.queryInterface( + XCommandProcessor.class, oObj ); + assure( "UCB does not implement mandatory interface XCommandProcessor!", + xCmdProc != null); + + ResourceCopier cp = new ResourceCopier( xCmdProc ); + + try { + cp.copyResource( httpSourceDir, fileTargetDir, fileName ); + } + catch(com.sun.star.uno.Exception e) { + e.printStackTrace((PrintWriter)log); + + // After this exception the test has failed and cannot continue. + failed( "Could not copy resource:" + e.getMessage() ); + } + } + + private final class ResourceCopier { + private XCommandProcessor m_cmdProc = null; + private CommandEnvironment m_env = new CommandEnvironment(); + + ResourceCopier( XCommandProcessor oCmdProc ) + { + m_cmdProc = oCmdProc; + } + + public void copyResource( + String sourceDir, String targetDir, String fileName ) + throws Exception { + + GlobalTransferCommandArgument transferArg + = new GlobalTransferCommandArgument( + TransferCommandOperation.COPY, + sourceDir + fileName, + targetDir, + "", + NameClash.ASK ); + + Command cmd = new Command( "globalTransfer", -1, transferArg ); + + m_cmdProc.execute( cmd, 0, m_env ); + } + } + + private final class CommandEnvironment implements XCommandEnvironment { + private final XInteractionHandler m_InteractionHandler + = new InteractionHadler(); + + public XInteractionHandler getInteractionHandler() { + return m_InteractionHandler; + } + + public XProgressHandler getProgressHandler() { + // not needed for the test. + return null; + } + } + + private final class InteractionHadler implements XInteractionHandler { + public void handle( /*IN*/XInteractionRequest Request ) { + + log.println( "Interaction Handler called." ); + + try { + NameClashResolveRequest req = (NameClashResolveRequest) + AnyConverter.toObject( + NameClashResolveRequest.class, Request.getRequest() ); + + log.println( "Interaction Handler: NameClashResolveRequest: " + + req.ClashingName ); + + XInteractionContinuation[] continuations + = Request.getContinuations(); + for ( int i = 0; i < continuations.length; ++i ) { +/* + XInteractionAbort xAbort + = (XInteractionAbort)UnoRuntime.queryInterface( + XInteractionAbort.class, continuations[ i ] ); + if ( xAbort != null ) { + log.println( "Interaction Handler selects: ABORT" ); + xAbort.select(); + return; + } +*/ +/* + XInteractionReplaceExistingData xReplace + = (XInteractionReplaceExistingData) + UnoRuntime.queryInterface( + XInteractionReplaceExistingData.class, + continuations[ i ] ); + if ( xReplace != null ) { + log.println( "Interaction Handler selects: REPLACE" ); + xReplace.select(); + return; + } +*/ + XInteractionSupplyName xSupplyName + = (XInteractionSupplyName) + UnoRuntime.queryInterface( + XInteractionSupplyName.class, + continuations[ i ] ); + if ( xSupplyName != null ) { + String newname = "renamed_" + req.ClashingName; + log.println( "Interaction Handler selects: NEW NAME: " + + newname ); + xSupplyName.setName( newname ); + xSupplyName.select(); + return; + } + } + } + catch ( IllegalArgumentException e ) + { + e.printStackTrace(); + } + } + } + +} diff --git a/ucb/test/com/sun/star/comp/ucb/makefile.mk b/ucb/test/com/sun/star/comp/ucb/makefile.mk new file mode 100644 index 000000000000..1f2e35593909 --- /dev/null +++ b/ucb/test/com/sun/star/comp/ucb/makefile.mk @@ -0,0 +1,60 @@ +#************************************************************************* +# +# 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 := ucb +PACKAGE := com$/sun$/star$/comp$/ucb +TARGET := test_com_sun_star_comp_ucb + +.INCLUDE : settings.mk + +JAVAFILES = $(subst,$(CLASSDIR)$/$(PACKAGE)$/, $(subst,.class,.java $(JAVACLASSFILES))) + +CLASSDIR !:= $(CLASSDIR)$/test + +JARFILES = OOoRunner.jar \ + ridl.jar \ + unoil.jar \ + juh.jar \ + jurt.jar + +JAVACLASSFILES = $(CLASSDIR)$/$(PACKAGE)$/GlobalTransfer_Test.class + +.INCLUDE: target.mk + +$(JAVAFILES): $(MISC)$/$(TARGET).createdclassdir + +$(MISC)$/$(TARGET).createdclassdir: + - $(MKDIR) $(CLASSDIR) + $(TOUCH) $@ + +#ALLTAR .PHONY: +runtest: + java -classpath $(CLASSPATH) org.openoffice.Runner -TestBase java_complex \ + -AppExecutionCommand "c:\staroffice8.m13\program\soffice -accept=socket,host=localhost,port=8100;urp;" \ + -o $(subst,$/,. $(PACKAGE)$/GlobalTransfer_Test) + diff --git a/ucb/workben/cachemap/cachemapobject1.cxx b/ucb/workben/cachemap/cachemapobject1.cxx new file mode 100644 index 000000000000..f37afa981414 --- /dev/null +++ b/ucb/workben/cachemap/cachemapobject1.cxx @@ -0,0 +1,90 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" +#include "cachemapobject1.hxx" +#include "osl/diagnose.h" +#include "osl/interlck.h" +#include "osl/mutex.hxx" +#include "rtl/ref.hxx" +#include "rtl/ustring.hxx" + +#ifndef INCLUDED_MEMORY +#include <memory> +#define INCLUDED_MEMORY +#endif + +using ucb::cachemap::Object1; +using ucb::cachemap::ObjectContainer1; + +inline +Object1::Object1(rtl::Reference< ObjectContainer1 > const & rContainer): + m_xContainer(rContainer), + m_nRefCount(0) +{ + OSL_ASSERT(m_xContainer.is()); +} + +inline Object1::~Object1() SAL_THROW(()) +{} + +void ObjectContainer1::releaseElement(Object1 * pElement) SAL_THROW(()) +{ + OSL_ASSERT(pElement); + bool bDelete = false; + { + osl::MutexGuard aGuard(m_aMutex); + if (osl_decrementInterlockedCount(&pElement->m_nRefCount) == 0) + { + m_aMap.erase(pElement->m_aContainerIt); + bDelete = true; + } + } + if (bDelete) + delete pElement; +} + +ObjectContainer1::ObjectContainer1() +{} + +ObjectContainer1::~ObjectContainer1() SAL_THROW(()) +{} + +rtl::Reference< Object1 > ObjectContainer1::get(rtl::OUString const & rKey) +{ + osl::MutexGuard aGuard(m_aMutex); + Map::iterator aIt(m_aMap.find(rKey)); + if (aIt == m_aMap.end()) + { + std::auto_ptr< Object1 > xElement(new Object1(this)); + aIt = m_aMap.insert(Map::value_type(rKey, xElement.get())).first; + aIt->second->m_aContainerIt = aIt; + xElement.release(); + } + return aIt->second; +} diff --git a/ucb/workben/cachemap/cachemapobject1.hxx b/ucb/workben/cachemap/cachemapobject1.hxx new file mode 100644 index 000000000000..fe729434471a --- /dev/null +++ b/ucb/workben/cachemap/cachemapobject1.hxx @@ -0,0 +1,104 @@ +/************************************************************************* + * + * 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 INCLUDED_UCB_CACHEMAPOBJECT1_HXX +#define INCLUDED_UCB_CACHEMAPOBJECT1_HXX + +#include "osl/interlck.h" +#include "osl/mutex.hxx" +#include "rtl/ref.hxx" +#include "sal/types.h" +#include "salhelper/simplereferenceobject.hxx" + +#ifndef INCLUDED_MAP +#include <map> +#define INCLUDED_MAP +#endif +#ifndef INCLUDED_MEMORY +#include <memory> +#define INCLUDED_MEMORY +#endif + +namespace rtl { class OUString; } +namespace ucb { namespace cachemap { class Object1; } } + +namespace ucb { namespace cachemap { + +class ObjectContainer1: public salhelper::SimpleReferenceObject +{ +public: + ObjectContainer1(); + + virtual ~ObjectContainer1() SAL_THROW(()); + + rtl::Reference< Object1 > get(rtl::OUString const & rKey); + +private: + typedef std::map< rtl::OUString, Object1 * > Map; + + Map m_aMap; + osl::Mutex m_aMutex; + + void releaseElement(Object1 * pElement) SAL_THROW(()); + + friend class Object1; // to access Map, releaseElement() +}; + +class Object1 +{ +public: + inline void acquire() SAL_THROW(()) + { osl_incrementInterlockedCount(&m_nRefCount); } + + inline void release() SAL_THROW(()) + { m_xContainer->releaseElement(this); } + +private: + rtl::Reference< ObjectContainer1 > m_xContainer; + ObjectContainer1::Map::iterator m_aContainerIt; + oslInterlockedCount m_nRefCount; + + inline Object1(rtl::Reference< ObjectContainer1 > const & rContainer); + + inline ~Object1() SAL_THROW(()); + + Object1(Object1 &); // not implemented + void operator =(Object1); // not implemented + + friend class ObjectContainer1; + // to access m_aContainerIt, m_nRefCount, Object1(), ~Object1() +#if defined WNT + friend struct std::auto_ptr< Object1 >; // to access ~Object1() + // work around compiler bug... +#else // WNT + friend class std::auto_ptr< Object1 >; // to access ~Object1() +#endif // WNT +}; + +} } + +#endif // INCLUDED_UCB_CACHEMAPOBJECT1_HXX diff --git a/ucb/workben/cachemap/cachemapobject2.hxx b/ucb/workben/cachemap/cachemapobject2.hxx new file mode 100644 index 000000000000..812f3b8e8a77 --- /dev/null +++ b/ucb/workben/cachemap/cachemapobject2.hxx @@ -0,0 +1,40 @@ +/************************************************************************* + * + * 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 INCLUDED_UCB_CACHEMAPOBJECT2_HXX +#define INCLUDED_UCB_CACHEMAPOBJECT2_HXX + +#include "cppuhelper/weak.hxx" + +namespace ucb { namespace cachemap { + +class Object2: public cppu::OWeakObject +{}; + +} } + +#endif // INCLUDED_UCB_CACHEMAPOBJECT2_HXX diff --git a/ucb/workben/cachemap/cachemapobject3.cxx b/ucb/workben/cachemap/cachemapobject3.cxx new file mode 100644 index 000000000000..f8787109e36b --- /dev/null +++ b/ucb/workben/cachemap/cachemapobject3.cxx @@ -0,0 +1,105 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" +#include "cachemapobject3.hxx" +#include "osl/diagnose.h" +#include "osl/interlck.h" +#include "osl/mutex.hxx" +#include "rtl/ref.hxx" +#include "rtl/ustring.hxx" + +#ifndef INCLUDED_MEMORY +#include <memory> +#define INCLUDED_MEMORY +#endif + +using ucb::cachemap::Object3; +using ucb::cachemap::ObjectContainer3; + +inline +Object3::Object3(rtl::Reference< ObjectContainer3 > const & rContainer): + m_xContainer(rContainer), + m_nRefCount(0) +{ + OSL_ASSERT(m_xContainer.is()); +} + +inline Object3::~Object3() SAL_THROW(()) +{} + +void Object3::release() SAL_THROW(()) +{ + if (osl_decrementInterlockedCount(&m_nRefCount) == 0) + { + m_xContainer->releaseElement(this); + delete this; + } +} + +void ObjectContainer3::releaseElement(Object3 * pElement) SAL_THROW(()) +{ + OSL_ASSERT(pElement); + osl::MutexGuard aGuard(m_aMutex); + if (pElement->m_aContainerIt != m_aMap.end()) + m_aMap.erase(pElement->m_aContainerIt); +} + +ObjectContainer3::ObjectContainer3() +{} + +ObjectContainer3::~ObjectContainer3() SAL_THROW(()) +{} + +rtl::Reference< Object3 > ObjectContainer3::get(rtl::OUString const & rKey) +{ + osl::MutexGuard aGuard(m_aMutex); + Map::iterator aIt(m_aMap.find(rKey)); + if (aIt == m_aMap.end()) + { + std::auto_ptr< Object3 > xElement(new Object3(this)); + aIt = m_aMap.insert(Map::value_type(rKey, xElement.get())).first; + aIt->second->m_aContainerIt = aIt; + xElement.release(); + return aIt->second; + } + else if (osl_incrementInterlockedCount(&aIt->second->m_nRefCount) > 1) + { + rtl::Reference< Object3 > xElement(aIt->second); + osl_decrementInterlockedCount(&aIt->second->m_nRefCount); + return xElement; + } + else + { + osl_decrementInterlockedCount(&aIt->second->m_nRefCount); + aIt->second->m_aContainerIt = m_aMap.end(); + aIt->second = new Object3(this); + aIt->second->m_aContainerIt = aIt; + return aIt->second; + } +} diff --git a/ucb/workben/cachemap/cachemapobject3.hxx b/ucb/workben/cachemap/cachemapobject3.hxx new file mode 100644 index 000000000000..1096d3babcc0 --- /dev/null +++ b/ucb/workben/cachemap/cachemapobject3.hxx @@ -0,0 +1,103 @@ +/************************************************************************* + * + * 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 INCLUDED_UCB_CACHEMAPOBJECT3_HXX +#define INCLUDED_UCB_CACHEMAPOBJECT3_HXX + +#include "osl/interlck.h" +#include "osl/mutex.hxx" +#include "rtl/ref.hxx" +#include "sal/types.h" +#include "salhelper/simplereferenceobject.hxx" + +#ifndef INCLUDED_MAP +#include <map> +#define INCLUDED_MAP +#endif +#ifndef INCLUDED_MEMORY +#include <memory> +#define INCLUDED_MEMORY +#endif + +namespace rtl { class OUString; } +namespace ucb { namespace cachemap { class Object3; } } + +namespace ucb { namespace cachemap { + +class ObjectContainer3: public salhelper::SimpleReferenceObject +{ +public: + ObjectContainer3(); + + virtual ~ObjectContainer3() SAL_THROW(()); + + rtl::Reference< Object3 > get(rtl::OUString const & rKey); + +private: + typedef std::map< rtl::OUString, Object3 * > Map; + + Map m_aMap; + osl::Mutex m_aMutex; + + void releaseElement(Object3 * pElement) SAL_THROW(()); + + friend class Object3; // to access Map, releaseElement() +}; + +class Object3 +{ +public: + inline void acquire() SAL_THROW(()) + { osl_incrementInterlockedCount(&m_nRefCount); } + + void release() SAL_THROW(()); + +private: + rtl::Reference< ObjectContainer3 > m_xContainer; + ObjectContainer3::Map::iterator m_aContainerIt; + oslInterlockedCount m_nRefCount; + + inline Object3(rtl::Reference< ObjectContainer3 > const & rContainer); + + inline ~Object3() SAL_THROW(()); + + Object3(Object3 &); // not implemented + void operator =(Object3); // not implemented + + friend class ObjectContainer3; + // to access m_aContainerIt, m_nRefCount, Object3(), ~Object3() +#if defined WNT + friend struct std::auto_ptr< Object3 >; // to access ~Object3() + // work around compiler bug... +#else // WNT + friend class std::auto_ptr< Object3 >; // to access ~Object3() +#endif // WNT +}; + +} } + +#endif // INCLUDED_UCB_CACHEMAPOBJECT3_HXX diff --git a/ucb/workben/cachemap/cachemapobjectcontainer2.cxx b/ucb/workben/cachemap/cachemapobjectcontainer2.cxx new file mode 100644 index 000000000000..3af959c17cf2 --- /dev/null +++ b/ucb/workben/cachemap/cachemapobjectcontainer2.cxx @@ -0,0 +1,68 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" +#include "cachemapobjectcontainer2.hxx" +#include "cachemapobject2.hxx" +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/XWeak.hpp" +#include "cppuhelper/weakref.hxx" +#include "osl/mutex.hxx" +#include "rtl/ref.hxx" +#include "rtl/ustring.hxx" + +using ucb::cachemap::Object2; +using ucb::cachemap::ObjectContainer2; +using namespace com::sun::star; + +ObjectContainer2::ObjectContainer2() +{} + +ObjectContainer2::~ObjectContainer2() SAL_THROW(()) +{} + +rtl::Reference< Object2 > ObjectContainer2::get(rtl::OUString const & rKey) +{ + rtl::Reference< Object2 > xElement; + { + osl::MutexGuard aGuard(m_aMutex); + Map::iterator aIt(m_aMap.find(rKey)); + if (aIt != m_aMap.end()) + xElement = static_cast< Object2 * >( + uno::Reference< uno::XWeak >( + aIt->second.get(), uno::UNO_QUERY). + get()); + if (!xElement.is()) + { + xElement = new Object2; + m_aMap[rKey] + = uno::WeakReference< Object2 >(xElement.get()); + } + } + return xElement; +} diff --git a/ucb/workben/cachemap/cachemapobjectcontainer2.hxx b/ucb/workben/cachemap/cachemapobjectcontainer2.hxx new file mode 100644 index 000000000000..1ec7cf82936b --- /dev/null +++ b/ucb/workben/cachemap/cachemapobjectcontainer2.hxx @@ -0,0 +1,73 @@ +/************************************************************************* + * + * 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 INCLUDED_UCB_CACHEMAPOBJECTCONTAINER2_HXX +#define INCLUDED_UCB_CACHEMAPOBJECTCONTAINER2_HXX + +#include "cppuhelper/weakref.hxx" +#include "osl/mutex.hxx" +#include "rtl/ref.hxx" +#include "sal/types.h" + +#ifndef INCLUDED_HASH_MAP +#include <hash_map> +#define INCLUDED_HASH_MAP +#endif + +namespace rtl { + class OUString; + struct OUStringHash; +} +namespace ucb { namespace cachemap { class Object2; } } + +namespace ucb { namespace cachemap { + +class ObjectContainer2 +{ +public: + ObjectContainer2(); + + ~ObjectContainer2() SAL_THROW(()); + + rtl::Reference< Object2 > get(rtl::OUString const & rKey); + +private: + typedef std::hash_map< rtl::OUString, + com::sun::star::uno::WeakReference< Object2 >, + rtl::OUStringHash > + Map; + + ObjectContainer2(ObjectContainer2 &); // not implemented + void operator =(ObjectContainer2); // not implemented + + Map m_aMap; + osl::Mutex m_aMutex; +}; + +} } + +#endif // INCLUDED_UCB_CACHEMAPOBJECTCONTAINER2_HXX diff --git a/ucb/workben/cachemap/cachemaptest.cxx b/ucb/workben/cachemap/cachemaptest.cxx new file mode 100644 index 000000000000..25f10f3318b1 --- /dev/null +++ b/ucb/workben/cachemap/cachemaptest.cxx @@ -0,0 +1,168 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" +#include "cachemapobject1.hxx" +#include "cachemapobject2.hxx" +#include "cachemapobject3.hxx" +#include "cachemapobjectcontainer2.hxx" + +#ifndef _SOL_TIME_H_ +#include "osl/time.h" +#endif +#include "rtl/ref.hxx" +#include "rtl/ustring.hxx" + +#ifndef INCLUDED_CSTDLIB +#include <cstdlib> +#define INCLUDED_CSTDLIB +#endif +#ifndef INCLUDED_MEMORY +#include <memory> +#define INCLUDED_MEMORY +#endif +#ifndef INCLUDED_STDIO_H +#include <stdio.h> // <iostream> or <cstdio> do not work well on all platforms +#define INCLUDED_STDIO_H +#endif + +using ucb::cachemap::Object1; +using ucb::cachemap::Object2; +using ucb::cachemap::Object3; +using ucb::cachemap::ObjectContainer1; +using ucb::cachemap::ObjectContainer2; +using ucb::cachemap::ObjectContainer3; + +namespace { + +// Give template function a dummy parameter, to work around MSVC++ bug: +template< typename Cont, typename ContRef, typename Obj > +sal_uInt32 test(Obj *) +{ + ContRef xCont(new Cont); + rtl::OUString aPrefix(RTL_CONSTASCII_USTRINGPARAM("key")); + sal_uInt32 nTimer = osl_getGlobalTimer(); + for (int i = 0; i < 100000; i += 5) + { + rtl::OUString + aKey0(aPrefix + + rtl::OUString::valueOf(static_cast< sal_Int32 >( + i % 100))); + rtl::Reference< Obj > xObj01(xCont->get(aKey0)); + {for (int j = 0; j < 50; ++j) + rtl::Reference< Obj > xRef(xObj01); + } + rtl::Reference< Obj > xObj02(xCont->get(aKey0)); + {for (int j = 0; j < 50; ++j) + rtl::Reference< Obj > xRef(xObj02); + } + + rtl::OUString + aKey1(aPrefix + + rtl::OUString::valueOf(static_cast< sal_Int32 >( + (i + 1) % 100))); + rtl::Reference< Obj > xObj11(xCont->get(aKey1)); + {for (int j = 0; j < 50; ++j) + rtl::Reference< Obj > xRef(xObj11); + } + rtl::Reference< Obj > xObj12(xCont->get(aKey1)); + {for (int j = 0; j < 50; ++j) + rtl::Reference< Obj > xRef(xObj12); + } + + rtl::OUString + aKey2(aPrefix + + rtl::OUString::valueOf(static_cast< sal_Int32 >( + (i + 2) % 100))); + rtl::Reference< Obj > xObj21(xCont->get(aKey2)); + {for (int j = 0; j < 50; ++j) + rtl::Reference< Obj > xRef(xObj21); + } + rtl::Reference< Obj > xObj22(xCont->get(aKey2)); + {for (int j = 0; j < 50; ++j) + rtl::Reference< Obj > xRef(xObj22); + } + + rtl::OUString + aKey3(aPrefix + + rtl::OUString::valueOf(static_cast< sal_Int32 >( + (i + 3) % 100))); + rtl::Reference< Obj > xObj31(xCont->get(aKey3)); + {for (int j = 0; j < 50; ++j) + rtl::Reference< Obj > xRef(xObj31); + } + rtl::Reference< Obj > xObj32(xCont->get(aKey3)); + {for (int j = 0; j < 50; ++j) + rtl::Reference< Obj > xRef(xObj32); + } + + rtl::OUString + aKey4(aPrefix + + rtl::OUString::valueOf(static_cast< sal_Int32 >( + (i + 4) % 100))); + rtl::Reference< Obj > xObj41(xCont->get(aKey4)); + {for (int j = 0; j < 50; ++j) + rtl::Reference< Obj > xRef(xObj41); + } + rtl::Reference< Obj > xObj42(xCont->get(aKey4)); + {for (int j = 0; j < 50; ++j) + rtl::Reference< Obj > xRef(xObj42); + } + } + return osl_getGlobalTimer() - nTimer; +} + +} + +int main() +{ + // Use the second set of measurements, to avoid startup inaccuracies: + for (int i = 0; i < 2; ++i) + printf("Version 1: %lu ms.\nVersion 2: %lu ms.\nVersion 3: %lu ms.\n", + static_cast< unsigned long >( + test< ObjectContainer1, + rtl::Reference< ObjectContainer1 >, + Object1 >(0)), + static_cast< unsigned long >( + test< ObjectContainer2, + std::auto_ptr< ObjectContainer2 >, + Object2 >(0)), + static_cast< unsigned long >( + test< ObjectContainer3, + rtl::Reference< ObjectContainer3 >, + Object3 >(0))); + return EXIT_SUCCESS; +} + +// unxsols3.pro: Version 1: 9137 ms. +// Version 2: 8634 ms. +// Version 3: 3166 ms. +// +// wntmsci7.pro: Version 1: 3846 ms. +// Version 2: 5598 ms. +// Version 3: 2704 ms. diff --git a/ucb/workben/cachemap/makefile.mk b/ucb/workben/cachemap/makefile.mk new file mode 100644 index 000000000000..53d50fcd2175 --- /dev/null +++ b/ucb/workben/cachemap/makefile.mk @@ -0,0 +1,52 @@ +#************************************************************************* +# +# 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 = ucb +TARGET = cachemap +TARGETTYPE = CUI +LIBTARGET = NO +ENABLE_EXCEPTIONS = TRUE + +.INCLUDE: settings.mk + +OBJFILES = \ + $(OBJ)$/cachemapobject1.obj \ + $(OBJ)$/cachemapobjectcontainer2.obj \ + $(OBJ)$/cachemapobject3.obj \ + $(OBJ)$/cachemaptest.obj + +APP1TARGET = $(TARGET) +APP1OBJS = $(OBJFILES) +APP1STDLIBS = \ + $(CPPULIB) \ + $(CPPUHELPERLIB) \ + $(SALLIB) \ + $(SALHELPERLIB) +APP1DEF = $(MISC)$/$(APP1TARGET).def + +.INCLUDE: target.mk diff --git a/ucb/workben/ucb/makefile.mk b/ucb/workben/ucb/makefile.mk new file mode 100644 index 000000000000..9a9992a3a7fd --- /dev/null +++ b/ucb/workben/ucb/makefile.mk @@ -0,0 +1,84 @@ +#************************************************************************* +# +# 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=ucb +TARGET=ucbdemo +TARGETTYPE=GUI +LIBTARGET=NO + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings --- + +.INCLUDE : settings.mk + +# --- Files --- + +OBJFILES=\ + $(OBJ)$/srcharg.obj \ + $(OBJ)$/ucbdemo.obj + +#SRSFILES= $(SRS)$/ucbdemo.srs + +# +# UCBDEMO +# +APP1TARGET= ucbdemo +APP1OBJS=\ + $(OBJ)$/srcharg.obj \ + $(OBJ)$/ucbdemo.obj +#APP1RES= $(RES)$/ucbdemo.res + +.IF "$(COMPHELPERLIB)"=="" + +.IF "$(GUI)" == "UNX" +COMPHELPERLIB=-licomphelp2 +.ENDIF # unx + +.IF "$(GUI)"=="WNT" +COMPHELPERLIB=icomphelp2.lib +.ENDIF # wnt + +.ENDIF + +APP1STDLIBS=\ + $(SALLIB) \ + $(VOSLIB) \ + $(CPPULIB) \ + $(CPPUHELPERLIB) \ + $(COMPHELPERLIB) \ + $(TOOLSLIB) \ + $(SVTOOLLIB) \ + $(VCLLIB) \ + $(UCBHELPERLIB) + +# --- Targets --- + +.INCLUDE : target.mk + diff --git a/ucb/workben/ucb/srcharg.cxx b/ucb/workben/ucb/srcharg.cxx new file mode 100644 index 000000000000..92b6dd188791 --- /dev/null +++ b/ucb/workben/ucb/srcharg.cxx @@ -0,0 +1,490 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +#include <limits> +#include <com/sun/star/ucb/RuleOperator.hpp> +#include <com/sun/star/ucb/SearchInfo.hpp> +#include <com/sun/star/util/Date.hpp> +#include <tools/date.hxx> +#include <tools/inetmime.hxx> +#include <tools/string.hxx> + +#ifndef CHAOS_UCBDEMO_SRCHARG_HXX +#include <srcharg.hxx> +#endif + +namespace unnamed_chaos_ucbdemo_srcharg {} +using namespace unnamed_chaos_ucbdemo_srcharg; + // unnamed namespaces don't work well yet... + +using namespace com::sun::star; + +//============================================================================ +// +// skipWhiteSpace +// +//============================================================================ + +namespace unnamed_chaos_ucbdemo_srcharg { + +void skipWhiteSpace(sal_Unicode const *& rBegin, sal_Unicode const * pEnd) +{ + while (rBegin != pEnd + && (*rBegin == '\n' || *rBegin == '\t' || *rBegin == ' ')) + ++rBegin; +} + +//============================================================================ +// +// scanAtom +// +//============================================================================ + +String scanAtom(sal_Unicode const *& rBegin, sal_Unicode const * pEnd) +{ + sal_Unicode const * pTheBegin = rBegin; + while (rBegin != pEnd && INetMIME::isAlpha(*rBegin)) + ++rBegin; + return String(pTheBegin, rBegin - pTheBegin); +} + +//============================================================================ +// +// scanProperty +// +//============================================================================ + +String scanProperty(sal_Unicode const *& rBegin, sal_Unicode const * pEnd) +{ + sal_Unicode const * pTheBegin = rBegin; + while (rBegin != pEnd + && !(*rBegin == '\n' || *rBegin == '\t' || *rBegin == ' ')) + ++rBegin; + return String(pTheBegin, rBegin - pTheBegin); +} + +//============================================================================ +// +// scanOperator +// +//============================================================================ + +String scanOperator(sal_Unicode const *& rBegin, sal_Unicode const * pEnd) +{ + sal_Unicode const * pTheBegin = rBegin; + while (rBegin != pEnd + && (INetMIME::isAlpha(*rBegin) || *rBegin == '!' + || *rBegin >= '<' && *rBegin <= '>')) + ++rBegin; + return String(pTheBegin, rBegin - pTheBegin); +} + +} + +//============================================================================ +// +// parseSearchArgument +// +//============================================================================ + +bool parseSearchArgument(String const & rInput, ucb::SearchInfo & rInfo) +{ + /* Format of rInput: + + argument = *option [criterium *("OR" criterium)] + + option = ("--RECURSE" "=" ("NONE" / "ONE" / "DEEP")) + / (("--BASE" / "--FOLDERVIEW" / "--DOCVIEW" + / "--INDIRECT") + "=" bool) + + criterium = "EMPTY" / (term *("AND" term)) + + term = text-term / date-term / numeric-term / bool-term + + text-term = property ("CONT" / "!CONT" / ">=" / "<=" / "==" / "!=") + string *("-C" / "-R") + + date-term = property + (((">=" / "<=" / "==" / "!=") date) + / (("OLDER" / "YOUNGER") number)) + + numeric-term = property (">=" / "<=" / "==" / "!=") number + + bool-term = property ("TRUE" / "FALSE") + + property = 1*VCHAR + + string = DQUOTE + *(<any Unicode code point except DQUOTE or "\"> + / ("\" %x75 4HEXDIG) ; \uHHHH + / ("\" (DQUOTE / "\"))) + DQUOTE + + date = 1*2DIGIT "/" 1*2DIGIT "/" 4DIGIT ; mm/dd/yyyy + + number = ["+" / "-"] 1*DIGIT + */ + + sal_Unicode const * p = rInput.GetBuffer(); + sal_Unicode const * pEnd = p + rInput.Len(); + + // Parse options: + rInfo.Recursion = ucb::SearchRecursion_ONE_LEVEL; + rInfo.IncludeBase = true; + rInfo.RespectFolderViewRestrictions = true; + rInfo.RespectDocViewRestrictions = false; + rInfo.FollowIndirections = false; + enum OptionID { OPT_RECURSE, OPT_BASE, OPT_FOLDERVIEW, OPT_DOCVIEW, + OPT_INDIRECT, OPT_Count }; + struct OptionInfo + { + bool m_bSpecified; + sal_Bool * m_pValue; + }; + OptionInfo aOptions[OPT_Count]; + aOptions[OPT_RECURSE].m_bSpecified = false; + aOptions[OPT_RECURSE].m_pValue = 0; + aOptions[OPT_BASE].m_bSpecified = false; + aOptions[OPT_BASE].m_pValue = &rInfo.IncludeBase; + aOptions[OPT_FOLDERVIEW].m_bSpecified = false; + aOptions[OPT_FOLDERVIEW].m_pValue + = &rInfo.RespectFolderViewRestrictions; + aOptions[OPT_DOCVIEW].m_bSpecified = false; + aOptions[OPT_DOCVIEW].m_pValue = &rInfo.RespectDocViewRestrictions; + aOptions[OPT_INDIRECT].m_bSpecified = false; + aOptions[OPT_INDIRECT].m_pValue = &rInfo.FollowIndirections; + while (p != pEnd) + { + sal_Unicode const * q = p; + + skipWhiteSpace(q, pEnd); + if (pEnd - q < 2 || *q++ != '-' || *q++ != '-') + break; + String aOption(scanAtom(q, pEnd)); + OptionID eID; + if (aOption.EqualsIgnoreCaseAscii("recurse")) + eID = OPT_RECURSE; + else if (aOption.EqualsIgnoreCaseAscii("base")) + eID = OPT_BASE; + else if (aOption.EqualsIgnoreCaseAscii("folderview")) + eID = OPT_FOLDERVIEW; + else if (aOption.EqualsIgnoreCaseAscii("docview")) + eID = OPT_DOCVIEW; + else if (aOption.EqualsIgnoreCaseAscii("indirect")) + eID = OPT_INDIRECT; + else + break; + + if (aOptions[eID].m_bSpecified) + break; + aOptions[eID].m_bSpecified = true; + + skipWhiteSpace(q, pEnd); + if (q == pEnd || *q++ != '=') + break; + + skipWhiteSpace(q, pEnd); + String aValue(scanAtom(q, pEnd)); + if (eID == OPT_RECURSE) + { + if (aValue.EqualsIgnoreCaseAscii("none")) + rInfo.Recursion = ucb::SearchRecursion_NONE; + else if (aValue.EqualsIgnoreCaseAscii("one")) + rInfo.Recursion = ucb::SearchRecursion_ONE_LEVEL; + else if (aValue.EqualsIgnoreCaseAscii("deep")) + rInfo.Recursion = ucb::SearchRecursion_DEEP; + else + break; + } + else if (aValue.EqualsIgnoreCaseAscii("true")) + *aOptions[eID].m_pValue = true; + else if (aValue.EqualsIgnoreCaseAscii("false")) + *aOptions[eID].m_pValue = false; + else + break; + + p = q; + } + + // Parse criteria: + ucb::SearchCriterium aCriterium; + for (;;) + { + sal_Unicode const * q = p; + + // Parse either property name or "empty": + skipWhiteSpace(q, pEnd); + String aProperty(scanProperty(q, pEnd)); + sal_Unicode const * pPropertyEnd = q; + + // Parse operator: + skipWhiteSpace(q, pEnd); + String aOperator(scanOperator(q, pEnd)); + struct Operator + { + sal_Char const * m_pName; + sal_Int16 m_nText; + sal_Int16 m_nDate; + sal_Int16 m_nNumeric; + sal_Int16 m_nBool; + }; + static Operator const aOperators[] + = { { "cont", ucb::RuleOperator::CONTAINS, 0, 0, 0 }, + { "!cont", ucb::RuleOperator::CONTAINSNOT, 0, 0, 0 }, + { ">=", ucb::RuleOperator::GREATEREQUAL, + ucb::RuleOperator::GREATEREQUAL, + ucb::RuleOperator::GREATEREQUAL, 0 }, + { "<=", ucb::RuleOperator::LESSEQUAL, + ucb::RuleOperator::LESSEQUAL, ucb::RuleOperator::LESSEQUAL, + 0 }, + { "==", ucb::RuleOperator::EQUAL, ucb::RuleOperator::EQUAL, + ucb::RuleOperator::EQUAL, 0 }, + { "!=", ucb::RuleOperator::NOTEQUAL, + ucb::RuleOperator::NOTEQUAL, ucb::RuleOperator::NOTEQUAL, + 0 }, + { "true", 0, 0, 0, ucb::RuleOperator::VALUE_TRUE }, + { "false", 0, 0, 0, ucb::RuleOperator::VALUE_FALSE } }; + int const nOperatorCount = sizeof aOperators / sizeof (Operator); + Operator const * pTheOperator = 0; + for (int i = 0; i < nOperatorCount; ++i) + if (aOperator.EqualsIgnoreCaseAscii(aOperators[i].m_pName)) + { + pTheOperator = aOperators + i; + break; + } + bool bTerm = pTheOperator != 0; + + sal_Int16 nOperatorID; + uno::Any aTheOperand; + bool bCaseSensitive = false; + bool bRegularExpression = false; + if (bTerm) + { + skipWhiteSpace(q, pEnd); + bool bHasOperand = false; + + // Parse string operand: + if (!bHasOperand && pTheOperator->m_nText) + { + if (q != pEnd && *q == '"') + { + String aString; + for (sal_Unicode const * r = q + 1;;) + { + if (r == pEnd) + break; + sal_Unicode c = *r++; + if (c == '"') + { + bHasOperand = true; + aTheOperand <<= rtl::OUString(aString); + nOperatorID = pTheOperator->m_nText; + q = r; + break; + } + if (c == '\\') + { + if (r == pEnd) + break; + c = *r++; + if (c == 'u') + { + if (pEnd - r < 4) + break; + c = 0; + bool bBad = false; + for (int i = 0; i < 4; ++i) + { + int nWeight + = INetMIME::getHexWeight(*r++); + if (nWeight < 0) + { + bBad = false; + break; + } + c = sal_Unicode(c << 4 | nWeight); + } + if (bBad) + break; + } + else if (c != '"' && c != '\\') + break; + } + aString += c; + } + } + + // Parse "-C" and "-R": + if (bHasOperand) + for (;;) + { + skipWhiteSpace(q, pEnd); + if (pEnd - q >= 2 && q[0] == '-' + && (q[1] == 'C' || q[1] == 'c') + && !bCaseSensitive) + { + bCaseSensitive = true; + q += 2; + } + else if (pEnd - q >= 2 && q[0] == '-' + && (q[1] == 'R' || q[1] == 'r') + && !bRegularExpression) + { + bRegularExpression = true; + q += 2; + } + else + break; + } + } + + // Parse date operand: + if (!bHasOperand && pTheOperator->m_nDate != 0) + { + sal_Unicode const * r = q; + bool bOK = true; + USHORT nMonth = 0; + if (bOK && r != pEnd && INetMIME::isDigit(*r)) + nMonth = INetMIME::getWeight(*r++); + else + bOK = false; + if (bOK && r != pEnd && INetMIME::isDigit(*r)) + nMonth = 10 * nMonth + INetMIME::getWeight(*r++); + if (!(bOK && r != pEnd && *r++ == '/')) + bOK = false; + USHORT nDay = 0; + if (bOK && r != pEnd && INetMIME::isDigit(*r)) + nDay = INetMIME::getWeight(*r++); + else + bOK = false; + if (bOK && r != pEnd && INetMIME::isDigit(*r)) + nDay = 10 * nDay + INetMIME::getWeight(*r++); + if (!(bOK && r != pEnd && *r++ == '/')) + bOK = false; + USHORT nYear = 0; + for (int i = 0; bOK && i < 4; ++i) + if (r != pEnd && INetMIME::isDigit(*r)) + nYear = 10 * nYear + INetMIME::getWeight(*r++); + else + bOK = false; + if (bOK && Date(nDay, nMonth, nYear).IsValid()) + { + bHasOperand = true; + aTheOperand <<= util::Date(nDay, nMonth, nYear); + nOperatorID = pTheOperator->m_nDate; + q = r; + } + } + + // Parse number operand: + if (!bHasOperand && pTheOperator->m_nNumeric != 0) + { + sal_Unicode const * r = q; + bool bNegative = false; + if (*r == '+') + ++r; + else if (*r == '-') + { + bNegative = true; + ++r; + } + sal_Int64 nNumber = 0; + bool bDigits = false; + while (r != pEnd && INetMIME::isDigit(*r)) + { + nNumber = 10 * nNumber + INetMIME::getWeight(*r++); + if (nNumber > std::numeric_limits< sal_Int32 >::max()) + { + bDigits = false; + break; + } + } + if (bDigits) + { + bHasOperand = true; + aTheOperand + <<= sal_Int32(bNegative ? -sal_Int32(nNumber) : + sal_Int32(nNumber)); + nOperatorID = pTheOperator->m_nNumeric; + q = r; + } + } + + // Bool operator has no operand: + if (!bHasOperand && pTheOperator->m_nBool != 0) + { + bHasOperand = true; + nOperatorID = pTheOperator->m_nBool; + } + + bTerm = bHasOperand; + } + + bool bEmpty = false; + if (bTerm) + { + aCriterium.Terms.realloc(aCriterium.Terms.getLength() + 1); + aCriterium.Terms[aCriterium.Terms.getLength() - 1] + = ucb::RuleTerm(aProperty, aTheOperand, nOperatorID, + bCaseSensitive, bRegularExpression); + } + else if (aCriterium.Terms.getLength() == 0 + && aProperty.EqualsIgnoreCaseAscii("empty")) + { + bEmpty = true; + q = pPropertyEnd; + } + + if (!(bTerm || bEmpty)) + break; + + p = q; + skipWhiteSpace(p, pEnd); + + q = p; + String aConnection(scanAtom(q, pEnd)); + if (p == pEnd || aConnection.EqualsIgnoreCaseAscii("or")) + { + rInfo.Criteria.realloc(rInfo.Criteria.getLength() + 1); + rInfo.Criteria[rInfo.Criteria.getLength() - 1] = aCriterium; + aCriterium = ucb::SearchCriterium(); + p = q; + } + else if (bTerm && aConnection.EqualsIgnoreCaseAscii("and")) + p = q; + else + break; + } + + skipWhiteSpace(p, pEnd); + return p == pEnd; +} + diff --git a/ucb/workben/ucb/srcharg.hxx b/ucb/workben/ucb/srcharg.hxx new file mode 100644 index 000000000000..822c063d5bab --- /dev/null +++ b/ucb/workben/ucb/srcharg.hxx @@ -0,0 +1,41 @@ +/************************************************************************* + * + * 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 UCBDEMO_SRCHARG_HXX +#define UCBDEMO_SRCHARG_HXX + +class String; +namespace com { namespace sun { namespace star { namespace ucb { + struct SearchInfo; +} } } } + +//============================================================================ +bool parseSearchArgument(String const & rInput, + com::sun::star::ucb::SearchInfo & rInfo); + +#endif // UCBDEMO_SRCHARG_HXX + diff --git a/ucb/workben/ucb/ucbdemo.cxx b/ucb/workben/ucb/ucbdemo.cxx new file mode 100644 index 000000000000..f2aa244d2871 --- /dev/null +++ b/ucb/workben/ucb/ucbdemo.cxx @@ -0,0 +1,2597 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +#include <stack> +#include <rtl/ustrbuf.hxx> +#include <vos/mutex.hxx> +#include <vos/process.hxx> +#include <cppuhelper/weak.hxx> +#include <cppuhelper/bootstrap.hxx> +#include <com/sun/star/ucb/ContentAction.hpp> +#include <com/sun/star/ucb/OpenCommandArgument2.hpp> +#include <com/sun/star/ucb/ContentResultSetCapability.hpp> +#include <com/sun/star/ucb/SearchCommandArgument.hpp> +#include <com/sun/star/ucb/NameClash.hpp> +#include <com/sun/star/ucb/TransferInfo.hpp> +#include <com/sun/star/ucb/GlobalTransferCommandArgument.hpp> +#include <com/sun/star/ucb/XContentIdentifierFactory.hpp> +#include <com/sun/star/ucb/CommandInfo.hpp> +#include <com/sun/star/ucb/XContentProviderManager.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/beans/Property.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/ucb/CHAOSProgressStart.hpp> +#include <com/sun/star/ucb/OpenMode.hpp> +#include <com/sun/star/ucb/ResultSetException.hpp> +#include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/beans/XPropertyContainer.hpp> +#include <com/sun/star/ucb/XProgressHandler.hpp> +#include <com/sun/star/ucb/XCommandEnvironment.hpp> +#include <com/sun/star/beans/XPropertiesChangeListener.hpp> +#include <com/sun/star/beans/XPropertiesChangeNotifier.hpp> +#include <com/sun/star/ucb/XCommandProcessor.hpp> +#include <com/sun/star/ucb/XDynamicResultSet.hpp> +#include <com/sun/star/sdbc/XRow.hpp> +#include <com/sun/star/ucb/XContentAccess.hpp> +#include <com/sun/star/ucb/XCommandInfo.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/ucb/XSortedDynamicResultSetFactory.hpp> +#include <com/sun/star/bridge/XUnoUrlResolver.hpp> +#include <comphelper/processfactory.hxx> +#include <ucbhelper/configurationkeys.hxx> +#include <ucbhelper/fileidentifierconverter.hxx> +#include <ucbhelper/contentbroker.hxx> +#include <tools/debug.hxx> + +#include "tools/time.hxx" +#include <vcl/wrkwin.hxx> +#include <vcl/toolbox.hxx> +#include <vcl/edit.hxx> +#include <vcl/lstbox.hxx> +#include <vcl/svapp.hxx> +#include <vcl/help.hxx> +#include <srcharg.hxx> + +using ucbhelper::getLocalFileURL; +using ucbhelper::getSystemPathFromFileURL; +using ucbhelper::getFileURLFromSystemPath; + +using namespace com::sun::star; + +/*======================================================================== + * + * MyOutWindow. + * + *======================================================================*/ + +#define MYOUTWINDOW_MAXLINES 4096 + +class MyOutWindow : public ListBox +{ +public: + MyOutWindow( Window *pParent, WinBits nWinStyle ) + : ListBox ( pParent, nWinStyle | WB_AUTOHSCROLL ) {} + ~MyOutWindow() {} + + void Append( const String &rLine ); +}; + +//------------------------------------------------------------------------- +void MyOutWindow::Append( const String &rLine ) +{ + String aLine( rLine ); + + xub_StrLen nPos = aLine.Search( '\n' ); + while ( nPos != STRING_NOTFOUND ) + { + if ( GetEntryCount() >= MYOUTWINDOW_MAXLINES ) + RemoveEntry( 0 ); + + InsertEntry( aLine.Copy( 0, nPos ) ); + + aLine.Erase( 0, nPos + 1 ); + nPos = aLine.Search( '\n' ); + } + + if ( GetEntryCount() >= MYOUTWINDOW_MAXLINES ) + RemoveEntry( 0 ); + + InsertEntry( aLine ); + + SetTopEntry( MYOUTWINDOW_MAXLINES - 1 ); +} + +/*======================================================================== + * + * MessagePrinter. + * + *=======================================================================*/ + +class MessagePrinter +{ +protected: + MyOutWindow* m_pOutEdit; + +public: + MessagePrinter( MyOutWindow* pOutEdit = NULL ) + : m_pOutEdit( pOutEdit ) {} + void setOutEdit( MyOutWindow* pOutEdit ) + { m_pOutEdit = pOutEdit; } + void print( const sal_Char* pText ); + void print( const UniString& rText ); +}; + +//------------------------------------------------------------------------- +void MessagePrinter::print( const sal_Char* pText ) +{ + print( UniString::CreateFromAscii( pText ) ); +} + +//------------------------------------------------------------------------- +void MessagePrinter::print( const UniString& rText ) +{ + vos::OGuard aGuard( Application::GetSolarMutex() ); + + if ( m_pOutEdit ) + { + m_pOutEdit->Append( rText ); + m_pOutEdit->Update(); + } +} + +//============================================================================ +// +// TestOutputStream +// +//============================================================================ + +class TestOutputStream: + public cppu::OWeakObject, + public io::XOutputStream +{ + rtl::OUString m_sStart; + bool m_bMore; + +public: + TestOutputStream(): m_bMore(false) {} + + virtual uno::Any SAL_CALL queryInterface(const uno::Type & rType) + throw(uno::RuntimeException); + virtual void SAL_CALL acquire() throw () + { OWeakObject::acquire(); } + + virtual void SAL_CALL release() throw () + { OWeakObject::release(); } + + virtual void SAL_CALL writeBytes(const uno::Sequence< sal_Int8 > & rData) + throw(uno::RuntimeException); + + virtual void SAL_CALL flush() throw() {} + + virtual void SAL_CALL closeOutput() throw() {}; + + rtl::OUString getStart() const; +}; + +//============================================================================ +// virtual +uno::Any SAL_CALL +TestOutputStream::queryInterface(const uno::Type & rType) + throw(uno::RuntimeException) +{ + uno::Any aRet = cppu::queryInterface(rType, + static_cast< io::XOutputStream * >(this)); + return aRet.hasValue() ? aRet : OWeakObject::queryInterface(rType); +} + +//============================================================================ +// virtual +void SAL_CALL TestOutputStream::writeBytes( + const uno::Sequence< sal_Int8 > & rData) + throw(uno::RuntimeException) +{ + sal_Int32 nLen = rData.getLength(); + if (m_sStart.getLength() + nLen > 500) + { + nLen = 500 - m_sStart.getLength(); + m_bMore = true; + } + m_sStart + += rtl::OUString(reinterpret_cast< const sal_Char * >(rData. + getConstArray()), + nLen, RTL_TEXTENCODING_ISO_8859_1); +} + +//============================================================================ +rtl::OUString TestOutputStream::getStart() const +{ + rtl::OUString sResult = m_sStart; + if (m_bMore) + sResult += rtl::OUString::createFromAscii("..."); + return sResult; +} + +/*======================================================================== + * + * ProgressHandler. + * + *=======================================================================*/ + +class ProgressHandler: + public cppu::OWeakObject, + public ucb::XProgressHandler +{ + MessagePrinter & m_rPrinter; + + rtl::OUString toString(const uno::Any & rStatus); + +public: + ProgressHandler(MessagePrinter & rThePrinter): m_rPrinter(rThePrinter) {} + + virtual uno::Any SAL_CALL queryInterface( + const uno::Type & rType) + throw(uno::RuntimeException); + + virtual void SAL_CALL acquire() throw () + { OWeakObject::acquire(); } + + virtual void SAL_CALL release() throw () + { OWeakObject::release(); } + + virtual void SAL_CALL push(const uno::Any & rStatus) + throw (uno::RuntimeException); + + virtual void SAL_CALL update(const uno::Any & rStatus) + throw (uno::RuntimeException); + + virtual void SAL_CALL pop() throw (uno::RuntimeException); +}; + +rtl::OUString ProgressHandler::toString(const uno::Any & rStatus) +{ + ucb::CHAOSProgressStart aStart; + if (rStatus >>= aStart) + { + rtl::OUString sResult; + if (aStart.Text.getLength() > 0) + { + sResult = aStart.Text; + sResult += rtl::OUString::createFromAscii(" "); + } + sResult += rtl::OUString::createFromAscii("["); + sResult += rtl::OUString::valueOf(aStart.Minimum); + sResult += rtl::OUString::createFromAscii(".."); + sResult += rtl::OUString::valueOf(aStart.Maximum); + sResult += rtl::OUString::createFromAscii("]"); + return sResult; + } + + rtl::OUString sText; + if (rStatus >>= sText) + return sText; + + sal_Int32 nValue; + if (rStatus >>= nValue) + { + rtl::OUString sResult = rtl::OUString::createFromAscii(".."); + sResult += rtl::OUString::valueOf(nValue); + sResult += rtl::OUString::createFromAscii(".."); + return rtl::OUString(sResult); + } + + return rtl::OUString::createFromAscii("(Unknown object)"); +} + +//============================================================================ +// virtual +uno::Any SAL_CALL +ProgressHandler::queryInterface( const uno::Type & rType ) + throw(uno::RuntimeException) +{ + uno::Any aRet = cppu::queryInterface( + rType, + static_cast< ucb::XProgressHandler* >(this)); + return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ); +} + +//============================================================================ +// virtual +void SAL_CALL ProgressHandler::push(const uno::Any & rStatus) + throw (uno::RuntimeException) +{ + rtl::OUString sMessage = rtl::OUString::createFromAscii("Status push: "); + sMessage += toString(rStatus); + m_rPrinter.print(sMessage); +} + +//============================================================================ +// virtual +void SAL_CALL ProgressHandler::update(const uno::Any & rStatus) + throw (uno::RuntimeException) +{ + rtl::OUString sMessage = rtl::OUString::createFromAscii("Status update: "); + sMessage += toString(rStatus); + m_rPrinter.print(sMessage); +} + +//============================================================================ +// virtual +void SAL_CALL ProgressHandler::pop() throw (uno::RuntimeException) +{ + m_rPrinter.print("Status pop"); +} + +/*======================================================================== + * + * Ucb. + * + *=======================================================================*/ + +#define UCB_MODULE_NAME "ucb1" + +class Ucb : public MessagePrinter +{ +private: + uno::Reference< lang::XMultiServiceFactory > m_xFac; + uno::Reference< ucb::XContentProvider > m_xProv; + uno::Reference< ucb::XContentIdentifierFactory > m_xIdFac; + rtl::OUString m_aConfigurationKey1; + rtl::OUString m_aConfigurationKey2; + sal_Bool m_bInited : 1; + + static rtl::OUString getUnoURL(); + +public: + Ucb( uno::Reference< lang::XMultiServiceFactory >& rxFactory, + rtl::OUString const & rConfigurationKey1, + rtl::OUString const & rConfigurationKey2 ); + ~Ucb(); + + sal_Bool init(); + + uno::Reference< lang::XMultiServiceFactory > getServiceFactory() const + { return m_xFac; } + + uno::Reference< ucb::XContentIdentifierFactory > + getContentIdentifierFactory(); + uno::Reference< ucb::XContentProvider > + getContentProvider(); + + static rtl::OUString m_aProtocol; +}; + +// static +rtl::OUString Ucb::m_aProtocol; + +//------------------------------------------------------------------------- +// static +rtl::OUString Ucb::getUnoURL() +{ + rtl::OUString aUnoURL(rtl::OUString::createFromAscii( + "uno:socket,host=localhost,port=8121;")); + if (m_aProtocol.getLength() == 0) + aUnoURL += rtl::OUString::createFromAscii("urp"); + else + aUnoURL += m_aProtocol; + aUnoURL += rtl::OUString::createFromAscii(";UCB.Factory"); + return aUnoURL; +} + +//------------------------------------------------------------------------- +Ucb::Ucb( uno::Reference< lang::XMultiServiceFactory >& rxFactory, + rtl::OUString const & rConfigurationKey1, + rtl::OUString const & rConfigurationKey2 ) +: m_xFac( rxFactory ), + m_aConfigurationKey1( rConfigurationKey1 ), + m_aConfigurationKey2( rConfigurationKey2 ), + m_bInited( sal_False ) +{ +} + +//------------------------------------------------------------------------- +Ucb::~Ucb() +{ +} + +//------------------------------------------------------------------------- +sal_Bool Ucb::init() +{ + if ( m_bInited ) + return sal_True; + + // Create auto configured UCB: + if (m_xFac.is()) + try + { + rtl::OUString aPipe; + vos::OSecurity().getUserIdent(aPipe); + uno::Sequence< uno::Any > aArgs(4); + aArgs[0] <<= m_aConfigurationKey1; + aArgs[1] <<= m_aConfigurationKey2; + aArgs[2] <<= rtl::OUString::createFromAscii("PIPE"); + aArgs[3] <<= aPipe; +#if 0 + m_xProv + = uno::Reference< XContentProvider >( + m_xFac-> + createInstanceWithArguments( + rtl::OUString::createFromAscii( + "com.sun.star.ucb." + "UniversalContentBroker"), + aArgs), + uno::UNO_QUERY); +#else + ::ucbhelper::ContentBroker::initialize( m_xFac, aArgs ); + m_xProv + = ::ucbhelper::ContentBroker::get()->getContentProviderInterface(); +#endif + } + catch (uno::Exception const &) {} + + if (m_xProv.is()) + { + print("UCB initialized"); + uno::Reference< ucb::XContentProviderManager > xProvMgr( + m_xProv, uno::UNO_QUERY); + if (xProvMgr.is()) + { + print("Registered schemes:"); + uno::Sequence< ucb::ContentProviderInfo > + aInfos(xProvMgr->queryContentProviders()); + for (sal_Int32 i = 0; i < aInfos.getLength(); ++i) + { + String aText(RTL_CONSTASCII_USTRINGPARAM(" ")); + aText += UniString(aInfos[i].Scheme); + print(aText); + } + } + } + else + print("Error initializing UCB"); + + m_bInited = m_xProv.is(); + return m_bInited; +} + +//------------------------------------------------------------------------- +uno::Reference< ucb::XContentIdentifierFactory > +Ucb::getContentIdentifierFactory() +{ + if ( !m_xIdFac.is() ) + { + if ( init() ) + m_xIdFac = uno::Reference< ucb::XContentIdentifierFactory >( + m_xProv, uno::UNO_QUERY ); + } + + return m_xIdFac; +} + +//------------------------------------------------------------------------- +uno::Reference< ucb::XContentProvider > Ucb::getContentProvider() +{ + if ( !m_xProv.is() ) + init(); + + return m_xProv; +} + +/*======================================================================== + * + * UcbTaskEnvironment. + * + *=======================================================================*/ + +class UcbTaskEnvironment : public cppu::OWeakObject, + public ucb::XCommandEnvironment +{ + uno::Reference< task::XInteractionHandler > m_xInteractionHandler; + uno::Reference< ucb::XProgressHandler > m_xProgressHandler; + +public: + UcbTaskEnvironment( const uno::Reference< task::XInteractionHandler>& + rxInteractionHandler, + const uno::Reference< ucb::XProgressHandler>& + rxProgressHandler ); + virtual ~UcbTaskEnvironment(); + + // Interface implementations... + + // XInterface + + virtual uno::Any SAL_CALL queryInterface( const uno::Type & rType ) + throw( uno::RuntimeException ); + virtual void SAL_CALL acquire() + throw(); + virtual void SAL_CALL release() + throw(); + + // XCommandEnvironemnt + + virtual uno::Reference<task::XInteractionHandler> SAL_CALL + getInteractionHandler() + throw (uno::RuntimeException) + { return m_xInteractionHandler; } + + virtual uno::Reference<ucb::XProgressHandler> SAL_CALL + getProgressHandler() + throw (uno::RuntimeException) + { return m_xProgressHandler; } + }; + +//------------------------------------------------------------------------- +UcbTaskEnvironment::UcbTaskEnvironment( + const uno::Reference< task::XInteractionHandler >& + rxInteractionHandler, + const uno::Reference< ucb::XProgressHandler >& + rxProgressHandler ) +: m_xInteractionHandler( rxInteractionHandler ), + m_xProgressHandler( rxProgressHandler ) +{ +} + +//------------------------------------------------------------------------- +// virtual +UcbTaskEnvironment::~UcbTaskEnvironment() +{ +} + +//---------------------------------------------------------------------------- +// +// XInterface methods +// +//---------------------------------------------------------------------------- + +// virtual +uno::Any SAL_CALL +UcbTaskEnvironment::queryInterface( const uno::Type & rType ) + throw( uno::RuntimeException ) +{ + uno::Any aRet = cppu::queryInterface( + rType, static_cast< ucb::XCommandEnvironment* >( this ) ); + return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ); +} + +//---------------------------------------------------------------------------- +// virtual +void SAL_CALL UcbTaskEnvironment::acquire() + throw() +{ + OWeakObject::acquire(); +} + +//---------------------------------------------------------------------------- +// virtual +void SAL_CALL UcbTaskEnvironment::release() + throw() +{ + OWeakObject::release(); +} + +/*======================================================================== + * + * UcbCommandProcessor. + * + *=======================================================================*/ + +class UcbCommandProcessor : public MessagePrinter +{ +protected: + Ucb& m_rUCB; + +private: + uno::Reference< ucb::XCommandProcessor > m_xProcessor; + sal_Int32 m_aCommandId; + +public: + UcbCommandProcessor( Ucb& rUCB, + const uno::Reference< + ucb::XCommandProcessor >& rxProcessor, + MyOutWindow* pOutEdit ); + + virtual ~UcbCommandProcessor(); + + uno::Any executeCommand( const rtl::OUString& rName, + const uno::Any& rArgument, + bool bPrint = true ); +}; + +//------------------------------------------------------------------------- +UcbCommandProcessor::UcbCommandProcessor( Ucb& rUCB, + const uno::Reference< + ucb::XCommandProcessor >& + rxProcessor, + MyOutWindow* pOutEdit) +: MessagePrinter( pOutEdit ), + m_rUCB( rUCB ), + m_xProcessor( rxProcessor ), + m_aCommandId( 0 ) +{ + if ( m_xProcessor.is() ) + { + // Generally, one command identifier per thread is enough. It + // can be used for all commands executed by the processor which + // created this id. + m_aCommandId = m_xProcessor->createCommandIdentifier(); + } +} + +//---------------------------------------------------------------------------- +// virtual +UcbCommandProcessor::~UcbCommandProcessor() +{ +} + +//---------------------------------------------------------------------------- +uno::Any UcbCommandProcessor::executeCommand( const rtl::OUString& rName, + const uno::Any& rArgument, + bool bPrint ) +{ + if ( m_xProcessor.is() ) + { + ucb::Command aCommand; + aCommand.Name = rName; + aCommand.Handle = -1; /* unknown */ + aCommand.Argument = rArgument; + + uno::Reference< task::XInteractionHandler > xInteractionHandler; + if (m_rUCB.getServiceFactory().is()) + xInteractionHandler + = uno::Reference< task::XInteractionHandler >( + m_rUCB.getServiceFactory()-> + createInstance( + rtl::OUString::createFromAscii( + "com.sun.star.task.InteractionHandler")), + uno::UNO_QUERY); + uno::Reference< ucb::XProgressHandler > + xProgressHandler(new ProgressHandler(m_rUCB)); + uno::Reference< ucb::XCommandEnvironment > xEnv( + new UcbTaskEnvironment( xInteractionHandler, xProgressHandler ) ); + + if ( bPrint ) + { + UniString aText( UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Executing command: " ) ) ); + aText += UniString( rName ); + print( aText ); + } + + // Execute command + uno::Any aResult; + bool bException = false; + bool bAborted = false; + try + { + aResult = m_xProcessor->execute( aCommand, m_aCommandId, xEnv ); + } + catch ( ucb::CommandAbortedException const & ) + { + bAborted = true; + } + catch ( uno::Exception const & ) + { + bException = true; + } + + if ( bPrint ) + { + if ( bException ) + print( "execute(...) threw an exception!" ); + + if ( bAborted ) + print( "execute(...) aborted!" ); + + if ( !bException && !bAborted ) + print( "execute() finished." ); + } + + return aResult; + } + + print( "executeCommand failed!" ); + return uno::Any(); +} + +/*======================================================================== + * + * UcbContent. + * + *=======================================================================*/ + +class UcbContent : public UcbCommandProcessor, + public cppu::OWeakObject, + public ucb::XContentEventListener, + public beans::XPropertiesChangeListener +{ + uno::Reference< ucb::XContent > m_xContent; + + struct OpenStackEntry + { + uno::Reference< ucb::XContentIdentifier > m_xIdentifier; + uno::Reference< ucb::XContent > m_xContent; + sal_uInt32 m_nLevel; + bool m_bUseIdentifier; + + OpenStackEntry(uno::Reference< ucb::XContentIdentifier > const & + rTheIdentifier, + sal_uInt32 nTheLevel): + m_xIdentifier(rTheIdentifier), m_nLevel(nTheLevel), + m_bUseIdentifier(true) {} + + OpenStackEntry(uno::Reference< ucb::XContent > const & rTheContent, + sal_uInt32 nTheLevel): + m_xContent(rTheContent), m_nLevel(nTheLevel), + m_bUseIdentifier(false) {} + }; + typedef std::stack< OpenStackEntry > OpenStack; + +private: + UcbContent( Ucb& rUCB, + uno::Reference< ucb::XContent >& rxContent, + MyOutWindow* pOutEdit ); + +protected: + virtual ~UcbContent(); + +public: + static UcbContent* create( + Ucb& rUCB, const UniString& rURL, MyOutWindow* pOutEdit ); + void dispose(); + + const UniString getURL() const; + const UniString getType() const; + + uno::Sequence< ucb::CommandInfo > getCommands(); + uno::Sequence< beans::Property > getProperties(); + + uno::Any getPropertyValue( const rtl::OUString& rName ); + void setPropertyValue( const rtl::OUString& rName, const uno::Any& rValue ); + void addProperty ( const rtl::OUString& rName, const uno::Any& rValue ); + void removeProperty ( const rtl::OUString& rName ); + + rtl::OUString getStringPropertyValue( const rtl::OUString& rName ); + void setStringPropertyValue( const rtl::OUString& rName, + const rtl::OUString& rValue ); + void addStringProperty( const rtl::OUString& rName, + const rtl::OUString& rValue ); + void open( const rtl::OUString & rName, const UniString& rInput, + bool bPrint, bool bTiming, bool bSort, + OpenStack * pStack = 0, sal_uInt32 nLevel = 0, + sal_Int32 nFetchSize = 0 ); + void openAll( Ucb& rUCB, bool bPrint, bool bTiming, bool bSort, + sal_Int32 nFetchSize ); + void transfer( const rtl::OUString& rSourceURL, sal_Bool bMove ); + void destroy(); + + // XInterface + virtual uno::Any SAL_CALL queryInterface( const uno::Type & rType ) + throw( uno::RuntimeException ); + virtual void SAL_CALL + acquire() + throw(); + virtual void SAL_CALL + release() + throw(); + + // XEventListener + // ( base interface of XContentEventListener, XPropertiesChangeListener ) + virtual void SAL_CALL + disposing( const lang::EventObject& Source ) + throw( uno::RuntimeException ); + + // XContentEventListener + virtual void SAL_CALL + contentEvent( const ucb::ContentEvent& evt ) + throw( uno::RuntimeException ); + + // XPropertiesChangeListener + virtual void SAL_CALL + propertiesChange( const uno::Sequence< beans::PropertyChangeEvent >& evt ) + throw( uno::RuntimeException ); +}; + +//------------------------------------------------------------------------- +UcbContent::UcbContent( Ucb& rUCB, + uno::Reference< ucb::XContent >& rxContent, + MyOutWindow* pOutEdit) +: UcbCommandProcessor( rUCB, + uno::Reference< ucb::XCommandProcessor >( + rxContent, uno::UNO_QUERY ), + pOutEdit ), + m_xContent( rxContent ) +{ +} + +//---------------------------------------------------------------------------- +// virtual +UcbContent::~UcbContent() +{ +} + +//------------------------------------------------------------------------- +// static +UcbContent* UcbContent::create( + Ucb& rUCB, const UniString& rURL, MyOutWindow* pOutEdit ) +{ + if ( !rURL.Len() ) + return NULL; + + ////////////////////////////////////////////////////////////////////// + // Get XContentIdentifier interface from UCB and let it create an + // identifer for the given URL. + ////////////////////////////////////////////////////////////////////// + + uno::Reference< ucb::XContentIdentifierFactory > xIdFac = + rUCB.getContentIdentifierFactory(); + if ( !xIdFac.is() ) + return NULL; + + uno::Reference< ucb::XContentIdentifier > xId = + xIdFac->createContentIdentifier( rURL ); + if ( !xId.is() ) + return NULL; + + ////////////////////////////////////////////////////////////////////// + // Get XContentProvider interface from UCB and let it create a + // content for the given identifier. + ////////////////////////////////////////////////////////////////////// + + uno::Reference< ucb::XContentProvider > xProv + = rUCB.getContentProvider(); + if ( !xProv.is() ) + return NULL; + + uno::Reference< ucb::XContent > xContent; + try + { + xContent = xProv->queryContent( xId ); + } + catch (ucb::IllegalIdentifierException const &) {} + if ( !xContent.is() ) + return NULL; + + UcbContent* pNew = new UcbContent( rUCB, xContent, pOutEdit ); + pNew->acquire(); + + // Register listener(s). + xContent->addContentEventListener( pNew ); + + uno::Reference< beans::XPropertiesChangeNotifier > xNotifier( + xContent, uno::UNO_QUERY ); + if ( xNotifier.is() ) + { + // Empty sequence -> interested in any property changes. + xNotifier->addPropertiesChangeListener( + uno::Sequence< rtl::OUString >(), pNew ); + } + + return pNew; +} + +//------------------------------------------------------------------------- +const UniString UcbContent::getURL() const +{ + uno::Reference< ucb::XContentIdentifier > xId( + m_xContent->getIdentifier() ); + if ( xId.is() ) + return UniString( xId->getContentIdentifier() ); + + return UniString(); +} + +//------------------------------------------------------------------------- +const UniString UcbContent::getType() const +{ + const UniString aType( m_xContent->getContentType() ); + return aType; +} + +//------------------------------------------------------------------------- +void UcbContent::dispose() +{ + uno::Reference< lang::XComponent > xComponent( m_xContent, uno::UNO_QUERY ); + if ( xComponent.is() ) + xComponent->dispose(); +} + +//---------------------------------------------------------------------------- +void UcbContent::open( const rtl::OUString & rName, const UniString& rInput, + bool bPrint, bool bTiming, bool bSort, + OpenStack * pStack, sal_uInt32 nLevel, + sal_Int32 nFetchSize ) +{ + uno::Any aArg; + + bool bDoSort = false; + + ucb::OpenCommandArgument2 aOpenArg; + if (rName.compareToAscii("search") == 0) + { + ucb::SearchCommandArgument aArgument; + if (!parseSearchArgument(rInput, aArgument.Info)) + { + print("Can't parse search argument"); + return; + } + aArgument.Properties.realloc(5); + aArgument.Properties[0].Name = rtl::OUString::createFromAscii("Title"); + aArgument.Properties[0].Handle = -1; + aArgument.Properties[1].Name + = rtl::OUString::createFromAscii("DateCreated"); + aArgument.Properties[1].Handle = -1; + aArgument.Properties[2].Name = rtl::OUString::createFromAscii("Size"); + aArgument.Properties[2].Handle = -1; + aArgument.Properties[3].Name + = rtl::OUString::createFromAscii("IsFolder"); + aArgument.Properties[3].Handle = -1; + aArgument.Properties[4].Name + = rtl::OUString::createFromAscii("IsDocument"); + aArgument.Properties[4].Handle = -1; + aArg <<= aArgument; + } + else + { + aOpenArg.Mode = ucb::OpenMode::ALL; + aOpenArg.Priority = 32768; +// if ( bFolder ) + { + // Property values which shall be in the result set... + uno::Sequence< beans::Property > aProps( 5 ); + beans::Property* pProps = aProps.getArray(); + pProps[ 0 ].Name = rtl::OUString::createFromAscii( "Title" ); + pProps[ 0 ].Handle = -1; // Important! +/**/ pProps[ 0 ].Type = getCppuType(static_cast< rtl::OUString * >(0)); + // HACK for sorting... + pProps[ 1 ].Name = rtl::OUString::createFromAscii( "DateCreated" ); + pProps[ 1 ].Handle = -1; // Important! + pProps[ 2 ].Name = rtl::OUString::createFromAscii( "Size" ); + pProps[ 2 ].Handle = -1; // Important! + pProps[ 3 ].Name = rtl::OUString::createFromAscii( "IsFolder" ); + pProps[ 3 ].Handle = -1; // Important! +/**/ pProps[ 3 ].Type = getCppuType(static_cast< sal_Bool * >(0)); + // HACK for sorting... + pProps[ 4 ].Name = rtl::OUString::createFromAscii( "IsDocument" ); + pProps[ 4 ].Handle = -1; // Important! + aOpenArg.Properties = aProps; + + bDoSort = bSort; + if (bDoSort) + { + // Sort criteria... Note that column numbering starts with 1! + aOpenArg.SortingInfo.realloc(2); + // primary sort criterium: column 4 --> IsFolder + aOpenArg.SortingInfo[ 0 ].ColumnIndex = 4; + aOpenArg.SortingInfo[ 0 ].Ascending = sal_False; + // secondary sort criterium: column 1 --> Title + aOpenArg.SortingInfo[ 1 ].ColumnIndex = 1; + aOpenArg.SortingInfo[ 1 ].Ascending = sal_True; + } + } +// else + aOpenArg.Sink + = static_cast< cppu::OWeakObject * >(new TestOutputStream); + aArg <<= aOpenArg; + } + +// putenv("PROT_REMOTE_ACTIVATE=1"); // to log remote uno traffic + + ULONG nTime = 0; + if ( bTiming ) + nTime = Time::GetSystemTicks(); + + uno::Any aResult = executeCommand( rName, aArg, bPrint ); + + uno::Reference< ucb::XDynamicResultSet > xDynamicResultSet; + if ( ( aResult >>= xDynamicResultSet ) && xDynamicResultSet.is() ) + { + if (bDoSort) + { + sal_Int16 nCaps = xDynamicResultSet->getCapabilities(); + if (!(nCaps & ucb::ContentResultSetCapability::SORTED)) + { + if (bPrint) + print("Result set rows are not sorted" + "---using sorting cursor"); + + uno::Reference< ucb::XSortedDynamicResultSetFactory > + xSortedFactory; + if (m_rUCB.getServiceFactory().is()) + xSortedFactory + = uno::Reference< + ucb::XSortedDynamicResultSetFactory >( + m_rUCB. + getServiceFactory()-> + createInstance( + rtl::OUString::createFromAscii( + "com.sun.star.ucb.SortedDynamic" + "ResultSetFactory")), + uno::UNO_QUERY); + uno::Reference< ucb::XDynamicResultSet > xSorted; + if (xSortedFactory.is()) + xSorted + = xSortedFactory-> + createSortedDynamicResultSet(xDynamicResultSet, + aOpenArg. + SortingInfo, + 0); + if (xSorted.is()) + xDynamicResultSet = xSorted; + else + print("Sorting cursor not available!"); + } + } + + uno::Reference< sdbc::XResultSet > xResultSet( + xDynamicResultSet->getStaticResultSet() ); + if ( xResultSet.is() ) + { + if ( bPrint ) + { + print( "Folder object opened - iterating:" ); + print( UniString::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( + "Content-ID : Title : Size : IsFolder : IsDocument\n" + "-------------------------------------------------" ) ) ); + } + + if (nFetchSize > 0) + { + bool bSet = false; + uno::Reference< beans::XPropertySet > xProperties( + xResultSet, uno::UNO_QUERY); + if (xProperties.is()) + try + { + xProperties-> + setPropertyValue(rtl::OUString::createFromAscii( + "FetchSize"), + uno::makeAny(nFetchSize)); + bSet = true; + } + catch (beans::UnknownPropertyException const &) {} + catch (beans::PropertyVetoException const &) {} + catch (lang::IllegalArgumentException const &) {} + catch (lang::WrappedTargetException const &) {} + if (!bSet) + print("Fetch size not set!"); + } + + try + { + ULONG n = 0; + uno::Reference< ucb::XContentAccess > xContentAccess( + xResultSet, uno::UNO_QUERY ); + uno::Reference< sdbc::XRow > xRow( xResultSet, uno::UNO_QUERY ); + + while ( xResultSet->next() ) + { + UniString aText; + + if ( bPrint ) + { + rtl::OUString aId( xContentAccess-> + queryContentIdentifierString() ); + aText += UniString::CreateFromInt32( ++n ); + aText.AppendAscii( RTL_CONSTASCII_STRINGPARAM( + ") " ) ); + aText += UniString( aId ); + aText.AppendAscii( RTL_CONSTASCII_STRINGPARAM( + " : " ) ); + } + + // Title: + UniString aTitle( xRow->getString( 1 ) ); + if ( bPrint ) + { + if ( aTitle.Len() == 0 && xRow->wasNull() ) + aText.AppendAscii( RTL_CONSTASCII_STRINGPARAM( + "<null>" ) ); + else + aText += aTitle; + aText.AppendAscii( RTL_CONSTASCII_STRINGPARAM( + " : " ) ); + } + + // Size: + sal_Int32 nSize = xRow->getInt( 3 ); + if ( bPrint ) + { + if ( nSize == 0 && xRow->wasNull() ) + aText.AppendAscii( RTL_CONSTASCII_STRINGPARAM( + "<null>" ) ); + else + aText += UniString::CreateFromInt32( nSize ); + aText.AppendAscii( RTL_CONSTASCII_STRINGPARAM( + " : " ) ); + } + + // IsFolder: + sal_Bool bFolder = xRow->getBoolean( 4 ); + if ( bPrint ) + { + if ( !bFolder && xRow->wasNull() ) + aText.AppendAscii( RTL_CONSTASCII_STRINGPARAM( + "<null>" ) ); + else + aText + += bFolder ? + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "true" ) ) : + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "false" ) ); + aText.AppendAscii( RTL_CONSTASCII_STRINGPARAM( + " : " ) ); + } + + // IsDocument: + sal_Bool bDocument = xRow->getBoolean( 5 ); + if ( bPrint ) + { + if ( !bFolder && xRow->wasNull() ) + aText.AppendAscii( RTL_CONSTASCII_STRINGPARAM( + "<null>" ) ); + else + aText + += bDocument ? + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "true" ) ) : + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "false" ) ); // IsDocument + } + + if ( bPrint ) + print( aText ); + + if ( pStack && bFolder ) + pStack->push( OpenStackEntry( +#if 1 + xContentAccess-> + queryContentIdentifier(), +#else + xContentAccess->queryContent(), +#endif + nLevel + 1 ) ); + } + } + catch ( ucb::ResultSetException ) + { + print( "ResultSetException caught!" ); + } + + if ( bPrint ) + print( "Iteration done." ); + } + } + + uno::Reference< lang::XComponent > xComponent( + xDynamicResultSet, uno::UNO_QUERY); + if (xComponent.is()) + xComponent->dispose(); + +// putenv("PROT_REMOTE_ACTIVATE="); // to log remote uno traffic + + if ( bTiming ) + { + nTime = Time::GetSystemTicks() - nTime; + UniString + aText( UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( "Operation took " ) ) ); + aText += UniString::CreateFromInt64( nTime ); + aText.AppendAscii( RTL_CONSTASCII_STRINGPARAM( " ms." ) ); + print( aText ); + } +} + +//---------------------------------------------------------------------------- +void UcbContent::openAll( Ucb& rUCB, bool bPrint, bool bTiming, bool bSort, + sal_Int32 nFetchSize ) +{ + ULONG nTime = 0; + if ( bTiming ) + nTime = Time::GetSystemTicks(); + + OpenStack aStack; + aStack.push( OpenStackEntry( m_xContent, 0 ) ); + + while ( !aStack.empty() ) + { + OpenStackEntry aEntry( aStack.top() ); + aStack.pop(); + + if ( bPrint ) + { + UniString aText; + for ( sal_uInt32 i = aEntry.m_nLevel; i != 0; --i ) + aText += '='; + aText.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "LEVEL " ) ); + aText += UniString::CreateFromInt64( aEntry.m_nLevel ); + + uno::Reference< ucb::XContentIdentifier > xID; + if ( aEntry.m_bUseIdentifier ) + xID = aEntry.m_xIdentifier; + else if ( aEntry.m_xContent.is() ) + xID = aEntry.m_xContent->getIdentifier(); + if ( xID.is() ) + { + aText.AppendAscii( RTL_CONSTASCII_STRINGPARAM( ": " ) ); + aText += UniString( xID->getContentIdentifier() ); + } + + print( aText ); + } + + uno::Reference< ucb::XContent > xChild; + if ( aEntry.m_bUseIdentifier ) + { + uno::Reference< ucb::XContentProvider > xProv + = rUCB.getContentProvider(); + if ( !xProv.is() ) + { + print( "No content provider" ); + return; + } + + try + { + xChild = xProv->queryContent( aEntry.m_xIdentifier ); + } + catch (ucb::IllegalIdentifierException const &) {} + } + else + xChild = aEntry.m_xContent; + if ( !xChild.is() ) + { + print( "No content" ); + return; + } + + UcbContent( m_rUCB, xChild, m_pOutEdit ). + open( UniString::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( + "open" ) ), + UniString(), bPrint, false, bSort, &aStack, + aEntry.m_nLevel, nFetchSize ); + } + + if ( bTiming ) + { + nTime = Time::GetSystemTicks() - nTime; + UniString + aText( UniString::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( + "Operation took " ) ) ); + aText += UniString::CreateFromInt64( nTime ); + aText.AppendAscii( RTL_CONSTASCII_STRINGPARAM( " ms." ) ); + print( aText ); + } +} + +//---------------------------------------------------------------------------- +void UcbContent::transfer( const rtl::OUString& rSourceURL, sal_Bool bMove ) +{ + if ( bMove ) + print( "Moving content..." ); + else + print( "Copying content..." ); + +#if 1 /* globalTransfer */ + + uno::Reference< ucb::XCommandProcessor > xCommandProcessor( + m_rUCB.getContentProvider(), uno::UNO_QUERY ); + if ( xCommandProcessor.is() ) + { + +#if 0 + ucb::Command aCommand( + rtl::OUString::createFromAscii( "getCommandInfo" ), -1, Any() ); + uno::Reference< ucb::XCommandInfo > xInfo; + xCommandProcessor->execute( + aCommand, 0, uno::Reference< ucb::XCommandEnvironment >() ) + >>= xInfo; + if ( xInfo.is() ) + { + ucb::CommandInfo aInfo + = xInfo->getCommandInfoByName( + rtl::OUString::createFromAscii( "globalTransfer" ) ); + + uno::Sequence< ucb::CommandInfo > aCommands + = xInfo->getCommands(); + const ucb::CommandInfo* pCommands = aCommands.getConstArray(); + + String aText( UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( "Commands:\n" ) ) ); + sal_uInt32 nCount = aCommands.getLength(); + for ( sal_uInt32 n = 0; n < nCount; ++n ) + { + aText.AppendAscii( RTL_CONSTASCII_STRINGPARAM( " " ) ); + aText += String( pCommands[ n ].Name ); + aText += '\n'; + } + print( aText ); + } +#endif + ucb::GlobalTransferCommandArgument aArg( + bMove ? ucb::TransferCommandOperation_MOVE + : ucb::TransferCommandOperation_COPY, + rSourceURL, + getURL(), + rtl::OUString(), + //rtl::OUString::createFromAscii( "NewTitle" ), + ucb::NameClash::ERROR ); + + ucb::Command aTransferCommand( rtl::OUString::createFromAscii( + "globalTransfer" ), + -1, + uno::makeAny( aArg ) ); + + uno::Reference< task::XInteractionHandler > xInteractionHandler; + if (m_rUCB.getServiceFactory().is()) + xInteractionHandler + = uno::Reference< task::XInteractionHandler >( + m_rUCB.getServiceFactory()-> + createInstance( + rtl::OUString::createFromAscii( + "com.sun.star.task.InteractionHandler")), + uno::UNO_QUERY); + uno::Reference< ucb::XProgressHandler > xProgressHandler( + new ProgressHandler(m_rUCB)); + uno::Reference< ucb::XCommandEnvironment > xEnv( + new UcbTaskEnvironment( xInteractionHandler, xProgressHandler ) ); + + try + { + xCommandProcessor->execute( aTransferCommand, 0, xEnv ); + } + catch ( uno::Exception const & ) + { + print( "globalTransfer threw exception!" ); + return; + } + + print( "globalTransfer finished successfully" ); + } + +#else /* transfer */ + + uno::Any aArg; + aArg <<= ucb::TransferInfo( + bMove, rSourceURL, rtl::OUString(), ucb::NameClash::ERROR ); + executeCommand( rtl::OUString::createFromAscii( "transfer" ), aArg ); + +// executeCommand( rtl::OUString::createFromAscii( "flush" ), Any() ); + +#endif +} + +//---------------------------------------------------------------------------- +void UcbContent::destroy() +{ + print( "Deleting content..." ); + + uno::Any aArg; + aArg <<= sal_Bool( sal_True ); // delete physically, not only to trash. + executeCommand( rtl::OUString::createFromAscii( "delete" ), aArg ); + +// executeCommand( rtl::OUString::createFromAscii( "flush" ), Any() ); +} + +//------------------------------------------------------------------------- +uno::Sequence< ucb::CommandInfo > UcbContent::getCommands() +{ + uno::Any aResult = executeCommand( + rtl::OUString::createFromAscii( "getCommandInfo" ), uno::Any() ); + + uno::Reference< ucb::XCommandInfo > xInfo; + if ( aResult >>= xInfo ) + { + uno::Sequence< ucb::CommandInfo > aCommands( + xInfo->getCommands() ); + const ucb::CommandInfo* pCommands = aCommands.getConstArray(); + + String aText( UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( "Commands:\n" ) ) ); + sal_uInt32 nCount = aCommands.getLength(); + for ( sal_uInt32 n = 0; n < nCount; ++n ) + { + aText.AppendAscii( RTL_CONSTASCII_STRINGPARAM( " " ) ); + aText += String( pCommands[ n ].Name ); + aText += '\n'; + } + print( aText ); + + return aCommands; + } + + print( "getCommands failed!" ); + return uno::Sequence< ucb::CommandInfo >(); +} + +//------------------------------------------------------------------------- +uno::Sequence< beans::Property > UcbContent::getProperties() +{ + uno::Any aResult = executeCommand( + rtl::OUString::createFromAscii( "getPropertySetInfo" ), uno::Any() ); + + uno::Reference< beans::XPropertySetInfo > xInfo; + if ( aResult >>= xInfo ) + { + uno::Sequence< beans::Property > aProps( xInfo->getProperties() ); + const beans::Property* pProps = aProps.getConstArray(); + + String aText( UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( "Properties:\n" ) ) ); + sal_uInt32 nCount = aProps.getLength(); + for ( sal_uInt32 n = 0; n < nCount; ++n ) + { + aText.AppendAscii( RTL_CONSTASCII_STRINGPARAM( " " ) ); + aText += UniString( pProps[ n ].Name ); + aText += '\n'; + } + print( aText ); + + return aProps; + } + + print( "getProperties failed!" ); + return uno::Sequence< beans::Property >(); +} + +//---------------------------------------------------------------------------- +uno::Any UcbContent::getPropertyValue( const rtl::OUString& rName ) +{ + uno::Sequence< beans::Property > aProps( 1 ); + beans::Property& rProp = aProps.getArray()[ 0 ]; + + rProp.Name = rName; + rProp.Handle = -1; /* unknown */ +// rProp.Type = ; +// rProp.Attributes = ; + + uno::Any aArg; + aArg <<= aProps; + + uno::Any aResult = executeCommand( + rtl::OUString::createFromAscii( "getPropertyValues" ), aArg ); + + uno::Reference< sdbc::XRow > xValues; + if ( aResult >>= xValues ) + return xValues->getObject( + 1, uno::Reference< container::XNameAccess>() ); + + print( "getPropertyValue failed!" ); + return uno::Any(); +} + +//---------------------------------------------------------------------------- +rtl::OUString UcbContent::getStringPropertyValue( const rtl::OUString& rName ) +{ + uno::Any aAny = getPropertyValue( rName ); + if ( aAny.getValueType() == getCppuType( (const ::rtl::OUString *)0 ) ) + { + const rtl::OUString aValue( + * static_cast< const rtl::OUString * >( aAny.getValue() ) ); + + UniString aText( rName ); + aText.AppendAscii( RTL_CONSTASCII_STRINGPARAM( " value: '" ) ); + aText += UniString( aValue ); + aText.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "'" ) ); + print( aText ); + + return aValue; + } + + print( "getStringPropertyValue failed!" ); + return rtl::OUString(); +} + +//---------------------------------------------------------------------------- +void UcbContent::setPropertyValue( const rtl::OUString& rName, + const uno::Any& rValue ) +{ + uno::Sequence< beans::PropertyValue > aProps( 1 ); + beans::PropertyValue& rProp = aProps.getArray()[ 0 ]; + + rProp.Name = rName; + rProp.Handle = -1; /* unknown */ + rProp.Value = rValue; +// rProp.State = ; + + uno::Any aArg; + aArg <<= aProps; + + executeCommand( rtl::OUString::createFromAscii( "setPropertyValues" ), + aArg ); + +// executeCommand( rtl::OUString::createFromAscii( "flush" ), Any() ); +} + +//---------------------------------------------------------------------------- +void UcbContent::setStringPropertyValue( const rtl::OUString& rName, + const rtl::OUString& rValue ) +{ + uno::Any aAny; + aAny <<= rValue; + setPropertyValue( rName, aAny ); + + UniString aText( rName ); + aText.AppendAscii( RTL_CONSTASCII_STRINGPARAM( " value set to: '" ) ); + aText += UniString( rValue ); + aText.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "'" ) ); + print( aText ); +} + +//---------------------------------------------------------------------------- +void UcbContent::addProperty( const rtl::OUString& rName, + const uno::Any& rValue ) +{ + uno::Reference< beans::XPropertyContainer > xContainer( m_xContent, + uno::UNO_QUERY ); + if ( xContainer.is() ) + { + UniString aText( UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Adding property: " ) ) ); + aText += UniString( rName ); + print( aText ); + + try + { + xContainer->addProperty( rName, 0, rValue ); + } + catch ( beans::PropertyExistException const & ) + { + print( "Adding property failed. Already exists!" ); + return; + } + catch ( beans::IllegalTypeException const & ) + { + print( "Adding property failed. Illegal Type!" ); + return; + } + catch ( lang::IllegalArgumentException const & ) + { + print( "Adding property failed. Illegal Argument!" ); + return; + } + + print( "Adding property succeeded." ); + return; + } + + print( "Adding property failed. No XPropertyContainer!" ); +} + +//---------------------------------------------------------------------------- +void UcbContent::addStringProperty( + const rtl::OUString& rName, const rtl::OUString& rValue ) +{ + uno::Any aValue; + aValue <<= rValue; + addProperty( rName, aValue ); +} + +//---------------------------------------------------------------------------- +void UcbContent::removeProperty( const rtl::OUString& rName ) +{ + uno::Reference< beans::XPropertyContainer > xContainer( m_xContent, + uno::UNO_QUERY ); + if ( xContainer.is() ) + { + UniString aText( UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Removing property: " ) ) ); + aText += UniString( rName ); + print( aText ); + + try + { + xContainer->removeProperty( rName ); + } + catch ( beans::UnknownPropertyException const & ) + { + print( "Adding property failed. Unknown!" ); + return; + } + + print( "Removing property succeeded." ); + return; + } + + print( "Removing property failed. No XPropertyContainer!" ); +} + +//---------------------------------------------------------------------------- +// +// XInterface methods +// +//---------------------------------------------------------------------------- + +// virtual +uno::Any SAL_CALL UcbContent::queryInterface( const uno::Type & rType ) + throw(uno::RuntimeException) +{ + uno::Any aRet = cppu::queryInterface( + rType, + static_cast< lang::XEventListener* >( + static_cast< ucb::XContentEventListener* >( this ) ), + static_cast< ucb::XContentEventListener* >( this ), + static_cast< beans::XPropertiesChangeListener* >( this ) ); + return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ); +} + +//---------------------------------------------------------------------------- +// virtual +void SAL_CALL UcbContent::acquire() + throw() +{ + OWeakObject::acquire(); +} + +//---------------------------------------------------------------------------- +// virtual +void SAL_CALL UcbContent::release() + throw() +{ + OWeakObject::release(); +} + +//---------------------------------------------------------------------------- +// +// XEventListener methods. +// +//---------------------------------------------------------------------------- + +// virtual +void SAL_CALL UcbContent::disposing( const lang::EventObject& /*Source*/ ) + throw( uno::RuntimeException ) +{ + print ( "Content: disposing..." ); +} + +//---------------------------------------------------------------------------- +// +// XContentEventListener methods, +// +//---------------------------------------------------------------------------- + +// virtual +void SAL_CALL UcbContent::contentEvent( const ucb::ContentEvent& evt ) + throw( uno::RuntimeException ) +{ + switch ( evt.Action ) + { + case ucb::ContentAction::INSERTED: + { + UniString aText( UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "contentEvent: INSERTED: " ) ) ); + if ( evt.Content.is() ) + { + uno::Reference< ucb::XContentIdentifier > xId( + evt.Content->getIdentifier() ); + aText += UniString( xId->getContentIdentifier() ); + aText.AppendAscii( RTL_CONSTASCII_STRINGPARAM( " - " ) ); + aText += UniString( evt.Content->getContentType() ); + } + + print( aText ); + break; + } + case ucb::ContentAction::REMOVED: + print( "contentEvent: REMOVED" ); + break; + + case ucb::ContentAction::DELETED: + print( "contentEvent: DELETED" ); + break; + + case ucb::ContentAction::EXCHANGED: + print( "contentEvent: EXCHANGED" ); + break; + + case ucb::ContentAction::SEARCH_MATCHED: + { + String aMatch(RTL_CONSTASCII_USTRINGPARAM( + "contentEvent: SEARCH MATCHED ")); + if (evt.Id.is()) + { + aMatch += String(evt.Id->getContentIdentifier()); + if (evt.Content.is()) + { + aMatch.AppendAscii(RTL_CONSTASCII_STRINGPARAM(" - ")); + aMatch += String(evt.Content->getContentType()); + } + } + else + aMatch.AppendAscii(RTL_CONSTASCII_STRINGPARAM("<no id>")); + print(aMatch); + break; + } + + default: + print( "contentEvent..." ); + break; + } +} + +//---------------------------------------------------------------------------- +// +// XPropertiesChangeListener methods. +// +//---------------------------------------------------------------------------- + +// virtual +void SAL_CALL UcbContent::propertiesChange( + const uno::Sequence< beans::PropertyChangeEvent >& evt ) + throw( uno::RuntimeException ) +{ + print( "propertiesChange..." ); + + sal_uInt32 nCount = evt.getLength(); + if ( nCount ) + { + const beans::PropertyChangeEvent* pEvents = evt.getConstArray(); + for ( sal_uInt32 n = 0; n < nCount; ++n ) + { + UniString aText( UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( " " ) ) ); + aText += UniString( pEvents[ n ].PropertyName ); + print( aText ); + } + } +} + +/*======================================================================== + * + * MyWin. + * + *=======================================================================*/ + +#define MYWIN_ITEMID_CLEAR 1 +#define MYWIN_ITEMID_CREATE 2 +#define MYWIN_ITEMID_RELEASE 3 +#define MYWIN_ITEMID_COMMANDS 4 +#define MYWIN_ITEMID_PROPS 5 +#define MYWIN_ITEMID_ADD_PROP 6 +#define MYWIN_ITEMID_REMOVE_PROP 7 +#define MYWIN_ITEMID_GET_PROP 8 +#define MYWIN_ITEMID_SET_PROP 9 +#define MYWIN_ITEMID_OPEN 10 +#define MYWIN_ITEMID_OPEN_ALL 11 +#define MYWIN_ITEMID_UPDATE 12 +#define MYWIN_ITEMID_SYNCHRONIZE 13 +#define MYWIN_ITEMID_COPY 14 +#define MYWIN_ITEMID_MOVE 15 +#define MYWIN_ITEMID_DELETE 16 +#define MYWIN_ITEMID_SEARCH 17 +#define MYWIN_ITEMID_TIMING 18 +#define MYWIN_ITEMID_SORT 19 +#define MYWIN_ITEMID_FETCHSIZE 20 +#define MYWIN_ITEMID_SYS2URI 21 +#define MYWIN_ITEMID_URI2SYS 22 +#define MYWIN_ITEMID_OFFLINE 23 +#define MYWIN_ITEMID_ONLINE 24 +#define MYWIN_ITEMID_REORGANIZE 25 + +//------------------------------------------------------------------------- +class MyWin : public WorkWindow +{ +private: + ToolBox* m_pTool; + Edit* m_pCmdEdit; + MyOutWindow* m_pOutEdit; + + Ucb m_aUCB; + UcbContent* m_pContent; + + sal_Int32 m_nFetchSize; + bool m_bTiming; + bool m_bSort; + +public: + MyWin( Window *pParent, WinBits nWinStyle, + uno::Reference< lang::XMultiServiceFactory >& rxFactory, + rtl::OUString const & rConfigurationKey1, + rtl::OUString const & rConfigurationKey2 ); + virtual ~MyWin(); + + void Resize( void ); + DECL_LINK ( ToolBarHandler, ToolBox* ); + + void print( const UniString& rText ); + void print( const sal_Char* pText ); +}; + +//------------------------------------------------------------------------- +MyWin::MyWin( Window *pParent, WinBits nWinStyle, + uno::Reference< lang::XMultiServiceFactory >& rxFactory, + rtl::OUString const & rConfigurationKey1, + rtl::OUString const & rConfigurationKey2 ) +: WorkWindow( pParent, nWinStyle ), + m_pTool( NULL ), + m_pOutEdit( NULL ), + m_aUCB( rxFactory, rConfigurationKey1, rConfigurationKey2 ), + m_pContent( NULL ), + m_nFetchSize( 0 ), + m_bTiming( false ), + m_bSort( false ) +{ + // ToolBox. + m_pTool = new ToolBox( this, WB_3DLOOK | WB_BORDER | WB_SCROLL ); + + m_pTool->InsertItem ( MYWIN_ITEMID_CLEAR, + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Clear" ) ) ); + m_pTool->SetHelpText( MYWIN_ITEMID_CLEAR, + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Clear the Output Window" ) ) ); + m_pTool->InsertSeparator(); + m_pTool->InsertItem ( MYWIN_ITEMID_CREATE, + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Create" ) ) ); + m_pTool->SetHelpText( MYWIN_ITEMID_CREATE, + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Create a content" ) ) ); + m_pTool->InsertItem ( MYWIN_ITEMID_RELEASE, + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Release" ) ) ); + m_pTool->SetHelpText( MYWIN_ITEMID_RELEASE, + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Release current content" ) ) ); + m_pTool->InsertSeparator(); + m_pTool->InsertItem ( MYWIN_ITEMID_COMMANDS, + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Commands" ) ) ); + m_pTool->SetHelpText( MYWIN_ITEMID_COMMANDS, + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Get Commands supported by the content" ) ) ); + m_pTool->InsertItem ( MYWIN_ITEMID_PROPS, + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Properties" ) ) ); + m_pTool->SetHelpText( MYWIN_ITEMID_PROPS, + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Get Properties supported by the content" ) ) ); + m_pTool->InsertSeparator(); + m_pTool->InsertItem ( MYWIN_ITEMID_ADD_PROP, + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "addProperty" ) ) ); + m_pTool->SetHelpText( MYWIN_ITEMID_ADD_PROP, + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Add a new string(!) property to the content. " + "Type the property name in the entry field and " + "push this button. The default value for the " + "property will be set to the string 'DefaultValue'" ) ) ); + m_pTool->InsertItem ( MYWIN_ITEMID_REMOVE_PROP, + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "removeProperty" ) ) ); + m_pTool->SetHelpText( MYWIN_ITEMID_REMOVE_PROP, + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Removes a property from the content. " + "Type the property name in the entry field and " + "push this button." ) ) ); + m_pTool->InsertItem ( MYWIN_ITEMID_GET_PROP, + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "getPropertyValue" ) ) ); + m_pTool->SetHelpText( MYWIN_ITEMID_GET_PROP, + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Get a string(!) property value from the content. " + "Type the property name in the entry field and " + "push this button to obtain the value" ) ) ); + m_pTool->InsertItem ( MYWIN_ITEMID_SET_PROP, + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "setPropertyValue" ) ) ); + m_pTool->SetHelpText( MYWIN_ITEMID_SET_PROP, + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Set a string(!) property value of the content." + "Type the property name in the entry field and " + "push this button to set the value to the string " + "'NewValue'" ) ) ); + m_pTool->InsertSeparator(); + m_pTool->InsertItem ( MYWIN_ITEMID_OPEN, + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Open" ) ) ); + m_pTool->SetHelpText( MYWIN_ITEMID_OPEN, + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Open the content" ) ) ); + m_pTool->InsertItem ( MYWIN_ITEMID_OPEN_ALL, + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Open All" ) ) ); + m_pTool->SetHelpText( MYWIN_ITEMID_OPEN_ALL, + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Open the content and all of its" + " children" ) ) ); + m_pTool->InsertItem ( MYWIN_ITEMID_UPDATE, + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Update" ) ) ); + m_pTool->SetHelpText( MYWIN_ITEMID_UPDATE, + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Update the content" ) ) ); + m_pTool->InsertItem ( MYWIN_ITEMID_SYNCHRONIZE, + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Synchronize" ) ) ); + m_pTool->SetHelpText( MYWIN_ITEMID_SYNCHRONIZE, + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Synchronize the content" ) ) ); + m_pTool->InsertItem ( MYWIN_ITEMID_SEARCH, + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Search" ) ) ); + m_pTool->SetHelpText( MYWIN_ITEMID_SEARCH, + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Search the content" ) ) ); + + m_pTool->InsertItem ( MYWIN_ITEMID_REORGANIZE, + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Reorganize" ) ) ); + m_pTool->SetHelpText( MYWIN_ITEMID_REORGANIZE, + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Reorganize the content storage" ) ) ); + + m_pTool->InsertSeparator(); + m_pTool->InsertItem ( MYWIN_ITEMID_COPY, + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Copy" ) ) ); + m_pTool->SetHelpText( MYWIN_ITEMID_COPY, + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Copy a content. Type the URL of the source " + "content into the entry field." ) ) ); + m_pTool->InsertItem ( MYWIN_ITEMID_MOVE, + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Move" ) ) ); + m_pTool->SetHelpText( MYWIN_ITEMID_MOVE, + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Move a content. Type the URL of the source " + "content into the entry field." ) ) ); + m_pTool->InsertItem ( MYWIN_ITEMID_DELETE, + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Delete" ) ) ); + m_pTool->SetHelpText( MYWIN_ITEMID_DELETE, + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Delete the content." ) ) ); + + m_pTool->InsertSeparator(); + m_pTool->InsertItem ( MYWIN_ITEMID_TIMING, + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Timing" ) ), + TIB_CHECKABLE | TIB_AUTOCHECK ); + m_pTool->SetHelpText( MYWIN_ITEMID_TIMING, + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Display execution times instead of" + " output" ) ) ); + m_pTool->InsertItem ( MYWIN_ITEMID_SORT, + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Sort" ) ), + TIB_CHECKABLE | TIB_AUTOCHECK ); + m_pTool->SetHelpText( MYWIN_ITEMID_SORT, + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Sort result sets" ) ) ); + m_pTool->InsertItem ( MYWIN_ITEMID_FETCHSIZE, + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Fetch Size" ) ) ); + m_pTool->SetHelpText( MYWIN_ITEMID_FETCHSIZE, + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Set cached cursor fetch size to positive value" ) ) ); + + m_pTool->InsertSeparator(); + m_pTool->InsertItem ( MYWIN_ITEMID_SYS2URI, + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "UNC>URI" ) ) ); + m_pTool->SetHelpText( MYWIN_ITEMID_SYS2URI, + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Translate 'System File Path' to URI," + " if possible" ) ) ); + m_pTool->InsertItem ( MYWIN_ITEMID_URI2SYS, + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "URI>UNC" ) ) ); + m_pTool->SetHelpText( MYWIN_ITEMID_URI2SYS, + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Translate URI to 'System File Path'," + " if possible" ) ) ); + + m_pTool->InsertSeparator(); + m_pTool->InsertItem ( MYWIN_ITEMID_OFFLINE, + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Offline" ) ) ); + m_pTool->SetHelpText( MYWIN_ITEMID_OFFLINE, + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Go offline" ) ) ); + m_pTool->InsertItem ( MYWIN_ITEMID_ONLINE, + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Online" ) ) ); + m_pTool->SetHelpText( MYWIN_ITEMID_ONLINE, + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Go back online" ) ) ); + + m_pTool->SetSelectHdl( LINK( this, MyWin, ToolBarHandler ) ); + m_pTool->Show(); + + // Edit. + m_pCmdEdit = new Edit( this ); + m_pCmdEdit->SetReadOnly( FALSE ); + m_pCmdEdit->SetText( UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( "file:///" ) ) ); + m_pCmdEdit->Show(); + + // MyOutWindow. + m_pOutEdit = new MyOutWindow( this, WB_HSCROLL | WB_VSCROLL | WB_BORDER ); + m_pOutEdit->SetReadOnly( TRUE ); + m_pOutEdit->Show(); + + m_aUCB.setOutEdit( m_pOutEdit ); +} + +//------------------------------------------------------------------------- +// virtual +MyWin::~MyWin() +{ + if ( m_pContent ) + { + m_pContent->dispose(); + m_pContent->release(); + } + + delete m_pTool; + delete m_pCmdEdit; + delete m_pOutEdit; +} + +//------------------------------------------------------------------------- +void MyWin::Resize() +{ + Size aWinSize = GetOutputSizePixel(); + int nWinW = aWinSize.Width(); + int nWinH = aWinSize.Height(); + int nBoxH = m_pTool->CalcWindowSizePixel().Height(); + + m_pTool->SetPosSizePixel ( + Point( 0, 0 ), Size ( nWinW, nBoxH ) ); + m_pCmdEdit->SetPosSizePixel( + Point( 0, nBoxH ), Size( nWinW, nBoxH ) ); + m_pOutEdit->SetPosSizePixel( + Point( 0, nBoxH + nBoxH ), Size ( nWinW, nWinH - ( nBoxH + nBoxH ) ) ); +} + +//------------------------------------------------------------------------- +void MyWin::print( const sal_Char* pText ) +{ + print( UniString::CreateFromAscii( pText ) ); +} + +//------------------------------------------------------------------------- +void MyWin::print( const UniString& rText ) +{ + vos::OGuard aGuard( Application::GetSolarMutex() ); + + if ( m_pOutEdit ) + { + m_pOutEdit->Append( rText ); + m_pOutEdit->Update(); + } +} + +//------------------------------------------------------------------------- +IMPL_LINK( MyWin, ToolBarHandler, ToolBox*, pToolBox ) +{ + USHORT nItemId = pToolBox->GetCurItemId(); + UniString aCmdLine = m_pCmdEdit->GetText(); + + ULONG n = Application::ReleaseSolarMutex(); + + switch( nItemId ) + { + case MYWIN_ITEMID_CLEAR: + { + vos::OGuard aGuard( Application::GetSolarMutex() ); + + m_pOutEdit->Clear(); + m_pOutEdit->Show(); + break; + } + + case MYWIN_ITEMID_CREATE: + if ( m_pContent ) + { + UniString aText( UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Content released: " ) ) ); + aText += m_pContent->getURL(); + + m_pContent->dispose(); + m_pContent->release(); + m_pContent = NULL; + + print( aText ); + } + + m_pContent = UcbContent::create( m_aUCB, aCmdLine, m_pOutEdit ); + if ( m_pContent ) + { + String aText( UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Created content: " ) ) ); + aText += String( m_pContent->getURL() ); + aText.AppendAscii( RTL_CONSTASCII_STRINGPARAM( " - " ) ); + aText += String( m_pContent->getType() ); + print( aText ); + } + else + { + String aText( UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Creation failed for content: " ) ) ); + aText += String( aCmdLine ); + print( aText ); + } + break; + + case MYWIN_ITEMID_RELEASE: + if ( m_pContent ) + { + UniString aText( UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( + "Content released: " ) ) ); + aText += m_pContent->getURL(); + + m_pContent->dispose(); + m_pContent->release(); + m_pContent = NULL; + + print( aText ); + } + else + print( "No content!" ); + + break; + + case MYWIN_ITEMID_COMMANDS: + if ( m_pContent ) + m_pContent->getCommands(); + else + print( "No content!" ); + + break; + + case MYWIN_ITEMID_PROPS: + if ( m_pContent ) + m_pContent->getProperties(); + else + print( "No content!" ); + + break; + + case MYWIN_ITEMID_ADD_PROP: + if ( m_pContent ) + m_pContent->addStringProperty( + aCmdLine, + rtl::OUString::createFromAscii( "DefaultValue" ) ); + else + print( "No content!" ); + + break; + + case MYWIN_ITEMID_REMOVE_PROP: + if ( m_pContent ) + m_pContent->removeProperty( aCmdLine ); + else + print( "No content!" ); + + break; + + case MYWIN_ITEMID_GET_PROP: + if ( m_pContent ) + m_pContent->getStringPropertyValue( aCmdLine ); + else + print( "No content!" ); + + break; + + case MYWIN_ITEMID_SET_PROP: + if ( m_pContent ) + m_pContent->setStringPropertyValue( + aCmdLine, + rtl::OUString::createFromAscii( "NewValue" ) ); + else + print( "No content!" ); + + break; + + case MYWIN_ITEMID_OPEN: + if ( m_pContent ) + m_pContent->open(rtl::OUString::createFromAscii("open"), + aCmdLine, !m_bTiming, m_bTiming, m_bSort, 0, + 0, m_nFetchSize); + else + print( "No content!" ); + + break; + + case MYWIN_ITEMID_OPEN_ALL: + if ( m_pContent ) + m_pContent->openAll(m_aUCB, !m_bTiming, m_bTiming, m_bSort, + m_nFetchSize); + else + print( "No content!" ); + + break; + + case MYWIN_ITEMID_UPDATE: + if ( m_pContent ) + m_pContent->open(rtl::OUString::createFromAscii("update"), + aCmdLine, !m_bTiming, m_bTiming, m_bSort, 0, + 0, m_nFetchSize); + else + print( "No content!" ); + + break; + + case MYWIN_ITEMID_SYNCHRONIZE: + if ( m_pContent ) + m_pContent->open(rtl::OUString::createFromAscii("synchronize"), + aCmdLine, !m_bTiming, m_bTiming, m_bSort, 0, + 0, m_nFetchSize); + else + print( "No content!" ); + + break; + + case MYWIN_ITEMID_SEARCH: + if ( m_pContent ) + m_pContent->open(rtl::OUString::createFromAscii("search"), + aCmdLine, !m_bTiming, m_bTiming, m_bSort, 0, + 0, m_nFetchSize); + else + print( "No content!" ); + + break; + + case MYWIN_ITEMID_REORGANIZE: + if ( m_pContent ) + m_pContent->executeCommand ( + rtl::OUString::createFromAscii ("reorganizeData"), + uno::Any()); + else + print( "No content!" ); + + break; + + case MYWIN_ITEMID_COPY: + if ( m_pContent ) + m_pContent->transfer( aCmdLine, sal_False ); + else + print( "No content!" ); + + break; + + case MYWIN_ITEMID_MOVE: + if ( m_pContent ) + m_pContent->transfer( aCmdLine, sal_True ); + else + print( "No content!" ); + + break; + + case MYWIN_ITEMID_DELETE: + if ( m_pContent ) + m_pContent->destroy(); + else + print( "No content!" ); + + break; + + case MYWIN_ITEMID_TIMING: + m_bTiming = m_pTool->IsItemChecked(MYWIN_ITEMID_TIMING) != false; + break; + + case MYWIN_ITEMID_SORT: + m_bSort = m_pTool->IsItemChecked(MYWIN_ITEMID_SORT) != false; + break; + + case MYWIN_ITEMID_FETCHSIZE: + { + m_nFetchSize = aCmdLine.ToInt32(); + String aText; + if (m_nFetchSize > 0) + { + aText.AssignAscii("Fetch size set to "); + aText += String::CreateFromInt32(m_nFetchSize); + } + else + aText.AssignAscii("Fetch size reset to default"); + print(aText); + break; + } + + case MYWIN_ITEMID_SYS2URI: + { + uno::Reference< ucb::XContentProviderManager > + xManager(m_aUCB.getContentProvider(), uno::UNO_QUERY); + DBG_ASSERT(xManager.is(), + "MyWin::ToolBarHandler(): Service lacks interface"); + + rtl::OUString aURL(getLocalFileURL(xManager)); + + String aText(RTL_CONSTASCII_USTRINGPARAM("Local file URL: ")); + aText += String(aURL); + aText.AppendAscii("\nConversion: "); + aText += aCmdLine; + aText.AppendAscii(" to "); + aText += String(getFileURLFromSystemPath(xManager, + aURL, + aCmdLine)); + print(aText); + break; + } + + case MYWIN_ITEMID_URI2SYS: + { + uno::Reference< ucb::XContentProviderManager > + xManager(m_aUCB.getContentProvider(), uno::UNO_QUERY); + DBG_ASSERT(xManager.is(), + "MyWin::ToolBarHandler(): Service lacks interface"); + + String aText(RTL_CONSTASCII_USTRINGPARAM("Conversion: ")); + aText += aCmdLine; + aText.AppendAscii(" to "); + aText += String(getSystemPathFromFileURL(xManager, + aCmdLine)); + print(aText); + break; + } + + case MYWIN_ITEMID_OFFLINE: + case MYWIN_ITEMID_ONLINE: + { + uno::Reference< ucb::XContentProviderManager > + xManager(m_aUCB.getContentProvider(), uno::UNO_QUERY); + uno::Reference< ucb::XCommandProcessor > xProcessor; + if (xManager.is()) + xProcessor + = uno::Reference< ucb::XCommandProcessor >( + xManager->queryContentProvider(aCmdLine), + uno::UNO_QUERY); + if (!xProcessor.is()) + { + String aText(RTL_CONSTASCII_USTRINGPARAM( + "No offline support for URL ")); + aText += aCmdLine; + print(aText); + break; + } + + rtl::OUString aName; + uno::Any aArgument; + if (nItemId == MYWIN_ITEMID_OFFLINE) + { + aName = rtl::OUString::createFromAscii("goOffline"); + + uno::Sequence< + uno::Reference< ucb::XContentIdentifier > > + aIdentifiers(1); + aIdentifiers[0] + = m_aUCB.getContentIdentifierFactory()-> + createContentIdentifier(aCmdLine); + aArgument <<= aIdentifiers; + } + else + aName = rtl::OUString::createFromAscii("goOnline"); + + UcbCommandProcessor(m_aUCB, xProcessor, m_pOutEdit). + executeCommand(aName, aArgument); + break; + } + + default: // Ignored. + break; + } + + Application::AcquireSolarMutex( n ); + return 0; +} + +/*======================================================================== + * + * MyApp. + * + *=======================================================================*/ +class MyApp : public Application +{ +public: + virtual void Main(); +}; + +MyApp aMyApp; + +//------------------------------------------------------------------------- +// virtual +void MyApp::Main() +{ + ////////////////////////////////////////////////////////////////////// + // Read command line params. + ////////////////////////////////////////////////////////////////////// + + rtl::OUString aConfigurationKey1(rtl::OUString::createFromAscii( + UCB_CONFIGURATION_KEY1_LOCAL)); + rtl::OUString aConfigurationKey2(rtl::OUString::createFromAscii( + UCB_CONFIGURATION_KEY2_OFFICE)); + + USHORT nParams = Application::GetCommandLineParamCount(); + for ( USHORT n = 0; n < nParams; ++n ) + { + String aParam( Application::GetCommandLineParam( n ) ); + if (aParam.CompareIgnoreCaseToAscii("-key=", + RTL_CONSTASCII_LENGTH("-key=")) + == COMPARE_EQUAL) + { + xub_StrLen nSlash + = aParam.Search('/', RTL_CONSTASCII_LENGTH("-key=")); + if (nSlash == STRING_NOTFOUND) + { + aConfigurationKey1 + = aParam.Copy(RTL_CONSTASCII_LENGTH("-key=")); + aConfigurationKey2 = rtl::OUString(); + } + else + { + aConfigurationKey1 + = aParam.Copy(RTL_CONSTASCII_LENGTH("-key="), + nSlash - RTL_CONSTASCII_LENGTH("-key=")); + aConfigurationKey2 + = aParam.Copy(nSlash + 1); + } + } + } + + ////////////////////////////////////////////////////////////////////// + // Initialize local Service Manager and basic services. + ////////////////////////////////////////////////////////////////////// + + uno::Reference< lang::XMultiServiceFactory > xFac; + try + { + uno::Reference< uno::XComponentContext > xCtx( + cppu::defaultBootstrap_InitialComponentContext() ); + if ( !xCtx.is() ) + { + DBG_ERROR( "Error creating initial component context!" ); + return; + } + + xFac = uno::Reference< lang::XMultiServiceFactory >( + xCtx->getServiceManager(), uno::UNO_QUERY ); + + if ( !xFac.is() ) + { + DBG_ERROR( "No service manager!" ); + return; + } + } + catch ( uno::Exception ) + { + DBG_ERROR( "Exception during creation of initial component context!" ); + return; + } + + comphelper::setProcessServiceFactory( xFac ); + + uno::Reference< lang::XComponent > xComponent( xFac, uno::UNO_QUERY ); + + ////////////////////////////////////////////////////////////////////// + // Create Application Window... + ////////////////////////////////////////////////////////////////////// + + Help::EnableBalloonHelp(); + + MyWin *pMyWin = new MyWin( NULL, WB_APP | WB_STDWORK, xFac, + aConfigurationKey1, aConfigurationKey2 ); + + pMyWin-> + SetText( + UniString::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( "UCB Demo/Test Application" ) ) ); + + pMyWin->SetPosSizePixel( 0, 0, 1024, 768 ); + + pMyWin->Show(); + + ////////////////////////////////////////////////////////////////////// + // Go... + ////////////////////////////////////////////////////////////////////// + + Execute(); + + ////////////////////////////////////////////////////////////////////// + // Destroy Application Window... + ////////////////////////////////////////////////////////////////////// + + delete pMyWin; + + ////////////////////////////////////////////////////////////////////// + // Cleanup. + ////////////////////////////////////////////////////////////////////// + + ::ucbhelper::ContentBroker::deinitialize(); + + // Dispose local service manager. + if ( xComponent.is() ) + xComponent->dispose(); +} + |