diff options
Diffstat (limited to 'unotools')
103 files changed, 25344 insertions, 0 deletions
diff --git a/unotools/inc/makefile.mk b/unotools/inc/makefile.mk new file mode 100644 index 000000000000..d6c17aaecb89 --- /dev/null +++ b/unotools/inc/makefile.mk @@ -0,0 +1,52 @@ +#************************************************************************* +# +# 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.3 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General 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=unotools +TARGET=inc + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/util$/makefile.pmk + +# --- Files -------------------------------------------------------- +# --- Targets ------------------------------------------------------- + +.INCLUDE : target.mk + +.IF "$(ENABLE_PCH)"!="" +ALLTAR : \ + $(SLO)$/precompiled.pch \ + $(SLO)$/precompiled_ex.pch + +.ENDIF # "$(ENABLE_PCH)"!="" + diff --git a/unotools/inc/pch/precompiled_unotools.cxx b/unotools/inc/pch/precompiled_unotools.cxx new file mode 100644 index 000000000000..a848d922583c --- /dev/null +++ b/unotools/inc/pch/precompiled_unotools.cxx @@ -0,0 +1,32 @@ +/************************************************************************* + * + * 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: precompiled_unotools.cxx,v $ + * $Revision: 1.3 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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_unotools.hxx" + diff --git a/unotools/inc/pch/precompiled_unotools.hxx b/unotools/inc/pch/precompiled_unotools.hxx new file mode 100644 index 000000000000..30979736a134 --- /dev/null +++ b/unotools/inc/pch/precompiled_unotools.hxx @@ -0,0 +1,35 @@ +/************************************************************************* + * + * 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: precompiled_unotools.hxx,v $ + * $Revision: 1.3 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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.701453 + +#ifdef PRECOMPILED_HEADERS +#endif + diff --git a/unotools/inc/unotools/accessiblerelationsethelper.hxx b/unotools/inc/unotools/accessiblerelationsethelper.hxx new file mode 100644 index 000000000000..e48850e3efc8 --- /dev/null +++ b/unotools/inc/unotools/accessiblerelationsethelper.hxx @@ -0,0 +1,164 @@ +/************************************************************************* + * + * 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: accessiblerelationsethelper.hxx,v $ + * $Revision: 1.6 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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 _UTL_ACCESSIBLERELATIONSETHELPER_HXX_ +#define _UTL_ACCESSIBLERELATIONSETHELPER_HXX_ + +#include "unotools/unotoolsdllapi.h" + +#ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLESSTATESET_HPP_ +#include <com/sun/star/accessibility/XAccessibleRelationSet.hpp> +#endif +#include <com/sun/star/uno/Reference.hxx> +#include <cppuhelper/weak.hxx> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XTypeProvider.hpp> +#include <com/sun/star/lang/XServiceName.hpp> +#include <vos/mutex.hxx> +#include <cppuhelper/implbase1.hxx> +#include <comphelper/servicehelper.hxx> + +class AccessibleRelationSetHelperImpl; + +//========================================================================= +//= XAccessibleRelationSet helper classes +//========================================================================= + +//... namespace utl ....................................................... +namespace utl +{ +//......................................................................... + +/** @descr + This base class provides an implementation of the + <code>AccessibleRelationSet</code> service. +*/ +class UNOTOOLS_DLLPUBLIC AccessibleRelationSetHelper + : public cppu::WeakImplHelper1< + ::com::sun::star::accessibility::XAccessibleRelationSet + > +{ +public: + //===== internal ======================================================== + AccessibleRelationSetHelper (); + AccessibleRelationSetHelper (const AccessibleRelationSetHelper& rHelper); +protected: + virtual ~AccessibleRelationSetHelper (void); +public: + + //===== XAccessibleRelationSet ========================================== + + /** Returns the number of relations in this relation set. + + @return + Returns the number of relations or zero if there are none. + */ + virtual sal_Int32 SAL_CALL getRelationCount( ) + throw (::com::sun::star::uno::RuntimeException); + + /** Returns the relation of this relation set that is specified by + the given index. + + @param nIndex + This index specifies the relatio to return. + + @return + For a valid index, i.e. inside the range 0 to the number of + relations minus one, the returned value is the requested + relation. If the index is invalid then the returned relation + has the type INVALID. + + */ + virtual ::com::sun::star::accessibility::AccessibleRelation SAL_CALL + getRelation( sal_Int32 nIndex ) + throw (::com::sun::star::lang::IndexOutOfBoundsException, + ::com::sun::star::uno::RuntimeException); + + /** Tests whether the relation set contains a relation matching the + specified key. + + @param aRelationType + The type of relation to look for in this set of relations. This + has to be one of the constants of + <type>AccessibleRelationType</type>. + + @return + Returns <TRUE/> if there is a (at least one) relation of the + given type and <FALSE/> if there is no such relation in the set. + */ + virtual sal_Bool SAL_CALL containsRelation( sal_Int16 aRelationType ) + throw (::com::sun::star::uno::RuntimeException); + + /** Retrieve and return the relation with the given relation type. + + @param aRelationType + The type of the relation to return. This has to be one of the + constants of <type>AccessibleRelationType</type>. + + @return + If a relation with the given type could be found than (a copy + of) this relation is returned. Otherwise a relation with the + type INVALID is returned. + */ + virtual ::com::sun::star::accessibility::AccessibleRelation SAL_CALL + getRelationByType( sal_Int16 aRelationType ) + throw (::com::sun::star::uno::RuntimeException); + + void AddRelation( + const ::com::sun::star::accessibility::AccessibleRelation& rRelation) + throw (::com::sun::star::uno::RuntimeException); + + //===== XTypeProvider =================================================== + + /** Returns a sequence of all supported interfaces. + */ + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> SAL_CALL + getTypes (void) + throw (::com::sun::star::uno::RuntimeException); + + /** Returns a implementation id. + */ + virtual ::com::sun::star::uno::Sequence<sal_Int8> SAL_CALL + getImplementationId (void) + throw (::com::sun::star::uno::RuntimeException); + +protected: + /// Mutex guarding this object. + ::vos::OMutex maMutex; + +private: + /// The implementation of this helper interface. + AccessibleRelationSetHelperImpl* mpHelperImpl; +}; + +//......................................................................... +} +//... namespace utl ....................................................... +#endif diff --git a/unotools/inc/unotools/accessiblestatesethelper.hxx b/unotools/inc/unotools/accessiblestatesethelper.hxx new file mode 100644 index 000000000000..421a77b78f2b --- /dev/null +++ b/unotools/inc/unotools/accessiblestatesethelper.hxx @@ -0,0 +1,186 @@ +/************************************************************************* + * + * 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: accessiblestatesethelper.hxx,v $ + * $Revision: 1.13 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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 _UTL_ACCESSIBLESTATESETHELPER_HXX_ +#define _UTL_ACCESSIBLESTATESETHELPER_HXX_ + +#include "unotools/unotoolsdllapi.h" + +#ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLESSTATESET_HPP_ +#include <com/sun/star/accessibility/XAccessibleStateSet.hpp> +#endif +#include <com/sun/star/uno/Reference.hxx> +#include <cppuhelper/weak.hxx> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XTypeProvider.hpp> +#include <com/sun/star/lang/XServiceName.hpp> +#include <vos/mutex.hxx> +#include <cppuhelper/implbase1.hxx> +#include <comphelper/servicehelper.hxx> + +class AccessibleStateSetHelperImpl; + +//========================================================================= +//= XAccessibleStateSet helper classes +//========================================================================= + +//... namespace utl ....................................................... +namespace utl +{ +//......................................................................... + +/** @descr + This base class provides an implementation of the + <code>AccessibleStateSet</code> service. +*/ +class UNOTOOLS_DLLPUBLIC AccessibleStateSetHelper + : public cppu::WeakImplHelper1< + ::com::sun::star::accessibility::XAccessibleStateSet + > +{ +public: + //===== internal ======================================================== + + AccessibleStateSetHelper (); + /** constructs an object with some states initially set + + <p>This ctor is compatible with + <method scope="comphelper">OAccessibleImplementationAccess::implGetForeignControlledStates</method></p> + + @param _nInitialStates + is a bit mask. Every bit 2^n means that the state number n (as got from the + AccessibleStateType constants) should be set initially. + */ + AccessibleStateSetHelper ( const sal_Int64 _nInitialStates ); + + AccessibleStateSetHelper ( const AccessibleStateSetHelper& rHelper ); +protected: + virtual ~AccessibleStateSetHelper (void); +public: + + //===== XAccessibleStateSet ============================================== + + /** Checks whether the current state set is empty. + + @return + Returns <TRUE/> if there is no state in this state set and + <FALSE/> if there is at least one state set in it. + */ + virtual sal_Bool SAL_CALL isEmpty () + throw (::com::sun::star::uno::RuntimeException); + + /** Checks if the given state is a member of the state set of this + object. + + @param aState + The state for which to check membership. This has to be one of + the constants of <type>AccessibleStateType</type>. + + @return + Returns <TRUE/> if the given state is a memeber of this object's + state set and <FALSE/> otherwise. + */ + virtual sal_Bool SAL_CALL contains (sal_Int16 aState) + throw (::com::sun::star::uno::RuntimeException); + + /** Checks if all of the given states are in this object's state + set. + + @param aStateSet + This sequence of states is interpreted as set and every of its + members, duplicates are ignored, is checked for membership in + this object's state set. Each state has to be one of the + constants of <type>AccessibleStateType</type>. + + @return + Returns <TRUE/> if all states of the given state set are members + of this object's state set. <FALSE/> is returned if at least + one of the states in the given state is not a member of this + object's state set. + */ + virtual sal_Bool SAL_CALL containsAll ( + const ::com::sun::star::uno::Sequence<sal_Int16>& rStateSet) + throw (::com::sun::star::uno::RuntimeException); + + /** Returns a sequence of all states. + */ + virtual com::sun::star::uno::Sequence<sal_Int16> SAL_CALL getStates() + throw (::com::sun::star::uno::RuntimeException); + + /** Adds a state to the set. + */ + void AddState(sal_Int16 aState) + throw (::com::sun::star::uno::RuntimeException); + + /** Removes a state from the set if the set contains the state, otherwise nothing is done. + */ + void RemoveState(sal_Int16 aState) + throw (::com::sun::star::uno::RuntimeException); + + /** Compares the set with the set given by rComparativeValue and puts the results + into rOldStates and rNewStates. + + rOldStates contains after call all states which are in the own set and + not in the comparative set. + + rNewStates contains after call all states which are in the comparative + set and not in the own set. + */ + sal_Bool Compare(const AccessibleStateSetHelper& rComparativeValue, + AccessibleStateSetHelper& rOldStates, + AccessibleStateSetHelper& rNewStates) + throw (::com::sun::star::uno::RuntimeException); + + //===== XTypeProvider =================================================== + + /** Returns a sequence of all supported interfaces. + */ + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> SAL_CALL + getTypes (void) + throw (::com::sun::star::uno::RuntimeException); + + /** Returns a implementation id. + */ + virtual ::com::sun::star::uno::Sequence<sal_Int8> SAL_CALL + getImplementationId (void) + throw (::com::sun::star::uno::RuntimeException); + +protected: + /// Mutex guarding this object. + ::vos::OMutex maMutex; + +private: + /// The implementation of this helper interface. + AccessibleStateSetHelperImpl* mpHelperImpl; +}; + +//......................................................................... +} +//... namespace utl ....................................................... +#endif diff --git a/unotools/inc/unotools/atom.hxx b/unotools/inc/unotools/atom.hxx new file mode 100644 index 000000000000..e8409f6ce5e6 --- /dev/null +++ b/unotools/inc/unotools/atom.hxx @@ -0,0 +1,135 @@ +/************************************************************************* + * + * 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: atom.hxx,v $ + * $Revision: 1.9 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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 _UTL_ATOM_HXX_ +#define _UTL_ATOM_HXX_ + +#include "unotools/unotoolsdllapi.h" +#include <rtl/ustring.hxx> +#include <osl/mutex.hxx> +#include <cppuhelper/implbase1.hxx> + +#include <hash_map> +#ifndef __SGI_STL_LIST +#include <list> +#endif +#include <com/sun/star/util/XAtomServer.hpp> + +#define INVALID_ATOM 0 + +namespace utl { + + struct AtomDescription + { + int atom; + ::rtl::OUString description; + }; + + class AtomProvider + { + int m_nAtoms; + ::std::hash_map< int, ::rtl::OUString, ::std::hash< int > > m_aStringMap; + ::std::hash_map< ::rtl::OUString, int, ::rtl::OUStringHash > m_aAtomMap; + public: + AtomProvider(); + ~AtomProvider(); + + int getAtom( const ::rtl::OUString&, sal_Bool bCreate = sal_False ); + int getLastAtom() const { return m_nAtoms-1; } + const ::rtl::OUString& getString( int ) const; + + void getAll( ::std::list< AtomDescription >& atoms ); + + void getRecent( int atom, ::std::list< AtomDescription >& atoms ); + + void overrideAtom( int atom, const ::rtl::OUString& description ); + + sal_Bool hasAtom( int atom ) const; + }; + + + class UNOTOOLS_DLLPUBLIC MultiAtomProvider + { + ::std::hash_map< int, AtomProvider*, ::std::hash< int > > m_aAtomLists; + public: + MultiAtomProvider(); + ~MultiAtomProvider(); + + int getLastAtom( int atomClass ) const; + + sal_Bool insertAtomClass( int atomClass ); + + int getAtom( int atomClass, const ::rtl::OUString& rString, sal_Bool bCreate = sal_False ); + + void getRecent( int atomClass, int atom, ::std::list< AtomDescription >& atoms ); + + const ::rtl::OUString& getString( int atomClass, int atom ) const; + void getClass( int atomClass, ::std::list< AtomDescription >& atoms ) const; + + void overrideAtom( int atomClass, int atom, const ::rtl::OUString& description ); + void overrideAtom( int atomClass, const ::com::sun::star::util::AtomDescription& newDescription ) + { overrideAtom( atomClass, newDescription.atom, newDescription.description ); } + sal_Bool hasAtom( int atomClass, int atom ) const; + }; + + class AtomServer : public ::cppu::WeakAggImplHelper1< ::com::sun::star::util::XAtomServer > + { + private: + MultiAtomProvider m_aProvider; + ::osl::Mutex m_aMutex; + public: + AtomServer(); + virtual ~AtomServer(); + + const ::rtl::OUString& getString( int atomClass, int atom ) const + { return m_aProvider.getString( atomClass, atom ); } + + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::util::AtomDescription > SAL_CALL getClass( sal_Int32 atomClass ) throw(); + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ::com::sun::star::util::AtomDescription > > SAL_CALL getClasses( const ::com::sun::star::uno::Sequence< sal_Int32 >& atomClasses ) throw(); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getAtomDescriptions( const ::com::sun::star::uno::Sequence< ::com::sun::star::util::AtomClassRequest >& atoms ) throw(); + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::util::AtomDescription > SAL_CALL getRecentAtoms( sal_Int32 atomClass, sal_Int32 atom ) throw(); + virtual sal_Int32 SAL_CALL getAtom( sal_Int32 atomClass, const ::rtl::OUString& description, sal_Bool create ) throw(); + }; + + class AtomClient + { + private: + ::com::sun::star::uno::Reference< ::com::sun::star::util::XAtomServer > m_xServer; + MultiAtomProvider m_aProvider; + public: + AtomClient( const ::com::sun::star::uno::Reference< ::com::sun::star::util::XAtomServer >& ); + ~AtomClient(); + + void updateAtomClasses( const ::com::sun::star::uno::Sequence< sal_Int32 >& atomClasses ); + int getAtom( int atomClass, const ::rtl::OUString& description, sal_Bool bCreate ); + const ::rtl::OUString& getString( int atomClass, int atom ); + }; +} + +#endif diff --git a/unotools/inc/unotools/bootstrap.hxx b/unotools/inc/unotools/bootstrap.hxx new file mode 100644 index 000000000000..d2c8a5f1875b --- /dev/null +++ b/unotools/inc/unotools/bootstrap.hxx @@ -0,0 +1,141 @@ +/************************************************************************* + * + * 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: bootstrap.hxx,v $ + * $Revision: 1.15.16.1 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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 "unotools/unotoolsdllapi.h" + +#ifndef _UTL_BOOTSTRAP_HXX +#define _UTL_BOOTSTRAP_HXX + +namespace rtl +{ + class OUString; +} + +namespace utl +{ +//----------------------------------------------------------------------------- + /** provides configuration information needed for application startup. + <p>This class handles the startup information for the office application. + It encapsulates knowledge of how to retriev such information and how + to diagnose failures to retriev required data. + </p> + */ + class UNOTOOLS_DLLPUBLIC Bootstrap + { + // the static interface + public: // some common information items + + /// retrieve the product key; defaults to executable name (without extension) + static rtl::OUString getProductKey(); + + /// retrieve the product key; uses the given default, if not found + static rtl::OUString getProductKey(rtl::OUString const& _sDefault); + + /// retrieve the product source (MWS name) + static ::rtl::OUString getProductSource(rtl::OUString const& _sDefault); + + /// retrieve the BUILDID information item; uses the given default, if not found + static rtl::OUString getBuildIdData(rtl::OUString const& _sDefault); + + /// retrieve the ALLUSERS information item from setup.ini file; uses the given default, if not found + static rtl::OUString getAllUsersValue(rtl::OUString const& _sDefault); + + /// reload cached data + static void reloadData(); + + public: // retrieve path information about the installatíon location + enum PathStatus + { + PATH_EXISTS, // Success: Found a path to an existing file or directory + PATH_VALID, // Found a valid path, but the file or directory does not exist + DATA_INVALID, // Retrieved a string for this path, that is not a valid file url or system path + DATA_MISSING, // Could not retrieve any data for this path + DATA_UNKNOWN // No attempt to retrieve data for this path was made + }; + + /// get a file URL to the common base installation [${insturl}] + static PathStatus locateBaseInstallation(rtl::OUString& _rURL); + + /// get a file URL to the user installation [${userurl}] + static PathStatus locateUserInstallation(rtl::OUString& _rURL); + + /// get a file URL to the shared data directory [default is ${insturl}/share] + static PathStatus locateSharedData(rtl::OUString& _rURL); + + /// get a file URL to the user data directory [default is ${userurl}/user] + static PathStatus locateUserData(rtl::OUString& _rURL); + + // the next two items are mainly supported for diagnostic purposes. both items may be unused + /// get a file URL to the bootstrap INI file used [e.g. ${insturl}/program/bootraprc] + static PathStatus locateBootstrapFile(rtl::OUString& _rURL); + /// get a file URL to the version locator INI file used [e.g. ${SYSUSERCONFIG}/sversion.ini] + static PathStatus locateVersionFile(rtl::OUString& _rURL); + + public: // evaluate the validity of the installation + /// high-level status of bootstrap success + enum Status + { + DATA_OK, /// user-dir and share-dir do exist, product key found or can be defaulted to exe-name + MISSING_USER_INSTALL, /// ${userurl} does not exist; or version-file cannot be found or is invalid + INVALID_USER_INSTALL, /// can locate ${userurl}, but user-dir is missing + INVALID_BASE_INSTALL /// other failure: e.g. cannot locate share-dir; bootstraprc missing or invalid; no product key + }; + + /// error code for detailed diagnostics of bootstrap failures + enum FailureCode + { + NO_FAILURE, /// bootstrap was successful + MISSING_INSTALL_DIRECTORY, /// the shared installation directory could not be located + MISSING_BOOTSTRAP_FILE, /// the bootstrap INI file could not be found or read + MISSING_BOOTSTRAP_FILE_ENTRY, /// the bootstrap INI is missing a required entry + INVALID_BOOTSTRAP_FILE_ENTRY, /// the bootstrap INI contains invalid data + MISSING_VERSION_FILE, /// the version locator INI file could not be found or read + MISSING_VERSION_FILE_ENTRY, /// the version locator INI has no entry for this version + INVALID_VERSION_FILE_ENTRY, /// the version locator INI entry is not a valid directory URL + MISSING_USER_DIRECTORY, /// the user installation directory does not exist + INVALID_BOOTSTRAP_DATA /// some bootstrap data was invalid in unexpected ways + }; + + /// Evaluates the status of the installation and returns a diagnostic message corresponding to this status + static Status checkBootstrapStatus(rtl::OUString& _rDiagnosticMessage); + + /** Evaluates the status of the installation and returns a diagnostic + message and error code corresponding to this status + */ + static Status checkBootstrapStatus(rtl::OUString& _rDiagnosticMessage, FailureCode& _rErrCode); + + public: + // singleton impl-class + class Impl; + static Impl const& data(); // the data related to the bootstrap.ini file + }; +//----------------------------------------------------------------------------- +} // namespace utl + +#endif // _UTL_BOOTSTRAP_HXX diff --git a/unotools/inc/unotools/calendarwrapper.hxx b/unotools/inc/unotools/calendarwrapper.hxx new file mode 100644 index 000000000000..c98e0867e8fa --- /dev/null +++ b/unotools/inc/unotools/calendarwrapper.hxx @@ -0,0 +1,136 @@ +/************************************************************************* + * + * 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: calendarwrapper.hxx,v $ + * $Revision: 1.10.24.1 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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 _UNOTOOLS_CALENDARWRAPPER_HXX +#define _UNOTOOLS_CALENDARWRAPPER_HXX + +#include <tools/datetime.hxx> +#include <tools/string.hxx> +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/i18n/Calendar.hpp> +#include <com/sun/star/lang/Locale.hpp> +#include "unotools/unotoolsdllapi.h" + +namespace com { namespace sun { namespace star { + namespace lang { + class XMultiServiceFactory; + } +}}} + +namespace com { namespace sun { namespace star { + namespace i18n { + class XExtendedCalendar; + } +}}} + + +class UNOTOOLS_DLLPUBLIC CalendarWrapper +{ + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xSMgr; + ::com::sun::star::uno::Reference< ::com::sun::star::i18n::XExtendedCalendar > xC; + + DateTime aEpochStart; // 1Jan1970 + +public: + CalendarWrapper( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > & xSF + ); + ~CalendarWrapper(); + + + // wrapper implementations of XCalendar + + void loadDefaultCalendar( const ::com::sun::star::lang::Locale& rLocale ); + void loadCalendar( const ::rtl::OUString& rUniqueID, const ::com::sun::star::lang::Locale& rLocale ); + ::com::sun::star::i18n::Calendar getLoadedCalendar() const; + ::com::sun::star::uno::Sequence< ::rtl::OUString > getAllCalendars( const ::com::sun::star::lang::Locale& rLocale ) const; + ::rtl::OUString getUniqueID() const; + /// set UTC date/time + void setDateTime( double nTimeInDays ); + /// get UTC date/time + double getDateTime() const; + /// convenience method to set local date/time + void setLocalDateTime( double nTimeInDays ); + /// convenience method to get local date/time + double getLocalDateTime() const; + + // wrapper implementations of XCalendar + + void setValue( sal_Int16 nFieldIndex, sal_Int16 nValue ); + sal_Bool isValid() const; + sal_Int16 getValue( sal_Int16 nFieldIndex ) const; + void addValue( sal_Int16 nFieldIndex, sal_Int32 nAmount ); + sal_Int16 getFirstDayOfWeek() const; + void setFirstDayOfWeek( sal_Int16 nDay ); + void setMinimumNumberOfDaysForFirstWeek( sal_Int16 nDays ); + sal_Int16 getMinimumNumberOfDaysForFirstWeek() const; + sal_Int16 getNumberOfMonthsInYear() const; + sal_Int16 getNumberOfDaysInWeek() const; + ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::CalendarItem > getMonths() const; + ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::CalendarItem > getDays() const; + String getDisplayName( sal_Int16 nCalendarDisplayIndex, sal_Int16 nIdx, sal_Int16 nNameType ) const; + + /** Convenience method to get timezone offset in milliseconds, taking both + fields ZONE_OFFSET and ZONE_OFFSET_SECOND_MILLIS into account. */ + sal_Int32 getZoneOffsetInMillis() const; + /** Convenience method to get DST offset in milliseconds, taking both + fields DST_OFFSET and DST_OFFSET_SECOND_MILLIS into account. */ + sal_Int32 getDSTOffsetInMillis() const; + + // wrapper implementations of XExtendedCalendar + + String getDisplayString( sal_Int32 nCalendarDisplayCode, sal_Int16 nNativeNumberMode ) const; + + + // convenience methods + + /// get epoch start (should be 01Jan1970) + inline const DateTime& getEpochStart() const + { return aEpochStart; } + + /// set a local (!) Gregorian DateTime + inline void setGregorianDateTime( const DateTime& rDateTime ) + { setLocalDateTime( rDateTime - aEpochStart ); } + + /// get the DateTime as a local (!) Gregorian DateTime + inline DateTime getGregorianDateTime() const + { return aEpochStart + getLocalDateTime(); } + +private: + + /** get timezone or DST offset in milliseconds, fields are + CalendarFieldIndex ZONE_OFFSET and ZONE_OFFSET_SECOND_MILLIS + respectively DST_OFFSET and DST_OFFSET_SECOND_MILLIS. + */ + sal_Int32 getCombinedOffsetInMillis( sal_Int16 nParentFieldIndex, sal_Int16 nChildFieldIndex ) const; +}; + +#endif diff --git a/unotools/inc/unotools/charclass.hxx b/unotools/inc/unotools/charclass.hxx new file mode 100644 index 000000000000..3caf0ea3cc6d --- /dev/null +++ b/unotools/inc/unotools/charclass.hxx @@ -0,0 +1,239 @@ +/************************************************************************* + * + * 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: charclass.hxx,v $ + * $Revision: 1.13 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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 "unotools/unotoolsdllapi.h" + +#ifndef _UNOTOOLS_CHARCLASS_HXX +#define _UNOTOOLS_CHARCLASS_HXX + +#include <ctype.h> // isdigit(), isalpha() +#include <tools/string.hxx> +#include <tools/solar.h> +#include <com/sun/star/i18n/KCharacterType.hpp> +#include <com/sun/star/i18n/KParseTokens.hpp> +#include <com/sun/star/i18n/KParseType.hpp> +#include <com/sun/star/i18n/ParseResult.hpp> +#include <com/sun/star/i18n/XCharacterClassification.hpp> +#include <osl/mutex.hxx> + +class String; +namespace com { namespace sun { namespace star { + namespace lang { + class XMultiServiceFactory; + } +}}} + +const sal_Int32 nCharClassAlphaType = + ::com::sun::star::i18n::KCharacterType::UPPER | + ::com::sun::star::i18n::KCharacterType::LOWER | + ::com::sun::star::i18n::KCharacterType::TITLE_CASE; + +const sal_Int32 nCharClassAlphaTypeMask = + nCharClassAlphaType | + ::com::sun::star::i18n::KCharacterType::PRINTABLE | + ::com::sun::star::i18n::KCharacterType::BASE_FORM; + +const sal_Int32 nCharClassLetterType = + nCharClassAlphaType | + ::com::sun::star::i18n::KCharacterType::LETTER; + +const sal_Int32 nCharClassLetterTypeMask = + nCharClassAlphaTypeMask | + ::com::sun::star::i18n::KCharacterType::LETTER; + +const sal_Int32 nCharClassNumericType = + ::com::sun::star::i18n::KCharacterType::DIGIT; + +const sal_Int32 nCharClassNumericTypeMask = + nCharClassNumericType | + ::com::sun::star::i18n::KCharacterType::PRINTABLE | + ::com::sun::star::i18n::KCharacterType::BASE_FORM; + + +class UNOTOOLS_DLLPUBLIC CharClass +{ + ::com::sun::star::lang::Locale aLocale; + ::com::sun::star::uno::Reference< ::com::sun::star::i18n::XCharacterClassification > xCC; + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xSMgr; + mutable ::osl::Mutex aMutex; + + // not implemented, prevent usage + CharClass( const CharClass& ); + CharClass& operator=( const CharClass& ); + + // instantiate component somehow + void getComponentInstance(); + +public: + /// Preferred ctor with service manager specified + CharClass( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > & xSF, + const ::com::sun::star::lang::Locale& rLocale + ); + + /// Depricated ctor, tries to get a process service manager or to load the + /// library directly. + CharClass( + const ::com::sun::star::lang::Locale& rLocale + ); + + ~CharClass(); + + /// set a new Locale + void setLocale( const ::com::sun::star::lang::Locale& rLocale ); + + /// get current Locale + const ::com::sun::star::lang::Locale& getLocale() const; + + + /// isdigit() on ascii values + static inline sal_Bool isAsciiDigit( sal_Unicode c ) + { return c < 128 ? sal_Bool(isdigit( (unsigned char) c ) != 0) : sal_False; } + + /// isalpha() on ascii values + static inline sal_Bool isAsciiAlpha( sal_Unicode c ) + { return c < 128 ? sal_Bool(isalpha( (unsigned char) c ) != 0) : sal_False; } + + /// isalnum() on ascii values + static inline sal_Bool isAsciiAlphaNumeric( sal_Unicode c ) + { return c < 128 ? sal_Bool(isalnum( (unsigned char) c ) != 0) : sal_False; } + + /// isdigit() on ascii values of entire string + static sal_Bool isAsciiNumeric( const String& rStr ); + + /// isalpha() on ascii values of entire string + static sal_Bool isAsciiAlpha( const String& rStr ); + + /// isalnum() on ascii values of entire string + static sal_Bool isAsciiAlphaNumeric( const String& rStr ); + + /// whether type is pure alpha or not, e.g. return of getStringType + static inline sal_Bool isAlphaType( sal_Int32 nType ) + { + return ((nType & nCharClassAlphaType) != 0) && + ((nType & ~(nCharClassAlphaTypeMask)) == 0); + } + + /// whether type is pure numeric or not, e.g. return of getStringType + static inline sal_Bool isNumericType( sal_Int32 nType ) + { + return ((nType & nCharClassNumericType) != 0) && + ((nType & ~(nCharClassNumericTypeMask)) == 0); + } + + /// whether type is pure alphanumeric or not, e.g. return of getStringType + static inline sal_Bool isAlphaNumericType( sal_Int32 nType ) + { + return ((nType & (nCharClassAlphaType | + nCharClassNumericType)) != 0) && + ((nType & ~(nCharClassAlphaTypeMask | + nCharClassNumericTypeMask)) == 0); + } + + /// whether type is pure letter or not, e.g. return of getStringType + static inline sal_Bool isLetterType( sal_Int32 nType ) + { + return ((nType & nCharClassLetterType) != 0) && + ((nType & ~(nCharClassLetterTypeMask)) == 0); + } + + /// whether type is pure letternumeric or not, e.g. return of getStringType + static inline sal_Bool isLetterNumericType( sal_Int32 nType ) + { + return ((nType & (nCharClassLetterType | + nCharClassNumericType)) != 0) && + ((nType & ~(nCharClassLetterTypeMask | + nCharClassNumericTypeMask)) == 0); + } + + + // Wrapper implementations of class CharacterClassification + + String toUpper( const String& rStr, xub_StrLen nPos, xub_StrLen nCount ) const; + String toLower( const String& rStr, xub_StrLen nPos, xub_StrLen nCount ) const; + String toTitle( const String& rStr, xub_StrLen nPos, xub_StrLen nCount ) const; + + ::rtl::OUString toUpper_rtl( const ::rtl::OUString& rStr, sal_Int32 nPos, sal_Int32 nCount ) const; + ::rtl::OUString toLower_rtl( const ::rtl::OUString& rStr, sal_Int32 nPos, sal_Int32 nCount ) const; + // use the postfix because compilers could get confused by the both similar versions + // (me thinks they shouldn't, but in fact MSCV 6 does) + + sal_Int16 getType( const String& rStr, xub_StrLen nPos ) const; + sal_Int16 getCharacterDirection( const String& rStr, xub_StrLen nPos ) const; + sal_Int16 getScript( const String& rStr, xub_StrLen nPos ) const; + sal_Int32 getCharacterType( const String& rStr, xub_StrLen nPos ) const; + sal_Int32 getStringType( const String& rStr, xub_StrLen nPos, xub_StrLen nCount ) const; + + ::com::sun::star::i18n::ParseResult parseAnyToken( + const String& rStr, + sal_Int32 nPos, + sal_Int32 nStartCharFlags, + const String& userDefinedCharactersStart, + sal_Int32 nContCharFlags, + const String& userDefinedCharactersCont ) const; + + ::com::sun::star::i18n::ParseResult parsePredefinedToken( + sal_Int32 nTokenType, + const String& rStr, + sal_Int32 nPos, + sal_Int32 nStartCharFlags, + const String& userDefinedCharactersStart, + sal_Int32 nContCharFlags, + const String& userDefinedCharactersCont ) const; + + + // Functionality of class International methods + + sal_Bool isAlpha( const String& rStr, xub_StrLen nPos ) const; + sal_Bool isLetter( const String& rStr, xub_StrLen nPos ) const; + sal_Bool isDigit( const String& rStr, xub_StrLen nPos ) const; + sal_Bool isAlphaNumeric( const String& rStr, xub_StrLen nPos ) const; + sal_Bool isLetterNumeric( const String& rStr, xub_StrLen nPos ) const; + sal_Bool isAlpha( const String& rStr ) const; + sal_Bool isLetter( const String& rStr ) const; + sal_Bool isNumeric( const String& rStr ) const; + sal_Bool isAlphaNumeric( const String& rStr ) const; + sal_Bool isLetterNumeric( const String& rStr ) const; + + void toUpper( String& rStr ) const + { rStr = toUpper( rStr, 0, rStr.Len() ); } + void toLower( String& rStr ) const + { rStr = toLower( rStr, 0, rStr.Len() ); } + inline String upper( const String& rStr ) const + { return toUpper( rStr, 0, rStr.Len() ); } + inline String lower( const String& rStr ) const + { return toLower( rStr, 0, rStr.Len() ); } + + const ::rtl::OUString& toUpper_rtl( ::rtl::OUString& _rStr ) const { return _rStr = toUpper_rtl( _rStr, 0, _rStr.getLength() ); } + const ::rtl::OUString& toLower_rtl( ::rtl::OUString& _rStr ) const { return _rStr = toLower_rtl( _rStr, 0, _rStr.getLength() ); } +}; + + + +#endif // _UNOTOOLS_CHARCLASS_HXX diff --git a/unotools/inc/unotools/collatorwrapper.hxx b/unotools/inc/unotools/collatorwrapper.hxx new file mode 100644 index 000000000000..7440822a1d3a --- /dev/null +++ b/unotools/inc/unotools/collatorwrapper.hxx @@ -0,0 +1,100 @@ +/************************************************************************* + * + * 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: collatorwrapper.hxx,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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 "unotools/unotoolsdllapi.h" + +#ifndef _UNOTOOLS_COLLATORWRAPPER_HXX +#define _UNOTOOLS_COLLATORWRAPPER_HXX + +#ifndef _COM_SUN_STAR_UTIL_XCOLLATOR_HPP_ +#include <com/sun/star/i18n/XCollator.hpp> +#endif + +namespace com { namespace sun { namespace star { namespace lang { + class XMultiServiceFactory; +}}}} + +class UNOTOOLS_DLLPUBLIC CollatorWrapper +{ + private: + + ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XMultiServiceFactory + > mxServiceFactory; + + ::com::sun::star::uno::Reference< + ::com::sun::star::i18n::XCollator + > mxInternationalCollator; + + public: + + CollatorWrapper ( + const ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XMultiServiceFactory > &xServiceFactoryIn); + + ~CollatorWrapper(); + + sal_Int32 + compareSubstring ( + const ::rtl::OUString& s1, sal_Int32 off1, sal_Int32 len1, + const ::rtl::OUString& s2, sal_Int32 off2, sal_Int32 len2) const; + + sal_Int32 + compareString ( + const ::rtl::OUString& s1, const ::rtl::OUString& s2) const; + + ::com::sun::star::uno::Sequence< ::rtl::OUString > + listCollatorAlgorithms ( + const ::com::sun::star::lang::Locale& rLocale) const; + + ::com::sun::star::uno::Sequence< sal_Int32 > + listCollatorOptions ( + const ::rtl::OUString& rAlgorithm) const; + + sal_Int32 + loadDefaultCollator ( + const ::com::sun::star::lang::Locale& rLocale, sal_Int32 nOption); + + sal_Int32 + loadCollatorAlgorithm ( + const ::rtl::OUString& rAlgorithm, + const ::com::sun::star::lang::Locale& rLocale, sal_Int32 nOption); + + void + loadCollatorAlgorithmWithEndUserOption ( + const ::rtl::OUString& rAlgorithm, + const ::com::sun::star::lang::Locale& rLocale, + const ::com::sun::star::uno::Sequence< sal_Int32 >& rOption); + + protected: + + CollatorWrapper(); +}; + +#endif /* _UNOTOOLS_COLLATORWRAPPER_HXX */ diff --git a/unotools/inc/unotools/componentresmodule.hxx b/unotools/inc/unotools/componentresmodule.hxx new file mode 100644 index 000000000000..59e05f085b1c --- /dev/null +++ b/unotools/inc/unotools/componentresmodule.hxx @@ -0,0 +1,206 @@ +/************************************************************************* + * + * 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: componentresmodule.hxx,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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 UNOTOOLS_INC_UNOTOOLS_COMPONENTRESMODULE_HXX +#define UNOTOOLS_INC_UNOTOOLS_COMPONENTRESMODULE_HXX + +#include <comphelper/componentmodule.hxx> +#include <unotools/unotoolsdllapi.h> + +/** === begin UNO includes === **/ +/** === end UNO includes === **/ +#include <tools/resid.hxx> + +#include <memory> + +class ResMgr; + +//........................................................................ +namespace utl +{ +//........................................................................ + + class OComponentResModuleImpl; + + //==================================================================== + //= OComponentResourceModule + //==================================================================== + /** extends the <type scope="comphelper">OModule</type> implementation with + simply resource access + */ + class UNOTOOLS_DLLPUBLIC OComponentResourceModule : public ::comphelper::OModule + { + private: + typedef ::comphelper::OModule BaseClass; + + private: + ::std::auto_ptr< OComponentResModuleImpl > m_pImpl; + + public: + OComponentResourceModule( const ::rtl::OString& _rResFilePrefix ); + ~OComponentResourceModule(); + + /// get the vcl res manager of the module + ResMgr* getResManager(); + + protected: + // OModule overridables + virtual void onFirstClient(); + virtual void onLastClient(); + }; + + //========================================================================= + //= ModuleRes + //========================================================================= + /** specialized ResId, using the ressource manager provided by a given <type>OModule</type> + */ + class UNOTOOLS_DLLPUBLIC ModuleRes : public ::ResId + { + public: + ModuleRes( USHORT _nId, OComponentResourceModule& _rModule ) : ResId( _nId, *_rModule.getResManager() ) { } + }; + + //==================================================================== + //= defining a concrete module + //==================================================================== +#define DEFINE_MODULE( ModuleClass, ClientClass, ResClass ) \ + /* -------------------------------------------------------------------- */ \ + class ModuleClass : public ::utl::OComponentResourceModule \ + { \ + friend struct CreateModuleClass; \ + typedef ::utl::OComponentResourceModule BaseClass; \ + \ + public: \ + static ModuleClass& getInstance(); \ + \ + private: \ + ModuleClass(); \ + }; \ + \ + /* -------------------------------------------------------------------- */ \ + class ClientClass : public ::comphelper::OModuleClient \ + { \ + private: \ + typedef ::comphelper::OModuleClient BaseClass; \ + \ + public: \ + ClientClass() : BaseClass( ModuleClass::getInstance() ) \ + { \ + } \ + }; \ + \ + /* -------------------------------------------------------------------- */ \ + class ResClass : public ::utl::ModuleRes \ + { \ + private: \ + typedef ::utl::ModuleRes BaseClass; \ + \ + public: \ + ResClass( USHORT _nId ) : BaseClass( _nId, ModuleClass::getInstance() ) \ + { \ + } \ + }; \ + \ + /* -------------------------------------------------------------------- */ \ + template < class TYPE > \ + class OAutoRegistration : public ::comphelper::OAutoRegistration< TYPE > \ + { \ + private: \ + typedef ::comphelper::OAutoRegistration< TYPE > BaseClass; \ + \ + public: \ + OAutoRegistration() : BaseClass( ModuleClass::getInstance() ) \ + { \ + } \ + }; \ + \ + /* -------------------------------------------------------------------- */ \ + template < class TYPE > \ + class OSingletonRegistration : public ::comphelper::OSingletonRegistration< TYPE > \ + { \ + private: \ + typedef ::comphelper::OSingletonRegistration< TYPE > BaseClass; \ + \ + public: \ + OSingletonRegistration() : BaseClass( ModuleClass::getInstance() ) \ + { \ + } \ + }; \ + \ + /* -------------------------------------------------------------------- */ \ + template < class TYPE > \ + class OLegacySingletonRegistration : public ::comphelper::OLegacySingletonRegistration< TYPE > \ + { \ + private: \ + typedef ::comphelper::OLegacySingletonRegistration< TYPE > BaseClass; \ + \ + public: \ + OLegacySingletonRegistration() : BaseClass( ModuleClass::getInstance() ) \ + { \ + } \ + }; + + + //==================================================================== + //= implementing a concrete module + //==================================================================== +#define IMPLEMENT_MODULE( ModuleClass, resprefix ) \ + struct CreateModuleClass \ + { \ + ModuleClass* operator()() \ + { \ + static ModuleClass* pModule = new ModuleClass; \ + return pModule; \ + /* yes, in theory, this is a resource leak, since the ModuleClass \ + will never be cleaned up. However, using a non-heap instance of ModuleClass \ + would not work: It would be cleaned up when the module is unloaded. \ + This might happen (and is likely to happen) *after* the tools-library \ + has been unloaded. However, the module's dtor is where we would delete \ + our resource manager (in case not all our clients de-registered) - which \ + would call into the already-unloaded tools-library. */ \ + } \ + }; \ + \ + ModuleClass::ModuleClass() \ + :BaseClass( ::rtl::OString( resprefix ) ) \ + { \ + } \ + \ + ModuleClass& ModuleClass::getInstance() \ + { \ + return *rtl_Instance< ModuleClass, CreateModuleClass, ::osl::MutexGuard, ::osl::GetGlobalMutex >:: \ + create( CreateModuleClass(), ::osl::GetGlobalMutex() ); \ + } \ + +//........................................................................ +} // namespace utl +//........................................................................ + +#endif // UNOTOOLS_INC_UNOTOOLS_COMPONENTRESMODULE_HXX + diff --git a/unotools/inc/unotools/configitem.hxx b/unotools/inc/unotools/configitem.hxx new file mode 100644 index 000000000000..f3b9db2da452 --- /dev/null +++ b/unotools/inc/unotools/configitem.hxx @@ -0,0 +1,214 @@ +/************************************************************************* + * + * 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: configitem.hxx,v $ + * $Revision: 1.26 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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 _UTL_CONFIGITEM_HXX_ +#define _UTL_CONFIGITEM_HXX_ + +#include <sal/types.h> +#include <rtl/ustring.hxx> +#include <com/sun/star/uno/Sequence.h> +#include <com/sun/star/uno/Reference.h> +#include "unotools/unotoolsdllapi.h" + +//----------------------------------------------------------------------------- +namespace com{ namespace sun{ namespace star{ + namespace uno{ + class Any; + } + namespace beans{ + struct PropertyValue; + } + namespace container{ + class XHierarchicalNameAccess; + } + namespace util{ + class XChangesListener; + } +}}} +//----------------------------------------------------------------------------- +namespace utl +{ +#define CONFIG_MODE_IMMEDIATE_UPDATE 0x00 +#define CONFIG_MODE_DELAYED_UPDATE 0x01 +#define CONFIG_MODE_ALL_LOCALES 0x02 +#define CONFIG_MODE_RELEASE_TREE 0x04 +#define CONFIG_MODE_IGNORE_ERRORS 0x08 // prevent assertions, if creation fails +#define CONFIG_MODE_PROPAGATE_ERRORS 0x10 // throw exceptions, if creation fails + + enum ConfigNameFormat + { + CONFIG_NAME_PLAINTEXT_NAME, // unescaped local node name, for user display etc. + CONFIG_NAME_LOCAL_NAME, // local node name, for use in XNameAccess etc. ("Item", "Q & A") + CONFIG_NAME_LOCAL_PATH, // one-level relative path, for use when building pathes etc. ("Item", "Typ['Q & A']") + CONFIG_NAME_FULL_PATH, // full absolute path. ("/org.openoffice.Sample/Group/Item", "/org.openoffice.Sample/Set/Typ['Q & A']") + + CONFIG_NAME_DEFAULT = CONFIG_NAME_LOCAL_PATH // default format + }; + + class ConfigChangeListener_Impl; + class ConfigManager; + struct ConfigItem_Impl; + + class UNOTOOLS_DLLPUBLIC ConfigItem + { + friend class ConfigChangeListener_Impl; + friend class ConfigManager; + + const rtl::OUString sSubTree; + com::sun::star::uno::Reference< com::sun::star::container::XHierarchicalNameAccess> + m_xHierarchyAccess; + com::sun::star::uno::Reference< com::sun::star::util::XChangesListener > + xChangeLstnr; + ConfigItem_Impl* pImpl; + + ConfigItem();// + void RemoveChangesListener(); + void CallNotify( + const com::sun::star::uno::Sequence<rtl::OUString>& aPropertyNames); + + //*********************************************************************************************************************** + // In special mode ALL_LOCALES we must support reading/writing of localized cfg entries as Sequence< PropertyValue >. + // These methods are helper to convert given lists of names and Any-values. + // format: PropertyValue.Name = <locale as ISO string> + // PropertyValue.Value = <value; type depends from cfg entry!> + // e.g. + // LOCALIZED NODE + // "UIName" + // LOCALE VALUE + // "de" "Mein Name" + // "en-US" "my name" + void impl_packLocalizedProperties ( const com::sun::star::uno::Sequence< rtl::OUString >& lInNames , + const com::sun::star::uno::Sequence< com::sun::star::uno::Any >& lInValues , + com::sun::star::uno::Sequence< com::sun::star::uno::Any >& lOutValues ); + void impl_unpackLocalizedProperties ( const com::sun::star::uno::Sequence< rtl::OUString >& lInNames , + const com::sun::star::uno::Sequence< com::sun::star::uno::Any >& lInValues , + com::sun::star::uno::Sequence< rtl::OUString >& lOutNames , + com::sun::star::uno::Sequence< com::sun::star::uno::Any >& lOutValues ); + + com::sun::star::uno::Reference< com::sun::star::container::XHierarchicalNameAccess> + GetTree(); + + protected: + ConfigItem(const rtl::OUString rSubTree, + sal_Int16 nMode = CONFIG_MODE_DELAYED_UPDATE); + ConfigItem(utl::ConfigManager& rManager, const rtl::OUString rSubTree); + + void SetModified (); // mark item as modified + void ClearModified(); // reset state after commit! + + com::sun::star::uno::Sequence< com::sun::star::uno::Any> + GetProperties(const com::sun::star::uno::Sequence< rtl::OUString >& rNames); + + com::sun::star::uno::Sequence< sal_Bool > + GetReadOnlyStates(const com::sun::star::uno::Sequence< rtl::OUString >& rNames); + + sal_Bool PutProperties( + const com::sun::star::uno::Sequence< rtl::OUString >& rNames, + const com::sun::star::uno::Sequence< com::sun::star::uno::Any>& rValues); + + /** enables notifications about changes on selected sub nodes/values + + Before calling this method a second time for a possibly changed node/value set, + you must disable the current notifications by calling DisableNotification. + + @see Notify + @see DisableNotification + */ + sal_Bool EnableNotification(const com::sun::star::uno::Sequence< rtl::OUString >& rNames, + sal_Bool bEnableInternalNotification = sal_False); + /** disables notifications about changes on sub nodes/values, which previosly had + been enabled with EnableNotification + @see Notify + @see EnableNotification + */ + void DisableNotification(); + sal_Bool IsInternalNotification()const {return IsInValueChange();} + + //returns all members of a node in a specific format + com::sun::star::uno::Sequence< rtl::OUString > + GetNodeNames(const rtl::OUString& rNode); + //returns all members of a node in a specific format + com::sun::star::uno::Sequence< rtl::OUString > + GetNodeNames(const rtl::OUString& rNode, ConfigNameFormat eFormat); + // remove all members of a set + sal_Bool ClearNodeSet(const rtl::OUString& rNode); + // remove selected members of a set + sal_Bool ClearNodeElements(const rtl::OUString& rNode, + com::sun::star::uno::Sequence< rtl::OUString >& rElements); + // change or add members to a set + sal_Bool SetSetProperties(const rtl::OUString& rNode, com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue > rValues); + // remove, change or add members of a set + sal_Bool ReplaceSetProperties(const rtl::OUString& rNode, com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue > rValues); + // add a new node without setting any properties + sal_Bool AddNode(const rtl::OUString& rNode, const rtl::OUString& rNewNode); + + /** get a name for a new element of a set node + @param _rSetNode + relative path to the set node + @param _rBaseName + <ul><li><b>in</b>: the base to use when calculating a new name</li> + <li><b>out</b>: an unused element name</li> + </ul> + @return <TRUE/> if a free name could be generated + */ + sal_Bool getUniqueSetElementName( const rtl::OUString& _rSetNode, rtl::OUString& _rBaseName); + + public: + virtual ~ConfigItem(); + + /** is called from the ConfigManager before application ends of from the + PropertyChangeListener if the sub tree broadcasts changes. */ + virtual void Notify( const com::sun::star::uno::Sequence<rtl::OUString>& aPropertyNames); + + /** is called from the ConfigManager if it is destroyed before the ConfigItem. */ + void ReleaseConfigMgr(); + + /** enable locking of the XHierarchicalNameAccess if CONFIG_MODE_RELEASE_TREE is set to + prevent multiple calls ConfigManager::AcquireTree() from a single Commit() operation*/ + void LockTree(); + void UnlockTree(); + + const rtl::OUString& GetSubTreeName() const {return sSubTree;} + + sal_Bool IsModified() const; + + /** writes the changed values into the sub tree. Always called in the Dtor of the derived class. */ + virtual void Commit(); + + sal_Bool IsInValueChange() const; + + sal_Int16 GetMode() const; + + /** checks if the configuration manager used by this item is valid. + */ + sal_Bool IsValidConfigMgr() const; + }; +}//namespace utl +#endif //_UTL_CONFIGITEM_HXX_ diff --git a/unotools/inc/unotools/configmgr.hxx b/unotools/inc/unotools/configmgr.hxx new file mode 100644 index 000000000000..679e90b17249 --- /dev/null +++ b/unotools/inc/unotools/configmgr.hxx @@ -0,0 +1,118 @@ +/************************************************************************* + * + * 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: configmgr.hxx,v $ + * $Revision: 1.22.26.1 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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 _UTL_CONFIGMGR_HXX_ +#define _UTL_CONFIGMGR_HXX_ + +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/uno/Any.hxx> +#include <rtl/ustring.hxx> +#include "unotools/unotoolsdllapi.h" + +//----------------------------------------------------------------------------- +namespace com{ namespace sun{ namespace star{ + namespace lang{ + class XMultiServiceFactory; + } + namespace container{ + class XHierarchicalNameAccess; + } +}}} + +//----------------------------------------------------------------------------- +namespace utl +{ + struct ConfigMgr_Impl; + class ConfigItem; + class UNOTOOLS_DLLPUBLIC ConfigManager + { + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > + xConfigurationProvider; + ConfigMgr_Impl* pMgrImpl; + + static ConfigManager* pConfigManager; + static void getBasisAboutBoxProductVersion( rtl::OUString& rVersion ); + + public: + ConfigManager(); + ConfigManager(com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory > xConfigProvider); + ~ConfigManager(); + + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > + GetConfigurationProvider(); + + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > + GetLocalConfigurationProvider(); + + com::sun::star::uno::Reference< com::sun::star::container::XHierarchicalNameAccess> + AddConfigItem(utl::ConfigItem& rCfgItem); + + void RegisterConfigItem(utl::ConfigItem& rCfgItem); + com::sun::star::uno::Reference< com::sun::star::container::XHierarchicalNameAccess> + AcquireTree(utl::ConfigItem& rCfgItem); + + + void RemoveConfigItem(utl::ConfigItem& rCfgItem); + + void StoreConfigItems(); + + static ConfigManager* GetConfigManager(); + static void RemoveConfigManager(); + static rtl::OUString GetConfigBaseURL(); + + enum ConfigProperty + { + INSTALLPATH, // deprecated. don't use + LOCALE, + OFFICEINSTALL, // deprecated. don't use + USERINSTALLURL, // deprecated. don't use + OFFICEINSTALLURL, // deprecated. don't use + PRODUCTNAME, + PRODUCTVERSION, + PRODUCTEXTENSION, + DEFAULTCURRENCY, + PRODUCTXMLFILEFORMATNAME, + PRODUCTXMLFILEFORMATVERSION, + WRITERCOMPATIBILITYVERSIONOOO11, + OPENSOURCECONTEXT, + ABOUTBOXPRODUCTVERSION + }; + //direct readonly access to some special configuration elements + static com::sun::star::uno::Any GetDirectConfigProperty(ConfigProperty eProp); + + sal_Bool IsLocalConfigProvider(); + com::sun::star::uno::Reference< com::sun::star::container::XHierarchicalNameAccess> + GetHierarchyAccess(const rtl::OUString& rFullPath); + com::sun::star::uno::Any GetLocalProperty(const rtl::OUString& rProperty); + void PutLocalProperty(const rtl::OUString& , const com::sun::star::uno::Any& rValue); + + }; +}//namespace utl +#endif //_UTL_CONFIGMGR_HXX_ diff --git a/unotools/inc/unotools/confignode.hxx b/unotools/inc/unotools/confignode.hxx new file mode 100644 index 000000000000..580274004e1a --- /dev/null +++ b/unotools/inc/unotools/confignode.hxx @@ -0,0 +1,340 @@ +/************************************************************************* + * + * 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: confignode.hxx,v $ + * $Revision: 1.10 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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 _UNOTOOLS_CONFIGNODE_HXX_ +#define _UNOTOOLS_CONFIGNODE_HXX_ + +#include "unotools/unotoolsdllapi.h" +#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/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/util/XChangesBatch.hpp> +#include <unotools/eventlisteneradapter.hxx> + +//........................................................................ +namespace utl +{ +//........................................................................ + + //======================================================================== + //= OConfigurationNode + //======================================================================== + class OConfigurationTreeRoot; + /** a small wrapper around a configuration node.<p/> + Nodes in the terminology used herein are <em>inner</em> nodes of a configuration + tree, which means <em>no leafs</em>. + */ + class UNOTOOLS_DLLPUBLIC OConfigurationNode : public ::utl::OEventListenerAdapter + { + private: + ::com::sun::star::uno::Reference< ::com::sun::star::container::XHierarchicalNameAccess > + m_xHierarchyAccess; /// accessing children grandchildren (mandatory interface of our UNO object) + ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > + m_xDirectAccess; /// accessing children (mandatory interface of our UNO object) + ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameReplace > + m_xReplaceAccess; /// replacing child values + ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer > + m_xContainerAccess; /// modifying set nodes (optional interface of our UNO object) + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > + m_xProvider; /// the configuration provider which supplied the nodes of the hierarchy we're a part of + sal_Bool m_bEscapeNames; /// escape names before accessing children ? + + ::rtl::OUString + m_sCompletePath; + + OConfigurationNode insertNode(const ::rtl::OUString& _rName,const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _xNode) const throw(); + protected: + /// constructs a node object with an interface representing a node + OConfigurationNode( + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxNode, + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxProvider); + + public: + /// constructs an empty and invalid node object + OConfigurationNode() :m_bEscapeNames(sal_False) { } + /// copy ctor + OConfigurationNode(const OConfigurationNode& _rSource); + + /// assigment + const OConfigurationNode& operator=(const OConfigurationNode& _rSource); + + /// dtor + ~OConfigurationNode() {} + + /** open a sub node + @param _rPath access path of the to-be-opened sub node. May be a hierarchical path. + */ + OConfigurationNode openNode(const ::rtl::OUString& _rPath) const throw(); + + OConfigurationNode openNode( const sal_Char* _pAsciiPath ) const + { + return openNode( ::rtl::OUString::createFromAscii( _pAsciiPath ) ); + } + + /** create a new child node + + If the object represents a set node, this method may be used to create a new child. For non-set-nodes, the + method will fail.<br/> + Unless the respective operations on the pure configuration API, the to-be-created node immediately + becomes a part of it's hierarchy, no explicit insertion is necessary. + @param _rName name for the new child. Must be level-1-depth. + */ + OConfigurationNode createNode(const ::rtl::OUString& _rName) const throw(); + + OConfigurationNode createNode( const sal_Char* _pAsciiName ) const + { + return createNode( ::rtl::OUString::createFromAscii( _pAsciiName ) ); + } + + /** appends a node under a new name + + If the object represents a set node, this method may be used to create a new child. For non-set-nodes, the + method will fail.<br/> + Unless the respective operations on the pure configuration API, the to-be-created node immediately + becomes a part of it's hierarchy, no explicit insertion is necessary. + @param _rName name for the new child. Must be level-1-depth. + @param _aNewNode the node which should be appended + */ + OConfigurationNode appendNode(const ::rtl::OUString& _rName,const OConfigurationNode& _aNewNode) const throw(); + + OConfigurationNode appendNode( const sal_Char* _pAsciiName, const OConfigurationNode& _aNewNode ) const + { + return appendNode( ::rtl::OUString::createFromAscii( _pAsciiName ), _aNewNode ); + } + + /** remove an existent child nod + + If the object represents a set node, this method may be used to delete an existent child. For non-set-nodes, + the method will fail. + */ + sal_Bool removeNode(const ::rtl::OUString& _rName) const throw(); + + sal_Bool removeNode( const sal_Char* _pAsciiName ) const + { + return removeNode( ::rtl::OUString::createFromAscii( _pAsciiName ) ); + } + + /** retrieves the content of a descendant + + the returned value may contain anything from an interface (if <arg>_rPath</arg> refers to inner node of + the configuration tree) to any explicit value (e.g. string, integer) or even void.<br/> + Unfortunately, this implies that if a void value is returned, you won't have a clue if this means + "the path does not exist" (besides the assertion made :), or if the value is really void. + */ + ::com::sun::star::uno::Any + getNodeValue(const ::rtl::OUString& _rPath) const throw(); + + ::com::sun::star::uno::Any + getNodeValue( const sal_Char* _pAsciiPath ) const + { + return getNodeValue( ::rtl::OUString::createFromAscii( _pAsciiPath ) ); + } + + /** write a node value<p/> + The value given is written into the node specified by the given relative path.<br/> + In opposite to <method>getNodeValue</method>, _rName must refer to a leaf in the configuration tree, not an inner + node. + @return sal_True if and only if the write was successfull. + */ + sal_Bool setNodeValue(const ::rtl::OUString& _rPath, const ::com::sun::star::uno::Any& _rValue) const throw(); + + sal_Bool setNodeValue( const sal_Char* _pAsciiPath, const ::com::sun::star::uno::Any& _rValue ) const + { + return setNodeValue( ::rtl::OUString::createFromAscii( _pAsciiPath ), _rValue ); + } + + /// return the names of the existing children + ::com::sun::star::uno::Sequence< ::rtl::OUString > + getNodeNames() const throw(); + + /** enables or disables name escaping when accessing direct children<p/> + Escaping is disabled by default, usually you enable it for set nodes (e.g. with calling setEscape(isSetNode)). + Once escaping is enabled, you should not access indirect children (e.g. openNode("child/grandchild"), 'cause + escaping for such names may not be supported by the underlying API objects. + @see getEscape + */ + void setEscape(sal_Bool _bEnable = sal_True); + /** get the flag specifying the current escape behaviour + @see setEscape + */ + sal_Bool getEscape() const { return m_bEscapeNames; } + + /** clone the object, creating a new hierarchy where the root represents the same node as the object + where this method is called does.<p/> + The new hierarchy does not share any updates with the one the object is a part of, i.e. any changes made + in the existing hierarchy are not visible to the newly created one until committed (and vice versa). + @param _rRoot out parameter. upon return, contains the object representing the root of the new hierarchy. + */ + OConfigurationTreeRoot cloneAsRoot() const throw(); + + /// invalidate the object + virtual void clear() throw(); + + // ----------------------- + // meta informations about the node + + /// checks whether or not the object represents a set node. + sal_Bool isSetNode() const; + + /// checks whether or not a direct child with a given name exists + sal_Bool hasByName(const ::rtl::OUString& _rName) const throw(); + sal_Bool hasByName( const sal_Char* _pAsciiName ) const { return hasByName( ::rtl::OUString::createFromAscii( _pAsciiName ) ); } + + /// checks whether or not a descendent (no matter if direct or indirect) with the given name exists + sal_Bool hasByHierarchicalName( const ::rtl::OUString& _rName ) const throw(); + sal_Bool hasByHierarchicalName( const sal_Char* _pAsciiName ) const { return hasByHierarchicalName( ::rtl::OUString::createFromAscii( _pAsciiName ) ); } + + /// check if the objects represents a valid configuration node + sal_Bool isValid() const { return m_xHierarchyAccess.is(); } + + /// check whether the object is read-only of updatable + sal_Bool isReadonly() const { return !m_xReplaceAccess.is(); } + + protected: + // OEventListenerAdapter + virtual void _disposing( const ::com::sun::star::lang::EventObject& _rSource ); + + protected: + enum NAMEORIGIN + { + NO_CONFIGURATION, /// the name came from a configuration node + NO_CALLER /// the name came from a client of this class + }; + ::rtl::OUString normalizeName(const ::rtl::OUString& _rName, NAMEORIGIN _eOrigin) const; + }; + + //======================================================================== + //= OConfigurationTreeRoot + //======================================================================== + /** a specialized version of a OConfigurationNode, representing the root + of a configuration sub tree<p/> + Only this class is able to commit any changes made any any OConfigurationNode + objects. + */ + class UNOTOOLS_DLLPUBLIC OConfigurationTreeRoot : public OConfigurationNode + { + ::com::sun::star::uno::Reference< ::com::sun::star::util::XChangesBatch > + m_xCommitter; + protected: + /** ctor<p/> + */ + OConfigurationTreeRoot( + const ::com::sun::star::uno::Reference< ::com::sun::star::util::XChangesBatch >& _rxRootNode, + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxProvider); + + /** ctor for a readonly node + */ + OConfigurationTreeRoot( + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxRootNode, + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxProvider); + + public: + /// modes to used when creating a top-level node object + enum CREATION_MODE + { + CM_READONLY, /// open the node (i.e. sub tree) for read access only + CM_UPDATABLE, /// open the node (i.e. sub tree) for read and write access + CM_PREFER_UPDATABLE /// open the node (i.e. sub tree) for read and write access, if this fails, open it for read acces + }; + + public: + /** default ctor<p/> + The object constructed here is invalid (i.e. <method>isValid</method> will return sal_False). + */ + OConfigurationTreeRoot() :OConfigurationNode() { } + + /// copy ctor + OConfigurationTreeRoot(const OConfigurationTreeRoot& _rSource) + :OConfigurationNode(_rSource), m_xCommitter(_rSource.m_xCommitter) { } + + /** open a new top-level configuration node + + opens a new node which is the root if an own configuration sub tree. This is what "top level" means: The + node does not have a parent. It does not mean that the node represents a module tree (like org.openoffice.Office.Writer + or such).<br/> + In opposite to <method>createWithServiceFactory</method>, createWithProvider expects a configuration provider + to work with. + + @param _rxConfProvider configuration provider to use when retrieving the node. + @param _rPath path to the node the object should represent + @param _nDepth depth for node retrieval + @param _eMode specifies which privileges should be applied when retrieving the node + + @see createWithServiceFactory + */ + static OConfigurationTreeRoot createWithProvider( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxConfProvider, + const ::rtl::OUString& _rPath, + sal_Int32 _nDepth = -1, + CREATION_MODE _eMode = CM_PREFER_UPDATABLE, + sal_Bool _bLazyWrite = sal_True + ); + + /** open a new top-level configuration node<p/> + opens a new node which is the root if an own configuration sub tree. This is what "top level" means: The + node does not have a parent. It does not mean that the node represents a module tree (like org.openoffice.Office.Writer + or such).<br/> + In opposite to <method>createWithProvider</method>, createWithProvider expects a service factory. This factory + is used to create a configuration provider, and this provider is used to retrieve the node + @see createWithProvider + @param _rxORB service factory to use to create the configuration provider. + @param _rPath path to the node the object should represent + @param _nDepth depth for node retrieval + @param _eMode specifies which privileges should be applied when retrieving the node + */ + static OConfigurationTreeRoot createWithServiceFactory(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB, + const ::rtl::OUString& _rPath, sal_Int32 _nDepth = -1, CREATION_MODE _eMode = CM_PREFER_UPDATABLE, sal_Bool _bLazyWrite = sal_True); + + /** tolerant version of the <member>createWithServiceFactory</member> + + <p>No assertions are thrown in case of an failure to initialize the configuration service, but once + the configuration could be initialized, errors in the creation of the specific node (e.g. because the + given node path does not exist) are still asserted.</p> + */ + static OConfigurationTreeRoot tryCreateWithServiceFactory( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB, + const ::rtl::OUString& _rPath, sal_Int32 _nDepth = -1, CREATION_MODE _eMode = CM_PREFER_UPDATABLE, sal_Bool _bLazyWrite = sal_True ); + + /** commit all changes made on the subtree the object is the root for<p/> + All changes made on any <type>OConfigurationNode</type> object retrieved (maybe indirect) from this root + object are committed when calling this method. + @return sal_True if and only if the commit was successfull + */ + sal_Bool commit() const throw(); + + /// invalidate the object + virtual void clear() throw(); + }; + +//........................................................................ +} // namespace utl +//........................................................................ + +#endif // _UNOTOOLS_CONFIGNODE_HXX_ + diff --git a/unotools/inc/unotools/configpathes.hxx b/unotools/inc/unotools/configpathes.hxx new file mode 100644 index 000000000000..081021145055 --- /dev/null +++ b/unotools/inc/unotools/configpathes.hxx @@ -0,0 +1,180 @@ +/************************************************************************* + * + * 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: configpathes.hxx,v $ + * $Revision: 1.5.22.1 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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 "unotools/unotoolsdllapi.h" + +#ifndef UNOTOOLS_CONFIGPATHES_HXX_INCLUDED +#define UNOTOOLS_CONFIGPATHES_HXX_INCLUDED +#include <sal/types.h> + +namespace rtl +{ + class OUString; +} + +//---------------------------------------------------------------------------- +namespace utl +{ +//---------------------------------------------------------------------------- + /** extract the local nodename and the parent nodepath + from a configuration path. + + @param _sInPath + A configuration path that is not an empty or root path.<BR/> + If this is not a valid configuration path, it is interpreted as + local name of a node. + + @param _rsOutPath + On exit: The configuration path obtained by dropping + the last level off <var>_sInPath</var>.<BR/> + If <var>_sInPath</var> could not be parsed as a valid + configuration path, this is set to an empty string. + + @param _rsLocalName + On exit: The plain (non-escaped) name of the node identified by + <var>_sInPath</var>. <BR/> + If <var>_sInPath</var> could not be parsed as a valid + configuration path, this is set to <var>_sInPath</var>. + + @returns + <TRUE/>, if a parent path could be set + <FALSE/>, if the path was a one-level path or an invalid path + + */ + UNOTOOLS_DLLPUBLIC sal_Bool splitLastFromConfigurationPath(::rtl::OUString const& _sInPath, + ::rtl::OUString& _rsOutPath, + ::rtl::OUString& _rsLocalName); + +//---------------------------------------------------------------------------- + /** extract the first nodename from a configuration path. + + @param _sInPath + A relative configuration path that is not empty.<BR/> + If this is not a valid configuration path, it is interpreted as + a single name of a node. + + @returns + The plain (non-escaped) name of the node that is the first step + when traversing <var>_sInPath</var>.<BR/> + If <var>_sInPath</var> could not be parsed as a valid + configuration path, it is returned unaltered. + + */ + UNOTOOLS_DLLPUBLIC ::rtl::OUString extractFirstFromConfigurationPath(::rtl::OUString const& _sInPath); + +//---------------------------------------------------------------------------- + /** check whether a path is to a nested node with respect to a parent path. + + @param _sNestedPath + A configuration path that maybe points to a descendant of the node + identified by <var>_sPrefixPath</var>, with both pathes starting + from the same node (or both being absolute). + + @param _sPrefixPath + A configuration path.<BR/> + If this path is absolute, <var>_sNestedPath</var> should be absolute; + If this path is relative, <var>_sNestedPath</var> should be relative; + If this path is empty, <var>_sNestedPath</var> may start with a '/', + which is disregarded. + + @returns + <TRUE/>, if <var>_sPrefixPath</var> is a prefix of <var>_sNestedPath</var>; + <FALSE/> otherwise.<BR/> + If both pathes are equal <TRUE/> is returned. + + */ + sal_Bool isPrefixOfConfigurationPath(::rtl::OUString const& _sNestedPath, + ::rtl::OUString const& _sPrefixPath); + +//---------------------------------------------------------------------------- + /** get the relative path to a nested node with respect to a parent path. + + @param _sNestedPath + A configuration path that points to a descendant of the node + identified by <var>_sPrefixPath</var>, with both pathes starting + from the same node (or both being absolute). + + @param _sPrefixPath + A configuration path.<BR/> + If this path is absolute, <var>_sNestedPath</var> must be absolute; + If this path is relative, <var>_sNestedPath</var> must be relative; + If this path is empty, <var>_sNestedPath</var> may start with a '/', + which is stripped. + + @returns + The remaining relative path from the target of <var>_sPrefixPath</var> + to the target of <var>_sNestedPath</var>.<BR/> + If <var>_sPrefixPath</var> is not a prefix of <var>_sNestedPath</var>, + <var>_sNestedPath</var> is returned unaltered. + + */ + UNOTOOLS_DLLPUBLIC ::rtl::OUString dropPrefixFromConfigurationPath(::rtl::OUString const& _sNestedPath, + ::rtl::OUString const& _sPrefixPath); + +//---------------------------------------------------------------------------- + /** Create a one-level relative configuration path from a set element name + without a known set element type. + + @param _sElementName + An arbitrary string that is to be interpreted as + name of a configuration set element. + + @returns + A one-level relative path to the element, of the form + "*['<Name>']", where <Name> is properly escaped. + + */ + UNOTOOLS_DLLPUBLIC ::rtl::OUString wrapConfigurationElementName(::rtl::OUString const& _sElementName); + +//---------------------------------------------------------------------------- + /** Create a one-level relative configuration path from a set element name + and a known set element type. + + @param _sElementName + An arbitrary string that is to be interpreted as + name of a configuration set element. + + @param _sTypeName + An string identifying the type of the element. Usually this is be + the name of the element-template of the set.<BR/> + + @returns + A one-level relative path to the element, of the form + "<Type>['<Name>']", where <Name> is properly escaped. + + */ + ::rtl::OUString wrapConfigurationElementName(::rtl::OUString const& _sElementName, + ::rtl::OUString const& _sTypeName); + +//---------------------------------------------------------------------------- +} // namespace utl +//---------------------------------------------------------------------------- + +#endif // UNOTOOLS_CONFIGPATHES_HXX_INCLUDED + diff --git a/unotools/inc/unotools/configvaluecontainer.hxx b/unotools/inc/unotools/configvaluecontainer.hxx new file mode 100644 index 000000000000..d4442d6bde6a --- /dev/null +++ b/unotools/inc/unotools/configvaluecontainer.hxx @@ -0,0 +1,239 @@ +/************************************************************************* + * + * 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: configvaluecontainer.hxx,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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 "unotools/unotoolsdllapi.h" + +#ifndef UNOTOOLS_CONFIGVALUECONTAINER_HXX +#define UNOTOOLS_CONFIGVALUECONTAINER_HXX +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <osl/mutex.hxx> + +//......................................................................... +namespace utl +{ +//......................................................................... + +#define CVC_READONLY_ACCESS 0x0000 +#define CVC_UPDATE_ACCESS 0x0001 + +#define CVC_LAZY_UPDATE 0x0000 +#define CVC_IMMEDIATE_UPDATE 0x0002 + + struct OConfigurationValueContainerImpl; + struct NodeValueAccessor; + //===================================================================== + //= OConfigurationValueContainer + //===================================================================== + /** allows simple access to static configuration structures. + + <p>The basic idea of this class is that it's clients (usually derived classes) simply register an + address in memory and a node path, and upon explicit request, the configuration value and the memory + are syncronized.<br/> + This means that when calling <method>read</method>, the current configuration values are copied into + the memory registered for them, and upon calling <method>write</method> the current values in memory + are set in the configuration nodes.</p> + + <p>This way, the usage of this class is pretty straight forward: derive your own class, spend some members + to it, and bind these members to configuration node (usually done in the ctor of the derived class).<br/> + In the dtor, simply call <method>write</method> and <method>commit</method>.</p> + + <p>There is no auto-commit mechanism in the dtor: In the usual scenario, when you derive from this class + and bind some members of your derived class to config nodes, this means that your members will be destroyed + before your base class' dtor is called, so accessing the memory during such a theoretical auto-commit would + yield undefined behaviour.</p> + */ + class UNOTOOLS_DLLPUBLIC OConfigurationValueContainer + { + private: + OConfigurationValueContainerImpl* + m_pImpl; + + protected: + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& + getServiceFactory( ) const; + + protected: + //----------------------------------------------------------------- + // construction/destruction + + /** constructs the object + + @param _rxORB + specifies the service factory which should be used to access the configuration + @param _rAccessSafety + As this class is intented to manipulate objects it does not hold itself (see the various + registerXXX methods), it needs to guard these access for muti threading safety.<br/> + The mutex given here is locked whenever such an access occurs. + @param _pConfigLocation + is an ASCII string describing the configurations node path + @param _nAccessFlags + specifies different aspects of the configuration aspect to be created, e.g. it's update mode etc.<br/> + See the CVC_xxx constants for what you can use here. + @param _nLevels + specifies the number of levels to access under the node given by <arg>_pConfigLocation</arg> + */ + OConfigurationValueContainer( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB, + ::osl::Mutex& _rAccessSafety, + const sal_Char* _pConfigLocation, + const sal_uInt16 _nAccessFlags = CVC_UPDATE_ACCESS | CVC_LAZY_UPDATE, + const sal_Int32 _nLevels = -1 + ); + + /** constructs the object + + @param _rxORB + specifies the service factory which should be used to access the configuration + @param _rAccessSafety + As this class is intented to manipulate objects it does not hold itself (see the various + registerXXX methods), it needs to guard these access for muti threading safety.<br/> + The mutex given here is locked whenever such an access occurs. + @param _rConfigLocation + describes the configurations node path + @param _nAccessFlags + specifies different aspects of the configuration aspect to be created, e.g. it's update mode etc.<br/> + See the CVC_xxx constants for what you can use here. + @param _nLevels + specifies the number of levels to access under the node given by <arg>_pConfigLocation</arg> + */ + OConfigurationValueContainer( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB, + ::osl::Mutex& _rAccessSafety, + const ::rtl::OUString& _rConfigLocation, + const sal_uInt16 _nAccessFlags = CVC_UPDATE_ACCESS | CVC_LAZY_UPDATE, + const sal_Int32 _nLevels = -1 + ); + + /// dtor + ~OConfigurationValueContainer(); + + //----------------------------------------------------------------- + // registering data containers + + /** registers a data accessor of an arbitrary type. + + <p>Usually, in your derived class you simply add a member of the correct type of the configuration + value, and then call this method with the address of this member.</p> + + <p>If the value you want to access may be <NULL/> at runtime, and if you want to recognize such + <NULL/> values, you may consider using <method>registerNullValueExchangeLocation</method>.</p> + + @param _pRelativePathAscii + is a relative (ASCII) path of the node which should be "mirrored" into the accessor. + @param _pContainer + points to the accessors location in memory. Usually, this is simply an address of your derived class + @param _rValueType + is the type of your accessort. This type must be supported by the configuration. + */ + void registerExchangeLocation( + const sal_Char* _pRelativePathAscii, + void* _pContainer, + const ::com::sun::star::uno::Type& _rValueType + ); + + /** registers a data accessor of an arbitrary type. + + <p>Usually, in your derived class you simply add a member of type <type scope="com.sun.star.uno">Any</type>, + and then call this method with the address of this member.</p> + + @param _pRelativePathAscii + is a relative (ASCII) path of the node which should be "mirrored" into the accessor. + @param _pContainer + points to the Any you want to hold the value + */ + void registerNullValueExchangeLocation( + const sal_Char* _pRelativePathAscii, + ::com::sun::star::uno::Any* _pContainer + ); + + public: + /** reads the configuration data + + <p>The current values of the nodes bound (using the registerXXX methods) is copied into their + respective exchange locations.</p> + + <p>Please note that any changes done to your exchange locations are overridden with the current config + values.</p> + + @see write + */ + void read( ); + + /** updates the configuration data + + <p>The current values in memory (your exchange locations registered using the registerXXX methods) is + forwarded to their respective configuration nodes.</p> + + <p>Note that calling <method>write</method>(<TRUE/) is the same as calling <method>commit</method>(<TRUE/>).</p> + + @precond + The access must have been created for update access + + @param _bCommit + If set to <TRUE/>, an automatic commit is done after the values have been synchronized.<br/> + If set to <FALSE/>, you must explicitly call <method>commit</method> to make your changes persistent. + + @see read + @see commit + */ + void write( sal_Bool _bCommit = sal_True ); + + /** commits any changes done + + <p>Note that calling <method>write</method>(<TRUE/) is the same as calling <method>commit</method>(<TRUE/>).</p> + + @precond + The access must have been created for update access + + @param _bWrite + If <TRUE/>, the current values in the exchange locations are written to the configuration nodes + before the changes are committed.<br/> + If <FALSE/>, only the current values in the config nodes (as present since the last call to + <method>write</method>) are committed. + */ + void commit( sal_Bool _bWrite = sal_True ); + + private: + /// implements the ctors + void implConstruct( + const ::rtl::OUString& _rConfigLocation, + const sal_uInt16 _nAccessFlags, + const sal_Int32 _nLevels + ); + + /// registers a value container + void implRegisterExchangeLocation( const NodeValueAccessor& _rAccessor ); + }; + +//......................................................................... +} // namespace utl +//......................................................................... + +#endif // UNOTOOLS_CONFIGVALUECONTAINER_HXX + diff --git a/unotools/inc/unotools/datetime.hxx b/unotools/inc/unotools/datetime.hxx new file mode 100644 index 000000000000..aaccfc29eb0f --- /dev/null +++ b/unotools/inc/unotools/datetime.hxx @@ -0,0 +1,66 @@ +/************************************************************************* + * + * 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: datetime.hxx,v $ + * $Revision: 1.6 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +//= conversions UNO3.TimeClass <-> Tools.TimeClass (Date/Time/DateTime) +#include "unotools/unotoolsdllapi.h" + +#ifndef _UNOTOOLS_DATETIME_HXX_ +#define _UNOTOOLS_DATETIME_HXX_ + +#include <com/sun/star/util/Date.hpp> +#include <com/sun/star/util/Time.hpp> +#include <com/sun/star/util/DateTime.hpp> + +class Date; +class Time; +class DateTime; + +//......................................................................... +namespace utl +{ +//......................................................................... + + namespace starutil = ::com::sun::star::util; + + UNOTOOLS_DLLPUBLIC void typeConvert(const Time& _rTime, starutil::Time& _rOut); + UNOTOOLS_DLLPUBLIC void typeConvert(const starutil::Time& _rTime, Time& _rOut); + + UNOTOOLS_DLLPUBLIC void typeConvert(const Date& _rDate, starutil::Date& _rOut); + UNOTOOLS_DLLPUBLIC void typeConvert(const starutil::Date& _rDate, Date& _rOut); + + UNOTOOLS_DLLPUBLIC void typeConvert(const DateTime& _rDateTime, starutil::DateTime& _rOut); + UNOTOOLS_DLLPUBLIC void typeConvert(const starutil::DateTime& _rDateTime, DateTime& _rOut); + +//......................................................................... +} // namespace utl +//......................................................................... + +#endif // _UNOTOOLS_DATETIME_HXX_ + diff --git a/unotools/inc/unotools/desktopterminationobserver.hxx b/unotools/inc/unotools/desktopterminationobserver.hxx new file mode 100644 index 000000000000..effa35a9e293 --- /dev/null +++ b/unotools/inc/unotools/desktopterminationobserver.hxx @@ -0,0 +1,82 @@ +/************************************************************************* + * + * 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: desktopterminationobserver.hxx,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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 "unotools/unotoolsdllapi.h" + +#ifndef UNOTOOLS_INC_UNOTOOLS_DESKTOPTERMINATIONOBSERVER_HXX +#define UNOTOOLS_INC_UNOTOOLS_DESKTOPTERMINATIONOBSERVER_HXX + +/** === begin UNO includes === **/ +/** === end UNO includes === **/ + +//........................................................................ +namespace utl +{ +//........................................................................ + + //==================================================================== + //= ITerminationListener + //==================================================================== + /** non-UNO version of the <type scope="com.sun.star.frame">XTerminateListener</type> + */ + class ITerminationListener + { + public: + virtual bool queryTermination() const = 0; + virtual void notifyTermination() = 0; + }; + + //==================================================================== + //= DesktopTerminationObserver + //==================================================================== + /** a class which allows non-UNO components to observe the desktop (aka application) + for it's shutdown + */ + class UNOTOOLS_DLLPUBLIC DesktopTerminationObserver + { + public: + /** registers a listener which should be notified when the desktop terminates + (which means the application is shutting down) + */ + static void registerTerminationListener( ITerminationListener* _pListener ); + + /** revokes a termination listener + */ + static void revokeTerminationListener( ITerminationListener* _pListener ); + + private: + DesktopTerminationObserver(); // never implemented, only static methods + }; + +//........................................................................ +} // namespace utl +//........................................................................ + +#endif // UNOTOOLS_INC_UNOTOOLS_DESKTOPTERMINATIONOBSERVER_HXX + diff --git a/unotools/inc/unotools/digitgroupingiterator.hxx b/unotools/inc/unotools/digitgroupingiterator.hxx new file mode 100644 index 000000000000..5525e01bb297 --- /dev/null +++ b/unotools/inc/unotools/digitgroupingiterator.hxx @@ -0,0 +1,207 @@ +/************************************************************************* + * + * 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: digitgroupingiterator.hxx,v $ + * $Revision: 1.3 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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_UNOTOOLS_DIGITGROUPINGITERATOR_HXX +#define INCLUDED_UNOTOOLS_DIGITGROUPINGITERATOR_HXX + +#include <com/sun/star/uno/Sequence.hxx> + +namespace utl { + +/** Iterator to be used with a digit grouping as obtained through + LocaleDataWrapper::getDigitGrouping(). + + The iterator advances over the digit groupings, returning the number of + digits per group. If the last group was encountered the iterator will + always return the last grouping. + + Grouping values are sanitized to be 0 <= value <= SAL_MAX_UINT16, even if + originally Int32, to be able to easily cast it down to String's xub_StrLen. + This shouldn't make any difference in practice. + + Usage example with a string buffer containing a decimal representation of + an integer number. Note that of course this loop could be optimized to not + count single characters but hunks of groups instead using the get() method, + this is just for illustrating usage. Anyway, for double values it is highly + more efficient to use ::rtl::math::doubleToString() and pass the grouping + sequence, instead of using this iterator and inserting charcters into + strings. + + DigitGroupingIterator aGrouping(...) + sal_Int32 nCount = 0; + sal_Int32 n = aBuffer.getLength(); + // >1 because we don't want to insert a separator if there is no leading digit. + while (n-- > 1) + { + if (++nCount >= aGrouping.getPos()) + { + aBuffer.insert( n, cSeparator); + nGroupDigits = aGrouping.advance(); + } + } + + */ + +class DigitGroupingIterator +{ + const ::com::sun::star::uno::Sequence< sal_Int32 > maGroupings; + + sal_Int32 mnGroup; // current active grouping + sal_Int32 mnDigits; // current active digits per group + sal_Int32 mnNextPos; // position (in digits) of next grouping + + void setInfinite() + { + mnGroup = maGroupings.getLength(); + } + + bool isInfinite() const + { + return mnGroup >= maGroupings.getLength(); + } + + sal_Int32 getGrouping() const + { + if (mnGroup < maGroupings.getLength()) + { + sal_Int32 n = maGroupings[mnGroup]; + OSL_ENSURE( 0 <= n && n <= SAL_MAX_UINT16, "DigitGroupingIterator::getGrouping: far out"); + if (n < 0) + n = 0; // sanitize ... + else if (n > SAL_MAX_UINT16) + n = SAL_MAX_UINT16; // limit for use with xub_StrLen + return n; + } + return 0; + } + + void setPos() + { + // someone might be playing jokes on us, so check for overflow + if (mnNextPos <= SAL_MAX_INT32 - mnDigits) + mnNextPos += mnDigits; + } + + void setDigits() + { + sal_Int32 nPrev = mnDigits; + mnDigits = getGrouping(); + if (!mnDigits) + { + mnDigits = nPrev; + setInfinite(); + } + setPos(); + } + + void initGrouping() + { + mnDigits = 3; // just in case of constructed with empty grouping + mnGroup = 0; + mnNextPos = 0; + setDigits(); + } + + // not implemented, prevent usage + DigitGroupingIterator(); + DigitGroupingIterator( const DigitGroupingIterator & ); + DigitGroupingIterator & operator=( const DigitGroupingIterator & ); + +public: + + explicit DigitGroupingIterator( const ::com::sun::star::uno::Sequence< sal_Int32 > & rGroupings ) + : maGroupings( rGroupings) + { + initGrouping(); + } + + /** Advance iterator to next grouping. */ + DigitGroupingIterator & advance() + { + if (isInfinite()) + setPos(); + else + { + ++mnGroup; + setDigits(); + } + return *this; + } + + /** Obtain current grouping. Always > 0. */ + sal_Int32 get() const + { + return mnDigits; + } + + /** The next position (in integer digits) from the right where to insert a + group separator. */ + sal_Int32 getPos() + { + return mnNextPos; + } + + /** Reset iterator to start again from the right beginning. */ + void reset() + { + initGrouping(); + } + + /** Create a sequence of bool values containing positions where to add a + separator when iterating forward over a string and copying digit per + digit. For example, for grouping in thousands and nIntegerDigits==7 the + sequence returned would be {1,0,0,1,0,0,0} so the caller would add a + separator after the 1st and the 4th digit. */ + static ::com::sun::star::uno::Sequence< sal_Bool > createForwardSequence( + sal_Int32 nIntegerDigits, + const ::com::sun::star::uno::Sequence< sal_Int32 > & rGroupings ) + { + if (nIntegerDigits <= 0) + return ::com::sun::star::uno::Sequence< sal_Bool >(); + DigitGroupingIterator aIterator( rGroupings); + ::com::sun::star::uno::Sequence< sal_Bool > aSeq( nIntegerDigits); + sal_Bool* pArr = aSeq.getArray(); + for (sal_Int32 j = 0; --nIntegerDigits >= 0; ++j) + { + if (j == aIterator.getPos()) + { + pArr[nIntegerDigits] = sal_True; + aIterator.advance(); + } + else + pArr[nIntegerDigits] = sal_False; + } + return aSeq; + } +}; + +} // namespace utl + +#endif // INCLUDED_UNOTOOLS_DIGITGROUPINGITERATOR_HXX diff --git a/unotools/inc/unotools/docinfohelper.hxx b/unotools/inc/unotools/docinfohelper.hxx new file mode 100644 index 000000000000..80534af1430e --- /dev/null +++ b/unotools/inc/unotools/docinfohelper.hxx @@ -0,0 +1,50 @@ +/************************************************************************* + * + * 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: docinfohelper.hxx,v $ + * $Revision: 1.3 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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 _UNOTOOLS_DOCINFOHELPER_HXX_ +#define _UNOTOOLS_DOCINFOHELPER_HXX_ + +#include <unotools/unotoolsdllapi.h> +#include <rtl/ustring.hxx> + +namespace utl +{ +class UNOTOOLS_DLLPUBLIC DocInfoHelper +{ +public: + static ::rtl::OUString GetGeneratorString(); + +}; + +} // namespace utl + + +#endif // _UNOTOOLS_DOCINFOHELPER_HXX_ + diff --git a/unotools/inc/unotools/eventlisteneradapter.hxx b/unotools/inc/unotools/eventlisteneradapter.hxx new file mode 100644 index 000000000000..9bd8586034bf --- /dev/null +++ b/unotools/inc/unotools/eventlisteneradapter.hxx @@ -0,0 +1,74 @@ +/************************************************************************* + * + * 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: eventlisteneradapter.hxx,v $ + * $Revision: 1.6 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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 "unotools/unotoolsdllapi.h" + +#ifndef _UNOTOOLS_EVENTLISTENERADAPTER_HXX_ +#define _UNOTOOLS_EVENTLISTENERADAPTER_HXX_ +#include <com/sun/star/lang/XComponent.hpp> + +//......................................................................... +namespace utl +{ +//......................................................................... + + struct OEventListenerAdapterImpl; + //===================================================================== + //= OEventListenerAdapter + //===================================================================== + /** base class for non-UNO dispose listeners + */ + class UNOTOOLS_DLLPUBLIC OEventListenerAdapter + { + friend class OEventListenerImpl; + + private: + UNOTOOLS_DLLPRIVATE OEventListenerAdapter( const OEventListenerAdapter& _rSource ); // never implemented + UNOTOOLS_DLLPRIVATE const OEventListenerAdapter& operator=( const OEventListenerAdapter& _rSource ); // never implemented + + protected: + OEventListenerAdapterImpl* m_pImpl; + + protected: + OEventListenerAdapter(); + virtual ~OEventListenerAdapter(); + + void startComponentListening( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent >& _rxComp ); + void stopComponentListening( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent >& _rxComp ); + void stopAllComponentListening( ); + + virtual void _disposing( const ::com::sun::star::lang::EventObject& _rSource ) = 0; + }; + +//......................................................................... +} // namespace utl +//......................................................................... + +#endif // _UNOTOOLS_EVENTLISTENERADAPTER_HXX_ + diff --git a/unotools/inc/unotools/idhelper.hxx b/unotools/inc/unotools/idhelper.hxx new file mode 100644 index 000000000000..a2aa28d26c1b --- /dev/null +++ b/unotools/inc/unotools/idhelper.hxx @@ -0,0 +1,213 @@ +/************************************************************************* + * + * 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: idhelper.hxx,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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 _UNOTOOLS_ID_HELPER_HXX_ +#define _UNOTOOLS_ID_HELPER_HXX_ + +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/lang/XTypeProvider.hpp> +#include <osl/mutex.hxx> +#include <comphelper/stl_types.hxx> +#include <cppuhelper/typeprovider.hxx> +#include <tools/debug.hxx> + +//......................................................................... +namespace utl +{ +//......................................................................... + +//========================================================================= +// to shorten some lines ... +typedef ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > TypeSequence; + +// compare to Sequences of Types +struct TypeSequenceLess : public ::std::binary_function<TypeSequence, TypeSequence, bool> +{ +public: + inline bool operator() (const TypeSequence& lhs, const TypeSequence& rhs) const + { + sal_Int32 nLengthLeft = lhs.getLength(); + sal_Int32 nLengthRight = rhs.getLength(); + + // first check the two lengths + if (nLengthLeft < nLengthRight) + return sal_True; + if (nLengthLeft > nLengthRight) + return sal_False; + + // both sequences have the same length -> check the type names + const ::com::sun::star::uno::Type* pTypesLeft = lhs.getConstArray(); + const ::com::sun::star::uno::Type* pTypesRight = rhs.getConstArray(); + for (sal_Int32 i=0; i<nLengthLeft; ++i, ++pTypesLeft, ++pTypesRight) + { + sal_Int32 nTypeNameCompare = pTypesLeft->getTypeName().compareTo(pTypesRight->getTypeName()); + if (nTypeNameCompare < 0) + return sal_True; + if (nTypeNameCompare > 0) + return sal_False; + } + + // both sequences are equal ... + return sal_False; + } +}; + +// declare the map +DECLARE_STL_MAP ( TypeSequence, + ::cppu::OImplementationId, + TypeSequenceLess, + MapType2Id + ); + +//......................................................................... +} // namespace utl +//......................................................................... + +//========================================================================= +/** defines a helper class for implementing the XTypeProvider::getImplementationId. + it maps sequences of ::com::sun::star::uno::Type to implementation ids + (which means sequences of bytes).<BR> + As there is no possibility to determine the time where the id's are no longer + needed (e.g. because the last instance of the class using this mechanism died) + the helper is "refcounted", i.e. there are acquire and release methods. + To simplify this there is a class classname##Ref which you may want to + use as an member of your classes. + <BR><BR> + As we don't want a global helper class which handles implementation id's + of components from all over the office (supposing somebody want's to use this :) + this is only a define. Wherever you have a "closed" area (which is small enough + and large enough :), see below) where diffenrent components want to use an id helper, + define your own one with this macro.<BR> + The more classes use this helper, the later redundant map entries will be + cleared. The less classes use it, the earlier map entries which may have + been reused will be cleared. +*/ +#define DECLARE_IMPLEMENTATIONID_HELPER(_namespace, classname) \ +namespace _namespace { \ +class classname \ +{ \ + friend class classname##Ref; \ + \ + static sal_Int32 s_nReferenced; \ + static void* s_pMap; \ + \ + static ::osl::Mutex s_aMutex; \ + \ +public: \ + static void acquire(); \ + static void release(); \ + \ + static ::com::sun::star::uno::Sequence< sal_Int8 > getImplementationId( \ + const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type >& _rTypes); \ + \ +private: \ + static void implCreateMap(); \ + \ + classname() { } \ +}; \ + \ +/*=======================================================================*/ \ +class classname##Ref \ +{ \ +public: \ + classname##Ref() { classname::acquire(); } \ + ~classname##Ref() { classname::release(); } \ +}; \ + \ +} /* _namespace */ \ + \ + +/************************************************************************* +************************************************************************** +*************************************************************************/ + +/** implement an id helper +*/ +#define IMPLEMENT_IMPLEMENTATIONID_HELPER(_namespace, classname) \ +namespace _namespace { \ + \ +/*=======================================================================*/ \ + \ +sal_Int32 classname::s_nReferenced(0); \ +void* classname::s_pMap = NULL; \ +::osl::Mutex classname::s_aMutex; \ + \ +/*-----------------------------------------------------------------------*/ \ +void classname::acquire() \ +{ \ + ::osl::MutexGuard aGuard(s_aMutex); \ + ++s_nReferenced; \ +} \ + \ +/*-----------------------------------------------------------------------*/ \ +void classname::release() \ +{ \ + ::osl::MutexGuard aGuard(s_aMutex); \ + if (!--s_nReferenced) \ + { \ + delete static_cast< ::utl::MapType2Id *>( s_pMap ); \ + s_pMap = NULL; \ + } \ +} \ + \ +/*-----------------------------------------------------------------------*/ \ +::com::sun::star::uno::Sequence< sal_Int8 > classname::getImplementationId( \ + const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type >& _rTypes) \ +{ \ + ::osl::MutexGuard aGuard(s_aMutex); \ + DBG_ASSERT(s_nReferenced, \ + "classname::getImplementationId : you need to hold a reference to this class in order to use it !"); \ + /* give the calling class a member of type classname##Ref and all is fine .... */ \ + \ + implCreateMap(); \ + \ + ::utl::MapType2Id* pMap = static_cast< ::utl::MapType2Id *>(s_pMap); \ + \ + ::cppu::OImplementationId& rId = (*pMap)[_rTypes]; \ + /* this will create an entry for the given type sequence, if neccessary */ \ + \ + return rId.getImplementationId(); \ +} \ + \ +/*-----------------------------------------------------------------------*/ \ +void classname::implCreateMap() \ +{ \ + if (s_pMap) \ + return; \ + s_pMap = new ::utl::MapType2Id(); \ +} \ + \ + \ +} /* _namespace */ \ + \ + + +#endif // _UNOTOOLS_ID_HELPER_HXX_ + diff --git a/unotools/inc/unotools/intlwrapper.hxx b/unotools/inc/unotools/intlwrapper.hxx new file mode 100644 index 000000000000..a48c9d20d0f4 --- /dev/null +++ b/unotools/inc/unotools/intlwrapper.hxx @@ -0,0 +1,126 @@ +/************************************************************************* + * + * 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: intlwrapper.hxx,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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 "unotools/unotoolsdllapi.h" + +#ifndef _UNOTOOLS_INTLWRAPPER_HXX +#define _UNOTOOLS_INTLWRAPPER_HXX +#include <unotools/charclass.hxx> +#include <unotools/localedatawrapper.hxx> +#include <unotools/calendarwrapper.hxx> +#include <unotools/collatorwrapper.hxx> +#include <i18npool/lang.h> + + +/** + A wrapper of I18N wrappers. Using this is more expensive than using some + single wrapper classes so use it only if you must pass a single pointer + without knowing in advance what is needed, e.g. for + SfxPoolItem::GetPresentation(). Remember that this wrapper was only created + for convenience to bypass some oddities, if possible don't use it. <p> + + Implemented are only the const get...() methods of the wrappers, which are + loaded on demand, for consistency reasons no change of locale is possible. + Only default calendar and default collator are supported. <p> + + One exception though is the calendar wrapper: to be able to set a value and + retrieve calendar values it is not const, so methods using this should + reset the calendar to the previous value if it isn't sure where the + IntlWrapper did come from. <p> + */ +class UNOTOOLS_DLLPUBLIC IntlWrapper +{ +private: + + ::com::sun::star::lang::Locale aLocale; + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xSMgr; + + CharClass* pCharClass; + LocaleDataWrapper* pLocaleData; + CalendarWrapper* pCalendar; + CollatorWrapper* pCollator; + CollatorWrapper* pCaseCollator; + + LanguageType eLanguage; + + void ImplNewCharClass() const; + void ImplNewLocaleData() const; + void ImplNewCalendar() const; + void ImplNewCollator( BOOL bCaseSensitive ) const; + + +public: + IntlWrapper( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > & xSF, + const ::com::sun::star::lang::Locale& rLocale + ); + IntlWrapper( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > & xSF, + LanguageType eLang + ); + ~IntlWrapper(); + + LanguageType getLanguage() const { return eLanguage; } + const ::com::sun::star::lang::Locale& getLocale() const { return aLocale; } + + const CharClass* getCharClass() const + { + if ( !pCharClass ) + ImplNewCharClass(); + return pCharClass; + } + const LocaleDataWrapper* getLocaleData() const + { + if ( !pLocaleData ) + ImplNewLocaleData(); + return pLocaleData; + } + CalendarWrapper* getCalendar() const + { + if ( !pCalendar ) + ImplNewCalendar(); + return pCalendar; + } + /// case insensitive collator, simple IGNORE_CASE + const CollatorWrapper* getCollator() const + { + if ( !pCollator ) + ImplNewCollator( FALSE ); + return pCollator; + } + /// case sensitive collator + const CollatorWrapper* getCaseCollator() const + { + if ( !pCaseCollator ) + ImplNewCollator( TRUE ); + return pCaseCollator; + } +}; + +#endif // _UNOTOOLS_INTLWRAPPER_HXX diff --git a/unotools/inc/unotools/localedatawrapper.hxx b/unotools/inc/unotools/localedatawrapper.hxx new file mode 100644 index 000000000000..5af352dd33c1 --- /dev/null +++ b/unotools/inc/unotools/localedatawrapper.hxx @@ -0,0 +1,366 @@ +/************************************************************************* + * + * 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: localedatawrapper.hxx,v $ + * $Revision: 1.31 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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 _UNOTOOLS_LOCALEDATAWRAPPER_HXX +#define _UNOTOOLS_LOCALEDATAWRAPPER_HXX + +#include <tools/string.hxx> +#include <com/sun/star/i18n/XLocaleData2.hpp> +#include <com/sun/star/i18n/LocaleItem.hpp> +#include <com/sun/star/i18n/reservedWords.hpp> +#include <unotools/readwritemutexguard.hxx> +#include "unotools/unotoolsdllapi.h" + +#ifndef BOOST_SHARED_PTR_HPP_INCLUDED +#include <boost/shared_ptr.hpp> +#endif + + +namespace com { namespace sun { namespace star { + namespace lang { + class XMultiServiceFactory; + } +}}} +class Date; +class Time; +class CalendarWrapper; + + +enum DateFormat { + MDY, + DMY, + YMD +}; + + +enum MeasurementSystem { + MEASURE_METRIC, + MEASURE_US +}; + + +class UNOTOOLS_DLLPUBLIC LocaleDataWrapper +{ + static BYTE nLocaleDataChecking; // 0:=dontknow, 1:=yes, 2:=no + + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xSMgr; + ::com::sun::star::uno::Reference< ::com::sun::star::i18n::XLocaleData2 > xLD; + ::com::sun::star::lang::Locale aLocale; + ::boost::shared_ptr< ::com::sun::star::i18n::Calendar > xDefaultCalendar; + ::com::sun::star::i18n::LocaleDataItem aLocaleDataItem; + ::com::sun::star::uno::Sequence< ::rtl::OUString > aReservedWordSeq; + ::com::sun::star::uno::Sequence< sal_Int32 > aGrouping; + // cached items + String aLocaleItem[::com::sun::star::i18n::LocaleItem::COUNT]; + String aReservedWord[::com::sun::star::i18n::reservedWords::COUNT]; + String aCurrSymbol; + String aCurrBankSymbol; + int nDateFormat; + int nLongDateFormat; + USHORT nCurrPositiveFormat; + USHORT nCurrNegativeFormat; + USHORT nCurrDigits; + BOOL bLocaleDataItemValid; + BOOL bReservedWordValid; + mutable ::utl::ReadWriteMutex aMutex; + + // dummies, to be implemented or provided by XML locale data + sal_Unicode cCurrZeroChar; + + + // not implemented, prevent usage + LocaleDataWrapper( const LocaleDataWrapper& ); + LocaleDataWrapper& operator=( const LocaleDataWrapper& ); + + // whenever Locale changes + void invalidateData(); + + void getOneLocaleItemImpl( sal_Int16 nItem ); + const String& getOneLocaleItem( sal_Int16 nItem ) const; + + void getOneReservedWordImpl( sal_Int16 nWord ); + const String& getOneReservedWord( sal_Int16 nWord ) const; + + void getCurrSymbolsImpl(); + void getCurrFormatsImpl(); + + void scanCurrFormatImpl( const String& rCode, + xub_StrLen nStart, xub_StrLen& nSign, + xub_StrLen& nPar, xub_StrLen& nNum, + xub_StrLen& nBlank, xub_StrLen& nSym ); + + void getDateFormatsImpl(); + DateFormat scanDateFormatImpl( const String& rCode ); + + void getDefaultCalendarImpl(); + + sal_Unicode* ImplAddFormatNum( sal_Unicode* pBuf, + sal_Int64 nNumber, USHORT nDecimals, + BOOL bUseThousandSep, BOOL bTrailingZeros ) const; + + void getDigitGroupingImpl(); + +public: + LocaleDataWrapper( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > & xSF, + const ::com::sun::star::lang::Locale& rLocale + ); + ~LocaleDataWrapper(); + + /** Get the service factory, meant to be able to create a CalendarWrapper + from a LocaleDataWrapper. Note that the service factory may be + non-existent if this LocaleDataWrapper was created without one and + lives "on the grassland". The CalendarWrapper ctor can handle that + though. */ + const ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XMultiServiceFactory > & getServiceFactory() + const { return xSMgr; } + + /// set a new Locale to request + void setLocale( const ::com::sun::star::lang::Locale& rLocale ); + + /// get current requested Locale + const ::com::sun::star::lang::Locale& getLocale() const; + + /// get current loaded Locale, which might differ from the requested Locale + ::com::sun::star::lang::Locale getLoadedLocale() const; + + + // Wrapper implementations of service LocaleData + + ::com::sun::star::i18n::LanguageCountryInfo getLanguageCountryInfo() const; + ::com::sun::star::i18n::LocaleDataItem getLocaleItem() const; + ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::Calendar > getAllCalendars() const; + /// NOTE: this wraps XLocaleData2::getAllCurrencies2() in fact. + ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::Currency2 > getAllCurrencies() const; + ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::FormatElement > getAllFormats() const; + ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::Implementation > getCollatorImplementations() const; + ::com::sun::star::uno::Sequence< ::rtl::OUString > getTransliterations() const; + ::com::sun::star::i18n::ForbiddenCharacters getForbiddenCharacters() const; + ::com::sun::star::uno::Sequence< ::rtl::OUString > getReservedWord() const; + ::com::sun::star::uno::Sequence< ::com::sun::star::lang::Locale > getAllInstalledLocaleNames() const; + + /// same as the wrapper implementation but static + static ::com::sun::star::uno::Sequence< ::com::sun::star::lang::Locale > getInstalledLocaleNames(); + + /** Get LanguageTypes for all installed locales which are unambiguous + convertible back and forth between locale ISO strings and MS-LCID + LanguageType. Upon the first time the function is called when + locale data checking is enabled, messages are shown for locales not + matching, excluding already known problems. + (e.g. used in number formatter dialog init) + */ + static ::com::sun::star::uno::Sequence< sal_uInt16 > getInstalledLanguageTypes(); + + /// maps the LocaleData string to the International enum + MeasurementSystem mapMeasurementStringToEnum( const String& rMS ) const; + + /// Convenience method to obtain the default calendar. + const ::boost::shared_ptr< ::com::sun::star::i18n::Calendar > getDefaultCalendar() const; + + /// Convenience method to obtain the day names of the default calendar. + const ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::CalendarItem > getDefaultCalendarDays() const; + + /// Convenience method to obtain the month names of the default calendar. + const ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::CalendarItem > getDefaultCalendarMonths() const; + + /** Obtain digit grouping. The usually known grouping by thousands (#,###) + is actually only one of possible groupings. Another one, for example, + used in India is group by 3 and then by 2 indefinitely (#,##,###). The + integer sequence returned here specifies grouping from right to left + (!), with a 0 entry designating the end of rules and the previous value + to be repeated indefinitely. Hence the sequence {3,0} specifies the + usual grouping by thousands, whereas the sequence {3,2,0} specifies + Indian grouping. The sal_Int32* getConstArray() can be passed directly + to the ::rtl::math::doubleToString() methods as argument for the + pGroups parameter. */ + const ::com::sun::star::uno::Sequence< sal_Int32 > getDigitGrouping() const; + + // Functionality of class International methods, LocaleItem + + inline const String& getDateSep() const + { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::DATE_SEPARATOR ); } + inline const String& getNumThousandSep() const + { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::THOUSAND_SEPARATOR ); } + inline const String& getNumDecimalSep() const + { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::DECIMAL_SEPARATOR ); } + inline const String& getTimeSep() const + { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::TIME_SEPARATOR ); } + inline const String& getTime100SecSep() const + { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::TIME_100SEC_SEPARATOR ); } + inline const String& getListSep() const + { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::LIST_SEPARATOR ); } + inline const String& getQuotationMarkStart() const + { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::SINGLE_QUOTATION_START ); } + inline const String& getQuotationMarkEnd() const + { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::SINGLE_QUOTATION_END ); } + inline const String& getDoubleQuotationMarkStart() const + { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::DOUBLE_QUOTATION_START ); } + inline const String& getDoubleQuotationMarkEnd() const + { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::DOUBLE_QUOTATION_END ); } + inline const String& getMeasurementSystem() const + { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::MEASUREMENT_SYSTEM ); } + inline MeasurementSystem getMeasurementSystemEnum() const + { return mapMeasurementStringToEnum( getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::MEASUREMENT_SYSTEM ) ); } + inline const String& getTimeAM() const + { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::TIME_AM ); } + inline const String& getTimePM() const + { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::TIME_PM ); } + inline const String& getLongDateDayOfWeekSep() const + { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::LONG_DATE_DAY_OF_WEEK_SEPARATOR ); } + inline const String& getLongDateDaySep() const + { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::LONG_DATE_DAY_SEPARATOR ); } + inline const String& getLongDateMonthSep() const + { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::LONG_DATE_MONTH_SEPARATOR ); } + inline const String& getLongDateYearSep() const + { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::LONG_DATE_YEAR_SEPARATOR ); } + + // currency + const String& getCurrSymbol() const; + const String& getCurrBankSymbol() const; + USHORT getCurrPositiveFormat() const; + USHORT getCurrNegativeFormat() const; + USHORT getCurrDigits() const; + + // simple date and time formatting + DateFormat getDateFormat() const; + DateFormat getLongDateFormat() const; + /// only numerical values of Gregorian calendar + String getDate( const Date& rDate ) const; + String getTime( const Time& rTime, BOOL bSec = TRUE, + BOOL b100Sec = FALSE ) const; + String getDuration( const Time& rTime, + BOOL bSec = TRUE, BOOL b100Sec = FALSE ) const; + + /** The CalendarWrapper already <b>MUST</b> + have loaded a calendar. + @param nDisplayDayOfWeek + 0 := abbreviated name + 1 := full name + @param bDayOfMonthWithLeadingZero + <FALSE/> := without leading zero + <TRUE/> := with leading zero if <10 + @param nDisplayMonth + 0 := abbreviated name + 1 := full name + @param bTwoDigitYear + <FALSE/> := full year + <TRUE/> := year % 100 + */ + String getLongDate( const Date& rDate, + CalendarWrapper& rCal, + sal_Int16 nDisplayDayOfWeek = 1, + sal_Bool bDayOfMonthWithLeadingZero = sal_False, + sal_Int16 nDisplayMonth = 1, + sal_Bool bTwoDigitYear = sal_False + ) const; + + /** Simple number formatting + @param nNumber + value * 10**nDecimals + @param bTrailingZeros + </TRUE> := always display trailing zeros in + decimal places, even if integer value. + </FALSE> := trailing zeros are only displayed + if the value is not an integer value. + */ + String getNum( sal_Int64 nNumber, USHORT nDecimals, + BOOL bUseThousandSep = TRUE, + BOOL bTrailingZeros = TRUE ) const; + + /// "Secure" currency formatted string. + String getCurr( sal_Int64 nNumber, USHORT nDecimals, + const String& rCurrencySymbol, + BOOL bUseThousandSep = TRUE ) const; + /** Default currency formatted string, use with + care as default currency may change in any + locale, for example, DEM -> EUR */ + String getCurr( sal_Int64 nNumber, USHORT nDecimals, + BOOL bUseThousandSep = TRUE ) const + { return getCurr( nNumber, nDecimals, + getCurrSymbol(), bUseThousandSep ); } + + // dummy returns, to be implemented + inline sal_Unicode getCurrZeroChar() const + { return cCurrZeroChar; } + inline BOOL isNumLeadingZero() const + { return TRUE; } + /// standard decimal places + inline USHORT getNumDigits() const + { return 2; } + inline BOOL isNumTrailingZeros() const + { return TRUE; } + + + // reserved words + + inline const String& getTrueWord() const + { return getOneReservedWord( ::com::sun::star::i18n::reservedWords::TRUE_WORD ); } + inline const String& getFalseWord() const + { return getOneReservedWord( ::com::sun::star::i18n::reservedWords::FALSE_WORD ); } + /// return a quarter string matching nQuarter (0..3) => "1st quarter" .. "4th quarter" + inline const String& getQuarterWord( sal_Int16 nQuarter ) const + { return getOneReservedWord( ::com::sun::star::i18n::reservedWords::QUARTER1_WORD + nQuarter ); } + inline const String& getAboveWord() const + { return getOneReservedWord( ::com::sun::star::i18n::reservedWords::ABOVE_WORD ); } + inline const String& getBelowWord() const + { return getOneReservedWord( ::com::sun::star::i18n::reservedWords::BELOW_WORD ); } + /// return a quarter abbreviation string matching nQuarter (0..3) => "Q1" .. "Q2" + inline const String& getQuarterAbbreviation( sal_Int16 nQuarter ) const + { return getOneReservedWord( ::com::sun::star::i18n::reservedWords::QUARTER1_ABBREVIATION + nQuarter ); } + + /** Return whether locale data checks are enabled. + Checks are enabled if the environment variable + OOO_ENABLE_LOCALE_DATA_CHECKS is set to 'Y' or 'Yes' (or any other + string starting with 'Y') or '1'. + Also used in conjunction with the number formatter. */ + static inline bool areChecksEnabled() + { + if (nLocaleDataChecking == 0) + evaluateLocaleDataChecking(); + return nLocaleDataChecking == 1; + } + + /** Append locale info to string, used with locale data checking. + A string similar to "de_DE requested\n en_US loaded" is appended. */ + String& appendLocaleInfo( String& rDebugMsg ) const; + + /** Ouput a message during locale data checking. The (UTF-8) string is + written to stderr and in a non-product build or if DBG_UTIL is enabled + also raised as an assertion message box. */ + static void outputCheckMessage( const String& rMsg ); + static void outputCheckMessage( const char* pStr); + +private: + static void evaluateLocaleDataChecking(); +}; + + +#endif // _UNOTOOLS_LOCALEDATAWRAPPER_HXX diff --git a/unotools/inc/unotools/localfilehelper.hxx b/unotools/inc/unotools/localfilehelper.hxx new file mode 100644 index 000000000000..a5b6fb44d818 --- /dev/null +++ b/unotools/inc/unotools/localfilehelper.hxx @@ -0,0 +1,71 @@ +/************************************************************************* + * + * 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: localfilehelper.hxx,v $ + * $Revision: 1.9 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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 _UNOTOOLS_LOCALFILEHELPER_HXX +#define _UNOTOOLS_LOCALFILEHELPER_HXX + +#include <com/sun/star/uno/Sequence.hxx> +#include "unotools/unotoolsdllapi.h" + +#include <rtl/ustring.hxx> +#include <tools/string.hxx> + +namespace utl +{ + +class UNOTOOLS_DLLPUBLIC LocalFileHelper +{ +public: + /** + Converts a "physical" file name into a "UCB compatible" URL ( if possible ). + If no UCP is available for the local file system, sal_False and an empty URL is returned. + Returning sal_True and an empty URL means that the URL doesn't point to a local file. + */ + static sal_Bool ConvertPhysicalNameToURL( const String& rName, String& rReturn ); + static sal_Bool ConvertSystemPathToURL( const String& rName, const String& rBaseURL, String& rReturn ); + + /** + Converts a "UCB compatible" URL into a "physical" file name. + If no UCP is available for the local file system, sal_False and an empty file name is returned, + otherwise sal_True and a valid URL, because a file name can always be converted if a UCP for the local + file system is present ( watch: this doesn't mean that this file really exists! ) + */ + static sal_Bool ConvertURLToPhysicalName( const String& rName, String& rReturn ); + static sal_Bool ConvertURLToSystemPath( const String& rName, String& rReturn ); + + static sal_Bool IsLocalFile( const String& rName ); + static sal_Bool IsFileContent( const String& rName ); + + static ::com::sun::star::uno::Sequence< ::rtl::OUString > + GetFolderContents( const ::rtl::OUString& rFolder, sal_Bool bFolder ); +}; + +} + +#endif diff --git a/unotools/inc/unotools/nativenumberwrapper.hxx b/unotools/inc/unotools/nativenumberwrapper.hxx new file mode 100644 index 000000000000..35f7ba632ca0 --- /dev/null +++ b/unotools/inc/unotools/nativenumberwrapper.hxx @@ -0,0 +1,78 @@ +/************************************************************************* + * + * 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: nativenumberwrapper.hxx,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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 "unotools/unotoolsdllapi.h" + +#ifndef _UNOTOOLS_NATIVENUMBERWRAPPER_HXX +#define _UNOTOOLS_NATIVENUMBERWRAPPER_HXX +#include <com/sun/star/i18n/XNativeNumberSupplier.hpp> + +namespace com { namespace sun { namespace star { + namespace lang { + class XMultiServiceFactory; + } +}}} + + +class UNOTOOLS_DLLPUBLIC NativeNumberWrapper +{ + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xSMgr; + ::com::sun::star::uno::Reference< ::com::sun::star::i18n::XNativeNumberSupplier > xNNS; + // not implemented, prevent usage + NativeNumberWrapper( const NativeNumberWrapper& ); + NativeNumberWrapper& operator=( const NativeNumberWrapper& ); + +public: + NativeNumberWrapper( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > & xSF + ); + + ~NativeNumberWrapper(); + + // Wrapper implementations of XNativeNumberSupplier + + ::rtl::OUString getNativeNumberString( + const ::rtl::OUString& rNumberString, + const ::com::sun::star::lang::Locale& rLocale, + sal_Int16 nNativeNumberMode ) const; + + sal_Bool isValidNatNum( + const ::com::sun::star::lang::Locale& rLocale, + sal_Int16 nNativeNumberMode ) const; + + ::com::sun::star::i18n::NativeNumberXmlAttributes convertToXmlAttributes( + const ::com::sun::star::lang::Locale& rLocale, + sal_Int16 nNativeNumberMode ) const; + + sal_Int16 convertFromXmlAttributes( + const ::com::sun::star::i18n::NativeNumberXmlAttributes& rAttr ) const; + +}; + +#endif // _UNOTOOLS_NATIVENUMBERWRAPPER_HXX diff --git a/unotools/inc/unotools/numberformatcodewrapper.hxx b/unotools/inc/unotools/numberformatcodewrapper.hxx new file mode 100644 index 000000000000..8e4f1ce793d0 --- /dev/null +++ b/unotools/inc/unotools/numberformatcodewrapper.hxx @@ -0,0 +1,79 @@ +/************************************************************************* + * + * 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: numberformatcodewrapper.hxx,v $ + * $Revision: 1.7 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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 _UNOTOOLS_NUMBERFORMATCODEWRAPPER_HXX +#define _UNOTOOLS_NUMBERFORMATCODEWRAPPER_HXX + +#include <com/sun/star/i18n/XNumberFormatCode.hpp> +#include "unotools/unotoolsdllapi.h" + +namespace com { namespace sun { namespace star { + namespace lang { + class XMultiServiceFactory; + } +}}} + + +class UNOTOOLS_DLLPUBLIC NumberFormatCodeWrapper +{ + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xSMgr; + ::com::sun::star::uno::Reference< ::com::sun::star::i18n::XNumberFormatCode > xNFC; + ::com::sun::star::lang::Locale aLocale; + + // not implemented, prevent usage + NumberFormatCodeWrapper( const NumberFormatCodeWrapper& ); + NumberFormatCodeWrapper& operator=( const NumberFormatCodeWrapper& ); + +public: + NumberFormatCodeWrapper( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > & xSF, + const ::com::sun::star::lang::Locale& rLocale + ); + + ~NumberFormatCodeWrapper(); + + + /// set a new Locale + void setLocale( const ::com::sun::star::lang::Locale& rLocale ); + + /// get current Locale + const ::com::sun::star::lang::Locale& getLocale() const { return aLocale; } + + + // Wrapper implementations of class NumberFormatCodeMapper + + ::com::sun::star::i18n::NumberFormatCode getDefault( sal_Int16 nFormatType, sal_Int16 nFormatUsage ) const; + ::com::sun::star::i18n::NumberFormatCode getFormatCode( sal_Int16 nFormatIndex ) const; + ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::NumberFormatCode > getAllFormatCode( sal_Int16 nFormatUsage ) const; + ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::NumberFormatCode > getAllFormatCodes() const; + +}; + +#endif // _UNOTOOLS_NUMBERFORMATCODEWRAPPER_HXX diff --git a/unotools/inc/unotools/processfactory.hxx b/unotools/inc/unotools/processfactory.hxx new file mode 100644 index 000000000000..795f4ee8839f --- /dev/null +++ b/unotools/inc/unotools/processfactory.hxx @@ -0,0 +1,62 @@ +/************************************************************************* + * + * 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: processfactory.hxx,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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 _UNOTOOLS_PROCESSFACTORY_HXX_ +#define _UNOTOOLS_PROCESSFACTORY_HXX_ + +#include "unotools/unotoolsdllapi.h" +#include <comphelper/processfactory.hxx> +#include <com/sun/star/uno/Reference.hxx> + +namespace com { namespace sun { namespace star { namespace lang { + class XMultiServiceFactory; +} } } } + +namespace utl +{ + +/** + * This function set the process service factory. + * + * @author Juergen Schmidt + */ +UNOTOOLS_DLLPUBLIC void setProcessServiceFactory(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xSMgr); + +/** + * This function get the process service factory. If no service factory is set the function returns + * a null interface. + * + * @author Juergen Schmidt + */ +UNOTOOLS_DLLPUBLIC ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > getProcessServiceFactory(); + +} + +#endif // _UNOTOOLS_PROCESSFACTORY_HXX_ + diff --git a/unotools/inc/unotools/progresshandlerwrap.hxx b/unotools/inc/unotools/progresshandlerwrap.hxx new file mode 100644 index 000000000000..c8394dc8577c --- /dev/null +++ b/unotools/inc/unotools/progresshandlerwrap.hxx @@ -0,0 +1,60 @@ +/************************************************************************* + * + * 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: progresshandlerwrap.hxx,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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 "unotools/unotoolsdllapi.h" + +#ifndef _UTL_PROGRESSHANDLERWRAP_HXX_ +#define _UTL_PROGRESSHANDLERWRAP_HXX_ +#include <cppuhelper/implbase1.hxx> +#include <com/sun/star/task/XStatusIndicator.hpp> +#include <com/sun/star/ucb/XProgressHandler.hpp> + +namespace utl +{ + +class UNOTOOLS_DLLPUBLIC ProgressHandlerWrap : public ::cppu::WeakImplHelper1< ::com::sun::star::ucb::XProgressHandler > +{ + ::com::sun::star::uno::Reference< ::com::sun::star::task::XStatusIndicator > m_xStatusIndicator; + +public: + ProgressHandlerWrap( ::com::sun::star::uno::Reference< ::com::sun::star::task::XStatusIndicator > xSI ); + + // XProgressHandler + virtual void SAL_CALL push( const ::com::sun::star::uno::Any& Status ) + throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL update( const ::com::sun::star::uno::Any& Status ) + throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL pop() + throw (::com::sun::star::uno::RuntimeException); +}; + +} // namespace utl + +#endif // _UTL_PROGRESSHANDLERWRAP_HXX_ + diff --git a/unotools/inc/unotools/propertysethelper.hxx b/unotools/inc/unotools/propertysethelper.hxx new file mode 100644 index 000000000000..04b027dc3546 --- /dev/null +++ b/unotools/inc/unotools/propertysethelper.hxx @@ -0,0 +1,99 @@ +/************************************************************************* + * + * 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: propertysethelper.hxx,v $ + * $Revision: 1.3 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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 _UTL_PROPERTYSETHELPER_HXX_ +#define _UTL_PROPERTYSETHELPER_HXX_ + +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/beans/XPropertyState.hpp> +#include <com/sun/star/beans/XMultiPropertySet.hpp> + +//========================================================================= +//= property helper classes +//========================================================================= + +//... namespace utl ....................................................... +namespace utl +{ +//......................................................................... + +class PropertySetInfo; +struct PropertyMapEntry; +class PropertySetHelperImpl; + +class PropertySetHelper : public ::com::sun::star::beans::XPropertySet, + public ::com::sun::star::beans::XPropertyState, + public ::com::sun::star::beans::XMultiPropertySet +{ +private: + PropertySetHelperImpl* mp; + +protected: + virtual void _setPropertyValues( const utl::PropertyMapEntry** ppEntries, const ::com::sun::star::uno::Any* pValues ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException ) = 0; + virtual void _getPropertyValues( const utl::PropertyMapEntry** ppEntries, ::com::sun::star::uno::Any* pValue ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException ) = 0; + + virtual void _getPropertyStates( const utl::PropertyMapEntry** ppEntries, ::com::sun::star::beans::PropertyState* pStates ) throw(::com::sun::star::beans::UnknownPropertyException ); + virtual void _setPropertyToDefault( const utl::PropertyMapEntry* pEntry ) throw(::com::sun::star::beans::UnknownPropertyException ); + virtual ::com::sun::star::uno::Any _getPropertyDefault( const utl::PropertyMapEntry* pEntry ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException ); + +public: + PropertySetHelper( utl::PropertySetInfo* pInfo ) throw(); + virtual ~PropertySetHelper() throw(); + + // 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); + + // XMultiPropertySet +// virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setPropertyValues( const ::com::sun::star::uno::Sequence< ::rtl::OUString >& aPropertyNames, const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aValues ) throw(::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::Sequence< ::com::sun::star::uno::Any > SAL_CALL getPropertyValues( const ::com::sun::star::uno::Sequence< ::rtl::OUString >& aPropertyNames ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addPropertiesChangeListener( const ::com::sun::star::uno::Sequence< ::rtl::OUString >& aPropertyNames, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertiesChangeListener >& xListener ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removePropertiesChangeListener( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertiesChangeListener >& xListener ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL firePropertiesChangeEvent( const ::com::sun::star::uno::Sequence< ::rtl::OUString >& aPropertyNames, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertiesChangeListener >& xListener ) throw(::com::sun::star::uno::RuntimeException); + + // XPropertyState + virtual ::com::sun::star::beans::PropertyState SAL_CALL getPropertyState( const ::rtl::OUString& PropertyName ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyState > SAL_CALL getPropertyStates( const ::com::sun::star::uno::Sequence< ::rtl::OUString >& aPropertyName ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setPropertyToDefault( const ::rtl::OUString& PropertyName ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Any SAL_CALL getPropertyDefault( const ::rtl::OUString& aPropertyName ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); +}; + +//......................................................................... +} +//... namespace utl ....................................................... + +#endif // _UTL_PROPERTYSETHELPER_HXX_ + diff --git a/unotools/inc/unotools/propertysetinfo.hxx b/unotools/inc/unotools/propertysetinfo.hxx new file mode 100644 index 000000000000..cd44940eb781 --- /dev/null +++ b/unotools/inc/unotools/propertysetinfo.hxx @@ -0,0 +1,96 @@ +/************************************************************************* + * + * 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: propertysetinfo.hxx,v $ + * $Revision: 1.3 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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 _UTL_PROPERTSETINFO_HXX_ +#define _UTL_PROPERTSETINFO_HXX_ + +#include <com/sun/star/uno/Type.h> +#include <com/sun/star/beans/XPropertySetInfo.hpp> +#include <cppuhelper/implbase1.hxx> +#include <comphelper/stl_types.hxx> + +//========================================================================= +//= property helper classes +//========================================================================= + +//... namespace utl ....................................................... +namespace utl +{ +//......................................................................... + +struct PropertyMapEntry +{ + const sal_Char* mpName; + sal_uInt16 mnNameLen; + sal_uInt16 mnWhich; + const com::sun::star::uno::Type* mpType; + sal_Int16 mnFlags; + sal_uInt8 mnMemberId; +}; + +DECLARE_STL_USTRINGACCESS_MAP( PropertyMapEntry*, PropertyMap ); + +class PropertyMapImpl; + +/** this class implements a XPropertySetInfo that is initialized with arrays of PropertyMapEntry. + It is used by the class PropertySetHelper. +*/ +class PropertySetInfo : public ::cppu::WeakImplHelper1< ::com::sun::star::beans::XPropertySetInfo > +{ +private: + PropertyMapImpl* mpMap; +public: + PropertySetInfo() throw(); + virtual ~PropertySetInfo() throw(); + + /** returns a stl map with all PropertyMapEntry pointer.<p> + The key is the property name. + */ + const PropertyMap* getPropertyMap() const throw(); + + /** adds an array of PropertyMapEntry to this instance.<p> + The end is marked with a PropertyMapEntry where mpName equals NULL + */ + void add( PropertyMapEntry* pMap ) throw(); + + /** removes an already added PropertyMapEntry which string in mpName equals to aName */ + void remove( const rtl::OUString& aName ) throw(); + + 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); +}; + +//......................................................................... +} +//... namespace utl ....................................................... + +#endif // _UTL_PROPERTSETINFO_HXX_ + diff --git a/unotools/inc/unotools/querydeep.hxx b/unotools/inc/unotools/querydeep.hxx new file mode 100644 index 000000000000..50af53d35dce --- /dev/null +++ b/unotools/inc/unotools/querydeep.hxx @@ -0,0 +1,489 @@ +/************************************************************************* + * + * 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: querydeep.hxx,v $ + * $Revision: 1.3 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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 _UNOTOOLS_QUERYDEEPINTERFACE_HXX +#define _UNOTOOLS_QUERYDEEPINTERFACE_HXX + +#include <com/sun/star/uno/XInterface.hpp> +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/uno/Type.hxx> + +/** */ //for docpp +namespace utl +{ + +//-------------------------------------------------------------------------------------------------------- +/** + * Inspect interfaces types whether they are related by inheritance. + *<BR> + * @return true if rType is derived from rBaseType + * @param rBaseType a <type>Type</type> of an interface. + * @param rType a <type>Type</type> of an interface. + */ +sal_Bool isDerivedFrom( + const ::com::sun::star::uno::Type & rBaseType, + const ::com::sun::star::uno::Type & rType ); + +//-------------------------------------------------------------------------------------------------------- +/** + * Inspect interface types whether they are related by inheritance. + *<BR> + * @return true if p is of a type derived from rBaseType + * @param rBaseType a <type>Type</type> of an interface. + * @param p a pointer to an interface. + */ +template <class Interface> +inline sal_Bool isDerivedFrom( + const ::com::sun::star::uno::Type& rBaseType, + Interface* /*p*/) +{ + return isDerivedFrom( + rBaseType, + ::getCppuType(static_cast<const ::com::sun::star::uno::Reference<Interface> *>(0))); +} + +//-------------------------------------------------------------------------------------------------------- +// possible optimization ? +// Any aRet(::cppu::queryInterface(rType, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12)); +// if (aRet.hasValue()) +// return aRet; + +/** + * Inspect types and choose return proper interface. + *<BR> + * @param p1 a pointer to an interface. + */ +template< class Interface1 > +inline ::com::sun::star::uno::Any queryDeepInterface( + const ::com::sun::star::uno::Type & rType, + Interface1 * p1 ) +{ + if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface1 > *>(0)))) + return ::com::sun::star::uno::Any( &p1, rType ); + else + return ::com::sun::star::uno::Any(); +} + +/** + * Inspect types and choose return proper interface. + *<BR> + * @param p1 a pointer to an interface. + * @param p2 a pointer to an interface. + */ +template< class Interface1, class Interface2 > +inline ::com::sun::star::uno::Any queryDeepInterface( + const ::com::sun::star::uno::Type & rType, + Interface1 * p1, Interface2 * p2 ) +{ + if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface1 > *>(0)))) + return ::com::sun::star::uno::Any( &p1, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface2 > *>(0)))) + return ::com::sun::star::uno::Any( &p2, rType ); + else + return ::com::sun::star::uno::Any(); +} + +/** + * Inspect types and choose return proper interface. + *<BR> + * @param p1 a pointer to an interface. + * @param p2 a pointer to an interface. + * @param p3 a pointer to an interface. + */ +template< class Interface1, class Interface2, class Interface3 > +inline ::com::sun::star::uno::Any queryDeepInterface( + const ::com::sun::star::uno::Type & rType, + Interface1 * p1, Interface2 * p2, Interface3 * p3 ) +{ + if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface1 > *>(0)))) + return ::com::sun::star::uno::Any( &p1, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface2 > *>(0)))) + return ::com::sun::star::uno::Any( &p2, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface3 > *>(0)))) + return ::com::sun::star::uno::Any( &p3, rType ); + else + return ::com::sun::star::uno::Any(); +} + +/** + * Inspect types and choose return proper interface. + *<BR> + * @param p1 a pointer to an interface. + * @param p2 a pointer to an interface. + * @param p3 a pointer to an interface. + * @param p4 a pointer to an interface. + */ +template< class Interface1, class Interface2, class Interface3, class Interface4 > +inline ::com::sun::star::uno::Any queryDeepInterface( + const ::com::sun::star::uno::Type & rType, + Interface1 * p1, Interface2 * p2, Interface3 * p3, Interface4 * p4 ) +{ + if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface1 > *>(0)))) + return ::com::sun::star::uno::Any( &p1, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface2 > *>(0)))) + return ::com::sun::star::uno::Any( &p2, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface3 > *>(0)))) + return ::com::sun::star::uno::Any( &p3, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface4 > *>(0)))) + return ::com::sun::star::uno::Any( &p4, rType ); + else + return ::com::sun::star::uno::Any(); +} + +/** + * Inspect types and choose return proper interface. + *<BR> + * @param p1 a pointer to an interface. + * @param p2 a pointer to an interface. + * @param p3 a pointer to an interface. + * @param p4 a pointer to an interface. + * @param p5 a pointer to an interface. + */ +template< class Interface1, class Interface2, class Interface3, class Interface4, class Interface5 > +inline ::com::sun::star::uno::Any queryDeepInterface( + const ::com::sun::star::uno::Type & rType, + Interface1 * p1, Interface2 * p2, Interface3 * p3, Interface4 * p4, Interface5 * p5 ) +{ + if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface1 > *>(0)))) + return ::com::sun::star::uno::Any( &p1, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface2 > *>(0)))) + return ::com::sun::star::uno::Any( &p2, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface3 > *>(0)))) + return ::com::sun::star::uno::Any( &p3, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface4 > *>(0)))) + return ::com::sun::star::uno::Any( &p4, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface5 > *>(0)))) + return ::com::sun::star::uno::Any( &p5, rType ); + else + return ::com::sun::star::uno::Any(); +} + +/** + * Inspect types and choose return proper interface. + *<BR> + * @param p1 a pointer to an interface. + * @param p2 a pointer to an interface. + * @param p3 a pointer to an interface. + * @param p4 a pointer to an interface. + * @param p5 a pointer to an interface. + * @param p6 a pointer to an interface. + */ +template< class Interface1, class Interface2, class Interface3, class Interface4, class Interface5, + class Interface6 > +inline ::com::sun::star::uno::Any queryDeepInterface( + const ::com::sun::star::uno::Type & rType, + Interface1 * p1, Interface2 * p2, Interface3 * p3, Interface4 * p4, Interface5 * p5, + Interface6 * p6 ) +{ + if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface1 > *>(0)))) + return ::com::sun::star::uno::Any( &p1, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface2 > *>(0)))) + return ::com::sun::star::uno::Any( &p2, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface3 > *>(0)))) + return ::com::sun::star::uno::Any( &p3, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface4 > *>(0)))) + return ::com::sun::star::uno::Any( &p4, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface5 > *>(0)))) + return ::com::sun::star::uno::Any( &p5, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface6 > *>(0)))) + return ::com::sun::star::uno::Any( &p6, rType ); + else + return ::com::sun::star::uno::Any(); +} + +/** + * Inspect types and choose return proper interface. + *<BR> + * @param p1 a pointer to an interface. + * @param p2 a pointer to an interface. + * @param p3 a pointer to an interface. + * @param p4 a pointer to an interface. + * @param p5 a pointer to an interface. + * @param p6 a pointer to an interface. + * @param p7 a pointer to an interface. + */ +template< class Interface1, class Interface2, class Interface3, class Interface4, class Interface5, + class Interface6, class Interface7 > +inline ::com::sun::star::uno::Any queryDeepInterface( + const ::com::sun::star::uno::Type & rType, + Interface1 * p1, Interface2 * p2, Interface3 * p3, Interface4 * p4, Interface5 * p5, + Interface6 * p6, Interface7 * p7 ) +{ + if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface1 > *>(0)))) + return ::com::sun::star::uno::Any( &p1, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface2 > *>(0)))) + return ::com::sun::star::uno::Any( &p2, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface3 > *>(0)))) + return ::com::sun::star::uno::Any( &p3, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface4 > *>(0)))) + return ::com::sun::star::uno::Any( &p4, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface5 > *>(0)))) + return ::com::sun::star::uno::Any( &p5, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface6 > *>(0)))) + return ::com::sun::star::uno::Any( &p6, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface7 > *>(0)))) + return ::com::sun::star::uno::Any( &p7, rType ); + else + return ::com::sun::star::uno::Any(); +} + +/** + * Inspect types and choose return proper interface. + *<BR> + * @param p1 a pointer to an interface. + * @param p2 a pointer to an interface. + * @param p3 a pointer to an interface. + * @param p4 a pointer to an interface. + * @param p5 a pointer to an interface. + * @param p6 a pointer to an interface. + * @param p7 a pointer to an interface. + * @param p8 a pointer to an interface. + */ +template< class Interface1, class Interface2, class Interface3, class Interface4, class Interface5, + class Interface6, class Interface7, class Interface8 > +inline ::com::sun::star::uno::Any queryDeepInterface( + const ::com::sun::star::uno::Type & rType, + Interface1 * p1, Interface2 * p2, Interface3 * p3, Interface4 * p4, Interface5 * p5, + Interface6 * p6, Interface7 * p7, Interface8 * p8 ) +{ + if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface1 > *>(0)))) + return ::com::sun::star::uno::Any( &p1, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface2 > *>(0)))) + return ::com::sun::star::uno::Any( &p2, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface3 > *>(0)))) + return ::com::sun::star::uno::Any( &p3, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface4 > *>(0)))) + return ::com::sun::star::uno::Any( &p4, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface5 > *>(0)))) + return ::com::sun::star::uno::Any( &p5, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface6 > *>(0)))) + return ::com::sun::star::uno::Any( &p6, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface7 > *>(0)))) + return ::com::sun::star::uno::Any( &p7, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface8 > *>(0)))) + return ::com::sun::star::uno::Any( &p8, rType ); + else + return ::com::sun::star::uno::Any(); +} + +/** + * Inspect types and choose return proper interface. + *<BR> + * @param p1 a pointer to an interface. + * @param p2 a pointer to an interface. + * @param p3 a pointer to an interface. + * @param p4 a pointer to an interface. + * @param p5 a pointer to an interface. + * @param p6 a pointer to an interface. + * @param p7 a pointer to an interface. + * @param p8 a pointer to an interface. + * @param p9 a pointer to an interface. + */ +template< class Interface1, class Interface2, class Interface3, class Interface4, class Interface5, + class Interface6, class Interface7, class Interface8, class Interface9 > +inline ::com::sun::star::uno::Any queryDeepInterface( + const ::com::sun::star::uno::Type & rType, + Interface1 * p1, Interface2 * p2, Interface3 * p3, Interface4 * p4, Interface5 * p5, + Interface6 * p6, Interface7 * p7, Interface8 * p8, Interface9 * p9 ) +{ + if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface1 > *>(0)))) + return ::com::sun::star::uno::Any( &p1, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface2 > *>(0)))) + return ::com::sun::star::uno::Any( &p2, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface3 > *>(0)))) + return ::com::sun::star::uno::Any( &p3, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface4 > *>(0)))) + return ::com::sun::star::uno::Any( &p4, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface5 > *>(0)))) + return ::com::sun::star::uno::Any( &p5, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface6 > *>(0)))) + return ::com::sun::star::uno::Any( &p6, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface7 > *>(0)))) + return ::com::sun::star::uno::Any( &p7, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface8 > *>(0)))) + return ::com::sun::star::uno::Any( &p8, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface9 > *>(0)))) + return ::com::sun::star::uno::Any( &p9, rType ); + else + return ::com::sun::star::uno::Any(); +} + +/** + * Inspect types and choose return proper interface. + *<BR> + * @param p1 a pointer to an interface. + * @param p2 a pointer to an interface. + * @param p3 a pointer to an interface. + * @param p4 a pointer to an interface. + * @param p5 a pointer to an interface. + * @param p6 a pointer to an interface. + * @param p7 a pointer to an interface. + * @param p8 a pointer to an interface. + * @param p9 a pointer to an interface. + * @param p10 a pointer to an interface. + */ +template< class Interface1, class Interface2, class Interface3, class Interface4, class Interface5, + class Interface6, class Interface7, class Interface8, class Interface9, class Interface10 > +inline ::com::sun::star::uno::Any queryDeepInterface( + const ::com::sun::star::uno::Type & rType, + Interface1 * p1, Interface2 * p2, Interface3 * p3, Interface4 * p4, Interface5 * p5, + Interface6 * p6, Interface7 * p7, Interface8 * p8, Interface9 * p9, Interface10 * p10 ) +{ + if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface1 > *>(0)))) + return ::com::sun::star::uno::Any( &p1, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface2 > *>(0)))) + return ::com::sun::star::uno::Any( &p2, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface3 > *>(0)))) + return ::com::sun::star::uno::Any( &p3, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface4 > *>(0)))) + return ::com::sun::star::uno::Any( &p4, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface5 > *>(0)))) + return ::com::sun::star::uno::Any( &p5, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface6 > *>(0)))) + return ::com::sun::star::uno::Any( &p6, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface7 > *>(0)))) + return ::com::sun::star::uno::Any( &p7, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface8 > *>(0)))) + return ::com::sun::star::uno::Any( &p8, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface9 > *>(0)))) + return ::com::sun::star::uno::Any( &p9, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface10 > *>(0)))) + return ::com::sun::star::uno::Any( &p10, rType ); + else + return ::com::sun::star::uno::Any(); +} + +/** + * Inspect types and choose return proper interface. + *<BR> + * @param p1 a pointer to an interface. + * @param p2 a pointer to an interface. + * @param p3 a pointer to an interface. + * @param p4 a pointer to an interface. + * @param p5 a pointer to an interface. + * @param p6 a pointer to an interface. + * @param p7 a pointer to an interface. + * @param p8 a pointer to an interface. + * @param p9 a pointer to an interface. + * @param p10 a pointer to an interface. + * @param p11 a pointer to an interface. + */ +template< class Interface1, class Interface2, class Interface3, class Interface4, class Interface5, + class Interface6, class Interface7, class Interface8, class Interface9, class Interface10, + class Interface11 > +inline ::com::sun::star::uno::Any queryDeepInterface( + const ::com::sun::star::uno::Type & rType, + Interface1 * p1, Interface2 * p2, Interface3 * p3, Interface4 * p4, Interface5 * p5, + Interface6 * p6, Interface7 * p7, Interface8 * p8, Interface9 * p9, Interface10 * p10, + Interface11 * p11 ) +{ + if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface1 > *>(0)))) + return ::com::sun::star::uno::Any( &p1, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface2 > *>(0)))) + return ::com::sun::star::uno::Any( &p2, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface3 > *>(0)))) + return ::com::sun::star::uno::Any( &p3, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface4 > *>(0)))) + return ::com::sun::star::uno::Any( &p4, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface5 > *>(0)))) + return ::com::sun::star::uno::Any( &p5, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface6 > *>(0)))) + return ::com::sun::star::uno::Any( &p6, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface7 > *>(0)))) + return ::com::sun::star::uno::Any( &p7, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface8 > *>(0)))) + return ::com::sun::star::uno::Any( &p8, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface9 > *>(0)))) + return ::com::sun::star::uno::Any( &p9, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface10 > *>(0)))) + return ::com::sun::star::uno::Any( &p10, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface11 > *>(0)))) + return ::com::sun::star::uno::Any( &p11, rType ); + else + return ::com::sun::star::uno::Any(); +} + +/** + * Inspect types and choose return proper interface. + *<BR> + * @param p1 a pointer to an interface. + * @param p2 a pointer to an interface. + * @param p3 a pointer to an interface. + * @param p4 a pointer to an interface. + * @param p5 a pointer to an interface. + * @param p6 a pointer to an interface. + * @param p7 a pointer to an interface. + * @param p8 a pointer to an interface. + * @param p9 a pointer to an interface. + * @param p10 a pointer to an interface. + * @param p11 a pointer to an interface. + * @param p12 a pointer to an interface. + */ +template< class Interface1, class Interface2, class Interface3, class Interface4, class Interface5, + class Interface6, class Interface7, class Interface8, class Interface9, class Interface10, + class Interface11, class Interface12 > +inline ::com::sun::star::uno::Any queryDeepInterface( + const ::com::sun::star::uno::Type & rType, + Interface1 * p1, Interface2 * p2, Interface3 * p3, Interface4 * p4, Interface5 * p5, + Interface6 * p6, Interface7 * p7, Interface8 * p8, Interface9 * p9, Interface10 * p10, + Interface11 * p11, Interface12 * p12 ) +{ + if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface1 > *>(0)))) + return ::com::sun::star::uno::Any( &p1, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface2 > *>(0)))) + return ::com::sun::star::uno::Any( &p2, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface3 > *>(0)))) + return ::com::sun::star::uno::Any( &p3, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface4 > *>(0)))) + return ::com::sun::star::uno::Any( &p4, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface5 > *>(0)))) + return ::com::sun::star::uno::Any( &p5, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface6 > *>(0)))) + return ::com::sun::star::uno::Any( &p6, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface7 > *>(0)))) + return ::com::sun::star::uno::Any( &p7, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface8 > *>(0)))) + return ::com::sun::star::uno::Any( &p8, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface9 > *>(0)))) + return ::com::sun::star::uno::Any( &p9, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface10 > *>(0)))) + return ::com::sun::star::uno::Any( &p10, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface11 > *>(0)))) + return ::com::sun::star::uno::Any( &p11, rType ); + else if (isDerivedFrom(rType, ::getCppuType(static_cast<const ::com::sun::star::uno::Reference< Interface12 > *>(0)))) + return ::com::sun::star::uno::Any( &p12, rType ); + else + return ::com::sun::star::uno::Any(); +} + +} // namespace utl + +#endif // _UNOTOOLS_QUERYDEEPINTERFACE_HXX + diff --git a/unotools/inc/unotools/readwritemutexguard.hxx b/unotools/inc/unotools/readwritemutexguard.hxx new file mode 100644 index 000000000000..46e3d36f2eac --- /dev/null +++ b/unotools/inc/unotools/readwritemutexguard.hxx @@ -0,0 +1,116 @@ +/************************************************************************* + * + * 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: readwritemutexguard.hxx,v $ + * $Revision: 1.3 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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_UNOTOOLS_READWRITEMUTEXGUARD_HXX +#define INCLUDED_UNOTOOLS_READWRITEMUTEXGUARD_HXX + +#include <osl/mutex.hxx> + +namespace utl { + +class ReadWriteGuard; +class ReadWriteMutex +{ + friend class ReadWriteGuard; + + sal_uInt32 nReadCount; + sal_uInt32 nBlockCriticalCount; + ::osl::Mutex* pMutex; + ::osl::Mutex* pWriteMutex; + +public: + ReadWriteMutex() + : nReadCount(0) + , nBlockCriticalCount(0) + , pMutex( new ::osl::Mutex ) + , pWriteMutex( new ::osl::Mutex ) + {} + ~ReadWriteMutex() + { + delete pMutex; + delete pWriteMutex; + } +}; + + +namespace ReadWriteGuardMode { +const sal_Int32 nWrite = 0x01; +const sal_Int32 nCriticalChange = 0x02 | nWrite; +const sal_Int32 nBlockCritical = 0x04; // only a block, not a read, exclusive flag! +} + +/** Enable multiple threads to read simultaneously, but a write blocks all + other reads and writes, and a read blocks any write. + Used in I18N wrappers to be able to maintain a single instance of a wrapper + for the standard Office locale. + NEVER construct a writing guard if there is already a reading guard in the + same context, the following will dead lock EVEN IN THE SAME THREAD! + void foo() + { + ReadWriteGuard aGuard1( aMutex ); + bar(); + } + void bar() + { + // waits forever for aGuard1 + ReadWriteGuard aGuard2( aMutex, ReadWriteGuardMode::nWrite ); + } + */ +class ReadWriteGuard +{ + ReadWriteMutex& rMutex; + sal_Int32 nMode; +public: + ReadWriteGuard( + ReadWriteMutex& rMutex, + sal_Int32 nRequestMode = 0 // read only + ); + ~ReadWriteGuard(); + + /** Be careful with this, it does wait for ANY read to complete. + The following will dead lock EVEN IN THE SAME THREAD! + void foo() + { + ReadWriteGuard aGuard1( aMutex ); + bar(); + } + void bar() + { + ReadWriteGuard aGuard2( aMutex ); + aGuard2.changeReadToWrite(); // waits forever for aGuard1 + } + */ + void changeReadToWrite(); +}; + +} // namespace utl + +#endif // INCLUDED_UNOTOOLS_READWRITEMUTEXGUARD_HXX + diff --git a/unotools/inc/unotools/regpathhelper.hxx b/unotools/inc/unotools/regpathhelper.hxx new file mode 100644 index 000000000000..4dd2b5fbeb79 --- /dev/null +++ b/unotools/inc/unotools/regpathhelper.hxx @@ -0,0 +1,74 @@ +/************************************************************************* + * + * 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: regpathhelper.hxx,v $ + * $Revision: 1.3 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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 _UNOTOOLS_REGPATHHELPER_HXX_ +#define _UNOTOOLS_REGPATHHELPER_HXX_ + +#include <rtl/ustring.hxx> + +namespace utl +{ + +/** + * This function returns a path to the user registry file. + * Search for the user registry using the following rules: + * <dl> + * <dt> 1. (for further use) search in sversion.ini (.sversionrc) for an entry + * REGISTRY_VERSION_STRING (example: UserRegistry 5.0/505=test.rdb) in the section + * [Registry]. If found, then take this value instead of the name "user.rdb". + * <dt> 2. Search in the config directory of the user for a file "user.rdb". If + * found return the full path and name of the file. If not found, retry this + * step with a dot before ".user.rdb". + * <dt> 3. If not found a new user registry with name "user.rdb" will be created in the user + * config directory. + * </dl> + *<BR> + * @author Juergen Schmidt + */ +::rtl::OUString getPathToUserRegistry(); + +/** + * This function returns a path to the system registry file. + * The system registry will always be searched in the same directory of the + * executable. The name of the system registry is "applicat.rdb". If the system + * registry was not found, then the environment variable STAR_REGISTRY will be checked. + * If this variable was set, it must contain a full path to a valid system registry. + * Search for the user registry using the following rules: + * + *<BR> + * @author Juergen Schmidt + */ + +::rtl::OUString getPathToSystemRegistry(); + +} + +#endif + diff --git a/unotools/inc/unotools/sharedunocomponent.hxx b/unotools/inc/unotools/sharedunocomponent.hxx new file mode 100644 index 000000000000..10c552c38336 --- /dev/null +++ b/unotools/inc/unotools/sharedunocomponent.hxx @@ -0,0 +1,373 @@ +/************************************************************************* + * + * 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: sharedunocomponent.hxx,v $ + * $Revision: 1.7 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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 UNOTOOLS_INC_SHAREDUNOCOMPONENT_HXX +#define UNOTOOLS_INC_SHAREDUNOCOMPONENT_HXX + +#include "unotoolsdllapi.h" + +#include <boost/shared_ptr.hpp> +#include <com/sun/star/uno/Reference.hxx> +#include <rtl/ref.hxx> + +namespace com { namespace sun { namespace star { + namespace lang { + class XComponent; + } +} } } +//............................................................................ +namespace utl +{ +//............................................................................ + + //======================================================================== + //= DisposableComponent + //======================================================================== + /** is a class which controls lifetime of an UNO component via ->XComponent::dispose + + You'll usually never use this class directly, but only as parameter for a + ->SharedUNOComponent class. + */ + class UNOTOOLS_DLLPUBLIC DisposableComponent + { + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent > + m_xComponent; + + public: + /** constructs a ->DisposableComponent instance + + @param _rxComponent + the component whose life time should be controlled by the instance. Must not be <NULL/>. + */ + DisposableComponent( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxComponent ); + + /** disposes the component represented by the instance + + The component is queried for ->XComponent(which <em>must</em> be supported), + and ->XComponent::dispose is invoked. A failure of this invocation (e.g. a thrown + exception) is silenced in release builds, and reported in debug builds. + */ + ~DisposableComponent(); + + private: + DisposableComponent(); // never implemented + DisposableComponent( const DisposableComponent& ); // never implemented + DisposableComponent& operator=( const DisposableComponent& ); // never implemented + }; + + //======================================================================== + //= CloseableComponent + //======================================================================== + class CloseableComponentImpl; + /** is a class which controls lifetime of an UNO component via ->XCloseable::close + + You'll usually never use this class directly, but only as parameter for a + ->SharedUNOComponent class. + */ + class UNOTOOLS_DLLPUBLIC CloseableComponent + { + private: + /** Our IMPL class. + */ + ::rtl::Reference< CloseableComponentImpl > m_pImpl; + + public: + /** constructs a ->CloseableComponent instance + + @param _rxComponent + the component whose life time should be controlled by the instance. Must not be <NULL/>. + */ + CloseableComponent( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxComponent ); + + /** destroys resources associated with this instance, and disposes the component + + The component is queried for ->XCloseable (which <em>must</em> be supported), + and ->XCloseable::close is invoked, with delivering the ownership. + If the invocation fails with a ->CloseVetoException, this is ignored, since in + this case the vetoing instance took the ownership. + + Any other failure will be reported in a debug version via assertion mechanisms, + and silenced in release builds. + */ + ~CloseableComponent(); + + private: + CloseableComponent(); // never implemented + CloseableComponent( const CloseableComponent& ); // never implemented + CloseableComponent& operator=( const CloseableComponent& ); // never implemented + }; + + //======================================================================== + //= SharedUNOComponent + //======================================================================== + /** is a helper class for sharing ownership of a UNO component + + If you need to share an UNO component, which normally needs a dedicated owner, + and is lifetime controlled by an explicit disposal action (not necessarily ->XComponent::dispose, + but <em>any</em> explicit method call, after which the object is considered + to be disposed), between different classes, ->SharedUNOComponent is what you need. + + Instead of passing around a <code>Reference< XFoo ></code>, and bothering + with ownership and disposal, you just use a <code>SharedUNOComponent< XFoo ></code>. + This instance can be passed around, including copying, and in nearly all respects behaves + like the original <code>Reference< XFoo ></code>. However, when the last + ->SharedUNOComponent referencing a certain <code>Reference< XFoo ></code> dies, it + will automatically get rid of the object held by this reference. + + @param INTERFACE + the UNO interface type as which the component should be held + + @param COMPONENT_HOLDER + a class which can be used to represent and dispose a UNO component. + The class must support (maybe explicit only) construction from a + <code>Reference< INTERFACE ></code>, and destruction. Upon destruction, + the class must dispose (by any suitable means) the component instance it was + constructed with. + */ + template < class INTERFACE, class COMPONENT = DisposableComponent > + class SharedUNOComponent + { + private: + typedef COMPONENT Component; + typedef ::boost::shared_ptr< Component > ComponentPointer; + + private: + ComponentPointer m_pComponent; + ::com::sun::star::uno::Reference< INTERFACE > m_xTypedComponent; + + public: + enum AssignmentMode + { + TakeOwnership, + NoTakeOwnership + }; + + public: + inline SharedUNOComponent() + { + } + + explicit inline SharedUNOComponent( const ::com::sun::star::uno::Reference< INTERFACE >& _rxComponent, AssignmentMode eMode = TakeOwnership ) + { + reset( _rxComponent, eMode ); + } + +#ifndef EXCEPTIONS_OFF + inline SharedUNOComponent( const ::com::sun::star::uno::XInterface* _pInterface, ::com::sun::star::uno::UnoReference_QueryThrow _queryThrow ) + { + set( _pInterface, _queryThrow ); + } + + inline SharedUNOComponent( const ::com::sun::star::uno::BaseReference & _rRef, ::com::sun::star::uno::UnoReference_QueryThrow _queryThrow ) + { + set( _rRef, _queryThrow ); + } + + inline SharedUNOComponent( const ::com::sun::star::uno::Any& _rAny, ::com::sun::star::uno::UnoReference_QueryThrow _queryThrow ) + { + set( _rAny, _queryThrow ); + } + + inline SharedUNOComponent( const SharedUNOComponent& _rxComponent, ::com::sun::star::uno::UnoReference_SetThrow _setThrow ) + { + set( _rxComponent, _setThrow ); + } +#endif + +// SharedUNOComponent& operator=( const ::com::sun::star::uno::Reference< INTERFACE >& _rxComponent ); + // this operator is not implemented by intention. There is no canonic ownership after this operatoer + // would hvae been applied: Should the SharedUNOComponent have the ownership of the component, + // or shouldn't it? Hard to guess, and probably wrong in 50 percent of all cases, anyway. So, + // instead of tempting clients of this class to use such a dangerous operator, we do + // not offer it at all. If you need to assign a Reference< INTERFACE > to your SharedUNOComponent, + // use the ->reset method. + + /** assigns a new component, and releases the old one + */ + void reset( const ::com::sun::star::uno::Reference< INTERFACE >& _rxComponent, AssignmentMode _eMode = TakeOwnership ); + + inline bool set( ::com::sun::star::uno::XInterface* _pInterface, ::com::sun::star::uno::UnoReference_Query _query ); + inline bool set( const ::com::sun::star::uno::BaseReference& _rRef, ::com::sun::star::uno::UnoReference_Query _query ); + inline bool set( const ::com::sun::star::uno::Any& _rAny, ::com::sun::star::uno::UnoReference_Query _query ); + +#ifndef EXCEPTIONS_OFF + inline void set( const ::com::sun::star::uno::XInterface* _pInterface, ::com::sun::star::uno::UnoReference_QueryThrow _queryThrow ); + inline void set( const ::com::sun::star::uno::BaseReference & _rRef, ::com::sun::star::uno::UnoReference_QueryThrow _queryThrow ); + inline void set( const ::com::sun::star::uno::Any& _rAny, ::com::sun::star::uno::UnoReference_QueryThrow _queryThrow ); + + inline void set( const INTERFACE* _pInterface, ::com::sun::star::uno::UnoReference_SetThrow _setThrow ); + inline void set( const ::com::sun::star::uno::Reference< INTERFACE >& _rRef, ::com::sun::star::uno::UnoReference_SetThrow _setThrow ); + inline void set( const SharedUNOComponent& _rComp, ::com::sun::star::uno::UnoReference_SetThrow _setThrow ); +#endif + + INTERFACE* SAL_CALL operator->() const; + + inline operator const ::com::sun::star::uno::Reference< INTERFACE >&() const + { + return m_xTypedComponent; + } + + inline const ::com::sun::star::uno::Reference< INTERFACE >& getTyped() const + { + return m_xTypedComponent; + } + + inline bool is() const + { + return m_xTypedComponent.is(); + } + + inline void clear() + { + m_pComponent.reset(); + m_xTypedComponent.clear(); + } + }; + + //------------------------------------------------------------------------- + template < class INTERFACE, class COMPONENT > + INTERFACE* SAL_CALL SharedUNOComponent< INTERFACE, COMPONENT >::operator->() const + { + return m_xTypedComponent.operator->(); + } + + //------------------------------------------------------------------------- + // assignments + template < class INTERFACE, class COMPONENT > + void SharedUNOComponent< INTERFACE, COMPONENT >::reset( const ::com::sun::star::uno::Reference< INTERFACE >& _rxComponent, AssignmentMode _eMode ) + { + m_pComponent.reset( _eMode == TakeOwnership ? new COMPONENT( _rxComponent ) : NULL ); + m_xTypedComponent = _rxComponent; + } + + //------------------------------------------------------------------------- + // comparison operators + template < class INTERFACE, class COMPONENT > + bool operator==( const ::com::sun::star::uno::Reference< INTERFACE >& _rLHS, const SharedUNOComponent< INTERFACE, COMPONENT >& _rRHS ) + { + return _rLHS == _rRHS.getTyped(); + } + + template < class INTERFACE, class COMPONENT > + bool operator==( const SharedUNOComponent< INTERFACE, COMPONENT >& _rLHS, const ::com::sun::star::uno::Reference< INTERFACE >& _rRHS ) + { + return _rLHS.getTyped() == _rRHS; + } + + //------------------------------------------------------------------------- + // conversion to Any + template < class INTERFACE, class COMPONENT > + inline void SAL_CALL operator <<= ( ::com::sun::star::uno::Any & rAny, const SharedUNOComponent< INTERFACE, COMPONENT >& value ) SAL_THROW( () ) + { + rAny <<= value.getTyped(); + } + + //------------------------------------------------------------------------- + template < class INTERFACE, class COMPONENT > + inline ::com::sun::star::uno::Any SAL_CALL makeAny( const SharedUNOComponent< INTERFACE, COMPONENT >& value ) SAL_THROW( () ) + { + return makeAny( value.getTyped() ); + } + +#ifndef EXCEPTIONS_OFF + //------------------------------------------------------------------------- + template < class INTERFACE, class COMPONENT > + void SharedUNOComponent< INTERFACE, COMPONENT >::set( const ::com::sun::star::uno::XInterface* _pInterface, ::com::sun::star::uno::UnoReference_QueryThrow _queryThrow ) + { + reset( ::com::sun::star::uno::Reference< INTERFACE >( _pInterface, _queryThrow ), TakeOwnership ); + } + + //------------------------------------------------------------------------- + template < class INTERFACE, class COMPONENT > + void SharedUNOComponent< INTERFACE, COMPONENT >::set( const ::com::sun::star::uno::BaseReference & _rRef, ::com::sun::star::uno::UnoReference_QueryThrow _queryThrow ) + { + reset( ::com::sun::star::uno::Reference< INTERFACE >( _rRef, _queryThrow ), TakeOwnership ); + } + + //------------------------------------------------------------------------- + template < class INTERFACE, class COMPONENT > + void SharedUNOComponent< INTERFACE, COMPONENT >::set( const ::com::sun::star::uno::Any& _rAny, ::com::sun::star::uno::UnoReference_QueryThrow _queryThrow ) + { + reset( ::com::sun::star::uno::Reference< INTERFACE >( _rAny, _queryThrow ), TakeOwnership ); + } + + //------------------------------------------------------------------------- + template < class INTERFACE, class COMPONENT > + void SharedUNOComponent< INTERFACE, COMPONENT >::set( const INTERFACE* _pInterface, ::com::sun::star::uno::UnoReference_SetThrow _setThrow ) + { + reset( ::com::sun::star::uno::Reference< INTERFACE >( _pInterface, _setThrow ), TakeOwnership ); + } + + //------------------------------------------------------------------------- + template < class INTERFACE, class COMPONENT > + void SharedUNOComponent< INTERFACE, COMPONENT >::set( const ::com::sun::star::uno::Reference< INTERFACE >& _rRef, ::com::sun::star::uno::UnoReference_SetThrow _setThrow ) + { + reset( ::com::sun::star::uno::Reference< INTERFACE >( _rRef, _setThrow ), TakeOwnership ); + } + + //------------------------------------------------------------------------- + template < class INTERFACE, class COMPONENT > + void SharedUNOComponent< INTERFACE, COMPONENT >::set( const SharedUNOComponent& _rComp, ::com::sun::star::uno::UnoReference_SetThrow _setThrow ) + { + *this = _rComp; + // provoke an exception in case the component is NULL + m_xTypedComponent.set( m_xTypedComponent, _setThrow ); + } +#endif + + //------------------------------------------------------------------------- + template < class INTERFACE, class COMPONENT > + bool SharedUNOComponent< INTERFACE, COMPONENT >::set( ::com::sun::star::uno::XInterface* _pInterface, ::com::sun::star::uno::UnoReference_Query _query ) + { + reset( ::com::sun::star::uno::Reference< INTERFACE >( _pInterface, _query ) ); + return is(); + } + + //------------------------------------------------------------------------- + template < class INTERFACE, class COMPONENT > + bool SharedUNOComponent< INTERFACE, COMPONENT >::set( const ::com::sun::star::uno::BaseReference& _rRef, ::com::sun::star::uno::UnoReference_Query _query ) + { + reset( ::com::sun::star::uno::Reference< INTERFACE >( _rRef, _query ) ); + return is(); + } + + //------------------------------------------------------------------------- + template < class INTERFACE, class COMPONENT > + bool SharedUNOComponent< INTERFACE, COMPONENT >::set( const ::com::sun::star::uno::Any& _rAny, ::com::sun::star::uno::UnoReference_Query _query ) + { + reset( ::com::sun::star::uno::Reference< INTERFACE >( _rAny, _query ) ); + return is(); + } + +//............................................................................ +} // namespace utl +//............................................................................ + +#endif // UNOTOOLS_INC_SHAREDUNOCOMPONENT_HXX diff --git a/unotools/inc/unotools/streamhelper.hxx b/unotools/inc/unotools/streamhelper.hxx new file mode 100644 index 000000000000..0dd6534eaeaa --- /dev/null +++ b/unotools/inc/unotools/streamhelper.hxx @@ -0,0 +1,119 @@ +/************************************************************************* + * + * 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: streamhelper.hxx,v $ + * $Revision: 1.6 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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 "unotools/unotoolsdllapi.h" + +#ifndef _UNOTOOLS_STREAMHELPER_HXX_ +#define _UNOTOOLS_STREAMHELPER_HXX_ +#include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/io/XSeekable.hpp> +#include <osl/mutex.hxx> +#include <cppuhelper/implbase1.hxx> +#include <cppuhelper/implbase2.hxx> +#include <tools/stream.hxx> + +namespace utl +{ + namespace stario = ::com::sun::star::io; + namespace staruno = ::com::sun::star::uno; + +/** + * The helper implementation for a using input streams based on SvLockBytes. + * + * @author Dirk Grobler + * @since 00/28/03 + */ + typedef ::cppu::WeakImplHelper2<stario::XInputStream, stario::XSeekable> InputStreamHelper_Base; + // needed for some compilers +class UNOTOOLS_DLLPUBLIC OInputStreamHelper : public InputStreamHelper_Base +{ + ::osl::Mutex m_aMutex; + SvLockBytesRef m_xLockBytes; + sal_uInt32 m_nActPos; + sal_Int32 m_nAvailable; // this is typically the chunk(buffer) size + +public: + OInputStreamHelper(const SvLockBytesRef& _xLockBytes, + sal_uInt32 _nAvailable, + sal_uInt32 _nPos = 0) + :m_xLockBytes(_xLockBytes) + ,m_nActPos(_nPos) + ,m_nAvailable(_nAvailable){} + +// staruno::XInterface + virtual void SAL_CALL acquire() throw (); + virtual void SAL_CALL release() throw (); + +// stario::XInputStream + virtual sal_Int32 SAL_CALL readBytes( staruno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead ) throw(stario::NotConnectedException, stario::BufferSizeExceededException, stario::IOException, staruno::RuntimeException); + virtual sal_Int32 SAL_CALL readSomeBytes( staruno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead ) throw(stario::NotConnectedException, stario::BufferSizeExceededException, stario::IOException, staruno::RuntimeException); + virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip ) throw(stario::NotConnectedException, stario::BufferSizeExceededException, stario::IOException, staruno::RuntimeException); + virtual sal_Int32 SAL_CALL available( ) throw(stario::NotConnectedException, stario::IOException, staruno::RuntimeException); + virtual void SAL_CALL closeInput( ) throw (stario::NotConnectedException, stario::IOException, staruno::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( ) 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); +}; + +/** + * The helper implementation for a using output streams based on SvLockBytes. + * + * @author Dirk Grobler + * @since 00/28/03 + */ +typedef ::cppu::WeakImplHelper1<stario::XOutputStream> OutputStreamHelper_Base; + // needed for some compilers +class UNOTOOLS_DLLPUBLIC OOutputStreamHelper : public OutputStreamHelper_Base +{ + ::osl::Mutex m_aMutex; + SvLockBytesRef m_xLockBytes; + sal_uInt32 m_nActPos; + +public: + OOutputStreamHelper(const SvLockBytesRef& _xLockBytes, sal_uInt32 _nPos = 0) + :m_xLockBytes(_xLockBytes) + ,m_nActPos(_nPos){} + +// staruno::XInterface + virtual void SAL_CALL acquire() throw (); + virtual void SAL_CALL release() throw (); + +// stario::XOutputStream + virtual void SAL_CALL writeBytes( const staruno::Sequence< sal_Int8 >& aData ) throw(stario::NotConnectedException, stario::BufferSizeExceededException, stario::IOException, staruno::RuntimeException); + virtual void SAL_CALL flush( ) throw(stario::NotConnectedException, stario::BufferSizeExceededException, stario::IOException, staruno::RuntimeException); + virtual void SAL_CALL closeOutput( ) throw(stario::NotConnectedException, stario::BufferSizeExceededException, stario::IOException, staruno::RuntimeException); +}; + +} // namespace utl + + +#endif // _UNOTOOLS_STREAM_WRAPPER_HXX_ + diff --git a/unotools/inc/unotools/streamsection.hxx b/unotools/inc/unotools/streamsection.hxx new file mode 100644 index 000000000000..4fa2e19b6e07 --- /dev/null +++ b/unotools/inc/unotools/streamsection.hxx @@ -0,0 +1,88 @@ +/************************************************************************* + * + * 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: streamsection.hxx,v $ + * $Revision: 1.3 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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 _UNOTOOLS_STREAMSECTION_HXX_ +#define _UNOTOOLS_STREAMSECTION_HXX_ + +#include <com/sun/star/io/XMarkableStream.hpp> +#include <com/sun/star/io/XDataInputStream.hpp> +#include <com/sun/star/io/XDataOutputStream.hpp> + +namespace utl +{ + + namespace stario = ::com::sun::star::io; + namespace staruno = ::com::sun::star::uno; + +/** implements handling for compatibly reading/writing data from/into an input/output stream. + data written in a block secured by this class should be readable by older versions which + use the same mechanism. + + @author Frank Schoenheit + @since 00/26/05 +*/ + +class OStreamSection +{ + staruno::Reference< stario::XMarkableStream > m_xMarkStream; + staruno::Reference< stario::XDataInputStream > m_xInStream; + staruno::Reference< stario::XDataOutputStream > m_xOutStream; + + sal_Int32 m_nBlockStart; + sal_Int32 m_nBlockLen; + +public: + /** starts reading of a "skippable" section of data within the given input stream<BR> + @param _rxInput the stream to read from. Must support the + <type scope="com::sun::star::io">XMarkableStream</type> interface + */ + OStreamSection(const staruno::Reference< stario::XDataInputStream >& _rxInput); + + /** starts writing of a "skippable" section of data into the given output stream + @param _rxOutput the stream the stream to write to. Must support the + <type scope="com::sun::star::io">XMarkableStream</type> interface + @param _nPresumedLength estimation for the length of the upcoming section. If greater 0, this + value will be written as section length and corrected (in the dtor) only if + needed. If you know how much bytes you are about to write, you may + want to use this param, saving some stream operations this way. + */ + OStreamSection(const staruno::Reference< stario::XDataOutputStream >& _rxOutput, sal_Int32 _nPresumedLength = 0); + + /** dtor. <BR>If constructed for writing, the section "opened" by this object will be "closed".<BR> + If constructed for reading, any remaining bytes 'til the end of the section will be skipped. + */ + ~OStreamSection(); +}; + +} // namespace utl + +#endif // _UNOTOOLS_STREAMSECTION_HXX_ + + diff --git a/unotools/inc/unotools/streamwrap.hxx b/unotools/inc/unotools/streamwrap.hxx new file mode 100644 index 000000000000..714129540412 --- /dev/null +++ b/unotools/inc/unotools/streamwrap.hxx @@ -0,0 +1,186 @@ +/************************************************************************* + * + * 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: streamwrap.hxx,v $ + * $Revision: 1.10 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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 "unotools/unotoolsdllapi.h" + +#ifndef _UTL_STREAM_WRAPPER_HXX_ +#define _UTL_STREAM_WRAPPER_HXX_ +#include <osl/mutex.hxx> +#include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/io/XSeekable.hpp> +#include <com/sun/star/io/XTruncate.hpp> +#include <com/sun/star/io/XStream.hpp> +#include <cppuhelper/implbase3.hxx> +#include <cppuhelper/implbase1.hxx> +#include <comphelper/uno3.hxx> + +class SvStream; + +namespace utl +{ + namespace stario = ::com::sun::star::io; + namespace staruno = ::com::sun::star::uno; + +//================================================================== +//= OInputStreamWrapper +//================================================================== +typedef ::cppu::WeakImplHelper1 < stario::XInputStream + > InputStreamWrapper_Base; + // needed for some compilers +/// helper class for wrapping an SvStream into an <type scope="com.sun.star.io">XInputStream</type> +class UNOTOOLS_DLLPUBLIC OInputStreamWrapper : public InputStreamWrapper_Base +{ +protected: + ::osl::Mutex m_aMutex; + SvStream* m_pSvStream; + sal_Bool m_bSvStreamOwner : 1; + OInputStreamWrapper() + { m_pSvStream = 0; m_bSvStreamOwner = sal_False; } + void SetStream(SvStream* _pStream, sal_Bool bOwner ) + { m_pSvStream = _pStream; m_bSvStreamOwner = bOwner; } + +public: + OInputStreamWrapper(SvStream& _rStream); + OInputStreamWrapper(SvStream* pStream, sal_Bool bOwner=sal_False); + virtual ~OInputStreamWrapper(); + +// UNO Anbindung + DECLARE_UNO3_AGG_DEFAULTS(OInputStreamWrapper, InputStreamWrapper_Base); + +// stario::XInputStream + virtual sal_Int32 SAL_CALL readBytes(staruno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead) throw(stario::NotConnectedException, stario::BufferSizeExceededException, staruno::RuntimeException); + virtual sal_Int32 SAL_CALL readSomeBytes(staruno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead) throw(stario::NotConnectedException, stario::BufferSizeExceededException, staruno::RuntimeException); + virtual void SAL_CALL skipBytes(sal_Int32 nBytesToSkip) throw(stario::NotConnectedException, stario::BufferSizeExceededException, staruno::RuntimeException); + virtual sal_Int32 SAL_CALL available() throw(stario::NotConnectedException, staruno::RuntimeException); + virtual void SAL_CALL closeInput() throw(stario::NotConnectedException, staruno::RuntimeException); + +protected: + /// throws a NotConnectedException if the object is not connected anymore + void checkConnected() const; + /// throws an exception according to the error flag of m_pSvStream + void checkError() const; +}; + +//================================================================== +//= OSeekableInputStreamWrapper +//================================================================== +typedef ::cppu::ImplHelper1 < ::com::sun::star::io::XSeekable + > OSeekableInputStreamWrapper_Base; +/** helper class for wrapping an SvStream into an <type scope="com.sun.star.io">XInputStream</type> + which is seekable (i.e. supports the <type scope="com.sun.star.io">XSeekable</type> interface). +*/ +class UNOTOOLS_DLLPUBLIC OSeekableInputStreamWrapper : public ::cppu::ImplInheritanceHelper1 < OInputStreamWrapper, com::sun::star::io::XSeekable > +{ +protected: + OSeekableInputStreamWrapper() {} +public: + OSeekableInputStreamWrapper(SvStream& _rStream); + OSeekableInputStreamWrapper(SvStream* _pStream, sal_Bool _bOwner = sal_False); + + // XSeekable + virtual void SAL_CALL seek( sal_Int64 _nLocation ) 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); +}; + +//================================================================== +//= OOutputStreamWrapper +//================================================================== +typedef ::cppu::WeakImplHelper1<stario::XOutputStream> OutputStreamWrapper_Base; + // needed for some compilers +class UNOTOOLS_DLLPUBLIC OOutputStreamWrapper : public OutputStreamWrapper_Base +{ +protected: + // TODO: thread safety! + SvStream& rStream; + +public: + OOutputStreamWrapper(SvStream& _rStream) :rStream(_rStream) { } + +// UNO Anbindung + DECLARE_UNO3_AGG_DEFAULTS(OOutputStreamWrapper, OutputStreamWrapper_Base); + +// stario::XOutputStream + virtual void SAL_CALL writeBytes(const staruno::Sequence< sal_Int8 >& aData) throw(stario::NotConnectedException, stario::BufferSizeExceededException, staruno::RuntimeException); + virtual void SAL_CALL flush() throw(stario::NotConnectedException, stario::BufferSizeExceededException, staruno::RuntimeException); + virtual void SAL_CALL closeOutput() throw(stario::NotConnectedException, stario::BufferSizeExceededException, staruno::RuntimeException); + +protected: + /// throws an exception according to the error flag of m_pSvStream + void checkError() const; +}; + +//================================================================== +//= OSeekableOutputStreamWrapper +//================================================================== +typedef ::cppu::ImplHelper1 < ::com::sun::star::io::XSeekable + > OSeekableOutputStreamWrapper_Base; +/** helper class for wrapping an SvStream into an <type scope="com.sun.star.io">XOutputStream</type> + which is seekable (i.e. supports the <type scope="com.sun.star.io">XSeekable</type> interface). +*/ +class UNOTOOLS_DLLPUBLIC OSeekableOutputStreamWrapper + :public OOutputStreamWrapper + ,public OSeekableOutputStreamWrapper_Base +{ +public: + OSeekableOutputStreamWrapper(SvStream& _rStream); + + // disambiguate 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( ) throw (); + virtual void SAL_CALL release( ) throw (); + + // XSeekable + virtual void SAL_CALL seek( sal_Int64 _nLocation ) 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); +}; + +class UNOTOOLS_DLLPUBLIC OStreamWrapper : public ::cppu::ImplInheritanceHelper3 < OSeekableInputStreamWrapper, com::sun::star::io::XStream, com::sun::star::io::XOutputStream, com::sun::star::io::XTruncate > +{ +public: + OStreamWrapper(SvStream& _rStream); + +// stario::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); + +// stario::XOutputStream + virtual void SAL_CALL writeBytes(const staruno::Sequence< sal_Int8 >& aData) throw(stario::NotConnectedException, stario::BufferSizeExceededException, staruno::RuntimeException); + virtual void SAL_CALL flush() throw(stario::NotConnectedException, stario::BufferSizeExceededException, staruno::RuntimeException); + virtual void SAL_CALL closeOutput() throw(stario::NotConnectedException, stario::BufferSizeExceededException, staruno::RuntimeException); + virtual void SAL_CALL truncate() throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); +}; + +} +// namespace utl + +#endif // _UTL_STREAM_WRAPPER_HXX_ + diff --git a/unotools/inc/unotools/tempfile.hxx b/unotools/inc/unotools/tempfile.hxx new file mode 100644 index 000000000000..fcd24a20be48 --- /dev/null +++ b/unotools/inc/unotools/tempfile.hxx @@ -0,0 +1,164 @@ +/************************************************************************* + * + * 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: tempfile.hxx,v $ + * $Revision: 1.10 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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 "unotools/unotoolsdllapi.h" + +#ifndef _UNOTOOLS_TEMPFILE_HXX +#define _UNOTOOLS_TEMPFILE_HXX + +#include <tools/string.hxx> +#include <tools/stream.hxx> + +namespace utl +{ + +struct TempFile_Impl; + +/** + The class TempFile gives access to temporary files in the local file system. Sometimes they are needed because a 3rd party + code has a file name based interface, or some file access has to be done locally without transferring tons of bytes to or + from a remote system. + Creating a UCB content on a TempFile is only possible if a UCP for the local file system is present. + TempFiles can always be accessed by SvFileStreams or Sot/SvStorages using the "physical" file name ( not the URL, because + this may be a non-file URL, see below ), but if a UCB content can be created, it is also possible to take the URL and use + the UCB helper classes for streams. For convenience use UcbStreamHelper. + A Tempfile always has a "physical" file name ( a file name in the local computers host notation ) but it has a + "UCB compatible" URL only if a UCP for the local file system exists. This URL may have its own URL scheme + ( not neccessarily "file://" ! ). The TempFile class methods take this into account, but other simple conversions like + the osl functions do not. + So it is a potential error to convert between the filename and the URL of a TempFile object using functions or methods + outside this class. +*/ + +class UNOTOOLS_DLLPUBLIC TempFile +{ + TempFile_Impl* pImp; + sal_Bool bKillingFileEnabled; + +protected: + +public: + /** + Create a temporary file or directory, in the default tempfile folder or if possible in a given folder. + This given folder ( the "parent" parameter ( if not NULL ) ) must be a "UCB compatible" URL. + The temporary object is created in the local file system, even if there is no UCB that can access it. + If the given folder is part of the local file system, the TempFile is created in this folder. + */ + TempFile( const String* pParent=NULL, sal_Bool bDirectory=sal_False ); + + /** + Same as above; additionally the name starts with some given characters followed by a counter ( example: + rLeadingChars="abc" means "abc0","abc1" and so on, depending on existing files in the folder ). + The extension string may be f.e. ".txt" or "", if no extension string is given, ".tmp" is used + */ + TempFile( const String& rLeadingChars, const String* pExtension=NULL, const String* pParent=NULL, + sal_Bool bDirectory=sal_False); + + /** + Same as above; additionally the name starts with some given characters followed by a counter ( example: + rLeadingChars="abc" means "abc0","abc1" and so on, depending on existing files in the folder ). + The extension string may be f.e. ".txt" or "", if no extension string is given, ".tmp" is used + @param _bStartWithZero If set to false names will be generated like "abc","abc0","abc1" + */ + TempFile( const String& rLeadingChars,sal_Bool _bStartWithZero, const String* pExtension=NULL, const String* pParent=NULL,sal_Bool bDirectory=sal_False); + + /** + TempFile will be removed from disk in dtor if EnableKillingTempFile was called before. + Temporary directories will be removed recursively in that case. + */ + ~TempFile(); + + /** + Returns sal_True if it has a valid file name. + */ + sal_Bool IsValid() const; + + /** + Returns the "UCB compatible" URL of the tempfile object. + If you want to have the "physical" file name, use the GetFileName() method of this object, because these + method uses the UCB for the conversion, but never use any external conversion functions for URLs into + "physical" names. + If no UCP is available for the local file system, an empty URL is returned. In this case you can't access + the file as a UCB content ! + */ + String GetURL() const; + + /** + Returns the "physical" name of the tempfile in host notation ( should only be used for 3rd party code + with file name interfaces ). + If you want to have the URL, use the GetURL() method of this object, but never use any external + conversion functions for "physical" names into URLs. + */ + String GetFileName() const; + + /** + Returns a stream to the tempfiles data; the stream is owned by the tempfile object, so you have to keep this + alive as long as you want to use the stream. If the TempFile object is destroyed, it also destroys the + stream object, the underlying file is only deleted if EnableKillingFile( sal_True ) has been called before! + */ + SvStream* GetStream( StreamMode eMode ); + + /** + Let the TempFile object close and destroy the owned stream object if any. + */ + void CloseStream(); + + /** + If enabled the file will be removed from disk when the dtor is called ( default is not enabled ) + */ + void EnableKillingFile( sal_Bool bEnable=sal_True ) + { bKillingFileEnabled = bEnable; } + + sal_Bool IsKillingFileEnabled() const + { return bKillingFileEnabled; } + + /** + Only create a "physical" file name for a temporary file that would be valid at that moment. + Should only be used for 3rd party code with a file name interface that wants to create the file by itself. + If you want to convert file name into a URL, always use class LocalFileHelper, but never use any + conversion functions of osl. + */ + static String CreateTempName( const String* pParent=NULL ); + + /** + The TempNameBaseDirectory is a subfolder in the folder that is passed as a "physical" file name in the + SetTempNameBaseDirectory method. + This subfolder will be used if a TempFile or TempName is created without a parent name or a parent name + that does not belong to the local file system. + The caller of the SetTempNameBase is responsible for deleting this folder and all temporary files in it. + The return value of both methods is the complete "physical" name of the tempname base folder. + It is not a URL because alle URLs must be "UCB compatible", so there may be no suitable URL at all. + */ + static String SetTempNameBaseDirectory( const String &rBaseName ); + static String GetTempNameBaseDirectory(); +}; + +} + +#endif diff --git a/unotools/inc/unotools/textsearch.hxx b/unotools/inc/unotools/textsearch.hxx new file mode 100644 index 000000000000..cbcaa9829674 --- /dev/null +++ b/unotools/inc/unotools/textsearch.hxx @@ -0,0 +1,199 @@ +/************************************************************************* + * + * 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: textsearch.hxx,v $ + * $Revision: 1.11 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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 "unotools/unotoolsdllapi.h" + +#ifndef _UNOTOOLS_TEXTSEARCH_HXX +#define _UNOTOOLS_TEXTSEARCH_HXX +#include <i18npool/lang.h> +#include <tools/string.hxx> +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/lang/Locale.hpp> +#include <com/sun/star/util/XTextSearch.hpp> +#include <com/sun/star/util/SearchOptions.hpp> + +// Forward-Deklaration +class CharClass; + +namespace com { + namespace sun { + namespace star { + namespace util { + struct SearchResult; + } + } + } +} + +// ............................................................................ +namespace utl +{ +// ............................................................................ + +// SS - Klasse fuers Suchen +class UNOTOOLS_DLLPUBLIC SearchParam +{ +public: + enum SearchType{ SRCH_NORMAL, SRCH_REGEXP, SRCH_LEVDIST }; + +private: + String sSrchStr; // the search string + String sReplaceStr; // the replace string + + SearchType eSrchType; // search normal/regular/LevDist + + int bWordOnly : 1; // used by normal search + int bSrchInSel : 1; // search only in the selection + int bCaseSense : 1; // + + // values for the "weight Levenshtein-Distance" + int bLEV_Relaxed : 1; + int nLEV_OtherX; + int nLEV_ShorterY; + int nLEV_LongerZ; + + // asian flags - used for the transliteration + long nTransliterationFlags; + +public: + SearchParam( const String &rText, + SearchType eSrchType = SearchParam::SRCH_NORMAL, + BOOL bCaseSens = TRUE, + BOOL bWrdOnly = FALSE, + BOOL bSrchInSel = FALSE ); + SearchParam( const SearchParam& ); + + const String& GetSrchStr() const { return sSrchStr; } + const String& GetReplaceStr() const { return sReplaceStr; } + SearchType GetSrchType() const { return eSrchType; } + + int IsCaseSensitive() const { return bCaseSense; } + int IsSrchInSelection() const { return bSrchInSel; } + int IsSrchWordOnly() const { return bWordOnly; } + + + void SetSrchStr( const String& rStr ) { sSrchStr = rStr; } + void SetReplaceStr( const String& rStr ) { sReplaceStr = rStr; } + void SetSrchType( SearchType eType ) { eSrchType = eType; } + + void SetCaseSensitive( int bFlag ) { bCaseSense = bFlag; } + void SetSrchInSelection( int bFlag ) { bSrchInSel = bFlag; } + void SetSrchWordOnly( int bFlag ) { bWordOnly = bFlag; } + + int IsSrchRelaxed() const { return bLEV_Relaxed; } + int GetLEVOther() const { return nLEV_OtherX; } + int GetLEVShorter() const { return nLEV_ShorterY; } + int GetLEVLonger() const { return nLEV_LongerZ; } + + void SetSrchRelaxed( int bFlag ) { bLEV_Relaxed = bFlag; } + void SetLEVOther( int nValue ) { nLEV_OtherX = nValue; } + void SetLEVShorter( int nValue ) { nLEV_ShorterY = nValue; } + void SetLEVLonger( int nValue ) { nLEV_LongerZ = nValue; } + + long GetTransliterationFlags() const { return nTransliterationFlags; } + void SetTransliterationFlags( long nValue ) { nTransliterationFlags = nValue; } +}; + +// Klasse zum Suchen eines Strings in einem String. +// Unterstuetzt werden folgende Verfahren: +// - normalen Text (Bayer/Moore) +// - regulaere Ausdruecke +// - gewichtete Levenshtein Distanz +// +// Es kann Vorwaerts und Rueckwaerts gesucht werden! + +class UNOTOOLS_DLLPUBLIC TextSearch +{ + struct CachedTextSearch + { + ::osl::Mutex mutex; + ::com::sun::star::util::SearchOptions Options; + ::com::sun::star::uno::Reference< ::com::sun::star::util::XTextSearch > xTextSearch; + }; + + static CachedTextSearch maCache; + + static ::com::sun::star::uno::Reference< ::com::sun::star::util::XTextSearch > + getXTextSearch( const ::com::sun::star::util::SearchOptions& rPara ); + + com::sun::star::uno::Reference < com::sun::star::util::XTextSearch > + xTextSearch; + + void Init( const SearchParam & rParam, + const ::com::sun::star::lang::Locale& rLocale ); + +public: + // rText ist der zusuchende String + // this first two CTORs are deprecated! + TextSearch( const SearchParam & rPara, LanguageType nLanguage ); + TextSearch( const SearchParam & rPara, const CharClass& rCClass ); + + TextSearch( const ::com::sun::star::util::SearchOptions& rPara ); + ~TextSearch(); + + /* search in the (selected) text the search string: + rScrTxt - the text, in in which we search + pStart - start position for the search + pEnde - end position for the search + + RETURN values == TRUE: something is found + - pStart start pos of the found text, + - pStart end pos of the found text, + - pSrchResult - the search result with all found + positions. Is only filled with more positions + if the regular expression handles groups. + + == FALSE: nothing found, pStart,pEnde unchanged. + + Definitions: start pos always inclusive, end pos always exclusive! + The position must always in the right direction! + search forward: start <= end + search backward: end <= start + */ + int SearchFrwrd( const String &rStr, + xub_StrLen* pStart, xub_StrLen* pEnde, + ::com::sun::star::util::SearchResult* pSrchResult = 0 ); + int SearchBkwrd( const String &rStr, + xub_StrLen* pStart, xub_StrLen* pEnde, + ::com::sun::star::util::SearchResult* pSrchResult = 0 ); + + void SetLocale( const ::com::sun::star::util::SearchOptions& rOpt, + const ::com::sun::star::lang::Locale& rLocale ); + + /* replace back references in the replace string by the sub expressions from the search result */ + void ReplaceBackReferences( String& rReplaceStr, const String &rStr, const ::com::sun::star::util::SearchResult& rResult ); + +}; + +// ............................................................................ +} // namespace utl +// ............................................................................ + +#endif + diff --git a/unotools/inc/unotools/transliterationwrapper.hxx b/unotools/inc/unotools/transliterationwrapper.hxx new file mode 100644 index 000000000000..3c5baf56b801 --- /dev/null +++ b/unotools/inc/unotools/transliterationwrapper.hxx @@ -0,0 +1,148 @@ +/************************************************************************* + * + * 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: transliterationwrapper.hxx,v $ + * $Revision: 1.15 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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 "unotools/unotoolsdllapi.h" + +#ifndef _UNOTOOLS_TRANSLITERATIONWRAPPER_HXX +#define _UNOTOOLS_TRANSLITERATIONWRAPPER_HXX +#include <tools/string.hxx> +#include <tools/solar.h> +#include <com/sun/star/i18n/XExtendedTransliteration.hpp> + +namespace com { namespace sun { namespace star { + namespace lang { + class XMultiServiceFactory; + } +}}} + +namespace utl +{ + +class UNOTOOLS_DLLPUBLIC TransliterationWrapper +{ + ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XMultiServiceFactory > xSMgr; + ::com::sun::star::uno::Reference< + ::com::sun::star::i18n::XExtendedTransliteration > xTrans; + ::com::sun::star::lang::Locale aLocale; + sal_uInt32 nType; + sal_uInt16 nLanguage; + mutable sal_Bool bFirstCall; + + // not implemented, prevent usage + TransliterationWrapper( const TransliterationWrapper& ); + TransliterationWrapper& operator=( const TransliterationWrapper& ); + + void loadModuleImpl() const; + void setLanguageLocaleImpl( sal_uInt16 nLang ); + +public: + TransliterationWrapper( const ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XMultiServiceFactory > & xSF, + sal_uInt32 nType ); + + ~TransliterationWrapper(); + + // get current Locale / Language + const ::com::sun::star::lang::Locale& getLocale() const { return aLocale;} + sal_uInt16 getLanguage() const { return nLanguage; } + + sal_uInt32 getType() const { return nType; } + + sal_Bool needLanguageForTheMode() const; + + /** set a new language and load the corresponding transliteration module if + needed for the mode set with nType in the ctor */ + void loadModuleIfNeeded( sal_uInt16 nLang ); + + /** Load the transliteration module specified by rModuleName, which has to + be the UNO service implementation name that is expanded to the full UNO + service implementation name, for example, "NumToCharKanjiShort_ja_JP" + expands to + "com.sun.star.i18n.Transliteration.NumToCharKanjiShort_ja_JP". + @ATTENTION! + This method ignores the mode type set with the constructor and + interferes with the loadModuleIfNeeded() method and the transliterate() + method that gets a LanguageType passed as parameter. Using one of + those may load a different module and overwrite this setting. Only the + transliterate() method that takes no LanguageType parameter may be used + for a specific module loaded with this method. */ + void loadModuleByImplName( const String& rModuleName, sal_uInt16 nLang ); + + /** This transliteration method corresponds with the loadModuleByImplName() + method. It relies on a module being loaded and does not try load one. + If for any reason the string can't be transliterated the original + string is returned. */ + String transliterate( const String& rStr, + xub_StrLen nStart, xub_StrLen nLen, + ::com::sun::star::uno::Sequence <sal_Int32>* pOffset ) const; + + // Wrapper implementations of class Transliteration + String transliterate( const String& rStr, sal_uInt16 nLanguage, + xub_StrLen nStart, xub_StrLen nLen, + ::com::sun::star::uno::Sequence <sal_Int32>* pOffset ); + + /** If two strings are equal per this transliteration. + Returns the number of matched code points in any case, even if strings + are not equal, for example: + equals( "a", 0, 1, nMatch1, "aaa", 0, 3, nMatch2 ) + returns false and nMatch:=1 and nMatch2:=1 + equals( "aab", 0, 3, nMatch1, "aaa", 0, 3, nMatch2 ) + returns false and nMatch:=2 and nMatch2:=2 + */ + sal_Bool equals( + const String& rStr1, sal_Int32 nPos1, sal_Int32 nCount1, sal_Int32& nMatch1, + const String& rStr2, sal_Int32 nPos2, sal_Int32 nCount2, sal_Int32& nMatch2 ) const; + + sal_Int32 compareSubstring( + const String& rStr1, sal_Int32 nOff1, sal_Int32 nLen1, + const String& rStr2, sal_Int32 nOff2, sal_Int32 nLen2 ) const; + + sal_Int32 compareString( const String& rStr1, const String& rStr2 ) const; + + + // helpers + + /** If two strings are really equal as per this translation, and not just + one string is matching the start of the other. Use this method instead + of compareString()==0 because it is much faster. + */ + sal_Bool isEqual( const String& rStr1, const String& rStr2 ) const; + + /** If string rStr1 matches the start of string rStr2, i.e. "a" in "aaa" + */ + sal_Bool isMatch( const String& rStr1, const String& rStr2 ) const; + +}; + +// ............................................................................ +} // namespace utl +// ............................................................................ + +#endif diff --git a/unotools/inc/unotools/ucbhelper.hxx b/unotools/inc/unotools/ucbhelper.hxx new file mode 100644 index 000000000000..59536df150c0 --- /dev/null +++ b/unotools/inc/unotools/ucbhelper.hxx @@ -0,0 +1,91 @@ +/************************************************************************* + * + * 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: ucbhelper.hxx,v $ + * $Revision: 1.11 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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 "unotools/unotoolsdllapi.h" + +#ifndef _UNOTOOLS_UCBHELPER_HXX +#define _UNOTOOLS_UCBHELPER_HXX + +// include --------------------------------------------------------------- +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/ucb/NameClash.hpp> +#include <com/sun/star/ucb/XContentProvider.hpp> + +#include <tools/string.hxx> + +namespace ucbhelper +{ + class Content; +} + +namespace utl +{ + class UNOTOOLS_DLLPUBLIC UCBContentHelper + { + private: + static sal_Bool Transfer_Impl( const String& rSource, const String& rDest, sal_Bool bMoveData, + sal_Int32 nNameClash ); + + public: + static sal_Bool IsDocument( const String& rContent ); + static sal_Bool IsFolder( const String& rContent ); + static sal_Bool GetTitle( const String& rContent, String& rTitle ); + static sal_Bool Kill( const String& rContent ); + + static ::com::sun::star::uno::Any GetProperty( const String& rURL, const ::rtl::OUString& rName ); + + static ::com::sun::star::uno::Sequence< ::rtl::OUString > + GetFolderContents( const String& rFolder, sal_Bool bFolder, sal_Bool bSorted = sal_False ); + static ::com::sun::star::uno::Sequence< ::rtl::OUString > GetResultSet( const String& rURL ); + + static sal_Bool CopyTo( const String& rSource, const String& rDest ); + static sal_Bool MoveTo( const String& rSource, const String& rDest, sal_Int32 nNameClash = com::sun::star::ucb::NameClash::ERROR ); + + static sal_Bool CanMakeFolder( const String& rFolder ); + static sal_Bool MakeFolder( const String& rFolder, sal_Bool bNewOnly = sal_False ); + static sal_Bool MakeFolder( ::ucbhelper::Content& rParent, + const String& rTitle, + ::ucbhelper::Content& rNewFolder, + sal_Bool bNewOnly = sal_False ); + static sal_Bool HasParentFolder( const String& rFolder ); + + static ULONG GetSize( const String& rContent ); + static sal_Bool IsYounger( const String& rIsYoung, const String& rIsOlder ); + + static sal_Bool Exists( const String& rContent ); + static sal_Bool FindInPath( const String& rPath, const String& rName, String& rFile, char cDelim = ';', BOOL bAllowWildCards = TRUE ); + static sal_Bool Find( const String& rFolder, const String& rName, String& rFile, BOOL bAllowWildCards = FALSE ); + static sal_Bool IsSubPath( const ::rtl::OUString& rPath, const ::rtl::OUString& rChildCandidate, const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContentProvider >& xContentProvider = ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContentProvider >() ); + }; +} + +#endif + + diff --git a/unotools/inc/unotools/ucblockbytes.hxx b/unotools/inc/unotools/ucblockbytes.hxx new file mode 100644 index 000000000000..5600cfdb16f4 --- /dev/null +++ b/unotools/inc/unotools/ucblockbytes.hxx @@ -0,0 +1,225 @@ +/************************************************************************* + * + * 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: ucblockbytes.hxx,v $ + * $Revision: 1.27 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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 _UNTOOLS_UCBLOCKBYTES_HXX +#define _UNTOOLS_UCBLOCKBYTES_HXX + +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/ucb/XContent.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include "unotools/unotoolsdllapi.h" + +#include <vos/thread.hxx> +#include <vos/conditn.hxx> +#include <vos/mutex.hxx> +#include <tools/stream.hxx> +#include <tools/link.hxx> +#include <tools/errcode.hxx> +#include <tools/datetime.hxx> + +namespace com +{ + namespace sun + { + namespace star + { + namespace task + { + class XInteractionHandler; + } + namespace io + { + class XStream; + class XInputStream; + class XOutputStream; + class XSeekable; + } + namespace ucb + { + class XContent; + } + namespace beans + { + struct PropertyValue; + } + } + } +} + +namespace utl +{ +SV_DECL_REF( UcbLockBytes ) + +class UcbLockBytesHandler : public SvRefBase +{ + sal_Bool m_bActive; +public: + enum LoadHandlerItem + { + DATA_AVAILABLE, + DONE, + CANCEL + }; + + UcbLockBytesHandler() + : m_bActive( sal_True ) + {} + + virtual void Handle( LoadHandlerItem nWhich, UcbLockBytesRef xLockBytes ) = 0; + void Activate( BOOL bActivate = sal_True ) { m_bActive = bActivate; } + sal_Bool IsActive() const { return m_bActive; } +}; + +SV_DECL_IMPL_REF( UcbLockBytesHandler ) + +#define NS_UNO ::com::sun::star::uno +#define NS_IO ::com::sun::star::io +#define NS_UCB ::com::sun::star::ucb +#define NS_BEANS ::com::sun::star::beans +#define NS_TASK ::com::sun::star::task + +class UNOTOOLS_DLLPUBLIC UcbLockBytes : public virtual SvLockBytes +{ + vos::OCondition m_aInitialized; + vos::OCondition m_aTerminated; + vos::OMutex m_aMutex; + + String m_aContentType; + String m_aRealURL; + DateTime m_aExpireDate; + + NS_UNO::Reference < NS_IO::XInputStream > m_xInputStream; + NS_UNO::Reference < NS_IO::XOutputStream > m_xOutputStream; + NS_UNO::Reference < NS_IO::XSeekable > m_xSeekable; + void* m_pCommandThread; // is alive only for compatibility reasons + UcbLockBytesHandlerRef m_xHandler; + + sal_uInt32 m_nRead; + sal_uInt32 m_nSize; + ErrCode m_nError; + + sal_Bool m_bTerminated : 1; + sal_Bool m_bDontClose : 1; + sal_Bool m_bStreamValid : 1; + + DECL_LINK( DataAvailHdl, void * ); + + UcbLockBytes( UcbLockBytesHandler* pHandler=NULL ); +protected: + virtual ~UcbLockBytes (void); + +public: + // properties: Referer, PostMimeType + static UcbLockBytesRef CreateLockBytes( const NS_UNO::Reference < NS_UCB::XContent >& xContent, + const ::rtl::OUString& rReferer, + const ::rtl::OUString& rMediaType, + const NS_UNO::Reference < NS_IO::XInputStream >& xPostData, + const NS_UNO::Reference < NS_TASK::XInteractionHandler >& xInter, + UcbLockBytesHandler* pHandler=0 ); + + static UcbLockBytesRef CreateLockBytes( const NS_UNO::Reference < NS_UCB::XContent >& xContent, + const NS_UNO::Sequence < NS_BEANS::PropertyValue >& rProps, + StreamMode eMode, + const NS_UNO::Reference < NS_TASK::XInteractionHandler >& xInter, + UcbLockBytesHandler* pHandler=0 ); + + static UcbLockBytesRef CreateInputLockBytes( const NS_UNO::Reference < NS_IO::XInputStream >& xContent ); + static UcbLockBytesRef CreateLockBytes( const NS_UNO::Reference < NS_IO::XStream >& xContent ); + + // SvLockBytes + virtual void SetSynchronMode (BOOL bSynchron); + virtual ErrCode ReadAt ( ULONG nPos, void *pBuffer, ULONG nCount, ULONG *pRead) const; + virtual ErrCode WriteAt ( ULONG, const void*, ULONG, ULONG *pWritten); + virtual ErrCode Flush (void) const; + virtual ErrCode SetSize (ULONG); + virtual ErrCode Stat ( SvLockBytesStat *pStat, SvLockBytesStatFlag) const; + + void SetError( ErrCode nError ) + { m_nError = nError; } + + ErrCode GetError() const + { return m_nError; } + + void Cancel(); // is alive only for compatibility reasons + + // the following properties are available when and after the first DataAvailable callback has been executed + String GetContentType() const; + String GetRealURL() const; + DateTime GetExpireDate() const; + + // calling this method delegates the responsibility to call closeinput to the caller! + NS_UNO::Reference < NS_IO::XInputStream > getInputStream(); + NS_UNO::Reference < NS_IO::XStream > getStream(); + +#if _SOLAR__PRIVATE + sal_Bool setInputStream_Impl( const NS_UNO::Reference < NS_IO::XInputStream > &rxInputStream, + sal_Bool bSetXSeekable = sal_True ); + sal_Bool setStream_Impl( const NS_UNO::Reference < NS_IO::XStream > &rxStream ); + void terminate_Impl (void); + + NS_UNO::Reference < NS_IO::XInputStream > getInputStream_Impl() const + { + vos::OGuard aGuard( SAL_CONST_CAST(UcbLockBytes*, this)->m_aMutex ); + return m_xInputStream; + } + + NS_UNO::Reference < NS_IO::XOutputStream > getOutputStream_Impl() const + { + vos::OGuard aGuard( SAL_CONST_CAST(UcbLockBytes*, this)->m_aMutex ); + return m_xOutputStream; + } + + NS_UNO::Reference < NS_IO::XSeekable > getSeekable_Impl() const + { + vos::OGuard aGuard( SAL_CONST_CAST(UcbLockBytes*, this)->m_aMutex ); + return m_xSeekable; + } + + sal_Bool hasInputStream_Impl() const + { + vos::OGuard aGuard( SAL_CONST_CAST(UcbLockBytes*, this)->m_aMutex ); + return m_xInputStream.is(); + } + + void setDontClose_Impl() + { m_bDontClose = sal_True; } + + void SetContentType_Impl( const String& rType ) { m_aContentType = rType; } + void SetRealURL_Impl( const String& rURL ) { m_aRealURL = rURL; } + void SetExpireDate_Impl( const DateTime& rDateTime ) { m_aExpireDate = rDateTime; } + void SetStreamValid_Impl(); +#endif +}; + +SV_IMPL_REF( UcbLockBytes ); + +} + +#endif diff --git a/unotools/inc/unotools/ucbstreamhelper.hxx b/unotools/inc/unotools/ucbstreamhelper.hxx new file mode 100644 index 000000000000..4bc9686ff587 --- /dev/null +++ b/unotools/inc/unotools/ucbstreamhelper.hxx @@ -0,0 +1,86 @@ +/************************************************************************* + * + * 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: ucbstreamhelper.hxx,v $ + * $Revision: 1.11 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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 _UNTOOLS_UCBSTREAMHELPER_HXX +#define _UNTOOLS_UCBSTREAMHELPER_HXX + +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/io/XStream.hpp> +#include "unotools/unotoolsdllapi.h" + +#include <tools/stream.hxx> + +namespace com +{ + namespace sun + { + namespace star + { + namespace task + { + class XInteractionHandler; + } + namespace io + { + class XStream; + class XInputStream; + } + } + } +} + +#define NS_UNO ::com::sun::star::uno +#define NS_IO ::com::sun::star::io +#define NS_TASK ::com::sun::star::task + +class String; +namespace utl +{ + class UcbLockBytesHandler; + + class UNOTOOLS_DLLPUBLIC UcbStreamHelper : public SvStream + { + public: + static SvStream* CreateStream( const String& rFileName, StreamMode eOpenMode, + UcbLockBytesHandler* pHandler=0, sal_Bool bForceSynchron=sal_True ); + static SvStream* CreateStream( const String& rFileName, StreamMode eOpenMode, + NS_UNO::Reference < NS_TASK::XInteractionHandler >, + UcbLockBytesHandler* pHandler=0, sal_Bool bForceSynchron=sal_True ); + static SvStream* CreateStream( const String& rFileName, StreamMode eOpenMode, + sal_Bool bFileExists, + UcbLockBytesHandler* pHandler=0, sal_Bool bForceSynchron=sal_True ); + static SvStream* CreateStream( NS_UNO::Reference < NS_IO::XInputStream > xStream ); + static SvStream* CreateStream( NS_UNO::Reference < NS_IO::XStream > xStream ); + static SvStream* CreateStream( NS_UNO::Reference < NS_IO::XInputStream > xStream, sal_Bool bCloseStream ); + static SvStream* CreateStream( NS_UNO::Reference < NS_IO::XStream > xStream, sal_Bool bCloseStream ); + }; +} + +#endif diff --git a/unotools/inc/unotools/unotoolsdllapi.h b/unotools/inc/unotools/unotoolsdllapi.h new file mode 100644 index 000000000000..6aefb84432ec --- /dev/null +++ b/unotools/inc/unotools/unotoolsdllapi.h @@ -0,0 +1,44 @@ +/************************************************************************* + * + * 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: unotoolsdllapi.h,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. + * + ************************************************************************/ + +#ifndef INCLUDED_UNOTOOLSDLLAPI_H +#define INCLUDED_UNOTOOLSDLLAPI_H + +#include "sal/types.h" + +#if defined(UNOTOOLS_DLLIMPLEMENTATION) +#define UNOTOOLS_DLLPUBLIC SAL_DLLPUBLIC_EXPORT +#else +#define UNOTOOLS_DLLPUBLIC SAL_DLLPUBLIC_IMPORT +#endif +#define UNOTOOLS_DLLPRIVATE SAL_DLLPRIVATE + +#endif /* INCLUDED_UNOTOOLSDLLAPI_H */ + diff --git a/unotools/inc/unotools/unotunnelhelper.hxx b/unotools/inc/unotools/unotunnelhelper.hxx new file mode 100644 index 000000000000..cfe6084577e6 --- /dev/null +++ b/unotools/inc/unotools/unotunnelhelper.hxx @@ -0,0 +1,199 @@ +/************************************************************************* + * + * 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: unotunnelhelper.hxx,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. + * + ************************************************************************/ + +#ifndef _UNOTOOLS_UNOTUNNELHLP_HXX +#define _UNOTOOLS_UNOTUNNELHLP_HXX + +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/lang/XUnoTunnel.hpp> +#include <rtl/uuid.h> +#include <rtl/memory.h> + +#ifndef _CPPUHELPER_EXTRACT_HXX_ +#include <cppuhelper/extract.hxx> +#endif + +namespace utl +{ +namespace staruno = ::com::sun::star::uno; +namespace starlang = ::com::sun::star::lang; + +//----------------------------------------------------------------------------------------------------------- +// to use the following, define +// sal_Bool getTunneledImplementation(Classname*& pObjImpl, staruno::Reference<starlang::XUnoTunnel> const& xObj); + +template <class Classname> +sal_Bool getImplementation(Classname*& pImpl, staruno::Reference<starlang::XUnoTunnel> const& xTunnel) + throw(staruno::RuntimeException) +{ + if (xTunnel.is()) + return getTunneledImplementation(pImpl, xTunnel); + + pImpl = 0; + return sal_False; +} + +template <class Classname> +sal_Bool getImplementation(Classname*& pImpl, staruno::Reference<staruno::XInterface> const& xObj) + throw(staruno::RuntimeException) +{ + staruno::Reference<starlang::XUnoTunnel> xTunnel(xObj,staruno::UNO_QUERY); + if (xTunnel.is()) + return getTunneledImplementation(pImpl, xTunnel); + + pImpl = 0; + return sal_False; +} + +template <class Classname> +sal_Bool getImplementation(Classname*& pImpl, staruno::Any const& aObj) + throw(staruno::RuntimeException) +{ + staruno::Reference<starlang::XUnoTunnel> xTunnel; + if (cppu::extractInterface(xTunnel, aObj)) + getTunneledImplementation(pImpl, xTunnel); + + pImpl = 0; + return sal_False; +} + +template <class Classname> +sal_Bool getImplementation(Classname*& pImpl, starlang::XUnoTunnel* pObj) + throw(staruno::RuntimeException) +{ + if (pObj) + { + staruno::Reference<starlang::XUnoTunnel> xTunnel(pObj); + return getTunneledImplementation(pImpl, xTunnel); + } + + pImpl = 0; + return sal_False; +} + +//----------------------------------------------------------------------------------------------------------- + +class UnoTunnelId +{ + sal_Int8 tunnelId[16]; +public: + UnoTunnelId(sal_Bool bUseMAC = sal_True) throw() + { + rtl_createUuid(reinterpret_cast<sal_uInt8*>(tunnelId),0,bUseMAC); + } + + staruno::Sequence<sal_Int8> getId() const throw(staruno::RuntimeException) + { + return staruno::Sequence<sal_Int8>(tunnelId, sizeof(tunnelId)); + } + + sal_Bool equalTo(staruno::Sequence<sal_Int8> const& rIdentifier) throw() + { + return rIdentifier.getLength() == sizeof(tunnelId) && + rtl_compareMemory(tunnelId, rIdentifier.getConstArray(), sizeof(tunnelId)) == 0; + } + + sal_Int8 const (&getIdBytes() const)[16] { return tunnelId; } +}; + +//----------------------------------------------------------------------------------------------------------- +template<class Classname> +class UnoTunnelImplBase +{ +protected: + Classname* ThisImplementation() throw() { return static_cast<Classname*>(this); } + + sal_Int64 makeUnoSomething() throw() + { + return reinterpret_cast<sal_Int64>(static_cast<void*>(ThisImplementation())); + } + + static Classname* extractUnoSomething(sal_Int64 nSomething) throw() + { + if (nSomething != sal_Int64()) + return static_cast<Classname*>(reinterpret_cast<void*>(nSomething)); + + return NULL; + } +#ifdef LINUX +public: +#endif + static Classname* + extractUnoSomething( + staruno::Reference<starlang::XUnoTunnel> const& xObj, + staruno::Sequence<sal_Int8> const& rMyTunnelId + ) + throw(staruno::RuntimeException) + { + return xObj.is() ? extractUnoSomething(xObj->getSomething(rMyTunnelId)) : NULL; + } +}; +//----------------------------------------------------------------------------------------------------------- + + +template<class Classname> +class UnoTunnelHelper : public UnoTunnelImplBase<Classname> +{ +protected: + static UnoTunnelId s_aTunnelId; + + sal_Int64 getSomething(staruno::Sequence<sal_Int8> const& rTunnelId) throw() + { + if (s_aTunnelId.equalTo(rTunnelId)) + return this->makeUnoSomething(); + else + return sal_Int64(); + } +public: + static staruno::Sequence<sal_Int8> getImplementationTunnelId() + throw(staruno::RuntimeException) + { + return s_aTunnelId.getId(); + } +#ifndef LINUX + friend sal_Bool getTunneledImplementation(Classname*& pImpl, staruno::Reference<starlang::XUnoTunnel> const& xObj) + throw(staruno::RuntimeException) + { + pImpl = UnoTunnelHelper<Classname>::UnoTunnelHelper<Classname>::extractUnoSomething( xObj, UnoTunnelHelper<Classname>::getImplementationTunnelId() ); + + return pImpl != 0; + } +#endif +}; +template<class Classname> +UnoTunnelId UnoTunnelHelper<Classname>::s_aTunnelId; + + +//----------------------------------------------------------------------------------------------------------- +} // namespace utl + +#endif // _UNOTOOLS_UNOTUNNELHLP_HXX + diff --git a/unotools/prj/build.lst b/unotools/prj/build.lst new file mode 100644 index 000000000000..bb63ba975ed2 --- /dev/null +++ b/unotools/prj/build.lst @@ -0,0 +1,12 @@ +ut unotools : comphelper cppuhelper offuh tools ucbhelper NULL +ut unotools usr1 - all ut_mkout NULL +ut unotools\inc nmake - all ut_inc NULL +ut unotools\source\misc nmake - all ut_misc ut_config ut_inc NULL +ut unotools\source\streaming nmake - all ut_streaming ut_inc NULL +ut unotools\source\config nmake - all ut_config ut_i18n ut_inc NULL +ut unotools\source\ucbhelper nmake - all ut_ucbhelper ut_inc NULL +ut unotools\source\processfactory nmake - all ut_procfact ut_inc NULL +ut unotools\source\i18n nmake - all ut_i18n ut_inc NULL +ut unotools\source\property nmake - all ut_property ut_inc NULL +ut unotools\source\accessibility nmake - all ut_accessibility ut_inc NULL +ut unotools\util nmake - all ut_util ut_config ut_i18n ut_misc ut_procfact ut_streaming ut_ucbhelper ut_property ut_accessibility NULL diff --git a/unotools/prj/d.lst b/unotools/prj/d.lst new file mode 100644 index 000000000000..ad8a764055b2 --- /dev/null +++ b/unotools/prj/d.lst @@ -0,0 +1,11 @@ +..\%__SRC%\bin\*.dll %_DEST%\bin%_EXT%\*.dll +..\%__SRC%\lib\*.lib %_DEST%\lib%_EXT%\*.lib +..\%__SRC%\lib\lib*.so %_DEST%\lib%_EXT% +..\%__SRC%\lib\*.dylib %_DEST%\lib%_EXT%\*.dylib +..\%__SRC%\lib\*.sl %_DEST%\lib%_EXT%\*.sl +..\%__SRC%\bin\*.bin %_DEST%\bin%_EXT%\*.bin +..\%__SRC%\inc\*.bin %_DEST%\bin%_EXT%\*.bin + +mkdir: %_DEST%\inc%_EXT%\unotools +..\inc\unotools\*.hxx %_DEST%\inc%_EXT%\unotools\*.hxx +..\inc\unotools\unotoolsdllapi.h %_DEST%\inc%_EXT%\unotools\unotoolsdllapi.h diff --git a/unotools/qa/complex/tempfile/TempFileTest.java b/unotools/qa/complex/tempfile/TempFileTest.java new file mode 100644 index 000000000000..cc3cc19231b0 --- /dev/null +++ b/unotools/qa/complex/tempfile/TempFileTest.java @@ -0,0 +1,34 @@ +/************************************************************************* + * + * 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: TempFileTest.java,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. + * + ************************************************************************/ +package complex.tempfile; + +public interface TempFileTest { + boolean test(); +} diff --git a/unotools/qa/complex/tempfile/TempFileUnitTest.java b/unotools/qa/complex/tempfile/TempFileUnitTest.java new file mode 100644 index 000000000000..3bac1809af7b --- /dev/null +++ b/unotools/qa/complex/tempfile/TempFileUnitTest.java @@ -0,0 +1,88 @@ +/************************************************************************* + * + * 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: TempFileUnitTest.java,v $ + * $Revision: 1.3 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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.tempfile; + +import complexlib.ComplexTestCase; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.ucb.XSimpleFileAccess; +import com.sun.star.uno.UnoRuntime; + +/* Document. + */ + +public class TempFileUnitTest extends ComplexTestCase { + private XMultiServiceFactory m_xMSF = null; + private XSimpleFileAccess m_xSFA = null; + + public String[] getTestMethodNames() { + return new String[] { + "ExecuteTest01", + "ExecuteTest02"}; + } + + public String getTestObjectName() { + return "TempFileUnitTest"; + } + + public void before() { + m_xMSF = (XMultiServiceFactory)param.getMSF(); + if ( m_xMSF == null ) { + failed ( "Cannot create service factory!" ); + } + try + { + Object oSFA = m_xMSF.createInstance( "com.sun.star.ucb.SimpleFileAccess" ); + m_xSFA = ( XSimpleFileAccess )UnoRuntime.queryInterface( XSimpleFileAccess.class, + oSFA ); + } + catch ( Exception e ) + { + failed ( "Cannot get simple file access! Exception: " + e); + } + if ( m_xSFA == null ) { + failed ( "Cannot get simple file access!" ); + } + } + + public void after() { + m_xMSF = null; + m_xSFA = null; + } + + public void ExecuteTest01() { + TempFileTest aTest = new Test01( m_xMSF, m_xSFA, log ); + assure( "Test01 failed!", aTest.test() ); + } + + public void ExecuteTest02() { + TempFileTest aTest = new Test02( m_xMSF, m_xSFA, log ); + assure( "Test02 failed!", aTest.test() ); + } +};
\ No newline at end of file diff --git a/unotools/qa/complex/tempfile/Test01.java b/unotools/qa/complex/tempfile/Test01.java new file mode 100644 index 000000000000..350127158033 --- /dev/null +++ b/unotools/qa/complex/tempfile/Test01.java @@ -0,0 +1,123 @@ +/************************************************************************* + * + * 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: Test01.java,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. + * + ************************************************************************/ +package complex.tempfile; + +import complexlib.ComplexTestCase; + +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.ucb.XSimpleFileAccess; +import com.sun.star.io.*; +import com.sun.star.uno.UnoRuntime; +import java.util.Random; + +import share.LogWriter; + +public class Test01 implements TempFileTest { + LogWriter m_aLogWriter; + XMultiServiceFactory m_xMSF = null; + XSimpleFileAccess m_xSFA = null; + TestHelper m_aTestHelper = null; + + public Test01(XMultiServiceFactory xMSF, XSimpleFileAccess xSFA, LogWriter aLogWriter) { + m_xMSF = xMSF; + m_xSFA = xSFA; + m_aTestHelper = new TestHelper(aLogWriter, "Test01: "); + } + + public boolean test() { + XTempFile xTempFile = null; + XTruncate xTruncate = null; + String sFileURL = null; + String sFileName = null; + //create a temporary file. + try { + Object oTempFile = m_xMSF.createInstance( "com.sun.star.io.TempFile" ); + xTempFile = (XTempFile) UnoRuntime.queryInterface( XTempFile.class, + oTempFile ); + m_aTestHelper.Message( "Tempfile created." ); + xTruncate = (XTruncate)UnoRuntime.queryInterface( XTruncate.class, + oTempFile ); + } catch( Exception e ) { + m_aTestHelper.Error( "Cannot create TempFile. exception: " + e ); + return false; + } + + //retrieve the tempfile URL + if ( xTempFile == null ) { + m_aTestHelper.Error( "Cannot get XTempFile interface." ); + return false; + } + + try { + //compare the file name with the name in the URL. + sFileURL = m_aTestHelper.GetTempFileURL( xTempFile ); + sFileName = m_aTestHelper.GetTempFileName( xTempFile ); + m_aTestHelper.CompareFileNameAndURL( sFileName, sFileURL ); + + //write to the stream using the service. + byte pBytesIn[] = new byte[9]; + byte pBytesOut1[][] = new byte [1][9]; + byte pBytesOut2[][] = new byte [1][9]; + Random oRandom = new Random(); + oRandom.nextBytes( pBytesIn ); + m_aTestHelper.WriteBytesWithStream( pBytesIn, xTempFile ); + + //check the result by reading from the service. + xTempFile.seek(0); + m_aTestHelper.ReadBytesWithStream( pBytesOut1, pBytesIn.length + 1, xTempFile ); + for ( int i = 0; i < pBytesIn.length ; i++ ) { + if ( pBytesOut1[0][i] != pBytesIn[i] ) { + m_aTestHelper.Error( "Tempfile outputs false data!" ); + } + } + + //check the result by reading from the file directly. + m_aTestHelper.ReadDirectlyFromTempFile( pBytesOut2, pBytesIn.length + 1, m_xSFA, sFileURL ); + for ( int i = 0; i < pBytesIn.length; i++ ) { + if ( pBytesOut2[0][i] != pBytesIn[i] ) { + m_aTestHelper.Error( "Tempfile contains false data!" ); + } + } + + //close the object(by closing input and output), check that the file was removed. + xTempFile.setRemoveFile( false ); + m_aTestHelper.CloseTempFile( xTempFile ); + if( !m_aTestHelper.IfTempFileExists( m_xSFA, sFileURL ) ) { + m_aTestHelper.Error( "TempFile mistakenly removed. " ); + } else { + m_aTestHelper.KillTempFile( sFileURL, m_xSFA ); + } + } catch ( Exception e ) { + m_aTestHelper.Error( "Exception: " + e ); + return false; + } + return true; + } +} diff --git a/unotools/qa/complex/tempfile/Test02.java b/unotools/qa/complex/tempfile/Test02.java new file mode 100644 index 000000000000..9667544afd5b --- /dev/null +++ b/unotools/qa/complex/tempfile/Test02.java @@ -0,0 +1,103 @@ +/************************************************************************* + * + * 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: Test02.java,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. + * + ************************************************************************/ +package complex.tempfile; + +import complexlib.ComplexTestCase; + +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.ucb.XSimpleFileAccess; +import com.sun.star.io.*; +import com.sun.star.lang.XServiceInfo; +import com.sun.star.uno.UnoRuntime; +import java.util.Random; +import share.LogWriter; + +public class Test02 implements TempFileTest { + + XMultiServiceFactory m_xMSF; + XSimpleFileAccess m_xSFA; + TestHelper m_aTestHelper; + + public Test02(XMultiServiceFactory xMSF, XSimpleFileAccess xSFA, LogWriter aLogWriter) { + m_xMSF = xMSF; + m_xSFA = xSFA; + m_aTestHelper = new TestHelper(aLogWriter, "Test02: "); + } + + public boolean test() { + Object oTempFile = null; + XTempFile xTempFile = null; + XTruncate xTruncate = null; + String sFileURL = null; + String sFileName = null; + //create a temporary file. + try { + oTempFile = m_xMSF.createInstance( "com.sun.star.io.TempFile" ); + xTempFile = (XTempFile) UnoRuntime.queryInterface( XTempFile.class, + oTempFile ); + m_aTestHelper.Message( "Tempfile created." ); + xTruncate = (XTruncate)UnoRuntime.queryInterface( XTruncate.class, + oTempFile ); + } catch(Exception e) { + m_aTestHelper.Error( "Cannot create TempFile. exception: " + e ); + return false; + } + try { + //write something. + byte pBytesIn[] = new byte[9]; + byte pBytesOut[][] = new byte[1][9]; + Random oRandom = new Random(); + oRandom.nextBytes( pBytesIn ); + m_aTestHelper.WriteBytesWithStream( pBytesIn, xTempFile ); + + //get the URL. + sFileURL = m_aTestHelper.GetTempFileURL( xTempFile ); + + //let the service not to remove the URL. + m_aTestHelper.SetTempFileRemove( xTempFile, false ); + + //close the tempfile by closing input and output. + m_aTestHelper.CloseTempFile( xTempFile ); + + //check that the file is still available. + //xTempFile.seek(0); + m_aTestHelper.ReadDirectlyFromTempFile( pBytesOut, pBytesIn.length + 1, m_xSFA, sFileURL ); + for ( int i = 0; i < pBytesIn.length; i++ ) { + if ( pBytesOut[0][i] != pBytesIn[i] ) { + m_aTestHelper.Error( "Tempfile contains false data!" ); + } + } + } catch ( Exception e) { + m_aTestHelper.Error("Exception: " + e); + return false; + } + return true; + } +} diff --git a/unotools/qa/complex/tempfile/TestHelper.java b/unotools/qa/complex/tempfile/TestHelper.java new file mode 100644 index 000000000000..ce7ba959096e --- /dev/null +++ b/unotools/qa/complex/tempfile/TestHelper.java @@ -0,0 +1,228 @@ +/************************************************************************* + * + * 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: TestHelper.java,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. + * + ************************************************************************/ +package complex.tempfile; + +import complexlib.ComplexTestCase; +import com.sun.star.lang.XMultiServiceFactory; + +import com.sun.star.io.*; + +import com.sun.star.uno.AnyConverter; +import com.sun.star.ucb.XSimpleFileAccess; +import com.sun.star.uno.UnoRuntime; +import share.LogWriter; + +public class TestHelper { + LogWriter m_aLogWriter; + String m_sTestPrefix; + + public TestHelper( LogWriter aLogWriter, String sTestPrefix ) { + m_aLogWriter = aLogWriter; + m_sTestPrefix = sTestPrefix; + } + public void SetTempFileRemove( XTempFile xTempFile, boolean b ) { + try { + xTempFile.setRemoveFile( b ); + } catch( Exception e ) { + Error( "Cannot set TempFileRemove. exception: " + e ); + } + } + + public boolean GetTempFileRemove ( XTempFile xTempFile ) { + boolean b = false; + try { + b = xTempFile.getRemoveFile(); + } catch( Exception e) { + Error( "Cannot get TempFileRemove. exception: " + e ); + } + return b; + } + + public String GetTempFileURL ( XTempFile xTempFile ) { + String sTempFileURL = null; + try { + sTempFileURL = AnyConverter.toString( xTempFile.getUri() ); + } catch (Exception e) { + Error ( "Cannot get TempFileURL. exception: " + e ); + } + if ( sTempFileURL == null || sTempFileURL == "" ) { + Error ( "Temporary file not valid." ); + } + return sTempFileURL; + } + + public String GetTempFileName( XTempFile xTempFile ) { + String sTempFileName = null; + try { + sTempFileName = AnyConverter.toString( xTempFile.getResourceName() ); + } catch ( Exception e ) { + Error( "Cannot get TempFileName. exception: " + e ); + } + if ( sTempFileName == null || sTempFileName == "") { + Error( "Temporary file not valid." ); + } + return sTempFileName; + } + + public boolean CompareFileNameAndURL ( String sTempFileName, String sTempFileURL ) { + boolean bRet = false; + try { + bRet = sTempFileURL.endsWith( sTempFileName.replaceAll( "\\\\" , "/" ) ); + Message ( "Compare file name and URL: " + + ( bRet ? "OK." : "ERROR: FILE NAME AND URL DO NOT MATCH." ) ); + } + catch ( Exception e ) { + Error ( "exception: " + e); + } + return bRet; + } + + public void WriteBytesWithStream( byte [] pBytes, XTempFile xTempFile ) { + try { + XOutputStream xOutTemp = xTempFile.getOutputStream(); + if ( xOutTemp == null ) { + Error( "Cannot get output stream." ); + } else { + xOutTemp.writeBytes( pBytes ); + Message ( "Write to tempfile successfully." ); + } + } catch ( Exception e ) { + Error( "Cannot write to stream. exception: " + e ); + } + } + + public void ReadBytesWithStream( byte [][] pBytes, int nBytes, XTempFile xTempFile ) { + try { + XInputStream xInTemp = xTempFile.getInputStream(); + if ( xInTemp == null ) { + Error( "Cannot get input stream from tempfile." ); + } else { + xInTemp.readBytes( pBytes, nBytes ); + Message ( "Read from tempfile successfully." ); + } + } catch ( Exception e ) { + Error( "Cannot read from stream. exception: " + e ); + } + } + public void ReadDirectlyFromTempFile( byte [][] pBytes, int nBytes, XSimpleFileAccess xSFA, String sTempFileURL ) + { + try + { + if ( xSFA != null ) { + XInputStream xInTemp = xSFA.openFileRead( sTempFileURL ); + if ( xInTemp != null ) + { + xInTemp.readBytes( pBytes, nBytes ); + xInTemp.closeInput(); + Message ( "Read directly from tempfile successfully." ); + } else { + Error ( "Cannot creat input stream from URL." ); + } + } + } + catch ( Exception e) + { + Error( "Exception caught in TestHelper." + + "ReadDirectlyFromTempFile(). exception: " + e ); + } + } + + public void CloseTempFile( XTempFile xTempFile ) { + XOutputStream xOutTemp = null; + XInputStream xInTemp = null; + try { + xOutTemp = xTempFile.getOutputStream(); + if ( xOutTemp == null ) { + Error( "Cannot get output stream." ); + } + } catch ( Exception e ) { + Error( "Cannot get output stream. exception:" + e ); + } + try { + xOutTemp.closeOutput(); + } catch( Exception e ) { + Error( "Cannot close output stream. exception:" + e ); + } + try { + xInTemp = xTempFile.getInputStream(); + if ( xInTemp == null ) { + Error( "Cannot get input stream." ); + } + } catch ( Exception e ) { + Error( "Cannot get input stream. exception:" + e ); + } + try { + xInTemp.closeInput(); + Message ( "Tempfile closed successfully." ); + } catch( Exception e ) { + Error( "Cannot close input stream. exception:" + e ); + } + } + + public void KillTempFile ( String sTempFileURL, XSimpleFileAccess xSFA ) { + try { + if ( sTempFileURL != null ) { + if ( xSFA != null ) { + xSFA.kill( sTempFileURL ); + Message ( "Tempfile killed successfully." ); + } + } + } + catch ( Exception e ) { + Error ( "Exception caught in TestHelper." + + "KillTempFile(): " + e); + } + } + + public boolean IfTempFileExists( XSimpleFileAccess xSFA, String sTempFileURL ) { + boolean bRet = false; + try { + if ( sTempFileURL != null ) { + if ( xSFA != null ) { + bRet = xSFA.exists( sTempFileURL ); + Message ( "Tempfile " + ( bRet ? "still " : "no longer " ) + "exists." ); + } + } + } + catch( Exception e ) { + Error( "Exception caught in TestHelper." + + "IfTempFileExists(): " + e ); + } + return bRet; + } + + public void Error( String sError ) { + m_aLogWriter.println( m_sTestPrefix + "Error: " + sError ); + } + + public void Message( String sMessage ) { + m_aLogWriter.println( m_sTestPrefix + sMessage ); + } +} diff --git a/unotools/qa/complex/tempfile/makefile.mk b/unotools/qa/complex/tempfile/makefile.mk new file mode 100644 index 000000000000..0a8f51e7e71b --- /dev/null +++ b/unotools/qa/complex/tempfile/makefile.mk @@ -0,0 +1,89 @@ +#************************************************************************* +# +# 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.3.20.1 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General 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 = TempFileUnitTest +PRJNAME = unotools +PACKAGE = complex$/tempfile + +# --- Settings ----------------------------------------------------- +.INCLUDE: settings.mk + + +#----- compile .java files ----------------------------------------- + +JARFILES = ridl.jar unoil.jar jurt.jar juh.jar java_uno.jar OOoRunner.jar + +JAVAFILES =\ + TempFileUnitTest.java\ + TempFileTest.java\ + TestHelper.java\ + Test01.java\ + Test02.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: run + +run: + +java -cp $(CLASSPATH) $(CT_APP) $(CT_TESTBASE) $(CT_APPEXECCOMMAND) $(CT_TEST) + + diff --git a/unotools/source/accessibility/accessiblerelationsethelper.cxx b/unotools/source/accessibility/accessiblerelationsethelper.cxx new file mode 100644 index 000000000000..419a072678df --- /dev/null +++ b/unotools/source/accessibility/accessiblerelationsethelper.cxx @@ -0,0 +1,275 @@ +/************************************************************************* + * + * 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: accessiblerelationsethelper.cxx,v $ + * $Revision: 1.10 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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_unotools.hxx" + + +#include "unotools/accessiblerelationsethelper.hxx" +#include <rtl/uuid.h> +#include <vector> +#include <comphelper/sequence.hxx> + +using namespace ::utl; +using namespace ::rtl; +using namespace ::com::sun::star; +using namespace ::com::sun::star::accessibility; + +class AccessibleRelationSetHelperImpl +{ +public: + AccessibleRelationSetHelperImpl(); + AccessibleRelationSetHelperImpl(const AccessibleRelationSetHelperImpl& rImpl); + ~AccessibleRelationSetHelperImpl(); + + sal_Int32 getRelationCount( ) + throw (uno::RuntimeException); + AccessibleRelation getRelation( sal_Int32 nIndex ) + throw (lang::IndexOutOfBoundsException, + uno::RuntimeException); + sal_Bool containsRelation( sal_Int16 aRelationType ) + throw (uno::RuntimeException); + AccessibleRelation getRelationByType( sal_Int16 aRelationType ) + throw (uno::RuntimeException); + void AddRelation(const AccessibleRelation& rRelation) + throw (uno::RuntimeException); + +private: + std::vector<AccessibleRelation> maRelations; +}; + +AccessibleRelationSetHelperImpl::AccessibleRelationSetHelperImpl() +{ +} + +AccessibleRelationSetHelperImpl::AccessibleRelationSetHelperImpl(const AccessibleRelationSetHelperImpl& rImpl) + : maRelations(rImpl.maRelations) +{ +} + +AccessibleRelationSetHelperImpl::~AccessibleRelationSetHelperImpl() +{ +} + +sal_Int32 AccessibleRelationSetHelperImpl::getRelationCount( ) + throw (uno::RuntimeException) +{ + return maRelations.size(); +} + +AccessibleRelation AccessibleRelationSetHelperImpl::getRelation( sal_Int32 nIndex ) + throw (lang::IndexOutOfBoundsException, + uno::RuntimeException) +{ + if ((nIndex < 0) || (static_cast<sal_uInt32>(nIndex) >= maRelations.size())) + throw lang::IndexOutOfBoundsException(); + return maRelations[nIndex]; +} + +sal_Bool AccessibleRelationSetHelperImpl::containsRelation( sal_Int16 aRelationType ) + throw (uno::RuntimeException) +{ + AccessibleRelation defaultRelation; // default is INVALID + AccessibleRelation relationByType = getRelationByType(aRelationType); + return relationByType.RelationType != defaultRelation.RelationType; +} + +AccessibleRelation AccessibleRelationSetHelperImpl::getRelationByType( sal_Int16 aRelationType ) + throw (uno::RuntimeException) +{ + sal_Int32 nCount(getRelationCount()); + sal_Int32 i(0); + sal_Bool bFound(sal_False); + while ((i < nCount) && !bFound) + { + if (maRelations[i].RelationType == aRelationType) + return maRelations[i]; + else + i++; + } + return AccessibleRelation(); +} + +void AccessibleRelationSetHelperImpl::AddRelation(const AccessibleRelation& rRelation) + throw (uno::RuntimeException) +{ + sal_Int32 nCount(getRelationCount()); + sal_Int32 i(0); + sal_Bool bFound(sal_False); + while ((i < nCount) && !bFound) + { + if (maRelations[i].RelationType == rRelation.RelationType) + bFound = sal_True; + else + i++; + } + if (bFound) + maRelations[i].TargetSet = comphelper::concatSequences(maRelations[i].TargetSet, rRelation.TargetSet); + else + maRelations.push_back(rRelation); +} + +//===== internal ============================================================ + +AccessibleRelationSetHelper::AccessibleRelationSetHelper () + : mpHelperImpl(NULL) +{ + mpHelperImpl = new AccessibleRelationSetHelperImpl(); +} + +AccessibleRelationSetHelper::AccessibleRelationSetHelper (const AccessibleRelationSetHelper& rHelper) + : cppu::WeakImplHelper1<XAccessibleRelationSet>() + , mpHelperImpl(NULL) +{ + if (rHelper.mpHelperImpl) + mpHelperImpl = new AccessibleRelationSetHelperImpl(*rHelper.mpHelperImpl); + else + mpHelperImpl = new AccessibleRelationSetHelperImpl(); +} + +AccessibleRelationSetHelper::~AccessibleRelationSetHelper(void) +{ + delete mpHelperImpl; +} + +//===== XAccessibleRelationSet ============================================== + + /** Returns the number of relations in this relation set. + + @return + Returns the number of relations or zero if there are none. + */ +sal_Int32 SAL_CALL + AccessibleRelationSetHelper::getRelationCount( ) + throw (uno::RuntimeException) +{ + ::vos::OGuard aGuard (maMutex); + return mpHelperImpl->getRelationCount(); +} + + /** Returns the relation of this relation set that is specified by + the given index. + + @param nIndex + This index specifies the relatio to return. + + @return + For a valid index, i.e. inside the range 0 to the number of + relations minus one, the returned value is the requested + relation. If the index is invalid then the returned relation + has the type INVALID. + + */ + AccessibleRelation SAL_CALL + AccessibleRelationSetHelper::getRelation( sal_Int32 nIndex ) + throw (lang::IndexOutOfBoundsException, + uno::RuntimeException) +{ + ::vos::OGuard aGuard (maMutex); + return mpHelperImpl->getRelation(nIndex); +} + + /** Tests whether the relation set contains a relation matching the + specified key. + + @param aRelationType + The type of relation to look for in this set of relations. This + has to be one of the constants of + <type>AccessibleRelationType</type>. + + @return + Returns <TRUE/> if there is a (at least one) relation of the + given type and <FALSE/> if there is no such relation in the set. + */ +sal_Bool SAL_CALL + AccessibleRelationSetHelper::containsRelation( sal_Int16 aRelationType ) + throw (uno::RuntimeException) +{ + ::vos::OGuard aGuard (maMutex); + return mpHelperImpl->containsRelation(aRelationType); +} + + /** Retrieve and return the relation with the given relation type. + + @param aRelationType + The type of the relation to return. This has to be one of the + constants of <type>AccessibleRelationType</type>. + + @return + If a relation with the given type could be found than (a copy + of) this relation is returned. Otherwise a relation with the + type INVALID is returned. + */ +AccessibleRelation SAL_CALL + AccessibleRelationSetHelper::getRelationByType( sal_Int16 aRelationType ) + throw (uno::RuntimeException) +{ + ::vos::OGuard aGuard (maMutex); + return mpHelperImpl->getRelationByType(aRelationType); +} + +void AccessibleRelationSetHelper::AddRelation(const AccessibleRelation& rRelation) + throw (uno::RuntimeException) +{ + ::vos::OGuard aGuard (maMutex); + mpHelperImpl->AddRelation(rRelation); +} + +//===== XTypeProvider ======================================================= + +uno::Sequence< ::com::sun::star::uno::Type> + AccessibleRelationSetHelper::getTypes (void) + throw (::com::sun::star::uno::RuntimeException) +{ + ::vos::OGuard aGuard (maMutex); + const ::com::sun::star::uno::Type aTypeList[] = { + ::getCppuType((const uno::Reference< + XAccessibleRelationSet>*)0), + ::getCppuType((const uno::Reference< + lang::XTypeProvider>*)0) + }; + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> + aTypeSequence (aTypeList, 2); + return aTypeSequence; +} + +uno::Sequence<sal_Int8> SAL_CALL + AccessibleRelationSetHelper::getImplementationId (void) + throw (::com::sun::star::uno::RuntimeException) +{ + ::vos::OGuard aGuard (maMutex); + static uno::Sequence<sal_Int8> aId; + if (aId.getLength() == 0) + { + aId.realloc (16); + rtl_createUuid ((sal_uInt8 *)aId.getArray(), 0, sal_True); + } + return aId; +} diff --git a/unotools/source/accessibility/accessiblestatesethelper.cxx b/unotools/source/accessibility/accessiblestatesethelper.cxx new file mode 100644 index 000000000000..71882d66278b --- /dev/null +++ b/unotools/source/accessibility/accessiblestatesethelper.cxx @@ -0,0 +1,349 @@ +/************************************************************************* + * + * 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: accessiblestatesethelper.cxx,v $ + * $Revision: 1.15 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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_unotools.hxx" + + +#include "unotools/accessiblestatesethelper.hxx" +#include <rtl/uuid.h> +#include <tools/debug.hxx> + +#if 0 +#include <bitset> +#endif + +// defines how many states the bitfield can contain +// it has the size of 64 because I use a uInt64 +#define BITFIELDSIZE 64 + +using namespace ::utl; +using namespace ::rtl; +using namespace ::com::sun::star; +using namespace ::com::sun::star::accessibility; + +class AccessibleStateSetHelperImpl +{ +public: + AccessibleStateSetHelperImpl(); + AccessibleStateSetHelperImpl(const AccessibleStateSetHelperImpl& rImpl); + ~AccessibleStateSetHelperImpl(); + + sal_Bool IsEmpty () + throw (uno::RuntimeException); + sal_Bool Contains (sal_Int16 aState) + throw (uno::RuntimeException); + uno::Sequence<sal_Int16> GetStates() + throw (uno::RuntimeException); + void AddState(sal_Int16 aState) + throw (uno::RuntimeException); + void RemoveState(sal_Int16 aState) + throw (uno::RuntimeException); + sal_Bool Compare(const AccessibleStateSetHelperImpl* pComparativeValue, + AccessibleStateSetHelperImpl* pOldStates, + AccessibleStateSetHelperImpl* pNewStates) + throw (uno::RuntimeException); + + inline void AddStates( const sal_Int64 _nStates ) SAL_THROW( ( ) ); + +private: +#if 0 + ::std::bitset<BITFIELDSIZE> maStates; //Bitfield +#endif + sal_uInt64 maStates; +}; + +AccessibleStateSetHelperImpl::AccessibleStateSetHelperImpl() + : maStates(0) +{ +} + +AccessibleStateSetHelperImpl::AccessibleStateSetHelperImpl(const AccessibleStateSetHelperImpl& rImpl) + : maStates(rImpl.maStates) +{ +} + +AccessibleStateSetHelperImpl::~AccessibleStateSetHelperImpl() +{ +} + +inline sal_Bool AccessibleStateSetHelperImpl::IsEmpty () + throw (uno::RuntimeException) +{ +#if 0 + return maStates.none(); +#endif + return maStates == 0; +} + +inline sal_Bool AccessibleStateSetHelperImpl::Contains (sal_Int16 aState) + throw (uno::RuntimeException) +{ + DBG_ASSERT(aState < BITFIELDSIZE, "the statesset is too small"); +#if 0 + return maStates.test(aState); +#endif + sal_uInt64 aTempBitSet(1); + aTempBitSet <<= aState; + return ((aTempBitSet & maStates) != 0); +} + +inline uno::Sequence<sal_Int16> AccessibleStateSetHelperImpl::GetStates() + throw (uno::RuntimeException) +{ + uno::Sequence<sal_Int16> aRet(BITFIELDSIZE); + sal_Int16* pSeq = aRet.getArray(); + sal_Int16 nStateCount(0); + for (sal_Int16 i = 0; i < BITFIELDSIZE; ++i) + if (Contains(i)) + { + *pSeq = i; + ++pSeq; + ++nStateCount; + } + aRet.realloc(nStateCount); + return aRet; +} + +inline void AccessibleStateSetHelperImpl::AddStates( const sal_Int64 _nStates ) SAL_THROW( ( ) ) +{ + maStates |= _nStates; +} + +inline void AccessibleStateSetHelperImpl::AddState(sal_Int16 aState) + throw (uno::RuntimeException) +{ + DBG_ASSERT(aState < BITFIELDSIZE, "the statesset is too small"); +#if 0 + maStates.set(aState); +#endif + sal_uInt64 aTempBitSet(1); + aTempBitSet <<= aState; + maStates |= aTempBitSet; +} + +inline void AccessibleStateSetHelperImpl::RemoveState(sal_Int16 aState) + throw (uno::RuntimeException) +{ + DBG_ASSERT(aState < BITFIELDSIZE, "the statesset is too small"); +#if 0 + maStates.set(aState, 0); +#endif + sal_uInt64 aTempBitSet(1); + aTempBitSet <<= aState; + aTempBitSet = ~aTempBitSet; + maStates &= aTempBitSet; +} + +inline sal_Bool AccessibleStateSetHelperImpl::Compare( + const AccessibleStateSetHelperImpl* pComparativeValue, + AccessibleStateSetHelperImpl* pOldStates, + AccessibleStateSetHelperImpl* pNewStates) + throw (uno::RuntimeException) +{ + sal_Bool bResult(sal_False); + if (pComparativeValue && pOldStates && pNewStates) + { + if (maStates == pComparativeValue->maStates) + bResult = sal_True; + else + { +#if 0 + std::bitset<BITFIELDSIZE> aTempBitSet(maStates); +#endif + sal_uInt64 aTempBitSet(maStates); + aTempBitSet ^= pComparativeValue->maStates; + pOldStates->maStates = aTempBitSet; + pOldStates->maStates &= maStates; + pNewStates->maStates = aTempBitSet; + pNewStates->maStates &= pComparativeValue->maStates; + } + } + return bResult; +} + + +//===== internal ============================================================ + +AccessibleStateSetHelper::AccessibleStateSetHelper () + : mpHelperImpl(NULL) +{ + mpHelperImpl = new AccessibleStateSetHelperImpl(); +} + +AccessibleStateSetHelper::AccessibleStateSetHelper ( const sal_Int64 _nInitialStates ) + : mpHelperImpl(NULL) +{ + mpHelperImpl = new AccessibleStateSetHelperImpl(); + mpHelperImpl->AddStates( _nInitialStates ); +} + +AccessibleStateSetHelper::AccessibleStateSetHelper (const AccessibleStateSetHelper& rHelper) + : cppu::WeakImplHelper1<XAccessibleStateSet>() + , mpHelperImpl(NULL) +{ + if (rHelper.mpHelperImpl) + mpHelperImpl = new AccessibleStateSetHelperImpl(*rHelper.mpHelperImpl); + else + mpHelperImpl = new AccessibleStateSetHelperImpl(); +} + +AccessibleStateSetHelper::~AccessibleStateSetHelper(void) +{ + delete mpHelperImpl; +} + +//===== XAccessibleStateSet ============================================== + + /** Checks whether the current state set is empty. + + @return + Returns <TRUE/> if there is no state in this state set and + <FALSE/> if there is at least one state set in it. + */ +sal_Bool SAL_CALL AccessibleStateSetHelper::isEmpty () + throw (uno::RuntimeException) +{ + ::vos::OGuard aGuard (maMutex); + return mpHelperImpl->IsEmpty(); +} + + /** Checks if the given state is a member of the state set of this + object. + + @param aState + The state for which to check membership. This has to be one of + the constants of <type>AccessibleStateType</type>. + + @return + Returns <TRUE/> if the given state is a memeber of this object's + state set and <FALSE/> otherwise. + */ +sal_Bool SAL_CALL AccessibleStateSetHelper::contains (sal_Int16 aState) + throw (uno::RuntimeException) +{ + ::vos::OGuard aGuard (maMutex); + return mpHelperImpl->Contains(aState); +} + + /** Checks if all of the given states are in this object's state + set. + + @param aStateSet + This sequence of states is interpreted as set and every of its + members, duplicates are ignored, is checked for membership in + this object's state set. Each state has to be one of the + constants of <type>AccessibleStateType</type>. + + @return + Returns <TRUE/> if all states of the given state set are members + of this object's state set. <FALSE/> is returned if at least + one of the states in the given state is not a member of this + object's state set. + */ +sal_Bool SAL_CALL AccessibleStateSetHelper::containsAll + (const uno::Sequence<sal_Int16>& rStateSet) + throw (uno::RuntimeException) +{ + ::vos::OGuard aGuard (maMutex); + sal_Int32 nCount(rStateSet.getLength()); + const sal_Int16* pStates = rStateSet.getConstArray(); + sal_Int32 i = 0; + sal_Bool bFound(sal_True); + while (i < nCount) + { + bFound = mpHelperImpl->Contains(pStates[i]); + i++; + } + return bFound; +} + +uno::Sequence<sal_Int16> SAL_CALL AccessibleStateSetHelper::getStates() + throw (uno::RuntimeException) +{ + ::vos::OGuard aGuard(maMutex); + return mpHelperImpl->GetStates(); +} + +void AccessibleStateSetHelper::AddState(sal_Int16 aState) + throw (uno::RuntimeException) +{ + ::vos::OGuard aGuard (maMutex); + mpHelperImpl->AddState(aState); +} + +void AccessibleStateSetHelper::RemoveState(sal_Int16 aState) + throw (uno::RuntimeException) +{ + ::vos::OGuard aGuard (maMutex); + mpHelperImpl->RemoveState(aState); +} + +sal_Bool AccessibleStateSetHelper::Compare( + const AccessibleStateSetHelper& rComparativeValue, + AccessibleStateSetHelper& rOldStates, + AccessibleStateSetHelper& rNewStates) + throw (uno::RuntimeException) +{ + ::vos::OGuard aGuard (maMutex); + return mpHelperImpl->Compare(rComparativeValue.mpHelperImpl, + rOldStates.mpHelperImpl, rNewStates.mpHelperImpl); +} + +//===== XTypeProvider ======================================================= + +uno::Sequence< ::com::sun::star::uno::Type> + AccessibleStateSetHelper::getTypes (void) + throw (::com::sun::star::uno::RuntimeException) +{ + const ::com::sun::star::uno::Type aTypeList[] = { + ::getCppuType((const uno::Reference< + XAccessibleStateSet>*)0), + ::getCppuType((const uno::Reference< + lang::XTypeProvider>*)0) + }; + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> + aTypeSequence (aTypeList, 2); + return aTypeSequence; +} + +uno::Sequence<sal_Int8> SAL_CALL + AccessibleStateSetHelper::getImplementationId (void) + throw (::com::sun::star::uno::RuntimeException) +{ + ::vos::OGuard aGuard (maMutex); + static uno::Sequence<sal_Int8> aId; + if (aId.getLength() == 0) + { + aId.realloc (16); + rtl_createUuid ((sal_uInt8 *)aId.getArray(), 0, sal_True); + } + return aId; +} diff --git a/unotools/source/accessibility/makefile.mk b/unotools/source/accessibility/makefile.mk new file mode 100644 index 000000000000..7ed2e2bffe74 --- /dev/null +++ b/unotools/source/accessibility/makefile.mk @@ -0,0 +1,52 @@ +#************************************************************************* +# +# 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.10 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General 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=..$/.. +PRJINC=..$/..$/inc +PRJNAME=unotools +TARGET=accessibility + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ---------------------------------- + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/util$/makefile.pmk + +# --- Files ------------------------------------- + +SLOFILES= $(SLO)$/accessiblestatesethelper.obj \ + $(SLO)$/accessiblerelationsethelper.obj + +# --- Targets ---------------------------------- + +.INCLUDE : target.mk + diff --git a/unotools/source/config/bootstrap.cxx b/unotools/source/config/bootstrap.cxx new file mode 100644 index 000000000000..d2a08a766e20 --- /dev/null +++ b/unotools/source/config/bootstrap.cxx @@ -0,0 +1,915 @@ +/************************************************************************* + * + * 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: bootstrap.cxx,v $ + * $Revision: 1.28.16.1 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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_unotools.hxx" + +#include <stdio.h> + +#include "unotools/bootstrap.hxx" + +// --------------------------------------------------------------------------------------- +#include <rtl/ustring.hxx> +#include <rtl/ustrbuf.hxx> +#include <osl/file.hxx> +#include <osl/mutex.hxx> +#include <osl/diagnose.h> +// --------------------------------------------------------------------------------------- +#include <rtl/bootstrap.hxx> +#include <osl/process.h> // for osl_getExecutableFile +#include "tools/getprocessworkingdir.hxx" + +// --------------------------------------------------------------------------------------- +// #define this to a non-zero value, if remembering defaults is not supported properly +#define RTL_BOOTSTRAP_DEFAULTS_BROKEN 1 + +// --------------------------------------------------------------------------------------- +#define BOOTSTRAP_DATA_NAME SAL_CONFIGFILE("bootstrap") + +#define BOOTSTRAP_ITEM_PRODUCT_KEY "ProductKey" +#define BOOTSTRAP_ITEM_PRODUCT_SOURCE "ProductSource" +#define BOOTSTRAP_ITEM_VERSIONFILE "Location" +#define BOOTSTRAP_ITEM_BUILDID "buildid" + +#define BOOTSTRAP_ITEM_BASEINSTALLATION "BaseInstallation" +#define BOOTSTRAP_ITEM_USERINSTALLATION "UserInstallation" + +#define BOOTSTRAP_ITEM_SHAREDIR "SharedDataDir" +#define BOOTSTRAP_ITEM_USERDIR "UserDataDir" + +#define BOOTSTRAP_DEFAULT_BASEINSTALL "$SYSBINDIR/.." + +#define BOOTSTRAP_DIRNAME_SHAREDIR "share" +#define BOOTSTRAP_DIRNAME_USERDIR "user" + +#define VERSIONFILE_SECTION "Versions" + +#define SETUP_DATA_NAME SAL_CONFIGFILE("setup") +#define SETUP_ITEM_ALLUSERS "ALLUSERS" +// --------------------------------------------------------------------------------------- +typedef char const * AsciiString; +// --------------------------------------------------------------------------------------- + +namespace utl +{ +// --------------------------------------------------------------------------------------- + using ::rtl::OUString; + using ::rtl::OUStringBuffer; + using ::rtl::OString; + +// --------------------------------------------------------------------------------------- +// Implementation class: Bootstrap::Impl +// --------------------------------------------------------------------------------------- + + class Bootstrap::Impl + { + OUString const m_aImplName; + public: // struct to cache the result of a path lookup + struct PathData + { + OUString path; + PathStatus status; + + PathData() + : path() + , status(DATA_UNKNOWN) + {} + }; + public: // data members + // base install data + PathData aBaseInstall_; + + // user install data + PathData aUserInstall_; + + // INI files + PathData aBootstrapINI_; + PathData aVersionINI_; + + // overall status + Status status_; + + public: // construction and initialization + explicit + Impl(OUString const& _aImplName) + : m_aImplName(_aImplName) + { + status_ = initialize(); + } + + Status initialize(); + + // access helper + OUString getBootstrapValue(OUString const& _sName, OUString const& _sDefault) const; + sal_Bool getVersionValue(OUString const& _sName, OUString& _rValue, OUString const& _sDefault) const; + + OUString getImplName() const { return m_aImplName; } + + private: // implementation + bool initBaseInstallationData(rtl::Bootstrap& _rData); + bool initUserInstallationData(rtl::Bootstrap& _rData); + }; +// --------------------------------------------------------------------------------------- + static OUString getExecutableDirectory(); +// --------------------------------------------------------------------------------------- + + static Bootstrap::Impl* s_pData = NULL; + + Bootstrap::Impl const& Bootstrap::data() + { + + if (!s_pData) + { + using namespace osl; + MutexGuard aGuard( Mutex::getGlobalMutex() ); + + // static Impl s_theData(getExecutableDirectory() + OUString(RTL_CONSTASCII_USTRINGPARAM("/"BOOTSTRAP_DATA_NAME))); + // s_pData = &s_theData; + rtl::OUString uri; + rtl::Bootstrap::get( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("BRAND_BASE_DIR")), uri); + s_pData = new Impl(uri + OUString(RTL_CONSTASCII_USTRINGPARAM("/program/"BOOTSTRAP_DATA_NAME))); + } + return *s_pData; + } + + void Bootstrap::reloadData() + { + if (s_pData != NULL) { + delete s_pData; + s_pData = NULL; + } + } + +// --------------------------------------------------------------------------------------- +// helper +// --------------------------------------------------------------------------------------- + +typedef Bootstrap::PathStatus PathStatus; + +sal_Unicode const cURLSeparator = '/'; + +// --------------------------------------------------------------------------------------- +static +inline +OUString getURLSeparator() +{ + static OUString theSep(&cURLSeparator,1); + return theSep; +} + +// --------------------------------------------------------------------------------------- +// path status utility function +static +PathStatus implCheckStatusOfURL(OUString const& _sURL, osl::DirectoryItem& aDirItem) +{ + using namespace osl; + + PathStatus eStatus = Bootstrap::DATA_UNKNOWN; + + if (_sURL.getLength() != 0) + { + switch( DirectoryItem::get(_sURL, aDirItem) ) + { + case DirectoryItem::E_None: // Success + eStatus = Bootstrap::PATH_EXISTS; + break; + + case DirectoryItem::E_NOENT: // No such file or directory<br> + eStatus = Bootstrap::PATH_VALID; + break; + + case DirectoryItem::E_INVAL: // the format of the parameters was not valid<br> + case DirectoryItem::E_NAMETOOLONG: // File name too long<br> + case DirectoryItem::E_NOTDIR: // A component of the path prefix of path is not a directory<p> + eStatus = Bootstrap::DATA_INVALID; + break; + + // how to handle these ? + case DirectoryItem::E_LOOP: // Too many symbolic links encountered<br> + case DirectoryItem::E_ACCES: // permission denied<br> + // any other error - what to do ? + default: + eStatus = Bootstrap::DATA_UNKNOWN; + break; + } + } + else + eStatus = Bootstrap::DATA_MISSING; + + return eStatus; +} +// --------------------------------------------------------------------------------------- + +static +bool implNormalizeURL(OUString & _sURL, osl::DirectoryItem& aDirItem) +{ + using namespace osl; + + OSL_PRECOND(aDirItem.is(), "Opened DirItem required"); + + static const sal_uInt32 cFileStatusMask = FileStatusMask_FileURL; + + FileStatus aFileStatus(cFileStatusMask); + + if (aDirItem.getFileStatus(aFileStatus) != DirectoryItem::E_None) + return false; + + OUString aNormalizedURL = aFileStatus.getFileURL(); + + if (aNormalizedURL.getLength() == 0) + return false; + + // #109863# sal/osl returns final slash for file URLs contradicting + // the URL/URI RFCs. + if ( aNormalizedURL.getStr()[aNormalizedURL.getLength()-1] != cURLSeparator ) + _sURL = aNormalizedURL; + else + _sURL = aNormalizedURL.copy( 0, aNormalizedURL.getLength()-1 ); + + return true; +} +// --------------------------------------------------------------------------------------- +static +bool implEnsureAbsolute(OUString & _rsURL) // also strips embedded dots !! +{ + using osl::File; + + OUString sBasePath; + OSL_VERIFY(tools::getProcessWorkingDir(&sBasePath)); + + OUString sAbsolute; + if ( File::E_None == File::getAbsoluteFileURL(sBasePath, _rsURL, sAbsolute)) + { + _rsURL = sAbsolute; + return true; + } + else + { + OSL_ENSURE(false, "Could not get absolute file URL for URL"); + return false; + } +} +/* old code to strip embedded dots + static OUString const sDots(RTL_CONSTASCII_USTRINGPARAM("/..")); + + sal_Int32 nDotsIndex = _rsURL.indexOf(sDots); + while (nDotsIndex >= 0) + { + OSL_ASSERT(_rsURL.indexOf(sDots) == nDotsIndex); + + sal_Int32 nStripIndex = _rsURL.lastIndexOf(cURLSeparator,nDotsIndex); + if (nStripIndex < 0 || nStripIndex+1 == nDotsIndex) + { + OSL_TRACE("Invalid use of dots in bootstrap URL"); + return false; + } + _rsURL = _rsURL.copy(0,nStripIndex) + _rsURL.copy(nDotsIndex + sDots.getLength()); + + nDotsIndex = _rsURL.indexOf(sDots,nStripIndex); + } + return true; +} + +*/ +// --------------------------------------------------------------------------------------- + +static +bool implMakeAbsoluteURL(OUString & _rsPathOrURL) +{ + using namespace osl; + + bool bURL; + + OUString sOther; + // check if it already was normalized + if ( File::E_None == File::getSystemPathFromFileURL(_rsPathOrURL, sOther) ) + { + bURL = true; + } + + else if ( File::E_None == File::getFileURLFromSystemPath(_rsPathOrURL, sOther) ) + { + _rsPathOrURL = sOther; + bURL = true; + } + else + bURL = false; + + return bURL && implEnsureAbsolute(_rsPathOrURL); +} +// --------------------------------------------------------------------------------------- +#if OSL_DEBUG_LEVEL > 0 +static +PathStatus dbgCheckStatusOfURL(OUString const& _sURL) +{ + using namespace osl; + + DirectoryItem aDirItem; + + return implCheckStatusOfURL(_sURL,aDirItem); +} +// --------------------------------------------------------------------------------------- +#endif + +static +PathStatus checkStatusAndNormalizeURL(OUString & _sURL) +{ + using namespace osl; + + PathStatus eStatus = Bootstrap::DATA_UNKNOWN; + + if (_sURL.getLength() == 0) + eStatus = Bootstrap::DATA_MISSING; + + else if ( !implMakeAbsoluteURL(_sURL) ) + eStatus = Bootstrap::DATA_INVALID; + + else + { + DirectoryItem aDirItem; + + eStatus = implCheckStatusOfURL(_sURL,aDirItem); + + if (eStatus == Bootstrap::PATH_EXISTS) + { + if (!implNormalizeURL(_sURL,aDirItem)) + OSL_ENSURE(false,"Unexpected failure getting actual URL for existing object"); + } + } + return eStatus; +} + + +// ---------------------------------------------------------------------------------- +// helpers to build and check a nested URL +static +PathStatus getDerivedPath( + OUString& _rURL, + OUString const& _aBaseURL, PathStatus _aBaseStatus, + OUString const& _sRelativeURL, + rtl::Bootstrap& _rData, OUString const& _sBootstrapParameter + ) +{ + OUString sDerivedURL; + + OSL_PRECOND(!_rData.getFrom(_sBootstrapParameter,sDerivedURL),"Setting for derived path is already defined"); + OSL_PRECOND(_sRelativeURL.getLength() != 0 && _sRelativeURL[0] != cURLSeparator,"Invalid Relative URL"); + + PathStatus aStatus = _aBaseStatus; + + // do we have a base path ? + if (_aBaseURL.getLength()) + { + OSL_PRECOND(_aBaseURL[_aBaseURL.getLength()-1] != cURLSeparator,"Unexpected: base URL ends in slash"); + + sDerivedURL = _aBaseURL + getURLSeparator() + _sRelativeURL; + + // a derived (nested) URL can only exist or have a lesser status, if the parent exists + if (aStatus == Bootstrap::PATH_EXISTS) + aStatus = checkStatusAndNormalizeURL(sDerivedURL); + + else // the relative appendix must be valid + OSL_ASSERT(aStatus != Bootstrap::PATH_VALID || dbgCheckStatusOfURL(sDerivedURL) == Bootstrap::PATH_VALID); + + _rData.getFrom(_sBootstrapParameter, _rURL, sDerivedURL); + + OSL_ENSURE(sDerivedURL == _rURL,"Could not set derived URL via Bootstrap default parameter"); + OSL_POSTCOND(RTL_BOOTSTRAP_DEFAULTS_BROKEN || + _rData.getFrom(_sBootstrapParameter,sDerivedURL) && sDerivedURL==_rURL,"Use of default did not affect bootstrap value"); + } + else + { + // clear the result + _rURL = _aBaseURL; + + // if we have no data it can't be a valid path + OSL_ASSERT( aStatus > Bootstrap::PATH_VALID ); + } + + + return aStatus; +} + +// ---------------------------------------------------------------------------------- +static +inline +PathStatus getDerivedPath( + OUString& _rURL, + Bootstrap::Impl::PathData const& _aBaseData, + OUString const& _sRelativeURL, + rtl::Bootstrap& _rData, OUString const& _sBootstrapParameter + ) +{ + return getDerivedPath(_rURL,_aBaseData.path,_aBaseData.status,_sRelativeURL,_rData,_sBootstrapParameter); +} + +// --------------------------------------------------------------------------------------- + +static +OUString getExecutableBaseName() +{ + OUString sExecutable; + + if (osl_Process_E_None == osl_getExecutableFile(&sExecutable.pData)) + { + // split the executable name + sal_Int32 nSepIndex = sExecutable.lastIndexOf(cURLSeparator); + + sExecutable = sExecutable.copy(nSepIndex + 1); + + // ... and get the basename (strip the extension) + sal_Unicode const cExtensionSep = '.'; + + sal_Int32 const nExtIndex = sExecutable.lastIndexOf(cExtensionSep); + sal_Int32 const nExtLength = sExecutable.getLength() - nExtIndex - 1; + if (0 < nExtIndex && nExtLength < 4) + sExecutable = sExecutable.copy(0,nExtIndex); + } + else + OSL_TRACE("Cannot get executable name: osl_getExecutableFile failed\n"); + + return sExecutable; +} + +// --------------------------------------------------------------------------------------- +static +OUString getExecutableDirectory() +{ + OUString sFileName; + OSL_VERIFY(osl_Process_E_None == osl_getExecutableFile(&sFileName.pData)); + + sal_Int32 nDirEnd = sFileName.lastIndexOf(cURLSeparator); + + OSL_ENSURE(nDirEnd >= 0, "Cannot locate executable directory"); + + return sFileName.copy(0,nDirEnd); +} + +// ---------------------------------------------------------------------------------- + +static +inline +Bootstrap::PathStatus updateStatus(Bootstrap::Impl::PathData & _rResult) +{ + return _rResult.status = checkStatusAndNormalizeURL(_rResult.path); +} +// --------------------------------------------------------------------------------------- + +static +Bootstrap::PathStatus implGetBootstrapFile(rtl::Bootstrap& _rData, Bootstrap::Impl::PathData & _rBootstrapFile) +{ + _rData.getIniName(_rBootstrapFile.path); + + return updateStatus(_rBootstrapFile); +} +// --------------------------------------------------------------------------------------- + +static +Bootstrap::PathStatus implGetVersionFile(rtl::Bootstrap& _rData, Bootstrap::Impl::PathData & _rVersionFile) +{ + OUString const csVersionFileItem(RTL_CONSTASCII_USTRINGPARAM(BOOTSTRAP_ITEM_VERSIONFILE)); + + _rData.getFrom(csVersionFileItem,_rVersionFile.path); + + return updateStatus(_rVersionFile); +} +// --------------------------------------------------------------------------------------- +// Error reporting + +static char const IS_MISSING[] = "is missing"; +static char const IS_INVALID[] = "is corrupt"; +static char const PERIOD[] = ". "; + +// --------------------------------------------------------------------------------------- +static void addFileError(OUStringBuffer& _rBuf, OUString const& _aPath, AsciiString _sWhat) +{ + OUString sSimpleFileName = _aPath.copy(1 +_aPath.lastIndexOf(cURLSeparator)); + + _rBuf.appendAscii("The configuration file"); + _rBuf.appendAscii(" '").append(sSimpleFileName).appendAscii("' "); + _rBuf.appendAscii(_sWhat).appendAscii(PERIOD); +} +// --------------------------------------------------------------------------------------- + +static void addMissingDirectoryError(OUStringBuffer& _rBuf, OUString const& _aPath) +{ + _rBuf.appendAscii("The configuration directory"); + _rBuf.appendAscii(" '").append(_aPath).appendAscii("' "); + _rBuf.appendAscii(IS_MISSING).appendAscii(PERIOD); +} +// --------------------------------------------------------------------------------------- + +static void addUnexpectedError(OUStringBuffer& _rBuf, AsciiString _sExtraInfo = NULL) +{ + if (NULL == _sExtraInfo) + _sExtraInfo = "An internal failure occurred"; + + _rBuf.appendAscii(_sExtraInfo).appendAscii(PERIOD); +} +// --------------------------------------------------------------------------------------- + +static Bootstrap::FailureCode describeError(OUStringBuffer& _rBuf, Bootstrap::Impl const& _rData) +{ + Bootstrap::FailureCode eErrCode = Bootstrap::INVALID_BOOTSTRAP_DATA; + + _rBuf.appendAscii("The program cannot be started. "); + + switch (_rData.aUserInstall_.status) + { + case Bootstrap::PATH_EXISTS: + switch (_rData.aBaseInstall_.status) + { + case Bootstrap::PATH_VALID: + addMissingDirectoryError(_rBuf, _rData.aBaseInstall_.path); + eErrCode = Bootstrap::MISSING_INSTALL_DIRECTORY; + break; + + case Bootstrap::DATA_INVALID: + addUnexpectedError(_rBuf,"The installation path is invalid"); + break; + + case Bootstrap::DATA_MISSING: + addUnexpectedError(_rBuf,"The installation path is not available"); + break; + + case Bootstrap::PATH_EXISTS: // seems to be all fine (?) + addUnexpectedError(_rBuf,""); + break; + + default: OSL_ASSERT(false); + addUnexpectedError(_rBuf); + break; + } + break; + + case Bootstrap::PATH_VALID: + addMissingDirectoryError(_rBuf, _rData.aUserInstall_.path); + eErrCode = Bootstrap::MISSING_USER_DIRECTORY; + break; + + // else fall through + case Bootstrap::DATA_INVALID: + if (_rData.aVersionINI_.status == Bootstrap::PATH_EXISTS) + { + addFileError(_rBuf, _rData.aVersionINI_.path, IS_INVALID); + eErrCode = Bootstrap::INVALID_VERSION_FILE_ENTRY; + break; + } + // else fall through + + case Bootstrap::DATA_MISSING: + switch (_rData.aVersionINI_.status) + { + case Bootstrap::PATH_EXISTS: + addFileError(_rBuf, _rData.aVersionINI_.path, "does not support the current version"); + eErrCode = Bootstrap::MISSING_VERSION_FILE_ENTRY; + break; + + case Bootstrap::PATH_VALID: + addFileError(_rBuf, _rData.aVersionINI_.path, IS_MISSING); + eErrCode = Bootstrap::MISSING_VERSION_FILE; + break; + + default: + switch (_rData.aBootstrapINI_.status) + { + case Bootstrap::PATH_EXISTS: + addFileError(_rBuf, _rData.aBootstrapINI_.path, IS_INVALID); + + if (_rData.aVersionINI_.status == Bootstrap::DATA_MISSING) + eErrCode = Bootstrap::MISSING_BOOTSTRAP_FILE_ENTRY; + else + eErrCode = Bootstrap::INVALID_BOOTSTRAP_FILE_ENTRY; + break; + + case Bootstrap::DATA_INVALID: OSL_ASSERT(false); + case Bootstrap::PATH_VALID: + addFileError(_rBuf, _rData.aBootstrapINI_.path, IS_MISSING); + eErrCode = Bootstrap::MISSING_BOOTSTRAP_FILE; + break; + + default: + addUnexpectedError(_rBuf); + break; + } + break; + } + break; + + default: OSL_ASSERT(false); + addUnexpectedError(_rBuf); + break; + } + + return eErrCode; +} +// --------------------------------------------------------------------------------------- +// --------------------------------------------------------------------------------------- +// class Bootstrap +// --------------------------------------------------------------------------------------- + +OUString Bootstrap::getProductKey() +{ + OUString const csProductKeyItem(RTL_CONSTASCII_USTRINGPARAM(BOOTSTRAP_ITEM_PRODUCT_KEY)); + + OUString const sDefaultProductKey = getExecutableBaseName(); + + return data().getBootstrapValue( csProductKeyItem, sDefaultProductKey ); +} +// --------------------------------------------------------------------------------------- + +OUString Bootstrap::getProductKey(OUString const& _sDefault) +{ + OUString const csProductKeyItem(RTL_CONSTASCII_USTRINGPARAM(BOOTSTRAP_ITEM_PRODUCT_KEY)); + + return data().getBootstrapValue( csProductKeyItem, _sDefault ); +} +// --------------------------------------------------------------------------------------- + +OUString Bootstrap::getProductSource(OUString const& _sDefault) +{ + OUString const csProductSourceItem(RTL_CONSTASCII_USTRINGPARAM(BOOTSTRAP_ITEM_PRODUCT_SOURCE)); + + OUString sProductSource; + // read ProductSource from version.ini (versionrc) + data().getVersionValue( csProductSourceItem, sProductSource, _sDefault ); + return sProductSource; +} +// --------------------------------------------------------------------------------------- + +OUString Bootstrap::getBuildIdData(OUString const& _sDefault) +{ + OUString const csBuildIdItem(RTL_CONSTASCII_USTRINGPARAM(BOOTSTRAP_ITEM_BUILDID)); + + OUString sBuildId; + // read buildid from version.ini (versionrc), if it doesn't exist or buildid is empty + if ( data().getVersionValue( csBuildIdItem, sBuildId, _sDefault ) != sal_True || + sBuildId.getLength() == 0 ) + // read buildid from bootstrap.ini (bootstraprc) + sBuildId = data().getBootstrapValue( csBuildIdItem, _sDefault ); + return sBuildId; +} +// --------------------------------------------------------------------------------------- + +OUString Bootstrap::getAllUsersValue(OUString const& _sDefault) +{ + OUString const csAllUsersItem(RTL_CONSTASCII_USTRINGPARAM(SETUP_ITEM_ALLUSERS)); + + rtl::Bootstrap aData( getExecutableDirectory() + OUString( RTL_CONSTASCII_USTRINGPARAM( "/"SETUP_DATA_NAME ) ) ); + OUString sResult; + aData.getFrom( csAllUsersItem, sResult, _sDefault ); + return sResult; +} +// --------------------------------------------------------------------------------------- + +Bootstrap::PathStatus Bootstrap::locateBaseInstallation(OUString& _rURL) +{ + Impl::PathData const& aPathData = data().aBaseInstall_; + + _rURL = aPathData.path; + return aPathData.status; +} +// --------------------------------------------------------------------------------------- + +PathStatus Bootstrap::locateUserInstallation(OUString& _rURL) +{ + Impl::PathData const& aPathData = data().aUserInstall_; + + _rURL = aPathData.path; + return aPathData.status; +} +// --------------------------------------------------------------------------------------- + +PathStatus Bootstrap::locateSharedData(OUString& _rURL) +{ + OUString const csShareDirItem(RTL_CONSTASCII_USTRINGPARAM(BOOTSTRAP_ITEM_SHAREDIR)); + + rtl::Bootstrap aData( data().getImplName() ); + + if ( aData.getFrom(csShareDirItem, _rURL) ) + { + return checkStatusAndNormalizeURL(_rURL); + } + else + { + OUString const csShareDir(RTL_CONSTASCII_USTRINGPARAM(BOOTSTRAP_DIRNAME_SHAREDIR)); + return getDerivedPath(_rURL, data().aBaseInstall_, csShareDir, aData, csShareDirItem); + } +} +// --------------------------------------------------------------------------------------- + +PathStatus Bootstrap::locateUserData(OUString& _rURL) +{ + OUString const csUserDirItem(RTL_CONSTASCII_USTRINGPARAM(BOOTSTRAP_ITEM_USERDIR)); + + rtl::Bootstrap aData( data().getImplName() ); + + if ( aData.getFrom(csUserDirItem, _rURL) ) + { + return checkStatusAndNormalizeURL(_rURL); + } + else + { + OUString const csUserDir(RTL_CONSTASCII_USTRINGPARAM(BOOTSTRAP_DIRNAME_USERDIR)); + return getDerivedPath(_rURL, data().aUserInstall_ ,csUserDir, aData, csUserDirItem); + } +} +// --------------------------------------------------------------------------------------- + +PathStatus Bootstrap::locateBootstrapFile(OUString& _rURL) +{ + Impl::PathData const& aPathData = data().aBootstrapINI_; + + _rURL = aPathData.path; + return aPathData.status; +} +// --------------------------------------------------------------------------------------- + +PathStatus Bootstrap::locateVersionFile(OUString& _rURL) +{ + Impl::PathData const& aPathData = data().aVersionINI_; + + _rURL = aPathData.path; + return aPathData.status; +} +// --------------------------------------------------------------------------------------- + +Bootstrap::Status Bootstrap::checkBootstrapStatus(OUString& _rDiagnosticMessage) +{ + FailureCode eDummyCode(NO_FAILURE); + + return checkBootstrapStatus(_rDiagnosticMessage,eDummyCode); +} +// --------------------------------------------------------------------------------------- + +Bootstrap::Status Bootstrap::checkBootstrapStatus(rtl::OUString& _rDiagnosticMessage, FailureCode& _rErrCode) +{ + Impl const& aData = data(); + + Status result = aData.status_; + + // maybe do further checks here + + OUStringBuffer sErrorBuffer; + if (result != DATA_OK) + _rErrCode = describeError(sErrorBuffer,aData); + + else + _rErrCode = NO_FAILURE; + + _rDiagnosticMessage = sErrorBuffer.makeStringAndClear(); + + return result; +} + +// --------------------------------------------------------------------------------------- +// class Bootstrap::Impl +// --------------------------------------------------------------------------------------- + +bool Bootstrap::Impl::initBaseInstallationData(rtl::Bootstrap& _rData) +{ + OUString const csBaseInstallItem( RTL_CONSTASCII_USTRINGPARAM(BOOTSTRAP_ITEM_BASEINSTALLATION) ); + OUString const csBaseInstallDefault( RTL_CONSTASCII_USTRINGPARAM(BOOTSTRAP_DEFAULT_BASEINSTALL) ); + + _rData.getFrom(csBaseInstallItem, aBaseInstall_.path, csBaseInstallDefault); + + bool bResult = (PATH_EXISTS == updateStatus(aBaseInstall_)); + + implGetBootstrapFile(_rData, aBootstrapINI_); + + return bResult; +} +// --------------------------------------------------------------------------------------- + +bool Bootstrap::Impl::initUserInstallationData(rtl::Bootstrap& _rData) +{ + OUString const csUserInstallItem( RTL_CONSTASCII_USTRINGPARAM(BOOTSTRAP_ITEM_USERINSTALLATION) ); + + if (_rData.getFrom(csUserInstallItem, aUserInstall_.path)) + { + updateStatus(aUserInstall_); + } + else + { + // should we do just this + aUserInstall_.status = DATA_MISSING; + + // .. or this - look for a single-user user directory ? + OUString const csUserDirItem(RTL_CONSTASCII_USTRINGPARAM(BOOTSTRAP_ITEM_USERDIR)); + OUString sDummy; + // look for $BASEINSTALLATION/user only if default UserDir setting is used + if (! _rData.getFrom(csUserDirItem, sDummy)) + { + OUString const csUserDir(RTL_CONSTASCII_USTRINGPARAM(BOOTSTRAP_DIRNAME_USERDIR)); + + if ( PATH_EXISTS == getDerivedPath(sDummy, aBaseInstall_, csUserDir, _rData, csUserDirItem) ) + aUserInstall_ = aBaseInstall_; + } + } + + bool bResult = (PATH_EXISTS == aUserInstall_.status); + + implGetVersionFile(_rData, aVersionINI_); + + return bResult; +} +// --------------------------------------------------------------------------------------- + +Bootstrap::Status Bootstrap::Impl::initialize() +{ + Bootstrap::Status result; + + rtl::Bootstrap aData( m_aImplName ); + + if (!initBaseInstallationData(aData)) + { + result = INVALID_BASE_INSTALL; + } + else if (!initUserInstallationData(aData)) + { + result = INVALID_USER_INSTALL; + + if (aUserInstall_.status >= DATA_MISSING) + { + switch (aVersionINI_.status) + { + case PATH_EXISTS: + case PATH_VALID: + result = MISSING_USER_INSTALL; + break; + + case DATA_INVALID: + case DATA_MISSING: + result = INVALID_BASE_INSTALL; + break; + default: + break; + } + } + } + else + { + result = DATA_OK; + } + return result; +} +// --------------------------------------------------------------------------------------- + +OUString Bootstrap::Impl::getBootstrapValue(OUString const& _sName, OUString const& _sDefault) const +{ + rtl::Bootstrap aData( m_aImplName ); + + OUString sResult; + aData.getFrom(_sName,sResult,_sDefault); + return sResult; +} +// --------------------------------------------------------------------------------------- + +sal_Bool Bootstrap::Impl::getVersionValue(OUString const& _sName, OUString& _rValue, OUString const& _sDefault) const +{ + // try to open version.ini (versionrc) + rtl::OUString uri; + rtl::Bootstrap::get( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("BRAND_BASE_DIR")), uri); + rtl::Bootstrap aData( uri + + OUString(RTL_CONSTASCII_USTRINGPARAM("/program/"SAL_CONFIGFILE("version"))) ); + if ( aData.getHandle() == NULL ) + // version.ini (versionrc) doesn't exist + return sal_False; + + // read value + aData.getFrom(_sName,_rValue,_sDefault); + return sal_True; +} +// --------------------------------------------------------------------------------------- + +} // namespace utl + diff --git a/unotools/source/config/configitem.cxx b/unotools/source/config/configitem.cxx new file mode 100644 index 000000000000..a6b3bbaa1e2f --- /dev/null +++ b/unotools/source/config/configitem.cxx @@ -0,0 +1,1423 @@ +/************************************************************************* + * + * 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: configitem.cxx,v $ + * $Revision: 1.52 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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_unotools.hxx" +#include "unotools/configitem.hxx" +#include "unotools/configmgr.hxx" +#include "unotools/configpathes.hxx" +#include <com/sun/star/beans/XMultiPropertySet.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/util/XChangesListener.hpp> +#include <com/sun/star/util/XChangesNotifier.hpp> +#include <com/sun/star/container/XHierarchicalNameAccess.hpp> +#include <com/sun/star/container/XHierarchicalName.hpp> +#include <com/sun/star/configuration/XTemplateContainer.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/util/XStringEscape.hpp> +#include <com/sun/star/util/XChangesBatch.hpp> +#include <osl/diagnose.h> + +#include <rtl/ustrbuf.hxx> + +using namespace utl; +using rtl::OUString; +using rtl::OString; +using namespace com::sun::star::uno; +using namespace com::sun::star::util; +using namespace com::sun::star::lang; +using namespace com::sun::star::beans; +using namespace com::sun::star::container; +using namespace com::sun::star::configuration; + +#define C2U(cChar) OUString::createFromAscii(cChar) +#include <cppuhelper/implbase1.hxx> // helper for implementations + +#ifdef DBG_UTIL +inline void lcl_CFG_DBG_EXCEPTION(const sal_Char* cText, const Exception& rEx) +{ + OString sMsg(cText); + sMsg += OString(rEx.Message.getStr(), rEx.Message.getLength(), RTL_TEXTENCODING_ASCII_US); + OSL_ENSURE(sal_False, sMsg.getStr()); +} +#define CATCH_INFO(a) \ +catch(Exception& rEx) \ +{ \ + lcl_CFG_DBG_EXCEPTION(a, rEx);\ +} +#else + #define lcl_CFG_DBG_EXCEPTION( a, b) + #define CATCH_INFO(a) catch(Exception& ){} +#endif + +namespace utl{ + class ConfigChangeListener_Impl : public cppu::WeakImplHelper1 + < + com::sun::star::util::XChangesListener + > + { + ConfigItem* pParent; + const Sequence< OUString > aPropertyNames; + public: + ConfigChangeListener_Impl(ConfigItem& rItem, const Sequence< OUString >& rNames); + ~ConfigChangeListener_Impl(); + + //XChangesListener + virtual void SAL_CALL changesOccurred( const ChangesEvent& Event ) throw(RuntimeException); + + //XEventListener + virtual void SAL_CALL disposing( const EventObject& Source ) throw(RuntimeException); + + }; +/* -----------------------------12.02.01 11:38-------------------------------- + + ---------------------------------------------------------------------------*/ +struct ConfigItem_Impl +{ + utl::ConfigManager* pManager; + sal_Int16 nMode; + sal_Bool bIsModified; + sal_Bool bEnableInternalNotification; + + sal_Int16 nInValueChange; + ConfigItem_Impl() : + pManager(0), + nMode(0), + bIsModified(sal_False), + bEnableInternalNotification(sal_False), + nInValueChange(0) + {} +}; +} +/* -----------------------------04.12.00 10:25-------------------------------- + + ---------------------------------------------------------------------------*/ +class ValueCounter_Impl +{ + sal_Int16& rCnt; +public: + ValueCounter_Impl(sal_Int16& rCounter): + rCnt(rCounter) + {rCnt++;} + ~ValueCounter_Impl() + { + OSL_ENSURE(rCnt>0, "RefCount < 0 ??"); + rCnt--; + } +}; +/* -----------------------------03.12.02 ------------------------------------- + + ---------------------------------------------------------------------------*/ +namespace +{ + // helper to achieve exception - safe handling of an Item under construction + template <class TYP> + class AutoDeleter // : Noncopyable + { + TYP* m_pItem; + public: + AutoDeleter(TYP * pItem) + : m_pItem(pItem) + { + } + + ~AutoDeleter() + { + delete m_pItem; + } + + void keep() { m_pItem = 0; } + }; +} +/* -----------------------------29.08.00 16:34-------------------------------- + + ---------------------------------------------------------------------------*/ +ConfigChangeListener_Impl::ConfigChangeListener_Impl( + ConfigItem& rItem, const Sequence< OUString >& rNames) : + pParent(&rItem), + aPropertyNames(rNames) +{ +} +/* -----------------------------29.08.00 16:34-------------------------------- + + ---------------------------------------------------------------------------*/ +ConfigChangeListener_Impl::~ConfigChangeListener_Impl() +{ +} +/* -----------------------------29.08.00 16:34-------------------------------- + + ---------------------------------------------------------------------------*/ +sal_Bool lcl_Find( + const rtl::OUString& rTemp, + const OUString* pCheckPropertyNames, + sal_Int32 nLength) +{ + //return true if the path is completely correct or if it is longer + //i.e ...Print/Content/Graphic and .../Print + for(sal_Int32 nIndex = 0; nIndex < nLength; nIndex++) + if( isPrefixOfConfigurationPath(rTemp, pCheckPropertyNames[nIndex]) ) + return sal_True; + return sal_False; +} +//----------------------------------------------------------------------------- +void ConfigChangeListener_Impl::changesOccurred( const ChangesEvent& rEvent ) throw(RuntimeException) +{ + const ElementChange* pElementChanges = rEvent.Changes.getConstArray(); + + Sequence<OUString> aChangedNames(rEvent.Changes.getLength()); + OUString* pNames = aChangedNames.getArray(); + + const OUString* pCheckPropertyNames = aPropertyNames.getConstArray(); + + sal_Int32 nNotify = 0; + for(int i = 0; i < aChangedNames.getLength(); i++) + { + OUString sTemp; + pElementChanges[i].Accessor >>= sTemp; + if(lcl_Find(sTemp, pCheckPropertyNames, aPropertyNames.getLength())) + pNames[nNotify++] = sTemp; + } + if(nNotify) + { + aChangedNames.realloc(nNotify); + pParent->CallNotify(aChangedNames); + } +} +/* -----------------------------29.08.00 16:34-------------------------------- + + ---------------------------------------------------------------------------*/ +void ConfigChangeListener_Impl::disposing( const EventObject& /*rSource*/ ) throw(RuntimeException) +{ + pParent->RemoveChangesListener(); +} +/* -----------------------------29.08.00 12:50-------------------------------- + + ---------------------------------------------------------------------------*/ +ConfigItem::ConfigItem(const OUString rSubTree, sal_Int16 nSetMode ) : + sSubTree(rSubTree), + pImpl(new ConfigItem_Impl) +{ + AutoDeleter<ConfigItem_Impl> aNewImpl(pImpl); + + pImpl->pManager = ConfigManager::GetConfigManager(); + pImpl->nMode = nSetMode; + if(0 != (nSetMode&CONFIG_MODE_RELEASE_TREE)) + pImpl->pManager->AddConfigItem(*this); + else + m_xHierarchyAccess = pImpl->pManager->AddConfigItem(*this); + + // no more exceptions after c'tor has finished + aNewImpl.keep(); + pImpl->nMode &= ~CONFIG_MODE_PROPAGATE_ERRORS; +} +/* -----------------------------17.11.00 13:53-------------------------------- + + ---------------------------------------------------------------------------*/ +ConfigItem::ConfigItem(utl::ConfigManager& rManager, const rtl::OUString rSubTree) : + sSubTree(rSubTree), + pImpl(new ConfigItem_Impl) +{ + pImpl->pManager = &rManager; + pImpl->nMode = CONFIG_MODE_IMMEDIATE_UPDATE; // does not allow exceptions + m_xHierarchyAccess = pImpl->pManager->AddConfigItem(*this); +} +//--------------------------------------------------------------------- +//--- 02.08.2002 16:33:23 ----------------------------------------------- +sal_Bool ConfigItem::IsValidConfigMgr() const +{ + return ( pImpl->pManager && pImpl->pManager->GetConfigurationProvider().is() ); +} + +/* -----------------------------29.08.00 12:52-------------------------------- + + ---------------------------------------------------------------------------*/ +ConfigItem::~ConfigItem() +{ + if(pImpl->pManager) + { + RemoveChangesListener(); + pImpl->pManager->RemoveConfigItem(*this); + } + delete pImpl; +} +/* -----------------------------29.08.00 12:52-------------------------------- + + ---------------------------------------------------------------------------*/ +void ConfigItem::Commit() +{ + OSL_ENSURE(sal_False, "Base class called"); +} +/* -----------------------------29.08.00 12:52-------------------------------- + + ---------------------------------------------------------------------------*/ +void ConfigItem::ReleaseConfigMgr() +{ + Reference<XHierarchicalNameAccess> xHierarchyAccess = GetTree(); + if(xHierarchyAccess.is()) + { + try + { + Reference<XChangesBatch> xBatch(xHierarchyAccess, UNO_QUERY); + xBatch->commitChanges(); + } + CATCH_INFO("Exception from commitChanges(): ") + } + RemoveChangesListener(); + OSL_ENSURE(pImpl->pManager, "ConfigManager already released"); + pImpl->pManager = 0; +} +/* -----------------------------29.08.00 12:52-------------------------------- + + ---------------------------------------------------------------------------*/ +void ConfigItem::CallNotify( const com::sun::star::uno::Sequence<OUString>& rPropertyNames ) +{ + if(!IsInValueChange() || pImpl->bEnableInternalNotification) + Notify(rPropertyNames); +} +/* -----------------------------29.08.00 12:52-------------------------------- + + ---------------------------------------------------------------------------*/ +void ConfigItem::Notify( const com::sun::star::uno::Sequence<OUString>& /*rPropertyNames*/) +{ + OSL_ENSURE(sal_False, "Base class called"); +} +/* -----------------------------12.12.00 17:09-------------------------------- + + ---------------------------------------------------------------------------*/ +sal_Bool lcl_IsLocalProperty(const OUString& rSubTree, const OUString& rProperty) +{ + static const sal_Char* aLocalProperties[] = + { + "Office.Common/Path/Current/Storage", + "Office.Common/Path/Current/Temp" + }; + static const int aLocalPropLen[] = + { + 34, + 31 + }; + OUString sProperty(rSubTree); + sProperty += C2U("/"); + sProperty += rProperty; + + if(sProperty.equalsAsciiL( aLocalProperties[0], aLocalPropLen[0]) || + sProperty.equalsAsciiL( aLocalProperties[1], aLocalPropLen[1])) + return sal_True; + + return sal_False; +} +/* -----------------------------10.04.01 15:00-------------------------------- + + ---------------------------------------------------------------------------*/ +void ConfigItem::impl_packLocalizedProperties( const Sequence< OUString >& lInNames , + const Sequence< Any >& lInValues , + Sequence< Any >& lOutValues ) +{ + // Safe impossible cases. + // This method should be called for special ConfigItem-mode only! + OSL_ENSURE( ((pImpl->nMode & CONFIG_MODE_ALL_LOCALES ) == CONFIG_MODE_ALL_LOCALES), "ConfigItem::impl_packLocalizedProperties()\nWrong call of this method detected!\n" ); + + sal_Int32 nSourceCounter ; // used to step during input lists + sal_Int32 nSourceSize ; // marks end of loop over input lists + sal_Int32 nDestinationCounter ; // actual position in output lists + sal_Int32 nPropertyCounter ; // counter of inner loop for Sequence< PropertyValue > + sal_Int32 nPropertiesSize ; // marks end of inner loop + Sequence< OUString > lPropertyNames ; // list of all locales for localized entry + Sequence< PropertyValue > lProperties ; // localized values of an configuration entry packed for return + Reference< XInterface > xLocalizedNode ; // if cfg entry is localized ... lInValues contains an XInterface! + + // Optimise follow algorithm ... A LITTLE BIT :-) + // There exist two different possibilities: + // i ) There exist no localized entries ... => size of lOutValues will be the same like lInNames/lInValues! + // ii) There exist some (mostly one or two) localized entries ... => size of lOutValues will be the same like lInNames/lInValues! + // ... Why? If a localized value exist - the any is filled with an XInterface object (is a SetNode-service). + // We read all his child nodes and pack it into Sequence< PropertyValue >. + // The result list we pack into the return any. We never change size of lists! + nSourceSize = lInNames.getLength(); + lOutValues.realloc( nSourceSize ); + + // Algorithm: + // Copy all names and values from in to out lists. + // Look for special localized entries ... You can detect it as "XInterface" packed into an Any. + // Use this XInterface-object to read all localized values and pack it into Sequence< PropertValue >. + // Add this list to out lists then. + + nDestinationCounter = 0; + for( nSourceCounter=0; nSourceCounter<nSourceSize; ++nSourceCounter ) + { + // If item a special localized one ... convert and pack it ... + if( lInValues[nSourceCounter].getValueTypeName() == C2U("com.sun.star.uno.XInterface") ) + { + lInValues[nSourceCounter] >>= xLocalizedNode; + Reference< XNameContainer > xSetAccess( xLocalizedNode, UNO_QUERY ); + if( xSetAccess.is() == sal_True ) + { + lPropertyNames = xSetAccess->getElementNames() ; + nPropertiesSize = lPropertyNames.getLength() ; + lProperties.realloc( nPropertiesSize ) ; + + for( nPropertyCounter=0; nPropertyCounter<nPropertiesSize; ++nPropertyCounter ) + { + #if OSL_DEBUG_LEVEL > 1 + // Sometimes it's better to see what's going on :-) + OUString sPropName = lInNames[nSourceCounter]; + OUString sLocaleName = lPropertyNames[nPropertyCounter]; + #endif + lProperties[nPropertyCounter].Name = lPropertyNames[nPropertyCounter] ; + OUString sLocaleValue; + xSetAccess->getByName( lPropertyNames[nPropertyCounter] ) >>= sLocaleValue ; + lProperties[nPropertyCounter].Value <<= sLocaleValue; + } + + lOutValues[nDestinationCounter] <<= lProperties; + } + } + // ... or copy normal items to return lists directly. + else + { + lOutValues[nDestinationCounter] = lInValues[nSourceCounter]; + } + ++nDestinationCounter; + } +} +/* -----------------------------10.04.01 15:00-------------------------------- + + ---------------------------------------------------------------------------*/ +void ConfigItem::impl_unpackLocalizedProperties( const Sequence< OUString >& lInNames , + const Sequence< Any >& lInValues , + Sequence< OUString >& lOutNames , + Sequence< Any >& lOutValues ) +{ + // Safe impossible cases. + // This method should be called for special ConfigItem-mode only! + OSL_ENSURE( ((pImpl->nMode & CONFIG_MODE_ALL_LOCALES ) == CONFIG_MODE_ALL_LOCALES), "ConfigItem::impl_unpackLocalizedProperties()\nWrong call of this method detected!\n" ); + + sal_Int32 nSourceCounter ; // used to step during input lists + sal_Int32 nSourceSize ; // marks end of loop over input lists + sal_Int32 nDestinationCounter ; // actual position in output lists + sal_Int32 nPropertyCounter ; // counter of inner loop for Sequence< PropertyValue > + sal_Int32 nPropertiesSize ; // marks end of inner loop + OUString sNodeName ; // base name of node ( e.g. "UIName/" ) ... expand to locale ( e.g. "UIName/de" ) + Sequence< PropertyValue > lProperties ; // localized values of an configuration entry getted from lInValues-Any + + // Optimise follow algorithm ... A LITTLE BIT :-) + // There exist two different possibilities: + // i ) There exist no localized entries ... => size of lOutNames/lOutValues will be the same like lInNames/lInValues! + // ii) There exist some (mostly one or two) localized entries ... => size of lOutNames/lOutValues will be some bytes greater then lInNames/lInValues. + // => I think we should make it fast for i). ii) is a special case and mustn't be SOOOO... fast. + // We should reserve same space for output list like input ones first. + // Follow algorithm looks for these borders and change it for ii) only! + // It will be faster then a "realloc()" call in every loop ... + nSourceSize = lInNames.getLength(); + + lOutNames.realloc ( nSourceSize ); + lOutValues.realloc ( nSourceSize ); + + // Algorithm: + // Copy all names and values from const to return lists. + // Look for special localized entries ... You can detect it as Sequence< PropertyValue > packed into an Any. + // Split it ... insert PropertyValue.Name to lOutNames and PropertyValue.Value to lOutValues. + + nDestinationCounter = 0; + for( nSourceCounter=0; nSourceCounter<nSourceSize; ++nSourceCounter ) + { + // If item a special localized one ... split it and insert his parts to output lists ... + if( lInValues[nSourceCounter].getValueType() == ::getCppuType( (const Sequence< PropertyValue >*)NULL ) ) + { + lInValues[nSourceCounter] >>= lProperties ; + sNodeName = lInNames[nSourceCounter] ; + sNodeName += C2U("/") ; + nPropertiesSize = lProperties.getLength() ; + + if( (nDestinationCounter+nPropertiesSize) > lOutNames.getLength() ) + { + lOutNames.realloc ( nDestinationCounter+nPropertiesSize ); + lOutValues.realloc ( nDestinationCounter+nPropertiesSize ); + } + + for( nPropertyCounter=0; nPropertyCounter<nPropertiesSize; ++nPropertyCounter ) + { + lOutNames [nDestinationCounter] = sNodeName + lProperties[nPropertyCounter].Name ; + lOutValues[nDestinationCounter] = lProperties[nPropertyCounter].Value ; + ++nDestinationCounter; + } + } + // ... or copy normal items to return lists directly. + else + { + if( (nDestinationCounter+1) > lOutNames.getLength() ) + { + lOutNames.realloc ( nDestinationCounter+1 ); + lOutValues.realloc ( nDestinationCounter+1 ); + } + + lOutNames [nDestinationCounter] = lInNames [nSourceCounter]; + lOutValues[nDestinationCounter] = lInValues[nSourceCounter]; + ++nDestinationCounter; + } + } +} +/* -----------------------------03.02.2003 14:44------------------------------ + + ---------------------------------------------------------------------------*/ +Sequence< sal_Bool > ConfigItem::GetReadOnlyStates(const com::sun::star::uno::Sequence< rtl::OUString >& rNames) +{ + sal_Int32 i; + + // size of return list is fix! + // Every item must match to length of incoming name list. + sal_Int32 nCount = rNames.getLength(); + Sequence< sal_Bool > lStates(nCount); + + // We must be shure to return a valid information everytime! + // Set default to non readonly ... similar to the configuration handling of this property. + for ( i=0; i<nCount; ++i) + lStates[i] = sal_False; + + // no access - no informations ... + Reference< XHierarchicalNameAccess > xHierarchyAccess = GetTree(); + if (!xHierarchyAccess.is()) + return lStates; + + for (i=0; i<nCount; ++i) + { + try + { + if(pImpl->pManager->IsLocalConfigProvider() && lcl_IsLocalProperty(sSubTree, rNames[i])) + { + OSL_ENSURE(sal_False, "ConfigItem::IsReadonly()\nlocal mode seams to be used!?\n"); + continue; + } + + OUString sName = rNames[i]; + OUString sPath; + OUString sProperty; + + ::utl::splitLastFromConfigurationPath(sName,sPath,sProperty); + if (!sPath.getLength() && !sProperty.getLength()) + { + OSL_ENSURE(sal_False, "ConfigItem::IsReadonly()\nsplitt failed\n"); + continue; + } + + Reference< XInterface > xNode; + Reference< XPropertySet > xSet ; + Reference< XPropertySetInfo > xInfo; + if (sPath.getLength()) + { + Any aNode = xHierarchyAccess->getByHierarchicalName(sPath); + if (!(aNode >>= xNode) || !xNode.is()) + { + OSL_ENSURE(sal_False, "ConfigItem::IsReadonly()\nno set available\n"); + continue; + } + } + else + { + xNode = Reference< XInterface >(xHierarchyAccess, UNO_QUERY); + } + + xSet = Reference< XPropertySet >(xNode, UNO_QUERY); + if (xSet.is()) + { + xInfo = xSet->getPropertySetInfo(); + OSL_ENSURE(xInfo.is(), "ConfigItem::IsReadonly()\ngetPropertySetInfo failed ...\n"); + } + else + { + xInfo = Reference< XPropertySetInfo >(xNode, UNO_QUERY); + OSL_ENSURE(xInfo.is(), "ConfigItem::IsReadonly()\nUNO_QUERY failed ...\n"); + } + + if (!xInfo.is()) + { + OSL_ENSURE(sal_False, "ConfigItem::IsReadonly()\nno prop info available\n"); + continue; + } + + Property aProp = xInfo->getPropertyByName(sProperty); + lStates[i] = ((aProp.Attributes & PropertyAttribute::READONLY) == PropertyAttribute::READONLY); + } + catch(Exception&){} + } + + return lStates; +} + +/* -----------------------------29.08.00 15:10-------------------------------- + + ---------------------------------------------------------------------------*/ +Sequence< Any > ConfigItem::GetProperties(const Sequence< OUString >& rNames) +{ + Sequence< Any > aRet(rNames.getLength()); + const OUString* pNames = rNames.getConstArray(); + Any* pRet = aRet.getArray(); + Reference<XHierarchicalNameAccess> xHierarchyAccess = GetTree(); + if(xHierarchyAccess.is()) + { + for(int i = 0; i < rNames.getLength(); i++) + { + try + { + if(pImpl->pManager->IsLocalConfigProvider() && lcl_IsLocalProperty(sSubTree, pNames[i])) + { + OUString sProperty(sSubTree); + sProperty += C2U("/"); + sProperty += pNames[i]; + pRet[i] = pImpl->pManager->GetLocalProperty(sProperty); + } + else + pRet[i] = xHierarchyAccess->getByHierarchicalName(pNames[i]); + } + #ifdef DBG_UTIL + catch(Exception& rEx) + { + OString sMsg("XHierarchicalNameAccess: "); + sMsg += OString(rEx.Message.getStr(), + rEx.Message.getLength(), + RTL_TEXTENCODING_ASCII_US); + sMsg += OString("\n"); + sMsg += OString(ConfigManager::GetConfigBaseURL().getStr(), + ConfigManager::GetConfigBaseURL().getLength(), + RTL_TEXTENCODING_ASCII_US); + sMsg += OString(sSubTree.getStr(), + sSubTree.getLength(), + RTL_TEXTENCODING_ASCII_US); + sMsg += OString("/"); + sMsg += OString(pNames[i].getStr(), + pNames[i].getLength(), + RTL_TEXTENCODING_ASCII_US); + OSL_ENSURE(sal_False, sMsg.getStr()); + } +#else + catch(Exception&){} +#endif + } + + // In special mode "ALL_LOCALES" we must convert localized values to Sequence< PropertyValue >. + if((pImpl->nMode & CONFIG_MODE_ALL_LOCALES ) == CONFIG_MODE_ALL_LOCALES) + { + Sequence< Any > lValues; + impl_packLocalizedProperties( rNames, aRet, lValues ); + aRet = lValues; + } + } + return aRet; +} +/* -----------------------------29.08.00 17:28-------------------------------- + + ---------------------------------------------------------------------------*/ +sal_Bool ConfigItem::PutProperties( const Sequence< OUString >& rNames, + const Sequence< Any>& rValues) +{ + ValueCounter_Impl aCounter(pImpl->nInValueChange); + Reference<XHierarchicalNameAccess> xHierarchyAccess = GetTree(); + Reference<XNameReplace> xTopNodeReplace(xHierarchyAccess, UNO_QUERY); + sal_Bool bRet = xHierarchyAccess.is() && xTopNodeReplace.is(); + if(bRet) + { + Sequence< OUString > lNames ; + Sequence< Any > lValues ; + const OUString* pNames = NULL ; + const Any* pValues = NULL ; + sal_Int32 nNameCount ; + if(( pImpl->nMode & CONFIG_MODE_ALL_LOCALES ) == CONFIG_MODE_ALL_LOCALES ) + { + // If ConfigItem works in "ALL_LOCALES"-mode ... we must support a Sequence< PropertyValue > + // as value of an localized configuration entry! + // How we can do that? + // We must split all PropertyValues to "Sequence< OUString >" AND "Sequence< Any >"! + impl_unpackLocalizedProperties( rNames, rValues, lNames, lValues ); + pNames = lNames.getConstArray (); + pValues = lValues.getConstArray (); + nNameCount = lNames.getLength (); + } + else + { + // This is the normal mode ... + // Use given input lists directly. + pNames = rNames.getConstArray (); + pValues = rValues.getConstArray (); + nNameCount = rNames.getLength (); + } + for(int i = 0; i < nNameCount; i++) + { + if(pImpl->pManager->IsLocalConfigProvider() && lcl_IsLocalProperty(sSubTree, pNames[i])) + { + OUString sProperty(sSubTree); + sProperty += C2U("/"); + sProperty += pNames[i]; + pImpl->pManager->PutLocalProperty(sProperty, pValues[i]); + } + else + { + try + { + OUString sNode, sProperty; + if (splitLastFromConfigurationPath(pNames[i],sNode, sProperty)) + { + Any aNode = xHierarchyAccess->getByHierarchicalName(sNode); + + Reference<XNameAccess> xNodeAcc; + aNode >>= xNodeAcc; + Reference<XNameReplace> xNodeReplace(xNodeAcc, UNO_QUERY); + Reference<XNameContainer> xNodeCont (xNodeAcc, UNO_QUERY); + + sal_Bool bExist = (xNodeAcc.is() && xNodeAcc->hasByName(sProperty)); + if (bExist && xNodeReplace.is()) + xNodeReplace->replaceByName(sProperty, pValues[i]); + else + if (!bExist && xNodeCont.is()) + xNodeCont->insertByName(sProperty, pValues[i]); + else + bRet = sal_False; + } + else //direct value + { + xTopNodeReplace->replaceByName(sProperty, pValues[i]); + } + } + CATCH_INFO("Exception from PutProperties: "); + } + } + try + { + Reference<XChangesBatch> xBatch(xHierarchyAccess, UNO_QUERY); + xBatch->commitChanges(); + } + CATCH_INFO("Exception from commitChanges(): ") + } + + return bRet; +} +/* -----------------------------08.12.05 15:27-------------------------------- + + ---------------------------------------------------------------------------*/ +void ConfigItem::DisableNotification() +{ + OSL_ENSURE( xChangeLstnr.is(), "ConfigItem::DisableNotification: notifications not enabled currently!" ); + RemoveChangesListener(); +} +/* -----------------------------29.08.00 16:19-------------------------------- + + ---------------------------------------------------------------------------*/ +sal_Bool ConfigItem::EnableNotification(const Sequence< OUString >& rNames, + sal_Bool bEnableInternalNotification ) + +{ + OSL_ENSURE(0 == (pImpl->nMode&CONFIG_MODE_RELEASE_TREE), "notification in CONFIG_MODE_RELEASE_TREE mode not possible"); + pImpl->bEnableInternalNotification = bEnableInternalNotification; + Reference<XHierarchicalNameAccess> xHierarchyAccess = GetTree(); + Reference<XChangesNotifier> xChgNot(xHierarchyAccess, UNO_QUERY); + if(!xChgNot.is()) + return sal_False; + + OSL_ENSURE(!xChangeLstnr.is(), "EnableNotification already called"); + if(xChangeLstnr.is()) + xChgNot->removeChangesListener( xChangeLstnr ); + sal_Bool bRet = sal_True; + + try + { + xChangeLstnr = new ConfigChangeListener_Impl(*this, rNames); + xChgNot->addChangesListener( xChangeLstnr ); + } + catch(RuntimeException& ) + { + bRet = sal_False; + } + return bRet; +} +/* -----------------------------29.08.00 16:47-------------------------------- + + ---------------------------------------------------------------------------*/ +void ConfigItem::RemoveChangesListener() +{ + Reference<XChangesNotifier> xChgNot(m_xHierarchyAccess, UNO_QUERY); + if(xChgNot.is() && xChangeLstnr.is()) + { + try + { + xChgNot->removeChangesListener( xChangeLstnr ); + xChangeLstnr = 0; + } + catch(Exception & ) + { + } + } +} +/* -----------------------------10.07.00 -------------------------------- + + ---------------------------------------------------------------------------*/ +void lcl_normalizeLocalNames(Sequence< OUString >& _rNames, ConfigNameFormat _eFormat, Reference<XInterface> const& _xParentNode) +{ + switch (_eFormat) + { + case CONFIG_NAME_LOCAL_NAME: + // unaltered - this is our input format + break; + + case CONFIG_NAME_FULL_PATH: + { + Reference<XHierarchicalName> xFormatter(_xParentNode, UNO_QUERY); + if (xFormatter.is()) + { + OUString * pNames = _rNames.getArray(); + for(int i = 0; i<_rNames.getLength(); ++i) + try + { + pNames[i] = xFormatter->composeHierarchicalName(pNames[i]); + } + CATCH_INFO("Exception from composeHierarchicalName(): ") + break; + } + } + OSL_ENSURE(false, "Cannot create absolute pathes: missing interface"); + // make local pathes instaed + + case CONFIG_NAME_LOCAL_PATH: + { + Reference<XTemplateContainer> xTypeContainer(_xParentNode, UNO_QUERY); + if (xTypeContainer.is()) + { + OUString sTypeName = xTypeContainer->getElementTemplateName(); + sTypeName = sTypeName.copy(sTypeName.lastIndexOf('/')+1); + + OUString * pNames = _rNames.getArray(); + for(int i = 0; i<_rNames.getLength(); ++i) + { + pNames[i] = wrapConfigurationElementName(pNames[i],sTypeName); + } + } + else + { + static const OUString sSetService(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.SetAccess")); + Reference<XServiceInfo> xSVI(_xParentNode, UNO_QUERY); + if (xSVI.is() && xSVI->supportsService(sSetService)) + { + OUString * pNames = _rNames.getArray(); + for(int i = 0; i<_rNames.getLength(); ++i) + { + pNames[i] = wrapConfigurationElementName(pNames[i]); + } + } + } + } + break; + + case CONFIG_NAME_PLAINTEXT_NAME: + { + Reference<XStringEscape> xEscaper(_xParentNode, UNO_QUERY); + if (xEscaper.is()) + { + OUString * pNames = _rNames.getArray(); + for(int i = 0; i<_rNames.getLength(); ++i) + try + { + pNames[i] = xEscaper->unescapeString(pNames[i]); + } + CATCH_INFO("Exception from unescapeString(): ") + } + } + break; + + } +} +/* -----------------------------10.07.00 -------------------------------- + + ---------------------------------------------------------------------------*/ +Sequence< OUString > ConfigItem::GetNodeNames(const OUString& rNode) +{ + ConfigNameFormat const eDefaultFormat = CONFIG_NAME_LOCAL_NAME; // CONFIG_NAME_DEFAULT; + + return GetNodeNames(rNode, eDefaultFormat); +} +/* -----------------------------15.09.00 12:06-------------------------------- + + ---------------------------------------------------------------------------*/ +Sequence< OUString > ConfigItem::GetNodeNames(const OUString& rNode, ConfigNameFormat eFormat) +{ + Sequence< OUString > aRet; + Reference<XHierarchicalNameAccess> xHierarchyAccess = GetTree(); + if(xHierarchyAccess.is()) + { + try + { + Reference<XNameAccess> xCont; + if(rNode.getLength()) + { + Any aNode = xHierarchyAccess->getByHierarchicalName(rNode); + aNode >>= xCont; + } + else + xCont = Reference<XNameAccess> (xHierarchyAccess, UNO_QUERY); + if(xCont.is()) + { + aRet = xCont->getElementNames(); + lcl_normalizeLocalNames(aRet,eFormat,xCont); + } + + } + CATCH_INFO("Exception from GetNodeNames: "); + } + return aRet; +} +/* -----------------------------15.09.00 15:52-------------------------------- + + ---------------------------------------------------------------------------*/ +sal_Bool ConfigItem::ClearNodeSet(const OUString& rNode) +{ + ValueCounter_Impl aCounter(pImpl->nInValueChange); + sal_Bool bRet = sal_False; + Reference<XHierarchicalNameAccess> xHierarchyAccess = GetTree(); + if(xHierarchyAccess.is()) + { + try + { + Reference<XNameContainer> xCont; + if(rNode.getLength()) + { + Any aNode = xHierarchyAccess->getByHierarchicalName(rNode); + aNode >>= xCont; + } + else + xCont = Reference<XNameContainer> (xHierarchyAccess, UNO_QUERY); + if(!xCont.is()) + return sal_False; + Sequence< OUString > aNames = xCont->getElementNames(); + const OUString* pNames = aNames.getConstArray(); + Reference<XChangesBatch> xBatch(xHierarchyAccess, UNO_QUERY); + for(sal_Int32 i = 0; i < aNames.getLength(); i++) + { + try + { + xCont->removeByName(pNames[i]); + } + CATCH_INFO("Exception from removeByName(): ") + } + xBatch->commitChanges(); + bRet = sal_True; + } + CATCH_INFO("Exception from ClearNodeSet") + } + return bRet; +} +/* -----------------------------24.11.00 10:58-------------------------------- + + ---------------------------------------------------------------------------*/ +sal_Bool ConfigItem::ClearNodeElements(const OUString& rNode, Sequence< OUString >& rElements) +{ + ValueCounter_Impl aCounter(pImpl->nInValueChange); + sal_Bool bRet = sal_False; + Reference<XHierarchicalNameAccess> xHierarchyAccess = GetTree(); + if(xHierarchyAccess.is()) + { + const OUString* pElements = rElements.getConstArray(); + try + { + Reference<XNameContainer> xCont; + if(rNode.getLength()) + { + Any aNode = xHierarchyAccess->getByHierarchicalName(rNode); + aNode >>= xCont; + } + else + xCont = Reference<XNameContainer> (xHierarchyAccess, UNO_QUERY); + if(!xCont.is()) + return sal_False; + try + { + for(sal_Int32 nElement = 0; nElement < rElements.getLength(); nElement++) + { + xCont->removeByName(pElements[nElement]); + } + Reference<XChangesBatch> xBatch(xHierarchyAccess, UNO_QUERY); + xBatch->commitChanges(); + } + CATCH_INFO("Exception from commitChanges(): ") + bRet = sal_True; + } + CATCH_INFO("Exception from GetNodeNames: ") + } + return bRet; +} +//---------------------------------------------------------------------------- +static inline +OUString lcl_extractSetPropertyName( const OUString& rInPath, const OUString& rPrefix ) +{ + OUString const sSubPath = dropPrefixFromConfigurationPath( rInPath, rPrefix); + return extractFirstFromConfigurationPath( sSubPath ); +} +//---------------------------------------------------------------------------- +static +Sequence< OUString > lcl_extractSetPropertyNames( const Sequence< PropertyValue >& rValues, const OUString& rPrefix ) +{ + const PropertyValue* pProperties = rValues.getConstArray(); + + Sequence< OUString > aSubNodeNames(rValues.getLength()); + OUString* pSubNodeNames = aSubNodeNames.getArray(); + + OUString sLastSubNode; + sal_Int32 nSubIndex = 0; + + for(sal_Int32 i = 0; i < rValues.getLength(); i++) + { + OUString const sSubPath = dropPrefixFromConfigurationPath( pProperties[i].Name, rPrefix); + OUString const sSubNode = extractFirstFromConfigurationPath( sSubPath ); + + if(sLastSubNode != sSubNode) + { + pSubNodeNames[nSubIndex++] = sSubNode; + } + + sLastSubNode = sSubNode; + } + aSubNodeNames.realloc(nSubIndex); + + return aSubNodeNames; +} +/* -----------------------------15.09.00 15:52-------------------------------- + add or change properties + ---------------------------------------------------------------------------*/ +sal_Bool ConfigItem::SetSetProperties( + const OUString& rNode, Sequence< PropertyValue > rValues) +{ + ValueCounter_Impl aCounter(pImpl->nInValueChange); + sal_Bool bRet = sal_True; + Reference<XHierarchicalNameAccess> xHierarchyAccess = GetTree(); + if(xHierarchyAccess.is()) + { + Reference<XChangesBatch> xBatch(xHierarchyAccess, UNO_QUERY); + try + { + Reference<XNameContainer> xCont; + if(rNode.getLength()) + { + Any aNode = xHierarchyAccess->getByHierarchicalName(rNode); + aNode >>= xCont; + } + else + xCont = Reference<XNameContainer> (xHierarchyAccess, UNO_QUERY); + if(!xCont.is()) + return sal_False; + + Reference<XSingleServiceFactory> xFac(xCont, UNO_QUERY); + + if(xFac.is()) + { + const Sequence< OUString > aSubNodeNames = lcl_extractSetPropertyNames(rValues, rNode); + + const sal_Int32 nSubNodeCount = aSubNodeNames.getLength(); + + for(sal_Int32 j = 0; j <nSubNodeCount ; j++) + { + if(!xCont->hasByName(aSubNodeNames[j])) + { + Reference<XInterface> xInst = xFac->createInstance(); + Any aVal; aVal <<= xInst; + xCont->insertByName(aSubNodeNames[j], aVal); + } + //set values + } + try + { + xBatch->commitChanges(); + } + CATCH_INFO("Exception from commitChanges(): ") + + const PropertyValue* pProperties = rValues.getConstArray(); + + Sequence< OUString > aSetNames(rValues.getLength()); + OUString* pSetNames = aSetNames.getArray(); + + Sequence< Any> aSetValues(rValues.getLength()); + Any* pSetValues = aSetValues.getArray(); + + sal_Bool bEmptyNode = rNode.getLength() == 0; + for(sal_Int32 k = 0; k < rValues.getLength(); k++) + { + pSetNames[k] = pProperties[k].Name.copy( bEmptyNode ? 1 : 0); + pSetValues[k] = pProperties[k].Value; + } + bRet = PutProperties(aSetNames, aSetValues); + } + else + { + //if no factory is available then the node contains basic data elements + const PropertyValue* pValues = rValues.getConstArray(); + for(int nValue = 0; nValue < rValues.getLength();nValue++) + { + try + { + OUString sSubNode = lcl_extractSetPropertyName( pValues[nValue].Name, rNode ); + + if(xCont->hasByName(sSubNode)) + xCont->replaceByName(sSubNode, pValues[nValue].Value); + else + xCont->insertByName(sSubNode, pValues[nValue].Value); + + OSL_ENSURE( xHierarchyAccess->hasByHierarchicalName(pValues[nValue].Name), + "Invalid config path" ); + } + CATCH_INFO("Exception form insert/replaceByName(): ") + } + xBatch->commitChanges(); + } + } +#ifdef DBG_UTIL + catch(Exception& rEx) + { + lcl_CFG_DBG_EXCEPTION("Exception from SetSetProperties: ", rEx); +#else + catch(Exception&) + { +#endif + bRet = sal_False; + } + } + return bRet; +} +/* -----------------------------15.09.00 15:52-------------------------------- + + ---------------------------------------------------------------------------*/ +sal_Bool ConfigItem::ReplaceSetProperties( + const OUString& rNode, Sequence< PropertyValue > rValues) +{ + ValueCounter_Impl aCounter(pImpl->nInValueChange); + sal_Bool bRet = sal_True; + Reference<XHierarchicalNameAccess> xHierarchyAccess = GetTree(); + if(xHierarchyAccess.is()) + { + Reference<XChangesBatch> xBatch(xHierarchyAccess, UNO_QUERY); + try + { + Reference<XNameContainer> xCont; + if(rNode.getLength()) + { + Any aNode = xHierarchyAccess->getByHierarchicalName(rNode); + aNode >>= xCont; + } + else + xCont = Reference<XNameContainer> (xHierarchyAccess, UNO_QUERY); + if(!xCont.is()) + return sal_False; + + // JB: Change: now the same name handling for sets of simple values + const Sequence< OUString > aSubNodeNames = lcl_extractSetPropertyNames(rValues, rNode); + const OUString* pSubNodeNames = aSubNodeNames.getConstArray(); + const sal_Int32 nSubNodeCount = aSubNodeNames.getLength(); + + Reference<XSingleServiceFactory> xFac(xCont, UNO_QUERY); + const bool isSimpleValueSet = !xFac.is(); + + //remove unknown members first + { + const Sequence<OUString> aContainerSubNodes = xCont->getElementNames(); + const OUString* pContainerSubNodes = aContainerSubNodes.getConstArray(); + + for(sal_Int32 nContSub = 0; nContSub < aContainerSubNodes.getLength(); nContSub++) + { + sal_Bool bFound = sal_False; + for(sal_Int32 j = 0; j < nSubNodeCount; j++) + { + if(pSubNodeNames[j] == pContainerSubNodes[nContSub]) + { + bFound = sal_True; + break; + } + } + if(!bFound) + try + { + xCont->removeByName(pContainerSubNodes[nContSub]); + } + catch (Exception & ) + { + if (isSimpleValueSet) + try + { + // #i37322#: fallback action: replace with <void/> + xCont->replaceByName(pContainerSubNodes[nContSub], Any()); + // fallback successfull: continue looping + continue; + } + catch (Exception &) + {} // propagate original exception, if fallback fails + + throw; + } + } + try { xBatch->commitChanges(); } + CATCH_INFO("Exception from commitChanges(): ") + } + + if(xFac.is()) // !isSimpleValueSet + { + for(sal_Int32 j = 0; j < nSubNodeCount; j++) + { + if(!xCont->hasByName(pSubNodeNames[j])) + { + //create if not available + Reference<XInterface> xInst = xFac->createInstance(); + Any aVal; aVal <<= xInst; + xCont->insertByName(pSubNodeNames[j], aVal); + } + } + try { xBatch->commitChanges(); } + CATCH_INFO("Exception from commitChanges(): ") + + const PropertyValue* pProperties = rValues.getConstArray(); + + Sequence< OUString > aSetNames(rValues.getLength()); + OUString* pSetNames = aSetNames.getArray(); + + Sequence< Any> aSetValues(rValues.getLength()); + Any* pSetValues = aSetValues.getArray(); + + sal_Bool bEmptyNode = rNode.getLength() == 0; + for(sal_Int32 k = 0; k < rValues.getLength(); k++) + { + pSetNames[k] = pProperties[k].Name.copy( bEmptyNode ? 1 : 0); + pSetValues[k] = pProperties[k].Value; + } + bRet = PutProperties(aSetNames, aSetValues); + } + else + { + const PropertyValue* pValues = rValues.getConstArray(); + + //if no factory is available then the node contains basic data elements + for(int nValue = 0; nValue < rValues.getLength();nValue++) + { + try + { + OUString sSubNode = lcl_extractSetPropertyName( pValues[nValue].Name, rNode ); + + if(xCont->hasByName(sSubNode)) + xCont->replaceByName(sSubNode, pValues[nValue].Value); + else + xCont->insertByName(sSubNode, pValues[nValue].Value); + } + CATCH_INFO("Exception from insert/replaceByName(): "); + } + xBatch->commitChanges(); + } + } +#ifdef DBG_UTIL + catch(Exception& rEx) + { + lcl_CFG_DBG_EXCEPTION("Exception from ReplaceSetProperties: ", rEx); +#else + catch(Exception&) + { +#endif + bRet = sal_False; + } + } + return bRet; +} +/* -----------------------------07.05.01 12:15-------------------------------- + + ---------------------------------------------------------------------------*/ +sal_Bool ConfigItem::getUniqueSetElementName( const ::rtl::OUString& _rSetNode, ::rtl::OUString& _rName) +{ + ::rtl::OUString sNewElementName; + Reference<XHierarchicalNameAccess> xHierarchyAccess = GetTree(); + sal_Bool bRet = sal_False; + if(xHierarchyAccess.is()) + { + try + { + Reference< XNameAccess > xSetNode; + xHierarchyAccess->getByHierarchicalName(_rSetNode) >>= xSetNode; + if (xSetNode.is()) + { + const sal_uInt32 nPrime = 65521; // a prime number + const sal_uInt32 nPrimeLess2 = nPrime - 2; + sal_uInt32 nEngendering = (rand() % nPrimeLess2) + 2; // the engendering of the field + + // the element which will loop through the field + sal_uInt32 nFieldElement = nEngendering; + + for (; 1 != nFieldElement; nFieldElement = (nFieldElement * nEngendering) % nPrime) + { + ::rtl::OUString sThisRoundTrial = _rName; + sThisRoundTrial += ::rtl::OUString::valueOf((sal_Int32)nFieldElement); + + if (!xSetNode->hasByName(sThisRoundTrial)) + { + _rName = sThisRoundTrial; + bRet = sal_True; + break; + } + } + } + } + CATCH_INFO("Exception from getUniqueSetElementName(): ") + } + return bRet; +} +/* -----------------------------23.01.01 12:49-------------------------------- + + ---------------------------------------------------------------------------*/ +sal_Bool ConfigItem::AddNode(const rtl::OUString& rNode, const rtl::OUString& rNewNode) +{ + ValueCounter_Impl aCounter(pImpl->nInValueChange); + sal_Bool bRet = sal_True; + Reference<XHierarchicalNameAccess> xHierarchyAccess = GetTree(); + if(xHierarchyAccess.is()) + { + Reference<XChangesBatch> xBatch(xHierarchyAccess, UNO_QUERY); + try + { + Reference<XNameContainer> xCont; + if(rNode.getLength()) + { + Any aNode = xHierarchyAccess->getByHierarchicalName(rNode); + aNode >>= xCont; + } + else + xCont = Reference<XNameContainer> (xHierarchyAccess, UNO_QUERY); + if(!xCont.is()) + return sal_False; + + Reference<XSingleServiceFactory> xFac(xCont, UNO_QUERY); + + if(xFac.is()) + { + if(!xCont->hasByName(rNewNode)) + { + Reference<XInterface> xInst = xFac->createInstance(); + Any aVal; aVal <<= xInst; + xCont->insertByName(rNewNode, aVal); + } + try + { + xBatch->commitChanges(); + } + CATCH_INFO("Exception from commitChanges(): ") + } + else + { + //if no factory is available then the node contains basic data elements + try + { + if(!xCont->hasByName(rNewNode)) + xCont->insertByName(rNewNode, Any()); + } + CATCH_INFO("Exception from AddNode(): ") + } + xBatch->commitChanges(); + } +#ifdef DBG_UTIL + catch(Exception& rEx) + { + lcl_CFG_DBG_EXCEPTION("Exception from AddNode(): ", rEx); +#else + catch(Exception&) + { +#endif + bRet = sal_False; + } + } + return bRet; +} +/* -----------------------------12.02.01 11:38-------------------------------- + + ---------------------------------------------------------------------------*/ +sal_Int16 ConfigItem::GetMode() const +{ + return pImpl->nMode; +} +/* -----------------------------12.02.01 13:31-------------------------------- + + ---------------------------------------------------------------------------*/ +void ConfigItem::SetModified() +{ + pImpl->bIsModified = sal_True; +} +/* -----------------------------05.05.01 14:07-------------------------------- + + ---------------------------------------------------------------------------*/ +void ConfigItem::ClearModified() +{ + pImpl->bIsModified = sal_False; +} +/* -----------------------------12.02.01 13:31-------------------------------- + + ---------------------------------------------------------------------------*/ +sal_Bool ConfigItem::IsModified() const +{ + return pImpl->bIsModified; +} +/* -----------------------------12.02.01 13:33-------------------------------- + + ---------------------------------------------------------------------------*/ +sal_Bool ConfigItem::IsInValueChange() const +{ + return pImpl->nInValueChange > 0; +} +/* -----------------------------21.06.01 12:26-------------------------------- + + ---------------------------------------------------------------------------*/ +Reference< XHierarchicalNameAccess> ConfigItem::GetTree() +{ + Reference< XHierarchicalNameAccess> xRet; + if(!m_xHierarchyAccess.is()) + xRet = pImpl->pManager->AcquireTree(*this); + else + xRet = m_xHierarchyAccess; + OSL_ENSURE(xRet.is(), "AcquireTree failed"); + return xRet; +} +/* -----------------------------22.06.01 08:42-------------------------------- + + ---------------------------------------------------------------------------*/ +void ConfigItem::LockTree() +{ + OSL_ENSURE(0 != (pImpl->nMode&CONFIG_MODE_RELEASE_TREE), "call LockTree in CONFIG_MODE_RELEASE_TREE mode, only"); + m_xHierarchyAccess = GetTree(); +} +/* -----------------------------22.06.01 08:42-------------------------------- + + ---------------------------------------------------------------------------*/ +void ConfigItem::UnlockTree() +{ + OSL_ENSURE(0 != (pImpl->nMode&CONFIG_MODE_RELEASE_TREE), "call UnlockTree in CONFIG_MODE_RELEASE_TREE mode, only"); + if(0 != (pImpl->nMode&CONFIG_MODE_RELEASE_TREE)) + m_xHierarchyAccess = 0; +} + + + diff --git a/unotools/source/config/configmgr.cxx b/unotools/source/config/configmgr.cxx new file mode 100644 index 000000000000..6a5d163871cd --- /dev/null +++ b/unotools/source/config/configmgr.cxx @@ -0,0 +1,735 @@ +/************************************************************************* + * + * 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: configmgr.cxx,v $ + * $Revision: 1.47.14.1 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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_unotools.hxx" +#include "unotools/configmgr.hxx" +#include "unotools/configitem.hxx" +#include "unotools/configpathes.hxx" +#include <unotools/processfactory.hxx> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/container/XHierarchicalNameAccess.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <osl/diagnose.h> +#include <rtl/bootstrap.hxx> +#include <rtl/instance.hxx> +#if OSL_DEBUG_LEVEL > 0 +#include <rtl/strbuf.hxx> +#endif + +#include <list> + +//----------------------------------------------------------------------------- + +using namespace utl; +using namespace rtl; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::beans; +using namespace com::sun::star::container; + +#define C2U(cChar) OUString::createFromAscii(cChar) +#define UNISTRING(s) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s)) + +//----------------------------------------------------------------------------- +const char* cConfigBaseURL = "/org.openoffice."; +//const char* cConfigBaseURL = "/com.sun.star."; +const char* cAccessSrvc = "com.sun.star.configuration.ConfigurationUpdateAccess"; + +namespace +{ + struct BrandName + : public rtl::Static< ::rtl::OUString, BrandName > {}; + struct ProductVersion + : public rtl::Static< ::rtl::OUString, ProductVersion > {}; + struct AboutBoxProductVersion + : public rtl::Static< ::rtl::OUString, AboutBoxProductVersion > {}; + struct ProductExtension + : public rtl::Static< ::rtl::OUString, ProductExtension > {}; + struct XMLFileFormatName + : public rtl::Static< ::rtl::OUString, XMLFileFormatName > {}; + struct XMLFileFormatVersion + : public rtl::Static< ::rtl::OUString, XMLFileFormatVersion > {}; + struct WriterCompatibilityVersionOOo11 + : public rtl::Static< ::rtl::OUString, WriterCompatibilityVersionOOo11 > {}; + struct OpenSourceContext : public rtl::StaticWithInit< sal_Int32, OpenSourceContext > + { + sal_Int32 operator() () { return sal_Int32( -1 ); } + }; + +} + +//----------------------------------------------------------------------------- +struct ConfigItemListEntry_Impl +{ + ConfigItem* pConfigItem; + + ConfigItemListEntry_Impl(ConfigItem* pItem ) : + pConfigItem(pItem){} +}; +typedef std::list<ConfigItemListEntry_Impl> ConfigItemList; +struct utl::ConfigMgr_Impl +{ + ConfigItemList aItemList; +}; + +/* -----------------------------28.08.00 15:35-------------------------------- + + ---------------------------------------------------------------------------*/ +ConfigManager::ConfigManager() : + pMgrImpl(new utl::ConfigMgr_Impl) +{ + GetConfigurationProvider(); // attempt to create the provider early +} +/* -----------------------------17.11.00 13:51-------------------------------- + + ---------------------------------------------------------------------------*/ +ConfigManager::ConfigManager(Reference< XMultiServiceFactory > xConfigProv) : + xConfigurationProvider(xConfigProv), + pMgrImpl(new utl::ConfigMgr_Impl) +{ +} +/* -----------------------------28.08.00 15:35-------------------------------- + + ---------------------------------------------------------------------------*/ +ConfigManager::~ConfigManager() +{ + //check list content -> should be empty! + OSL_ENSURE(pMgrImpl->aItemList.empty(), "some ConfigItems are still alive"); + if(!pMgrImpl->aItemList.empty()) + { + ConfigItemList::iterator aListIter; + for(aListIter = pMgrImpl->aItemList.begin(); aListIter != pMgrImpl->aItemList.end(); ++aListIter) + { + ConfigItemListEntry_Impl& rEntry = *aListIter; + rEntry.pConfigItem->ReleaseConfigMgr(); + } + pMgrImpl->aItemList.erase(pMgrImpl->aItemList.begin(), pMgrImpl->aItemList.end()); + } + delete pMgrImpl; + +} +/* -----------------------------28.08.00 16:17-------------------------------- + + ---------------------------------------------------------------------------*/ +Reference< XMultiServiceFactory > ConfigManager::GetConfigurationProvider() +{ + if(!xConfigurationProvider.is()) + { + Reference< XMultiServiceFactory > xMSF = ::utl::getProcessServiceFactory(); + if ( xMSF.is() ) + { + try + { + xConfigurationProvider = Reference< XMultiServiceFactory > + (xMSF->createInstance( + C2U("com.sun.star.configuration.ConfigurationProvider")), + UNO_QUERY); + } +#ifdef DBG_UTIL + catch(Exception& rEx) + { + static sal_Bool bMessage = sal_True; + if(bMessage) + { + bMessage = sal_False; + OString sMsg("CreateInstance with arguments exception: "); + sMsg += OString(rEx.Message.getStr(), + rEx.Message.getLength(), + RTL_TEXTENCODING_ASCII_US); + OSL_ENSURE(sal_False, sMsg.getStr()); + } + } +#else + catch(Exception&){} +#endif + } + } + return xConfigurationProvider; +} +/* -----------------------------03.12.02 ------------------------------------- + + ---------------------------------------------------------------------------*/ +namespace +{ + // helper to achieve exception - safe registration of a ConfigItem under construction + class RegisterConfigItemHelper // : Noncopyable + { + utl::ConfigManager & rCfgMgr; + utl::ConfigItem* pCfgItem; + public: + RegisterConfigItemHelper(utl::ConfigManager & rMgr, utl::ConfigItem& rCfgItem) + : rCfgMgr(rMgr) + , pCfgItem(&rCfgItem) + { + rCfgMgr.RegisterConfigItem(rCfgItem); + } + + ~RegisterConfigItemHelper() + { + if (pCfgItem) rCfgMgr.RemoveConfigItem(*pCfgItem); + } + + void keep() { pCfgItem = 0; } + }; +} +/* -----------------------------12.12.00 17:19-------------------------------- + + ---------------------------------------------------------------------------*/ +Reference< XMultiServiceFactory > ConfigManager::GetLocalConfigurationProvider() +{ + return GetConfigurationProvider(); +} +/* -----------------------------29.08.00 12:35-------------------------------- + + ---------------------------------------------------------------------------*/ +Reference< XHierarchicalNameAccess > ConfigManager::AddConfigItem(utl::ConfigItem& rCfgItem) +{ + RegisterConfigItemHelper registeredItem(*this,rCfgItem); + Reference< XHierarchicalNameAccess > xTree = AcquireTree(rCfgItem); + registeredItem.keep(); + return xTree; +} +/* -----------------------------21.06.01 12:20-------------------------------- + + ---------------------------------------------------------------------------*/ +void ConfigManager::RegisterConfigItem(utl::ConfigItem& rCfgItem) +{ + ConfigItemList::iterator aListIter = pMgrImpl->aItemList.begin(); +#ifdef DBG_UTIL + for(aListIter = pMgrImpl->aItemList.begin(); aListIter != pMgrImpl->aItemList.end(); ++aListIter) + { + ConfigItemListEntry_Impl& rEntry = *aListIter; + if(rEntry.pConfigItem == &rCfgItem) + OSL_ENSURE(sal_False, "RegisterConfigItem: already inserted!"); + } +#endif + pMgrImpl->aItemList.insert(aListIter, ConfigItemListEntry_Impl(&rCfgItem)); +} +/* -----------------------------21.06.01 12:20-------------------------------- + + ---------------------------------------------------------------------------*/ +Reference< XHierarchicalNameAccess> ConfigManager::AcquireTree(utl::ConfigItem& rCfgItem) +{ + ConfigItemList::iterator aListIter = pMgrImpl->aItemList.begin(); +#ifdef DBG_UTIL + sal_Bool bFound = sal_False; + for(aListIter = pMgrImpl->aItemList.begin(); aListIter != pMgrImpl->aItemList.end(); ++aListIter) + { + ConfigItemListEntry_Impl& rEntry = *aListIter; + if(rEntry.pConfigItem == &rCfgItem) + { + bFound = sal_True; + break; + } + } + OSL_ENSURE(bFound, "AcquireTree: ConfigItem unknown!"); +#endif + OUString sPath = C2U(cConfigBaseURL); + sPath += rCfgItem.GetSubTreeName(); + Sequence< Any > aArgs(2); + Any* pArgs = aArgs.getArray(); + PropertyValue aPath; + aPath.Name = C2U("nodepath"); + aPath.Value <<= sPath; + pArgs[0] <<= aPath; + sal_Bool bLazy = 0 != (rCfgItem.GetMode()&CONFIG_MODE_DELAYED_UPDATE); + PropertyValue aUpdate; + aUpdate.Name = C2U("lazywrite"); + aUpdate.Value.setValue(&bLazy, ::getBooleanCppuType()); + pArgs[1] <<= aUpdate; + + // Initialize item with support for reading/writing more then one locales at same time! + // It's neccessary for creation of a complete configuration entry without changing office locale + // at runtime. + if((rCfgItem.GetMode() & CONFIG_MODE_ALL_LOCALES) == CONFIG_MODE_ALL_LOCALES) + { + sal_Int32 nCount = aArgs.getLength(); + aArgs.realloc(nCount+1); + + PropertyValue aAllLocale; + aAllLocale.Name = C2U("locale"); + aAllLocale.Value <<= C2U("*" ); + aArgs[nCount] <<= aAllLocale; + } + + Reference< XMultiServiceFactory > xCfgProvider = GetConfigurationProvider(); + Reference< XInterface > xIFace; + if(xCfgProvider.is()) + { + try + { + xIFace = xCfgProvider->createInstanceWithArguments( + C2U(cAccessSrvc), + aArgs); + } + catch(Exception& rEx) + { + if (CONFIG_MODE_PROPAGATE_ERRORS & rCfgItem.GetMode()) + { + OSL_TRACE("ConfigItem: Propagating creation error: %s\n", + OUStringToOString(rEx.Message,RTL_TEXTENCODING_ASCII_US).getStr()); + + throw; + } +#ifdef DBG_UTIL + if(0 == (CONFIG_MODE_IGNORE_ERRORS & rCfgItem.GetMode())) + { + OString sMsg("CreateInstance exception: "); + sMsg += OString(rEx.Message.getStr(), + rEx.Message.getLength(), + RTL_TEXTENCODING_ASCII_US); + OSL_ENSURE(sal_False, sMsg.getStr()); + } +#endif + } + } + return Reference<XHierarchicalNameAccess>(xIFace, UNO_QUERY); +} +/* -----------------------------29.08.00 12:35-------------------------------- + + ---------------------------------------------------------------------------*/ +void ConfigManager::RemoveConfigItem(utl::ConfigItem& rCfgItem) +{ + if( !pMgrImpl->aItemList.empty() ) + { + ConfigItemList::iterator aListIter = pMgrImpl->aItemList.begin(); + for(aListIter = pMgrImpl->aItemList.begin(); aListIter != pMgrImpl->aItemList.end(); ++aListIter) + { + ConfigItemListEntry_Impl& rEntry = *aListIter; + if(rEntry.pConfigItem == &rCfgItem) + { + pMgrImpl->aItemList.erase(aListIter); + break; + } + } + } +} +/* -----------------------------30.08.00 15:04-------------------------------- + + ---------------------------------------------------------------------------*/ +void ConfigManager::StoreConfigItems() +{ + if(!pMgrImpl->aItemList.empty()) + { + ConfigItemList::iterator aListIter = pMgrImpl->aItemList.begin(); + for(aListIter = pMgrImpl->aItemList.begin(); aListIter != pMgrImpl->aItemList.end(); ++aListIter) + { + ConfigItemListEntry_Impl& rEntry = *aListIter; + if(rEntry.pConfigItem->IsModified()) + { + rEntry.pConfigItem->Commit(); + rEntry.pConfigItem->ClearModified(); + } + } + } +} +ConfigManager* ConfigManager::pConfigManager = 0; +/* -----------------------------07.09.00 11:06-------------------------------- + + ---------------------------------------------------------------------------*/ +ConfigManager* ConfigManager::GetConfigManager() +{ + if(!pConfigManager) + { + pConfigManager = new ConfigManager(); + } + return pConfigManager; +} +/* -----------------------------07.09.00 11:06-------------------------------- + + ---------------------------------------------------------------------------*/ +void ConfigManager::RemoveConfigManager() +{ + if(pConfigManager) + { + delete pConfigManager; + pConfigManager = 0; + } +} +/* -----------------------------08.09.00 13:22-------------------------------- + + ---------------------------------------------------------------------------*/ +rtl::OUString ConfigManager::GetConfigBaseURL() +{ + return C2U(cConfigBaseURL); +} +/* -----------------------------25.09.00 16:34-------------------------------- + + ---------------------------------------------------------------------------*/ +Any ConfigManager::GetDirectConfigProperty(ConfigProperty eProp) +{ + switch(eProp) + { + case INSTALLPATH: + OSL_ENSURE( false, + "ConfigManager::GetDirectConfigProperty: " + "INSTALLPATH no longer supported." ); + return Any(); + case USERINSTALLURL: + OSL_ENSURE( false, + "ConfigManager::GetDirectConfigProperty: " + "USERINSTALLURL no longer supported." ); + return Any(); + case OFFICEINSTALL: + OSL_ENSURE( false, + "ConfigManager::GetDirectConfigProperty: " + "OFFICEINSTALL no longer supported." ); + return Any(); + case OFFICEINSTALLURL: + OSL_ENSURE( false, + "ConfigManager::GetDirectConfigProperty: " + "OFFICEINSTALLURL no longer supported." ); + return Any(); + default: + break; + } + + Any aRet; + ::rtl::OUString &rBrandName = BrandName::get(); + if ( eProp == PRODUCTNAME && rBrandName.getLength() ) + { + aRet <<= rBrandName; + return aRet; + } + + rtl::OUString &rProductVersion = ProductVersion::get(); + if ( eProp == PRODUCTVERSION && rProductVersion.getLength() ) + { + aRet <<= rProductVersion; + return aRet; + } + + rtl::OUString &rAboutBoxProductVersion = AboutBoxProductVersion::get(); + if ( eProp == ABOUTBOXPRODUCTVERSION && rAboutBoxProductVersion.getLength() ) + { + aRet <<= rAboutBoxProductVersion; + return aRet; + } + + rtl::OUString &rProductExtension = ProductExtension::get(); + if ( eProp == PRODUCTEXTENSION && rProductExtension.getLength() ) + { + aRet <<= rProductExtension; + return aRet; + } + + rtl::OUString &rXMLFileFormatName = XMLFileFormatName::get(); + if ( eProp == PRODUCTXMLFILEFORMATNAME && rXMLFileFormatName.getLength() ) + { + aRet <<= rXMLFileFormatName; + return aRet; + } + + rtl::OUString &rXMLFileFormatVersion = XMLFileFormatVersion::get(); + if ( eProp == PRODUCTXMLFILEFORMATVERSION && rXMLFileFormatVersion.getLength() ) + { + aRet <<= rXMLFileFormatVersion; + return aRet; + } + + sal_Int32 &rOpenSourceContext = OpenSourceContext::get(); + if ( eProp == OPENSOURCECONTEXT && ( rOpenSourceContext >= 0 ) ) + { + aRet <<= rOpenSourceContext; + return aRet; + } + + rtl::OUString &rWriterCompatibilityVersionOOo11 = WriterCompatibilityVersionOOo11::get(); + if ( eProp == WRITERCOMPATIBILITYVERSIONOOO11 && rWriterCompatibilityVersionOOo11.getLength() ) + { + aRet <<= rWriterCompatibilityVersionOOo11; + return aRet; + } + + if (eProp == PRODUCTEXTENSION) { + rtl::OUString name( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "${BRAND_BASE_DIR}/program/edition/edition.ini"))); + rtl::Bootstrap::expandMacros(name); + if (rtl::Bootstrap(name).getFrom( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("EDITIONNAME")), + rProductExtension)) + { + return com::sun::star::uno::Any(rProductExtension); + } + } + + OUString sPath = C2U(cConfigBaseURL); + switch(eProp) + { + case LOCALE: sPath += C2U("Setup/L10N"); break; + + case PRODUCTNAME: + case PRODUCTVERSION: + case PRODUCTEXTENSION: + case PRODUCTXMLFILEFORMATNAME : + case PRODUCTXMLFILEFORMATVERSION: + case OPENSOURCECONTEXT: + case ABOUTBOXPRODUCTVERSION: sPath += C2U("Setup/Product"); break; + + case DEFAULTCURRENCY: sPath += C2U("Setup/L10N"); break; + + case WRITERCOMPATIBILITYVERSIONOOO11: + sPath += C2U("Office.Compatibility/WriterCompatibilityVersion"); break; + default: + break; + } + Sequence< Any > aArgs(1); + aArgs[0] <<= sPath; + Reference< XMultiServiceFactory > xCfgProvider = GetConfigManager()->GetConfigurationProvider(); + if(!xCfgProvider.is()) + return aRet; + Reference< XInterface > xIFace; + try + { + xIFace = xCfgProvider->createInstanceWithArguments( + C2U(cAccessSrvc), + aArgs); + + } + catch(Exception&){} + Reference<XNameAccess> xDirectAccess(xIFace, UNO_QUERY); + if(xDirectAccess.is()) + { + OUString sProperty; + switch(eProp) + { + case LOCALE: sProperty = C2U("ooLocale"); break; + case PRODUCTNAME: sProperty = C2U("ooName"); break; + case PRODUCTVERSION: sProperty = C2U("ooSetupVersion"); break; + case ABOUTBOXPRODUCTVERSION: sProperty = C2U("ooSetupVersionAboutBox"); break; + case PRODUCTEXTENSION: sProperty = C2U("ooSetupExtension"); break; + case PRODUCTXMLFILEFORMATNAME: sProperty = C2U("ooXMLFileFormatName"); break; + case PRODUCTXMLFILEFORMATVERSION: sProperty = C2U("ooXMLFileFormatVersion"); break; + case OPENSOURCECONTEXT: sProperty = C2U("ooOpenSourceContext"); break; + case DEFAULTCURRENCY: sProperty = C2U("ooSetupCurrency"); break; + case WRITERCOMPATIBILITYVERSIONOOO11: sProperty = C2U("OOo11"); break; + default: + break; + } + try + { + aRet = xDirectAccess->getByName(sProperty); + } + catch(Exception&) + { + #if OSL_DEBUG_LEVEL > 0 + rtl::OStringBuffer aBuf(256); + aBuf.append( "ConfigManager::GetDirectConfigProperty: could not retrieve the property \"" ); + aBuf.append( rtl::OUStringToOString( sProperty, RTL_TEXTENCODING_ASCII_US ) ); + aBuf.append( "\" under \"" ); + aBuf.append( rtl::OUStringToOString( sPath, RTL_TEXTENCODING_ASCII_US ) ); + aBuf.append( "\" (caught an exception)!" ); + OSL_ENSURE( sal_False, aBuf.getStr() ); + #endif + } + } + + if ( eProp == PRODUCTNAME ) + aRet >>= rBrandName; + + if ( eProp == PRODUCTXMLFILEFORMATNAME ) + aRet >>= rXMLFileFormatName; + + if ( eProp == PRODUCTXMLFILEFORMATVERSION ) + aRet >>= rXMLFileFormatVersion; + + if ( eProp == PRODUCTVERSION ) + aRet >>= rProductVersion; + + if ( eProp == ABOUTBOXPRODUCTVERSION ) + { + aRet >>= rAboutBoxProductVersion; + getBasisAboutBoxProductVersion( rAboutBoxProductVersion ); + aRet <<= rAboutBoxProductVersion; + } + + if ( eProp == PRODUCTEXTENSION ) + aRet >>= rProductExtension; + + if ( eProp == WRITERCOMPATIBILITYVERSIONOOO11 ) + aRet >>= rWriterCompatibilityVersionOOo11; + + if ( eProp == OPENSOURCECONTEXT ) + aRet >>= rOpenSourceContext; + + return aRet; +} + +/*---------------------------------------------------------------------------*/ +void ConfigManager::getBasisAboutBoxProductVersion( OUString& rVersion ) +{ + rtl::OUString aPackageVersion = UNISTRING( "${$OOO_BASE_DIR/program/" SAL_CONFIGFILE("version") ":OOOPackageVersion}" ); + rtl::Bootstrap::expandMacros( aPackageVersion ); + + if ( aPackageVersion.getLength() ) + { + sal_Int32 nTokIndex = 0; + rtl::OUString aVersionMinor = aPackageVersion.getToken( 1, '.', nTokIndex ); + rtl::OUString aVersionMicro; + + if ( nTokIndex > 0 ) + aVersionMicro = aPackageVersion.getToken( 0, '.', nTokIndex ); + + if ( aVersionMinor.getLength() == 0 ) + aVersionMinor = UNISTRING( "0" ); + if ( aVersionMicro.getLength() == 0 ) + aVersionMicro = UNISTRING( "0" ); + + sal_Int32 nIndex = rVersion.indexOf( '.' ); + if ( nIndex == -1 ) + { + rVersion += UNISTRING( "." ); + rVersion += aVersionMinor; + } + else + { + nIndex = rVersion.indexOf( '.', nIndex+1 ); + } + if ( nIndex == -1 ) + { + rVersion += UNISTRING( "." ); + rVersion += aVersionMicro; + } + else + { + rVersion = rVersion.replaceAt( nIndex+1, rVersion.getLength()-nIndex-1, aVersionMicro ); + } + } +} + +/* -----------------------------12.12.00 17:22-------------------------------- + + ---------------------------------------------------------------------------*/ +Reference< XHierarchicalNameAccess> ConfigManager::GetHierarchyAccess(const OUString& rFullPath) +{ + Sequence< Any > aArgs(1); + aArgs[0] <<= rFullPath; + Reference< XMultiServiceFactory > xCfgProvider = GetLocalConfigurationProvider(); + Reference< XInterface > xIFace; + if(xCfgProvider.is()) + { + try + { + xIFace = xCfgProvider->createInstanceWithArguments( + C2U(cAccessSrvc), + aArgs); + } +#ifdef DBG_UTIL + catch(Exception& rEx) + { + OString sMsg("CreateInstance exception: "); + sMsg += OString(rEx.Message.getStr(), + rEx.Message.getLength(), + RTL_TEXTENCODING_ASCII_US); + OSL_ENSURE(sal_False, sMsg.getStr()); + } +#else + catch(Exception&){} +#endif + } + return Reference<XHierarchicalNameAccess>(xIFace, UNO_QUERY); +} +/* -----------------------------12.12.00 17:17-------------------------------- + + ---------------------------------------------------------------------------*/ +Any ConfigManager::GetLocalProperty(const OUString& rProperty) +{ + OUString sPath = C2U(cConfigBaseURL); + sPath += rProperty; + + OUString sNode, sProperty; + OSL_VERIFY( splitLastFromConfigurationPath(sPath, sNode, sProperty) ); + + Reference< XNameAccess> xAccess( GetHierarchyAccess(sNode), UNO_QUERY ); + Any aRet; + try + { + if(xAccess.is()) + aRet = xAccess->getByName(sProperty); + } +#ifdef DBG_UTIL + catch(Exception& rEx) + { + OString sMsg("GetLocalProperty: "); + sMsg += OString(rEx.Message.getStr(), + rEx.Message.getLength(), + RTL_TEXTENCODING_ASCII_US); + OSL_ENSURE(sal_False, sMsg.getStr()); + } +#else + catch(Exception&){} +#endif + return aRet; +} +/* -----------------------------12.12.00 17:17-------------------------------- + + ---------------------------------------------------------------------------*/ +void ConfigManager::PutLocalProperty(const OUString& rProperty, const Any& rValue) +{ + OUString sPath = C2U(cConfigBaseURL); + sPath += rProperty; + + OUString sNode, sProperty; + OSL_VERIFY( splitLastFromConfigurationPath(sPath, sNode, sProperty) ); + + Reference<XNameReplace> xNodeReplace(GetHierarchyAccess(sNode), UNO_QUERY); + if(xNodeReplace.is()) + { + try + { + xNodeReplace->replaceByName(sProperty, rValue); + } +#ifdef DBG_UTIL + catch(Exception& rEx) + { + OString sMsg("PutLocalProperty: "); + sMsg += OString(rEx.Message.getStr(), + rEx.Message.getLength(), + RTL_TEXTENCODING_ASCII_US); + OSL_ENSURE(sal_False, sMsg.getStr()); + } +#else + catch(Exception& ){} +#endif + } +} +/* -----------------------------13.12.00 08:47-------------------------------- + + ---------------------------------------------------------------------------*/ +sal_Bool ConfigManager::IsLocalConfigProvider() +{ + return false; +} + diff --git a/unotools/source/config/confignode.cxx b/unotools/source/config/confignode.cxx new file mode 100644 index 000000000000..4b1b9fe272db --- /dev/null +++ b/unotools/source/config/confignode.cxx @@ -0,0 +1,705 @@ +/************************************************************************* + * + * 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: confignode.cxx,v $ + * $Revision: 1.12 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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_unotools.hxx" + +#include <unotools/confignode.hxx> +#include <unotools/configpathes.hxx> +#include <tools/diagnose_ex.h> +#include <osl/diagnose.h> +#include <com/sun/star/container/XHierarchicalName.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/util/XStringEscape.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <comphelper/extract.hxx> +#include <rtl/string.hxx> +#if OSL_DEBUG_LEVEL > 0 +#include <rtl/strbuf.hxx> +#endif + +//........................................................................ +namespace utl +{ +//........................................................................ + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::util; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::container; + + //======================================================================== + //= OConfigurationNode + //======================================================================== + //------------------------------------------------------------------------ + OConfigurationNode::OConfigurationNode(const Reference< XInterface >& _rxNode, const Reference< XMultiServiceFactory >& _rxProvider) + :m_xProvider(_rxProvider) + ,m_bEscapeNames(sal_False) + { + OSL_ENSURE(_rxNode.is(), "OConfigurationNode::OConfigurationNode: invalid node interface!"); + if (_rxNode.is()) + { + // collect all interfaces necessary + m_xHierarchyAccess = Reference< XHierarchicalNameAccess >(_rxNode, UNO_QUERY); + m_xDirectAccess = Reference< XNameAccess >(_rxNode, UNO_QUERY); + + // reset _all_ interfaces if _one_ of them is not supported + if (!m_xHierarchyAccess.is() || !m_xDirectAccess.is()) + { + m_xHierarchyAccess = NULL; + m_xDirectAccess = NULL; + } + + // now for the non-critical interfaces + m_xReplaceAccess = Reference< XNameReplace >(_rxNode, UNO_QUERY); + m_xContainerAccess = Reference< XNameContainer >(_rxNode, UNO_QUERY); + } + + Reference< XComponent > xConfigNodeComp(m_xDirectAccess, UNO_QUERY); + if (xConfigNodeComp.is()) + startComponentListening(xConfigNodeComp); + + if (isValid()) + setEscape(isSetNode()); + } + + //------------------------------------------------------------------------ + OConfigurationNode::OConfigurationNode(const OConfigurationNode& _rSource) + :OEventListenerAdapter() + ,m_xHierarchyAccess(_rSource.m_xHierarchyAccess) + ,m_xDirectAccess(_rSource.m_xDirectAccess) + ,m_xReplaceAccess(_rSource.m_xReplaceAccess) + ,m_xContainerAccess(_rSource.m_xContainerAccess) + ,m_xProvider(_rSource.m_xProvider) + ,m_bEscapeNames(_rSource.m_bEscapeNames) + ,m_sCompletePath(_rSource.m_sCompletePath) + { + Reference< XComponent > xConfigNodeComp(m_xDirectAccess, UNO_QUERY); + if (xConfigNodeComp.is()) + startComponentListening(xConfigNodeComp); + } + + //------------------------------------------------------------------------ + const OConfigurationNode& OConfigurationNode::operator=(const OConfigurationNode& _rSource) + { + stopAllComponentListening(); + + m_xHierarchyAccess = _rSource.m_xHierarchyAccess; + m_xDirectAccess = _rSource.m_xDirectAccess; + m_xContainerAccess = _rSource.m_xContainerAccess; + m_xReplaceAccess = _rSource.m_xReplaceAccess; + m_xProvider = _rSource.m_xProvider; + m_bEscapeNames = _rSource.m_bEscapeNames; + m_sCompletePath = _rSource.m_sCompletePath; + + Reference< XComponent > xConfigNodeComp(m_xDirectAccess, UNO_QUERY); + if (xConfigNodeComp.is()) + startComponentListening(xConfigNodeComp); + + return *this; + } + + //------------------------------------------------------------------------ + void OConfigurationNode::_disposing( const EventObject& _rSource ) + { + Reference< XComponent > xDisposingSource(_rSource.Source, UNO_QUERY); + Reference< XComponent > xConfigNodeComp(m_xDirectAccess, UNO_QUERY); + if (xDisposingSource.get() == xConfigNodeComp.get()) + clear(); + } + + //------------------------------------------------------------------------ + ::rtl::OUString OConfigurationNode::normalizeName(const ::rtl::OUString& _rName, NAMEORIGIN _eOrigin) const + { + ::rtl::OUString sName(_rName); + if (getEscape()) + { + Reference< XStringEscape > xEscaper(m_xDirectAccess, UNO_QUERY); + OSL_ENSURE(xEscaper.is(), "OConfigurationNode::normalizeName: missing an interface!"); + if (xEscaper.is() && sName.getLength()) + { + try + { + if (NO_CALLER == _eOrigin) + sName = xEscaper->escapeString(sName); + else + sName = xEscaper->unescapeString(sName); + } + catch(IllegalArgumentException&) + { + OSL_ENSURE(sal_False, "OConfigurationNode::normalizeName: illegal argument (caught an exception saying so)!"); + } + catch(Exception&) + { + OSL_ENSURE(sal_False, "OConfigurationNode::normalizeName: caught an exception!"); + } + } + } + return sName; + } + + //------------------------------------------------------------------------ + Sequence< ::rtl::OUString > OConfigurationNode::getNodeNames() const throw() + { + OSL_ENSURE(m_xDirectAccess.is(), "OConfigurationNode::getNodeNames: object is invalid!"); + Sequence< ::rtl::OUString > aReturn; + if (m_xDirectAccess.is()) + { + try + { + aReturn = m_xDirectAccess->getElementNames(); + // normalize the names + ::rtl::OUString* pNames = aReturn.getArray(); + for (sal_Int32 i=0; i<aReturn.getLength(); ++i, ++pNames) + *pNames = normalizeName(*pNames, NO_CONFIGURATION); + } + catch(Exception&) + { + OSL_ENSURE(sal_False, "OConfigurationNode::getNodeNames: caught a generic exception!"); + } + } + + return aReturn; + } + + //------------------------------------------------------------------------ + sal_Bool OConfigurationNode::removeNode(const ::rtl::OUString& _rName) const throw() + { + OSL_ENSURE(m_xContainerAccess.is(), "OConfigurationNode::removeNode: object is invalid!"); + if (m_xContainerAccess.is()) + { + try + { + ::rtl::OUString sName = normalizeName(_rName, NO_CALLER); + m_xContainerAccess->removeByName(sName); + return sal_True; + } + catch (NoSuchElementException&) + { + #if OSL_DEBUG_LEVEL > 0 + rtl::OStringBuffer aBuf( 256 ); + aBuf.append("OConfigurationNode::removeNode: there is no element named!"); + aBuf.append( rtl::OUStringToOString( _rName, RTL_TEXTENCODING_ASCII_US ) ); + aBuf.append( "!" ); + OSL_ENSURE(sal_False, aBuf.getStr()); + #endif + } + catch (WrappedTargetException&) + { + OSL_ENSURE(sal_False, "OConfigurationNode::removeNode: caught a WrappedTargetException!"); + } + catch(Exception&) + { + OSL_ENSURE(sal_False, "OConfigurationNode::removeNode: caught a generic exception!"); + } + } + return sal_False; + } + //------------------------------------------------------------------------ + OConfigurationNode OConfigurationNode::insertNode(const ::rtl::OUString& _rName,const Reference< XInterface >& _xNode) const throw() + { + if(_xNode.is()) + { + try + { + ::rtl::OUString sName = normalizeName(_rName, NO_CALLER); + m_xContainerAccess->insertByName(sName, makeAny(_xNode)); + // if we're here, all was ok ... + return OConfigurationNode(_xNode, m_xProvider); + } + catch(const Exception&) + { + DBG_UNHANDLED_EXCEPTION(); + } + + // dispose the child if it has already been created, but could not be inserted + Reference< XComponent > xChildComp(_xNode, UNO_QUERY); + if (xChildComp.is()) + try { xChildComp->dispose(); } catch(Exception&) { } + } + + return OConfigurationNode(); + } + //------------------------------------------------------------------------ + OConfigurationNode OConfigurationNode::createNode(const ::rtl::OUString& _rName) const throw() + { + Reference< XSingleServiceFactory > xChildFactory(m_xContainerAccess, UNO_QUERY); + OSL_ENSURE(xChildFactory.is(), "OConfigurationNode::createNode: object is invalid or read-only!"); + + if (xChildFactory.is()) // implies m_xContainerAccess.is() + { + Reference< XInterface > xNewChild; + try + { + xNewChild = xChildFactory->createInstance(); + } + catch(const Exception&) + { + DBG_UNHANDLED_EXCEPTION(); + } + return insertNode(_rName,xNewChild); + } + + return OConfigurationNode(); + } + + //------------------------------------------------------------------------ + OConfigurationNode OConfigurationNode::appendNode(const ::rtl::OUString& _rName,const OConfigurationNode& _aNewNode) const throw() + { + return insertNode(_rName,_aNewNode.m_xDirectAccess); + } + //------------------------------------------------------------------------ + OConfigurationNode OConfigurationNode::openNode(const ::rtl::OUString& _rPath) const throw() + { + OSL_ENSURE(m_xDirectAccess.is(), "OConfigurationNode::openNode: object is invalid!"); + OSL_ENSURE(m_xHierarchyAccess.is(), "OConfigurationNode::openNode: object is invalid!"); + try + { + ::rtl::OUString sNormalized = normalizeName(_rPath, NO_CALLER); + + Reference< XInterface > xNode; + if (m_xDirectAccess.is() && m_xDirectAccess->hasByName(sNormalized)) + { + if (!::cppu::extractInterface(xNode, m_xDirectAccess->getByName(sNormalized))) + OSL_ENSURE(sal_False, "OConfigurationNode::openNode: could not open the node!"); + } + else if (m_xHierarchyAccess.is()) + { + if (!::cppu::extractInterface(xNode, m_xHierarchyAccess->getByHierarchicalName(_rPath))) + OSL_ENSURE(sal_False, "OConfigurationNode::openNode: could not open the node!"); + } + if (xNode.is()) + return OConfigurationNode(xNode, m_xProvider); + } + catch(NoSuchElementException& e) + { + (void)e; + #if OSL_DEBUG_LEVEL > 0 + rtl::OStringBuffer aBuf( 256 ); + aBuf.append("OConfigurationNode::openNode: there is no element named "); + aBuf.append( rtl::OUStringToOString( _rPath, RTL_TEXTENCODING_ASCII_US ) ); + aBuf.append("!"); + OSL_ENSURE(sal_False, aBuf.getStr()); + #endif + } + catch(Exception&) + { + OSL_ENSURE(sal_False, "OConfigurationNode::openNode: caught an exception while retrieving the node!"); + } + return OConfigurationNode(); + } + + //------------------------------------------------------------------------ + void OConfigurationNode::setEscape(sal_Bool _bEnable) + { + m_bEscapeNames = _bEnable && Reference< XStringEscape >::query(m_xDirectAccess).is(); + OSL_ENSURE(m_bEscapeNames || !_bEnable, + "OConfigurationNode::setEscape: escaping not enabled - missing the appropriate interface on the node!"); + } + + //------------------------------------------------------------------------ + sal_Bool OConfigurationNode::isSetNode() const + { + sal_Bool bIsSet = sal_False; + Reference< XServiceInfo > xSI(m_xHierarchyAccess, UNO_QUERY); + if (xSI.is()) + { + try { bIsSet = xSI->supportsService(::rtl::OUString::createFromAscii("com.sun.star.configuration.SetAccess")); } + catch(Exception&) { } + } + return bIsSet; + } + + //--------------------------------------------------------------------- + //--- 20.08.01 19:03:20 ----------------------------------------------- + + sal_Bool OConfigurationNode::hasByHierarchicalName( const ::rtl::OUString& _rName ) const throw() + { + OSL_ENSURE( m_xHierarchyAccess.is(), "OConfigurationNode::hasByHierarchicalName: no hierarchy access!" ); + try + { + if ( m_xHierarchyAccess.is() ) + { + ::rtl::OUString sName = normalizeName( _rName, NO_CALLER ); + return m_xHierarchyAccess->hasByHierarchicalName( sName ); + } + } + catch(Exception&) + { + } + return sal_False; + } + + //------------------------------------------------------------------------ + sal_Bool OConfigurationNode::hasByName(const ::rtl::OUString& _rName) const throw() + { + OSL_ENSURE(m_xDirectAccess.is(), "OConfigurationNode::hasByName: object is invalid!"); + try + { + ::rtl::OUString sName = normalizeName(_rName, NO_CALLER); + if (m_xDirectAccess.is()) + return m_xDirectAccess->hasByName(sName); + } + catch(Exception&) + { + } + return sal_False; + } + + //------------------------------------------------------------------------ + sal_Bool OConfigurationNode::setNodeValue(const ::rtl::OUString& _rPath, const Any& _rValue) const throw() + { + sal_Bool bResult = false; + + OSL_ENSURE(m_xReplaceAccess.is(), "OConfigurationNode::setNodeValue: object is invalid!"); + if (m_xReplaceAccess.is()) + { + try + { + // check if _rPath is a level-1 path + ::rtl::OUString sNormalizedName = normalizeName(_rPath, NO_CALLER); + if (m_xReplaceAccess->hasByName(sNormalizedName)) + { + m_xReplaceAccess->replaceByName(sNormalizedName, _rValue); + bResult = true; + } + + // check if the name refers to a indirect descendant + else if (m_xHierarchyAccess.is() && m_xHierarchyAccess->hasByHierarchicalName(_rPath)) + { + OSL_ASSERT(_rPath.getLength()); + + ::rtl::OUString sParentPath, sLocalName; + + if ( splitLastFromConfigurationPath(_rPath, sParentPath, sLocalName) ) + { + OConfigurationNode aParentAccess = openNode(sParentPath); + if (aParentAccess.isValid()) + bResult = aParentAccess.setNodeValue(sLocalName, _rValue); + } + else + { + m_xReplaceAccess->replaceByName(sLocalName, _rValue); + bResult = true; + } + } + + } + catch(IllegalArgumentException&) + { + OSL_ENSURE(sal_False, "OConfigurationNode::setNodeValue: could not replace the value: caught an IllegalArgumentException!"); + } + catch(NoSuchElementException&) + { + OSL_ENSURE(sal_False, "OConfigurationNode::setNodeValue: could not replace the value: caught a NoSuchElementException!"); + } + catch(WrappedTargetException&) + { + OSL_ENSURE(sal_False, "OConfigurationNode::setNodeValue: could not replace the value: caught a WrappedTargetException!"); + } + catch(Exception&) + { + OSL_ENSURE(sal_False, "OConfigurationNode::setNodeValue: could not replace the value: caught a generic Exception!"); + } + + + } + return bResult; + } + + //------------------------------------------------------------------------ + Any OConfigurationNode::getNodeValue(const ::rtl::OUString& _rPath) const throw() + { + OSL_ENSURE(m_xDirectAccess.is(), "OConfigurationNode::hasByName: object is invalid!"); + OSL_ENSURE(m_xHierarchyAccess.is(), "OConfigurationNode::hasByName: object is invalid!"); + Any aReturn; + try + { + ::rtl::OUString sNormalizedPath = normalizeName(_rPath, NO_CALLER); + if (m_xDirectAccess.is() && m_xDirectAccess->hasByName(sNormalizedPath) ) + { + aReturn = m_xDirectAccess->getByName(sNormalizedPath); + } + else if (m_xHierarchyAccess.is()) + { + aReturn = m_xHierarchyAccess->getByHierarchicalName(_rPath); + } + } + catch(NoSuchElementException& e) + { + #if OSL_DEBUG_LEVEL > 0 + rtl::OStringBuffer aBuf( 256 ); + aBuf.append("OConfigurationNode::getNodeValue: caught a NoSuchElementException while trying to open "); + aBuf.append( rtl::OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US ) ); + OSL_ENSURE(sal_False, aBuf.getStr()); + #else + (void)e; + #endif + } + return aReturn; + } + + //------------------------------------------------------------------------ + OConfigurationTreeRoot OConfigurationNode::cloneAsRoot() const throw() + { + OSL_ENSURE(m_xHierarchyAccess.is(), "OConfigurationNode::cloneAsRoot: object is invalid!"); + if (m_xHierarchyAccess.is()) + { + // first get the complete path of the node we represent + ::rtl::OUString sCompletePath; + Reference< XHierarchicalName > xNodeNameAccess(m_xHierarchyAccess, UNO_QUERY); + if (xNodeNameAccess.is()) + { + try + { + sCompletePath = xNodeNameAccess->getHierarchicalName(); + OSL_ENSURE(sCompletePath.getLength(), "OConfigurationNode::cloneAsRoot: invalid path retrieved!"); + } + catch(Exception&) + { + OSL_ENSURE(sal_False, "OConfigurationNode::cloneAsRoot: could not retrieve the node path!"); + } + } + + // then create a new tree root object with that path and our provider + OSL_ENSURE(m_xProvider.is(), "OConfigurationNode::cloneAsRoot: have an invalid provider!"); + if (sCompletePath.getLength() && m_xProvider.is()) + { + return OConfigurationTreeRoot::createWithProvider(m_xProvider, sCompletePath, -1, isReadonly() ? OConfigurationTreeRoot::CM_READONLY : OConfigurationTreeRoot::CM_PREFER_UPDATABLE); + } + } + return OConfigurationTreeRoot(); + } + + //------------------------------------------------------------------------ + void OConfigurationNode::clear() throw() + { + m_xHierarchyAccess.clear(); + m_xDirectAccess.clear(); + m_xReplaceAccess.clear(); + m_xContainerAccess.clear(); + } + + //======================================================================== + //= OConfigurationTreeRoot + //======================================================================== + //------------------------------------------------------------------------ + OConfigurationTreeRoot::OConfigurationTreeRoot(const Reference< XChangesBatch >& _rxRootNode, const Reference< XMultiServiceFactory >& _rxProvider) + :OConfigurationNode(_rxRootNode.get(), _rxProvider) + ,m_xCommitter(_rxRootNode) + { + } + + //------------------------------------------------------------------------ + OConfigurationTreeRoot::OConfigurationTreeRoot(const Reference< XInterface >& _rxRootNode, const Reference< XMultiServiceFactory >& _rxProvider) + :OConfigurationNode(_rxRootNode.get(), _rxProvider) + { + } + + //------------------------------------------------------------------------ + void OConfigurationTreeRoot::clear() throw() + { + OConfigurationNode::clear(); + m_xCommitter.clear(); + } + + //------------------------------------------------------------------------ + sal_Bool OConfigurationTreeRoot::commit() const throw() + { + OSL_ENSURE(isValid(), "OConfigurationTreeRoot::commit: object is invalid!"); + if (!isValid()) + return sal_False; + OSL_ENSURE(m_xCommitter.is(), "OConfigurationTreeRoot::commit: I'm a readonly node!"); + if (!m_xCommitter.is()) + return sal_False; + + try + { + m_xCommitter->commitChanges(); + return sal_True; + } + catch(WrappedTargetException&) + { + OSL_ENSURE(sal_False, "OConfigurationTreeRoot::commit: caught a WrappedTargetException!"); + } + catch(RuntimeException&) + { + OSL_ENSURE(sal_False, "OConfigurationTreeRoot::commit: caught a RuntimeException!"); + } + return sal_False; + } + + namespace + { + static const ::rtl::OUString& lcl_getProviderServiceName( ) + { + static ::rtl::OUString s_sProviderServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationProvider" ) ); + return s_sProviderServiceName; + } + } + + //------------------------------------------------------------------------ + OConfigurationTreeRoot OConfigurationTreeRoot::createWithProvider(const Reference< XMultiServiceFactory >& _rxConfProvider, const ::rtl::OUString& _rPath, sal_Int32 _nDepth, CREATION_MODE _eMode, sal_Bool _bLazyWrite) + { + OSL_ENSURE(_rxConfProvider.is(), "OConfigurationTreeRoot::createWithProvider: invalid provider!"); + +#ifdef DBG_UTIL + if (_rxConfProvider.is()) + { + try + { + Reference< XServiceInfo > xSI(_rxConfProvider, UNO_QUERY); + if (!xSI.is()) + { + OSL_ENSURE(sal_False, "OConfigurationTreeRoot::createWithProvider: no XServiceInfo interface on the provider!"); + } + else + { + OSL_ENSURE(xSI->supportsService( lcl_getProviderServiceName( ) ), + "OConfigurationTreeRoot::createWithProvider: sure this is a provider? Missing the ConfigurationProvider service!"); + } + } + catch(const Exception&) + { + OSL_ENSURE(sal_False, "OConfigurationTreeRoot::createWithProvider: unable to check the service conformance of the provider given!"); + } + } +#endif + + sal_Bool bTryAgain(sal_False); + do + { + if (_rxConfProvider.is()) + { + try + { + Sequence< Any > aCreationArgs(3); + aCreationArgs[0] = makeAny(PropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("nodepath")), 0, makeAny(_rPath), PropertyState_DIRECT_VALUE)); + aCreationArgs[1] = makeAny(PropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("depth")), 0, makeAny((sal_Int32)_nDepth), PropertyState_DIRECT_VALUE)); + aCreationArgs[2] = makeAny(PropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("lazywrite")), 0, ::cppu::bool2any(_bLazyWrite), PropertyState_DIRECT_VALUE)); + + ::rtl::OUString sAccessService = ::rtl::OUString::createFromAscii(CM_READONLY == _eMode + ? "com.sun.star.configuration.ConfigurationAccess" + : "com.sun.star.configuration.ConfigurationUpdateAccess"); + + Reference< XInterface > xRoot = _rxConfProvider->createInstanceWithArguments(sAccessService, aCreationArgs); + if (!xRoot.is()) + { + OSL_ENSURE(sal_False, "OConfigurationTreeRoot::createWithProvider: could not create the node access!"); + } + else if (CM_READONLY == _eMode) + { + return OConfigurationTreeRoot(xRoot, _rxConfProvider); + } + else + { // get the changes batch interface + Reference< XChangesBatch > xCommitter(xRoot, UNO_QUERY); + if (xCommitter.is()) + return OConfigurationTreeRoot(xCommitter, _rxConfProvider); + else + OSL_ENSURE(sal_False, "OConfigurationTreeRoot::createWithProvider: invalid root object (missing interface XChangesBatch)!"); + + // dispose the object if it is already created, but unusable + Reference< XComponent > xComp(xRoot, UNO_QUERY); + if (xComp.is()) + try { xComp->dispose(); } catch(Exception&) { } + } + } + catch(Exception& e) + { + #if OSL_DEBUG_LEVEL > 0 + ::rtl::OString sMessage( "OConfigurationTreeRoot::createWithProvider: caught an exception while creating the access object!\nmessage:\n" ); + sMessage += ::rtl::OString( e.Message.getStr(), e.Message.getLength(), RTL_TEXTENCODING_ASCII_US ); + OSL_ENSURE( sal_False, sMessage.getStr() ); + #else + (void)e; + #endif + } + } + bTryAgain = CM_PREFER_UPDATABLE == _eMode; + if (bTryAgain) + _eMode = CM_READONLY; + } + while (bTryAgain); + + return OConfigurationTreeRoot(); + } + + //------------------------------------------------------------------------ + OConfigurationTreeRoot OConfigurationTreeRoot::createWithServiceFactory(const Reference< XMultiServiceFactory >& _rxORB, const ::rtl::OUString& _rPath, sal_Int32 _nDepth, CREATION_MODE _eMode, sal_Bool _bLazyWrite) + { + OSL_ENSURE(_rxORB.is(), "OConfigurationTreeRoot::createWithServiceFactory: invalid service factory!"); + if (_rxORB.is()) + { + try + { + Reference< XInterface > xProvider = _rxORB->createInstance( lcl_getProviderServiceName( ) ); + OSL_ENSURE(xProvider.is(), "OConfigurationTreeRoot::createWithServiceFactory: could not instantiate the config provider service!"); + Reference< XMultiServiceFactory > xProviderAsFac(xProvider, UNO_QUERY); + OSL_ENSURE(xProviderAsFac.is() || !xProvider.is(), "OConfigurationTreeRoot::createWithServiceFactory: the provider is missing an interface!"); + if (xProviderAsFac.is()) + return createWithProvider(xProviderAsFac, _rPath, _nDepth, _eMode, _bLazyWrite); + } + catch(Exception&) + { + OSL_ENSURE(sal_False, "OConfigurationTreeRoot::createWithServiceFactory: error while instantiating the provider service!"); + } + } + return OConfigurationTreeRoot(); + } + + //------------------------------------------------------------------------ + OConfigurationTreeRoot OConfigurationTreeRoot::tryCreateWithServiceFactory( const Reference< XMultiServiceFactory >& _rxORB, + const ::rtl::OUString& _rPath, sal_Int32 _nDepth , CREATION_MODE _eMode , sal_Bool _bLazyWrite ) + { + OSL_ENSURE( _rxORB.is(), "OConfigurationTreeRoot::tryCreateWithServiceFactory: invalid service factory!" ); + if ( _rxORB.is() ) + { + try + { + Reference< XMultiServiceFactory > xConfigFactory( _rxORB->createInstance( lcl_getProviderServiceName( ) ), UNO_QUERY ); + if ( xConfigFactory.is() ) + return createWithProvider( xConfigFactory, _rPath, _nDepth, _eMode, _bLazyWrite ); + } + catch(Exception&) + { + // silent this, 'cause the contract of this method states "no assertions" + } + } + return OConfigurationTreeRoot(); + } + +//........................................................................ +} // namespace utl +//........................................................................ + diff --git a/unotools/source/config/configpathes.cxx b/unotools/source/config/configpathes.cxx new file mode 100644 index 000000000000..3e90823a7975 --- /dev/null +++ b/unotools/source/config/configpathes.cxx @@ -0,0 +1,306 @@ +/************************************************************************* + * + * 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: configpathes.cxx,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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_unotools.hxx" + +#include "unotools/configpathes.hxx" +#include <rtl/ustring.hxx> +#include <rtl/ustrbuf.hxx> +#include <osl/diagnose.h> + +//---------------------------------------------------------------------------- +namespace utl +{ +//---------------------------------------------------------------------------- + + using ::rtl::OUString; + using ::rtl::OUStringBuffer; + +//---------------------------------------------------------------------------- + +static +void lcl_resolveCharEntities(OUString & aLocalString) +{ + sal_Int32 nEscapePos=aLocalString.indexOf('&'); + if (nEscapePos < 0) return; + + OUStringBuffer aResult; + sal_Int32 nStart = 0; + + do + { + sal_Unicode ch = 0; + if (aLocalString.matchAsciiL(RTL_CONSTASCII_STRINGPARAM("&"),nEscapePos)) + ch = '&'; + + else if (aLocalString.matchAsciiL(RTL_CONSTASCII_STRINGPARAM("'"),nEscapePos)) + ch = '\''; + + else if (aLocalString.matchAsciiL(RTL_CONSTASCII_STRINGPARAM("""),nEscapePos)) + ch = '"'; + + OSL_ENSURE(ch,"Configuration path contains '&' that is not part of a valid character escape"); + if (ch) + { + aResult.append(aLocalString.copy(nStart,nEscapePos-nStart)).append(ch); + + sal_Int32 nEscapeEnd=aLocalString.indexOf(';',nEscapePos); + nStart = nEscapeEnd+1; + nEscapePos=aLocalString.indexOf('&',nStart); + } + else + { + nEscapePos=aLocalString.indexOf('&',nEscapePos+1); + } + } + while ( nEscapePos > 0); + + aResult.append(aLocalString.copy(nStart)); + + aLocalString = aResult.makeStringAndClear(); +} + +//---------------------------------------------------------------------------- +sal_Bool splitLastFromConfigurationPath(OUString const& _sInPath, + OUString& _rsOutPath, + OUString& _rsLocalName) +{ + sal_Int32 nStart,nEnd; + + sal_Int32 nPos = _sInPath.getLength()-1; + + // strip trailing slash + if (nPos > 0 && _sInPath[ nPos ] == sal_Unicode('/')) + { + OSL_ENSURE(false, "Invalid config path: trailing '/' is not allowed"); + --nPos; + } + + // check for predicate ['xxx'] or ["yyy"] + if (nPos > 0 && _sInPath[ nPos ] == sal_Unicode(']')) + { + sal_Unicode chQuote = _sInPath[--nPos]; + + if (chQuote == '\'' || chQuote == '\"') + { + nEnd = nPos; + nPos = _sInPath.lastIndexOf(chQuote,nEnd); + nStart = nPos + 1; + --nPos; // nPos = rInPath.lastIndexOf('[',nPos); + } + else // allow [xxx] + { + nEnd = nPos + 1; + nPos = _sInPath.lastIndexOf('[',nEnd); + nStart = nPos + 1; + } + + OSL_ENSURE(nPos >= 0 && _sInPath[nPos] == '[', "Invalid config path: unmatched quotes or brackets"); + if (nPos >= 0 && _sInPath[nPos] == '[') + { + nPos = _sInPath.lastIndexOf('/',nPos); + } + else // defined behavior for invalid pathes + { + nStart = 0, nEnd = _sInPath.getLength(); + nPos = -1; + } + + } + else + { + nEnd = nPos+1; + nPos = _sInPath.lastIndexOf('/',nEnd); + nStart = nPos + 1; + } + OSL_ASSERT( -1 <= nPos && + nPos < nStart && + nStart < nEnd && + nEnd <= _sInPath.getLength() ); + + OSL_ASSERT(nPos == -1 || _sInPath[nPos] == '/'); + OSL_ENSURE(nPos != 0 , "Invalid config child path: immediate child of root"); + + _rsLocalName = _sInPath.copy(nStart, nEnd-nStart); + _rsOutPath = (nPos > 0) ? _sInPath.copy(0,nPos) : OUString(); + lcl_resolveCharEntities(_rsLocalName); + + return nPos >= 0; +} + +//---------------------------------------------------------------------------- +OUString extractFirstFromConfigurationPath(OUString const& _sInPath) +{ + sal_Int32 nSep = _sInPath.indexOf('/'); + sal_Int32 nBracket = _sInPath.indexOf('['); + + sal_Int32 nStart = nBracket + 1; + sal_Int32 nEnd = nSep; + + if (0 <= nBracket) // found a bracket-quoted relative path + { + if (nSep < 0 || nBracket < nSep) // and the separator comes after it + { + sal_Unicode chQuote = _sInPath[nStart]; + if (chQuote == '\'' || chQuote == '\"') + { + ++nStart; + nEnd = _sInPath.indexOf(chQuote, nStart+1); + nBracket = nEnd+1; + } + else + { + nEnd = _sInPath.indexOf(']',nStart); + nBracket = nEnd; + } + OSL_ENSURE(nEnd > nStart && _sInPath[nBracket] == ']', "Invalid config path: improper mismatch of quote or bracket"); + OSL_DEBUG_ONLY(nSep = nBracket+1); + OSL_ENSURE(nSep == _sInPath.getLength() || _sInPath[nSep] == '/', "Invalid config path: brackets not followed by slash"); + } + else // ... but our initial element name is in simple form + nStart = 0; + } + + OUString sResult = (nEnd >= 0) ? _sInPath.copy(nStart, nEnd-nStart) : _sInPath; + lcl_resolveCharEntities(sResult); + return sResult; +} + +//---------------------------------------------------------------------------- + +// find the position after the prefix in the nested path +static inline +sal_Int32 lcl_findPrefixEnd(OUString const& _sNestedPath, OUString const& _sPrefixPath) +{ + // TODO: currently handles only exact prefix matches + sal_Int32 nPrefixLength = _sPrefixPath.getLength(); + + OSL_ENSURE(nPrefixLength == 0 || _sPrefixPath[nPrefixLength-1] != '/', + "Cannot handle slash-terminated prefix pathes"); + + sal_Bool bIsPrefix; + if (_sNestedPath.getLength() > nPrefixLength) + { + bIsPrefix = _sNestedPath[nPrefixLength] == '/' && + _sNestedPath.compareTo(_sPrefixPath,nPrefixLength) == 0; + ++nPrefixLength; + } + else if (_sNestedPath.getLength() == nPrefixLength) + { + bIsPrefix = _sNestedPath.equals(_sPrefixPath); + } + else + { + bIsPrefix = false; + } + + return bIsPrefix ? nPrefixLength : 0; +} + +//---------------------------------------------------------------------------- +sal_Bool isPrefixOfConfigurationPath(OUString const& _sNestedPath, + OUString const& _sPrefixPath) +{ + return _sPrefixPath.getLength() == 0 || lcl_findPrefixEnd(_sNestedPath,_sPrefixPath) != 0; +} + +//---------------------------------------------------------------------------- +OUString dropPrefixFromConfigurationPath(OUString const& _sNestedPath, + OUString const& _sPrefixPath) +{ + if ( sal_Int32 nPrefixEnd = lcl_findPrefixEnd(_sNestedPath,_sPrefixPath) ) + { + return _sNestedPath.copy(nPrefixEnd); + } + else + { + OSL_ENSURE(_sPrefixPath.getLength() == 0, "Path does not start with expected prefix"); + + return _sNestedPath; + } +} + +//---------------------------------------------------------------------------- +static +OUString lcl_wrapName(const OUString& _sContent, const OUString& _sType) +{ + const sal_Unicode * const pBeginContent = _sContent.getStr(); + const sal_Unicode * const pEndContent = pBeginContent + _sContent.getLength(); + + OSL_PRECOND(_sType.getLength(), "Unexpected config type name: empty"); + OSL_PRECOND(pBeginContent <= pEndContent, "Invalid config name: empty"); + + if (pBeginContent == pEndContent) + return _sType; + + rtl::OUStringBuffer aNormalized(_sType.getLength() + _sContent.getLength() + 4); // reserve approximate size initially + + // prefix: type, opening bracket and quote + aNormalized.append( _sType ).appendAscii( RTL_CONSTASCII_STRINGPARAM("['") ); + + // content: copy over each char and handle escaping + for(const sal_Unicode* pCur = pBeginContent; pCur != pEndContent; ++pCur) + { + // append (escape if needed) + switch(*pCur) + { + case sal_Unicode('&') : aNormalized.appendAscii( RTL_CONSTASCII_STRINGPARAM("&") ); break; + case sal_Unicode('\''): aNormalized.appendAscii( RTL_CONSTASCII_STRINGPARAM("'") ); break; + case sal_Unicode('\"'): aNormalized.appendAscii( RTL_CONSTASCII_STRINGPARAM(""") ); break; + + default: aNormalized.append( *pCur ); + } + } + + // suffix: closing quote and bracket + aNormalized.appendAscii( RTL_CONSTASCII_STRINGPARAM("']") ); + + return aNormalized.makeStringAndClear(); +} + +//---------------------------------------------------------------------------- + +OUString wrapConfigurationElementName(OUString const& _sElementName) +{ + return lcl_wrapName(_sElementName, OUString(RTL_CONSTASCII_USTRINGPARAM("*")) ); +} + +//---------------------------------------------------------------------------- + +OUString wrapConfigurationElementName(OUString const& _sElementName, + OUString const& _sTypeName) +{ + // todo: check that _sTypeName is valid + return lcl_wrapName(_sElementName, _sTypeName); +} + +//---------------------------------------------------------------------------- +} // namespace utl diff --git a/unotools/source/config/configvaluecontainer.cxx b/unotools/source/config/configvaluecontainer.cxx new file mode 100644 index 000000000000..6c7962cc09c1 --- /dev/null +++ b/unotools/source/config/configvaluecontainer.cxx @@ -0,0 +1,459 @@ +/************************************************************************* + * + * 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: configvaluecontainer.cxx,v $ + * $Revision: 1.9 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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_unotools.hxx" +#include <unotools/configvaluecontainer.hxx> +#include <unotools/confignode.hxx> +#include <tools/debug.hxx> +#include <comphelper/stl_types.hxx> +#include <uno/data.h> +#include <algorithm> + +#ifdef DBG_UTIL +#include <rtl/strbuf.hxx> +#endif + +//......................................................................... +namespace utl +{ +//......................................................................... + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::lang; + + //===================================================================== + //= NodeValueAccessor + //===================================================================== + enum LocationType + { + ltSimplyObjectInstance, + ltAnyInstance, + + ltUnbound + }; + + struct NodeValueAccessor + { + private: + ::rtl::OUString sRelativePath; // the relative path of the node + LocationType eLocationType; // the type of location where the value is stored + void* pLocation; // the pointer to the location + Type aDataType; // the type object pointed to by pLocation + + public: + NodeValueAccessor( const ::rtl::OUString& _rNodePath ); + + void bind( void* _pLocation, const Type& _rType ); + void bind( Any* _pLocation ); + + bool isBound( ) const { return ( ltUnbound != eLocationType ) && ( NULL != pLocation ); } + const ::rtl::OUString& getPath( ) const { return sRelativePath; } + LocationType getLocType( ) const { return eLocationType; } + void* getLocation( ) const { return pLocation; } + const Type& getDataType( ) const { return aDataType; } + + bool operator == ( const NodeValueAccessor& rhs ) const; + bool operator != ( const NodeValueAccessor& rhs ) const { return !operator == ( rhs ); } + }; + + //--------------------------------------------------------------------- + //--- 20.08.01 17:21:13 ----------------------------------------------- + + NodeValueAccessor::NodeValueAccessor( const ::rtl::OUString& _rNodePath ) + :sRelativePath( _rNodePath ) + ,eLocationType( ltUnbound ) + ,pLocation( NULL ) + { + } + + //--------------------------------------------------------------------- + //--- 20.08.01 17:06:36 ----------------------------------------------- + + bool NodeValueAccessor::operator == ( const NodeValueAccessor& rhs ) const + { + return ( sRelativePath == rhs.sRelativePath ) + && ( eLocationType == rhs.eLocationType ) + && ( pLocation == rhs.pLocation ); + } + + //--------------------------------------------------------------------- + //--- 20.08.01 17:47:43 ----------------------------------------------- + + void NodeValueAccessor::bind( void* _pLocation, const Type& _rType ) + { + DBG_ASSERT( !isBound(), "NodeValueAccessor::bind: already bound!" ); + + eLocationType = ltSimplyObjectInstance; + pLocation = _pLocation; + aDataType = _rType; + } + + //--------------------------------------------------------------------- + //--- 20.08.01 17:48:47 ----------------------------------------------- + + void NodeValueAccessor::bind( Any* _pLocation ) + { + DBG_ASSERT( !isBound(), "NodeValueAccessor::bind: already bound!" ); + + eLocationType = ltAnyInstance; + pLocation = _pLocation; + aDataType = ::getCppuType( _pLocation ); + } + + //--------------------------------------------------------------------- + //--- 20.08.01 17:42:17 ----------------------------------------------- + + #ifndef UNX + static + #endif + void lcl_copyData( const NodeValueAccessor& _rAccessor, const Any& _rData, ::osl::Mutex& _rMutex ) + { + ::osl::MutexGuard aGuard( _rMutex ); + + DBG_ASSERT( _rAccessor.isBound(), "::utl::lcl_copyData: invalid accessor!" ); + switch ( _rAccessor.getLocType() ) + { + case ltSimplyObjectInstance: + { + if ( _rData.hasValue() ) + { +#ifdef DBG_UTIL + sal_Bool bSuccess = +#endif + // assign the value + uno_type_assignData( + _rAccessor.getLocation(), _rAccessor.getDataType().getTypeLibType(), + const_cast< void* >( _rData.getValue() ), _rData.getValueType().getTypeLibType(), + (uno_QueryInterfaceFunc)cpp_queryInterface, (uno_AcquireFunc)cpp_acquire, (uno_ReleaseFunc)cpp_release + ); + #ifdef DBG_UTIL + rtl::OStringBuffer aBuf( 256 ); + aBuf.append("::utl::lcl_copyData( Accessor, Any ): could not assign the data (node path: "); + aBuf.append( rtl::OUStringToOString( _rAccessor.getPath(), RTL_TEXTENCODING_ASCII_US ) ); + aBuf.append( " !" ); + DBG_ASSERT( bSuccess, aBuf.getStr() ); + #endif + } + else { + DBG_WARNING( "::utl::lcl_copyData: NULL value lost!" ); + } + } + break; + case ltAnyInstance: + // a simple assignment of an Any ... + *static_cast< Any* >( _rAccessor.getLocation() ) = _rData; + break; + default: + break; + } + } + + //--------------------------------------------------------------------- + //--- 21.08.01 12:06:43 ----------------------------------------------- + + #ifndef UNX + static + #endif + void lcl_copyData( Any& _rData, const NodeValueAccessor& _rAccessor, ::osl::Mutex& _rMutex ) + { + ::osl::MutexGuard aGuard( _rMutex ); + + DBG_ASSERT( _rAccessor.isBound(), "::utl::lcl_copyData: invalid accessor!" ); + switch ( _rAccessor.getLocType() ) + { + case ltSimplyObjectInstance: + // a simple setValue .... + _rData.setValue( _rAccessor.getLocation(), _rAccessor.getDataType() ); + break; + + case ltAnyInstance: + // a simple assignment of an Any ... + _rData = *static_cast< Any* >( _rAccessor.getLocation() ); + break; + default: + break; + } + } + + //===================================================================== + //= functors on NodeValueAccessor instances + //===================================================================== + + //--------------------------------------------------------------------- + //--- 21.08.01 12:01:16 ----------------------------------------------- + + /// base class for functors syncronizing between exchange locations and config sub nodes + struct SubNodeAccess : public ::std::unary_function< NodeValueAccessor, void > + { + protected: + const OConfigurationNode& m_rRootNode; + ::osl::Mutex& m_rMutex; + + public: + SubNodeAccess( const OConfigurationNode& _rRootNode, ::osl::Mutex& _rMutex ) + :m_rRootNode( _rRootNode ) + ,m_rMutex( _rMutex ) + { + } + }; + + //--------------------------------------------------------------------- + //--- 21.08.01 11:25:56 ----------------------------------------------- + + struct UpdateFromConfig : public SubNodeAccess + { + public: + UpdateFromConfig( const OConfigurationNode& _rRootNode, ::osl::Mutex& _rMutex ) : SubNodeAccess( _rRootNode, _rMutex ) { } + + void operator() ( NodeValueAccessor& _rAccessor ) + { + ::utl::lcl_copyData( _rAccessor, m_rRootNode.getNodeValue( _rAccessor.getPath( ) ), m_rMutex ); + } + }; + + //--------------------------------------------------------------------- + //--- 21.08.01 11:25:56 ----------------------------------------------- + + struct UpdateToConfig : public SubNodeAccess + { + public: + UpdateToConfig( const OConfigurationNode& _rRootNode, ::osl::Mutex& _rMutex ) : SubNodeAccess( _rRootNode, _rMutex ) { } + + void operator() ( NodeValueAccessor& _rAccessor ) + { + Any aNewValue; + lcl_copyData( aNewValue, _rAccessor, m_rMutex ); + m_rRootNode.setNodeValue( _rAccessor.getPath( ), aNewValue ); + } + }; + + //--------------------------------------------------------------------- + //--- 20.08.01 16:58:24 ----------------------------------------------- + + DECLARE_STL_VECTOR( NodeValueAccessor, NodeValueAccessors ); + + //===================================================================== + //= OConfigurationValueContainerImpl + //===================================================================== + struct OConfigurationValueContainerImpl + { + Reference< XMultiServiceFactory > xORB; // the service factory + ::osl::Mutex& rMutex; // the mutex for accessing the data containers + OConfigurationTreeRoot aConfigRoot; // the configuration node we're accessing + + NodeValueAccessors aAccessors; // the accessors to the node values + + OConfigurationValueContainerImpl( const Reference< XMultiServiceFactory >& _rxORB, ::osl::Mutex& _rMutex ) + :xORB( _rxORB ) + ,rMutex( _rMutex ) + { + } + }; + + //===================================================================== + //= OConfigurationValueContainer + //===================================================================== + + //--------------------------------------------------------------------- + //--- 20.08.01 15:53:35 ----------------------------------------------- + + OConfigurationValueContainer::OConfigurationValueContainer( + const Reference< XMultiServiceFactory >& _rxORB, ::osl::Mutex& _rAccessSafety, + const sal_Char* _pConfigLocation, const sal_uInt16 _nAccessFlags, const sal_Int32 _nLevels ) + :m_pImpl( new OConfigurationValueContainerImpl( _rxORB, _rAccessSafety ) ) + { + implConstruct( ::rtl::OUString::createFromAscii( _pConfigLocation ), _nAccessFlags, _nLevels ); + } + + //--------------------------------------------------------------------- + //--- 20.08.01 15:55:20 ----------------------------------------------- + + OConfigurationValueContainer::OConfigurationValueContainer( + const Reference< XMultiServiceFactory >& _rxORB, ::osl::Mutex& _rAccessSafety, + const ::rtl::OUString& _rConfigLocation, const sal_uInt16 _nAccessFlags, const sal_Int32 _nLevels ) + :m_pImpl( new OConfigurationValueContainerImpl( _rxORB, _rAccessSafety ) ) + { + implConstruct( _rConfigLocation, _nAccessFlags, _nLevels ); + } + + //--------------------------------------------------------------------- + //--- 20.08.01 16:01:29 ----------------------------------------------- + + OConfigurationValueContainer::~OConfigurationValueContainer() + { + delete m_pImpl; + } + + //--------------------------------------------------------------------- + //--- 20.08.01 15:59:13 ----------------------------------------------- + + const Reference< XMultiServiceFactory >& OConfigurationValueContainer::getServiceFactory( ) const + { + return m_pImpl->xORB; + } + + //--------------------------------------------------------------------- + //--- 20.08.01 16:02:07 ----------------------------------------------- + + void OConfigurationValueContainer::implConstruct( const ::rtl::OUString& _rConfigLocation, + const sal_uInt16 _nAccessFlags, const sal_Int32 _nLevels ) + { + DBG_ASSERT( !m_pImpl->aConfigRoot.isValid(), "OConfigurationValueContainer::implConstruct: already initialized!" ); + + // ................................. + // create the configuration node we're about to work with + m_pImpl->aConfigRoot = OConfigurationTreeRoot::createWithServiceFactory( + m_pImpl->xORB, + _rConfigLocation, + _nLevels, + ( _nAccessFlags & CVC_UPDATE_ACCESS ) ? OConfigurationTreeRoot::CM_PREFER_UPDATABLE : OConfigurationTreeRoot::CM_READONLY, + ( _nAccessFlags & CVC_IMMEDIATE_UPDATE ) ? sal_False : sal_True + ); + #ifdef DBG_UTIL + rtl::OStringBuffer aBuf(256); + aBuf.append("Could not access the configuration node located at "); + aBuf.append( rtl::OUStringToOString( _rConfigLocation, RTL_TEXTENCODING_ASCII_US ) ); + aBuf.append( " !" ); + DBG_ASSERT( m_pImpl->aConfigRoot.isValid(), aBuf.getStr() ); + #endif + } + + //--------------------------------------------------------------------- + //--- 20.08.01 16:39:05 ----------------------------------------------- + + void OConfigurationValueContainer::registerExchangeLocation( const sal_Char* _pRelativePath, + void* _pContainer, const Type& _rValueType ) + { + // checks .... + DBG_ASSERT( _pContainer, "OConfigurationValueContainer::registerExchangeLocation: invalid container location!" ); + DBG_ASSERT( ( TypeClass_CHAR == _rValueType.getTypeClass( ) ) + || ( TypeClass_BOOLEAN == _rValueType.getTypeClass( ) ) + || ( TypeClass_BYTE == _rValueType.getTypeClass( ) ) + || ( TypeClass_SHORT == _rValueType.getTypeClass( ) ) + || ( TypeClass_LONG == _rValueType.getTypeClass( ) ) + || ( TypeClass_DOUBLE == _rValueType.getTypeClass( ) ) + || ( TypeClass_STRING == _rValueType.getTypeClass( ) ) + || ( TypeClass_SEQUENCE == _rValueType.getTypeClass( ) ), + "OConfigurationValueContainer::registerExchangeLocation: invalid type!" ); + + // build an accessor for this container + NodeValueAccessor aNewAccessor( ::rtl::OUString::createFromAscii( _pRelativePath ) ); + aNewAccessor.bind( _pContainer, _rValueType ); + + // insert it into our structure + implRegisterExchangeLocation( aNewAccessor ); + } + + //--------------------------------------------------------------------- + //--- 21.08.01 14:44:45 ----------------------------------------------- + + void OConfigurationValueContainer::registerNullValueExchangeLocation( const sal_Char* _pRelativePath, Any* _pContainer ) + { + // build an accessor for this container + NodeValueAccessor aNewAccessor( ::rtl::OUString::createFromAscii( _pRelativePath ) ); + aNewAccessor.bind( _pContainer ); + + // insert it into our structure + implRegisterExchangeLocation( aNewAccessor ); + } + + //--------------------------------------------------------------------- + //--- 21.08.01 10:23:34 ----------------------------------------------- + + void OConfigurationValueContainer::read( ) + { + for_each( + m_pImpl->aAccessors.begin(), + m_pImpl->aAccessors.end(), + UpdateFromConfig( m_pImpl->aConfigRoot, m_pImpl->rMutex ) + ); + } + + //--------------------------------------------------------------------- + //--- 21.08.01 12:04:48 ----------------------------------------------- + + void OConfigurationValueContainer::write( sal_Bool _bCommit ) + { + // collect the current values in the exchange locations + for_each( + m_pImpl->aAccessors.begin(), + m_pImpl->aAccessors.end(), + UpdateToConfig( m_pImpl->aConfigRoot, m_pImpl->rMutex ) + ); + + // commit the changes done (if requested) + if ( _bCommit ) + commit( sal_False ); + } + + //--------------------------------------------------------------------- + //--- 21.08.01 12:09:45 ----------------------------------------------- + + void OConfigurationValueContainer::commit( sal_Bool _bWrite ) + { + // write the current values in the exchange locations (if requested) + if ( _bWrite ) + write( sal_False ); + + // commit the changes done + m_pImpl->aConfigRoot.commit( ); + } + + //--------------------------------------------------------------------- + //--- 20.08.01 17:29:27 ----------------------------------------------- + + void OConfigurationValueContainer::implRegisterExchangeLocation( const NodeValueAccessor& _rAccessor ) + { + // some checks + DBG_ASSERT( !m_pImpl->aConfigRoot.isValid() || m_pImpl->aConfigRoot.hasByHierarchicalName( _rAccessor.getPath() ), + "OConfigurationValueContainer::implRegisterExchangeLocation: invalid relative path!" ); + +#ifdef DBG_UTIL + // another check (should be the first container for this node) + ConstNodeValueAccessorsIterator aExistent = ::std::find( + m_pImpl->aAccessors.begin(), + m_pImpl->aAccessors.end(), + _rAccessor + ); + DBG_ASSERT( m_pImpl->aAccessors.end() == aExistent, "OConfigurationValueContainer::implRegisterExchangeLocation: already registered a container for this subnode!" ); +#endif + + // remember the accessor + m_pImpl->aAccessors.push_back( _rAccessor ); + + // and initially fill the value + lcl_copyData( _rAccessor, m_pImpl->aConfigRoot.getNodeValue( _rAccessor.getPath() ), m_pImpl->rMutex ); + } + +//......................................................................... +} // namespace utl +//......................................................................... + diff --git a/unotools/source/config/docinfohelper.cxx b/unotools/source/config/docinfohelper.cxx new file mode 100644 index 000000000000..bd2fd4fd24ea --- /dev/null +++ b/unotools/source/config/docinfohelper.cxx @@ -0,0 +1,119 @@ +/************************************************************************* + * + * 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: docinfohelper.cxx,v $ + * $Revision: 1.3 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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_unotools.hxx" + +#include <rtl/ustrbuf.hxx> +#include <tools/inetdef.hxx> +#include <unotools/configmgr.hxx> +#include <unotools/bootstrap.hxx> +#include <unotools/docinfohelper.hxx> + +using namespace ::com::sun::star; + +namespace utl +{ + +::rtl::OUString DocInfoHelper::GetGeneratorString() +{ + rtl::OUStringBuffer aResult; + + // First product: branded name + version + // version is <product_versions>_<product_extension>$<platform> + utl::ConfigManager* pMgr = utl::ConfigManager::GetConfigManager(); + if ( pMgr ) + { + // plain product name + rtl::OUString aValue; + uno::Any aAny = pMgr->GetDirectConfigProperty( + utl::ConfigManager::PRODUCTNAME); + if ( (aAny >>= aValue) && aValue.getLength() ) + { + aResult.append( aValue.replace( ' ', '_' ) ); + aResult.append( (sal_Unicode)'/' ); + + aAny = pMgr->GetDirectConfigProperty( + utl::ConfigManager::PRODUCTVERSION); + if ( (aAny >>= aValue) && aValue.getLength() ) + { + aResult.append( aValue.replace( ' ', '_' ) ); + + aAny = pMgr->GetDirectConfigProperty( + utl::ConfigManager::PRODUCTEXTENSION); + if ( (aAny >>= aValue) && aValue.getLength() ) + { + aResult.append( (sal_Unicode)'_' ); + aResult.append( aValue.replace( ' ', '_' ) ); + } + } + + aResult.append( (sal_Unicode)'$' ); + aResult.append( ::rtl::OUString::createFromAscii( + TOOLS_INETDEF_OS ).replace( ' ', '_' ) ); + + aResult.append( (sal_Unicode)' ' ); + } + } + + // second product: OpenOffice.org_project/<build_information> + // build_information has '(' and '[' encoded as '$', ')' and ']' ignored + // and ':' replaced by '-' + { + aResult.appendAscii( "OpenOffice.org_project/" ); + ::rtl::OUString aDefault; + ::rtl::OUString aBuildId( Bootstrap::getBuildIdData( aDefault ) ); + for( sal_Int32 i=0; i < aBuildId.getLength(); i++ ) + { + sal_Unicode c = aBuildId[i]; + switch( c ) + { + case '(': + case '[': + aResult.append( (sal_Unicode)'$' ); + break; + case ')': + case ']': + break; + case ':': + aResult.append( (sal_Unicode)'-' ); + break; + default: + aResult.append( c ); + break; + } + } + } + + return aResult.makeStringAndClear(); +} + +} // end of namespace utl + diff --git a/unotools/source/config/makefile.mk b/unotools/source/config/makefile.mk new file mode 100644 index 000000000000..bd5a1b16512f --- /dev/null +++ b/unotools/source/config/makefile.mk @@ -0,0 +1,59 @@ +#************************************************************************* +# +# 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.15 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General 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=..$/.. +PRJINC=..$/..$/inc +PRJNAME=unotools +TARGET=config + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ---------------------------------- + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/util$/makefile.pmk + + +# --- Files ------------------------------------- + +SLOFILES=\ + $(SLO)$/configvaluecontainer.obj \ + $(SLO)$/confignode.obj \ + $(SLO)$/configitem.obj \ + $(SLO)$/configmgr.obj \ + $(SLO)$/configpathes.obj \ + $(SLO)$/docinfohelper.obj \ + $(SLO)$/bootstrap.obj + +# --- Targets ---------------------------------- + +.INCLUDE : target.mk + diff --git a/unotools/source/i18n/calendarwrapper.cxx b/unotools/source/i18n/calendarwrapper.cxx new file mode 100644 index 000000000000..1d83761b5cea --- /dev/null +++ b/unotools/source/i18n/calendarwrapper.cxx @@ -0,0 +1,683 @@ +/************************************************************************* + * + * 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: calendarwrapper.cxx,v $ + * $Revision: 1.15.24.1 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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_unotools.hxx" + +#include <unotools/calendarwrapper.hxx> +#include <tools/string.hxx> +#include <tools/debug.hxx> + +#ifndef _COMPHELPER_COMPONENTFACTORY_HXX_ +#include <comphelper/componentfactory.hxx> +#endif +#include <com/sun/star/i18n/CalendarFieldIndex.hpp> +#include <com/sun/star/i18n/XExtendedCalendar.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> + +#define CALENDAR_LIBRARYNAME "i18n" +#define CALENDAR_SERVICENAME "com.sun.star.i18n.LocaleCalendar" + + +using namespace ::com::sun::star; +using namespace ::com::sun::star::i18n; +using namespace ::com::sun::star::uno; + + +const double MILLISECONDS_PER_DAY = 1000.0 * 60.0 * 60.0 * 24.0; + + +CalendarWrapper::CalendarWrapper( + const Reference< lang::XMultiServiceFactory > & xSF + ) + : + xSMgr( xSF ), + aEpochStart( Date( 1, 1, 1970 ) ) +{ + if ( xSMgr.is() ) + { + try + { + xC = Reference< XExtendedCalendar > ( xSMgr->createInstance( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( CALENDAR_SERVICENAME ) ) ), + uno::UNO_QUERY ); + } + catch ( Exception& e ) + { +#ifndef PRODUCT + ByteString aMsg( "CalendarWrapper ctor: Exception caught\n" ); + aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); + DBG_ERRORFILE( aMsg.GetBuffer() ); +#else + (void)e; +#endif + } + } + else + { // try to get an instance somehow + DBG_ERRORFILE( "CalendarWrapper: no service manager, trying own" ); + try + { + Reference< XInterface > xI = ::comphelper::getComponentInstance( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( LLCF_LIBNAME( CALENDAR_LIBRARYNAME ) ) ), + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( CALENDAR_SERVICENAME ) ) ); + if ( xI.is() ) + { + Any x = xI->queryInterface( ::getCppuType((const Reference< XExtendedCalendar >*)0) ); + x >>= xC; + } + } + catch ( Exception& e ) + { +#ifndef PRODUCT + ByteString aMsg( "getComponentInstance: Exception caught\n" ); + aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); + DBG_ERRORFILE( aMsg.GetBuffer() ); +#else + (void)e; +#endif + } + } +} + + +CalendarWrapper::~CalendarWrapper() +{ +} + + +void CalendarWrapper::loadDefaultCalendar( const ::com::sun::star::lang::Locale& rLocale ) +{ + try + { + if ( xC.is() ) + xC->loadDefaultCalendar( rLocale ); + } + catch ( Exception& e ) + { +#ifndef PRODUCT + ByteString aMsg( "loadDefaultCalendar: Exception caught\n" ); + aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); + DBG_ERRORFILE( aMsg.GetBuffer() ); +#else + (void)e; +#endif + } +} + + +void CalendarWrapper::loadCalendar( const ::rtl::OUString& rUniqueID, const ::com::sun::star::lang::Locale& rLocale ) +{ + try + { + if ( xC.is() ) + xC->loadCalendar( rUniqueID, rLocale ); + } + catch ( Exception& e ) + { +#ifndef PRODUCT + ByteString aMsg( "loadCalendar: Exception caught\nrequested: " ); + aMsg += ByteString( String( rUniqueID ), RTL_TEXTENCODING_UTF8 ); + aMsg += " Locale: "; + aMsg += ByteString( String( rLocale.Language ), RTL_TEXTENCODING_UTF8 ); + aMsg += '_'; + aMsg += ByteString( String( rLocale.Country ), RTL_TEXTENCODING_UTF8 ); + aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); + DBG_ERRORFILE( aMsg.GetBuffer() ); +#else + (void)e; +#endif + } +} + + +::com::sun::star::i18n::Calendar CalendarWrapper::getLoadedCalendar() const +{ + try + { + if ( xC.is() ) + return xC->getLoadedCalendar(); + } + catch ( Exception& e ) + { +#ifndef PRODUCT + ByteString aMsg( "getLoadedCalendar: Exception caught\n" ); + aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); + DBG_ERRORFILE( aMsg.GetBuffer() ); +#else + (void)e; +#endif + } + return ::com::sun::star::i18n::Calendar(); +} + + +::com::sun::star::uno::Sequence< ::rtl::OUString > CalendarWrapper::getAllCalendars( const ::com::sun::star::lang::Locale& rLocale ) const +{ + try + { + if ( xC.is() ) + return xC->getAllCalendars( rLocale ); + } + catch ( Exception& e ) + { +#ifndef PRODUCT + ByteString aMsg( "getAllCalendars: Exception caught\n" ); + aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); + DBG_ERRORFILE( aMsg.GetBuffer() ); +#else + (void)e; +#endif + } + return ::com::sun::star::uno::Sequence< ::rtl::OUString > (0); +} + + +::rtl::OUString CalendarWrapper::getUniqueID() const +{ + try + { + if ( xC.is() ) + return xC->getUniqueID(); + } + catch ( Exception& e ) + { +#ifndef PRODUCT + ByteString aMsg( "getUniqueID: Exception caught\n" ); + aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); + DBG_ERRORFILE( aMsg.GetBuffer() ); +#else + (void)e; +#endif + } + return ::rtl::OUString(); +} + + +void CalendarWrapper::setDateTime( double nTimeInDays ) +{ + try + { + if ( xC.is() ) + xC->setDateTime( nTimeInDays ); + } + catch ( Exception& e ) + { +#ifndef PRODUCT + ByteString aMsg( "setDateTime: Exception caught\n" ); + aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); + DBG_ERRORFILE( aMsg.GetBuffer() ); +#else + (void)e; +#endif + } +} + + +double CalendarWrapper::getDateTime() const +{ + try + { + if ( xC.is() ) + return xC->getDateTime(); + } + catch ( Exception& e ) + { +#ifndef PRODUCT + ByteString aMsg( "getDateTime: Exception caught\n" ); + aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); + DBG_ERRORFILE( aMsg.GetBuffer() ); +#else + (void)e; +#endif + } + return 0.0; +} + + +sal_Int32 CalendarWrapper::getCombinedOffsetInMillis( + sal_Int16 nParentFieldIndex, sal_Int16 nChildFieldIndex ) const +{ + sal_Int32 nOffset = 0; + try + { + if ( xC.is() ) + { + nOffset = static_cast<sal_Int32>( xC->getValue( nParentFieldIndex )) * 60000; + sal_Int16 nSecondMillis = xC->getValue( nChildFieldIndex ); + if (nOffset < 0) + nOffset -= static_cast<sal_uInt16>( nSecondMillis); + else + nOffset += static_cast<sal_uInt16>( nSecondMillis); + } + } + catch ( Exception& e ) + { +#ifndef PRODUCT + ByteString aMsg( "setLocalDateTime: Exception caught\n" ); + aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); + DBG_ERRORFILE( aMsg.GetBuffer() ); +#else + (void)e; +#endif + } + return nOffset; +} + + +sal_Int32 CalendarWrapper::getZoneOffsetInMillis() const +{ + return getCombinedOffsetInMillis( CalendarFieldIndex::ZONE_OFFSET, + CalendarFieldIndex::ZONE_OFFSET_SECOND_MILLIS); +} + + +sal_Int32 CalendarWrapper::getDSTOffsetInMillis() const +{ + return getCombinedOffsetInMillis( CalendarFieldIndex::DST_OFFSET, + CalendarFieldIndex::DST_OFFSET_SECOND_MILLIS); +} + + +void CalendarWrapper::setLocalDateTime( double nTimeInDays ) +{ + try + { + if ( xC.is() ) + { + // First set a nearby value to obtain the timezone and DST offset. + // This is necessary to let ICU choose the corresponding + // OlsonTimeZone transitions. Since ICU incorporates also + // historical data even the timezone may differ for different + // dates! (Which was the cause for #i76623# when the timezone of a + // previously set date was used.) Timezone may also include + // seconds, so use milliseconds field as well. + xC->setDateTime( nTimeInDays ); + sal_Int32 nZone1 = getZoneOffsetInMillis(); + sal_Int32 nDST1 = getDSTOffsetInMillis(); + double nLoc = nTimeInDays - (double)(nZone1 + nDST1) / MILLISECONDS_PER_DAY; + xC->setDateTime( nLoc ); + sal_Int32 nZone2 = getZoneOffsetInMillis(); + sal_Int32 nDST2 = getDSTOffsetInMillis(); + // If DSTs differ after calculation, we crossed boundaries. Do it + // again, this time using the DST corrected initial value for the + // real local time. + // See also localtime/gmtime conversion pitfalls at + // http://www.erack.de/download/timetest.c + if ( nDST1 != nDST2 ) + { + nLoc = nTimeInDays - (double)(nZone2 + nDST2) / MILLISECONDS_PER_DAY; + xC->setDateTime( nLoc ); + // #i17222# If the DST onset rule says to switch from 00:00 to + // 01:00 and we tried to set onsetDay 00:00 with DST, the + // result was onsetDay-1 23:00 and no DST, which is not what we + // want. So once again without DST, resulting in onsetDay + // 01:00 and DST. Yes, this seems to be weird, but logically + // correct. + sal_Int32 nDST3 = getDSTOffsetInMillis(); + if ( nDST2 != nDST3 && !nDST3 ) + { + nLoc = nTimeInDays - (double)(nZone2 + nDST3) / MILLISECONDS_PER_DAY; + xC->setDateTime( nLoc ); + } + } + } + } + catch ( Exception& e ) + { +#ifndef PRODUCT + ByteString aMsg( "setLocalDateTime: Exception caught\n" ); + aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); + DBG_ERRORFILE( aMsg.GetBuffer() ); +#else + (void)e; +#endif + } +} + + +double CalendarWrapper::getLocalDateTime() const +{ + try + { + if ( xC.is() ) + { + double nTimeInDays = xC->getDateTime(); + sal_Int32 nZone = getZoneOffsetInMillis(); + sal_Int32 nDST = getDSTOffsetInMillis(); + nTimeInDays += (double)(nZone + nDST) / MILLISECONDS_PER_DAY; + return nTimeInDays; + } + } + catch ( Exception& e ) + { +#ifndef PRODUCT + ByteString aMsg( "getLocalDateTime: Exception caught\n" ); + aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); + DBG_ERRORFILE( aMsg.GetBuffer() ); +#else + (void)e; +#endif + } + return 0.0; +} + + +void CalendarWrapper::setValue( sal_Int16 nFieldIndex, sal_Int16 nValue ) +{ + try + { + if ( xC.is() ) + xC->setValue( nFieldIndex, nValue ); + } + catch ( Exception& e ) + { +#ifndef PRODUCT + ByteString aMsg( "setValue: Exception caught\n" ); + aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); + DBG_ERRORFILE( aMsg.GetBuffer() ); +#else + (void)e; +#endif + } +} + + +sal_Bool CalendarWrapper::isValid() const +{ + try + { + if ( xC.is() ) + return xC->isValid(); + } + catch ( Exception& e ) + { +#ifndef PRODUCT + ByteString aMsg( "isValid: Exception caught\n" ); + aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); + DBG_ERRORFILE( aMsg.GetBuffer() ); +#else + (void)e; +#endif + } + return sal_False; +} + + +sal_Int16 CalendarWrapper::getValue( sal_Int16 nFieldIndex ) const +{ + try + { + if ( xC.is() ) + return xC->getValue( nFieldIndex ); + } + catch ( Exception& e ) + { +#ifndef PRODUCT + ByteString aMsg( "getValue: Exception caught\n" ); + aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); + DBG_ERRORFILE( aMsg.GetBuffer() ); +#else + (void)e; +#endif + } + return 0; +} + + +void CalendarWrapper::addValue( sal_Int16 nFieldIndex, sal_Int32 nAmount ) +{ + try + { + if ( xC.is() ) + xC->addValue( nFieldIndex, nAmount ); + } + catch ( Exception& e ) + { +#ifndef PRODUCT + ByteString aMsg( "addValue: Exception caught\n" ); + aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); + DBG_ERRORFILE( aMsg.GetBuffer() ); +#else + (void)e; +#endif + } +} + + +sal_Int16 CalendarWrapper::getFirstDayOfWeek() const +{ + try + { + if ( xC.is() ) + return xC->getFirstDayOfWeek(); + } + catch ( Exception& e ) + { +#ifndef PRODUCT + ByteString aMsg( "getFirstDayOfWeek: Exception caught\n" ); + aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); + DBG_ERRORFILE( aMsg.GetBuffer() ); +#else + (void)e; +#endif + } + return 0; +} + + +void CalendarWrapper::setFirstDayOfWeek( sal_Int16 nDay ) +{ + try + { + if ( xC.is() ) + xC->setFirstDayOfWeek( nDay ); + } + catch ( Exception& e ) + { +#ifndef PRODUCT + ByteString aMsg( "setFirstDayOfWeek: Exception caught\n" ); + aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); + DBG_ERRORFILE( aMsg.GetBuffer() ); +#else + (void)e; +#endif + } +} + + +void CalendarWrapper::setMinimumNumberOfDaysForFirstWeek( sal_Int16 nDays ) +{ + try + { + if ( xC.is() ) + xC->setMinimumNumberOfDaysForFirstWeek( nDays ); + } + catch ( Exception& e ) + { +#ifndef PRODUCT + ByteString aMsg( "setMinimumNumberOfDaysForFirstWeek: Exception caught\n" ); + aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); + DBG_ERRORFILE( aMsg.GetBuffer() ); +#else + (void)e; +#endif + } +} + + +sal_Int16 CalendarWrapper::getMinimumNumberOfDaysForFirstWeek() const +{ + try + { + if ( xC.is() ) + return xC->getMinimumNumberOfDaysForFirstWeek(); + } + catch ( Exception& e ) + { +#ifndef PRODUCT + ByteString aMsg( "getMinimumNumberOfDaysForFirstWeek: Exception caught\n" ); + aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); + DBG_ERRORFILE( aMsg.GetBuffer() ); +#else + (void)e; +#endif + } + return 0; +} + + +sal_Int16 CalendarWrapper::getNumberOfMonthsInYear() const +{ + try + { + if ( xC.is() ) + return xC->getNumberOfMonthsInYear(); + } + catch ( Exception& e ) + { +#ifndef PRODUCT + ByteString aMsg( "getNumberOfMonthsInYear: Exception caught\n" ); + aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); + DBG_ERRORFILE( aMsg.GetBuffer() ); +#else + (void)e; +#endif + } + return 0; +} + + +sal_Int16 CalendarWrapper::getNumberOfDaysInWeek() const +{ + try + { + if ( xC.is() ) + return xC->getNumberOfDaysInWeek(); + } + catch ( Exception& e ) + { +#ifndef PRODUCT + ByteString aMsg( "getNumberOfDaysInWeek: Exception caught\n" ); + aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); + DBG_ERRORFILE( aMsg.GetBuffer() ); +#else + (void)e; +#endif + } + return 0; +} + + +::com::sun::star::uno::Sequence< ::com::sun::star::i18n::CalendarItem > CalendarWrapper::getMonths() const +{ + try + { + if ( xC.is() ) + return xC->getMonths(); + } + catch ( Exception& e ) + { +#ifndef PRODUCT + ByteString aMsg( "getMonths: Exception caught\n" ); + aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); + DBG_ERRORFILE( aMsg.GetBuffer() ); +#else + (void)e; +#endif + } + return ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::CalendarItem > (0); +} + + +::com::sun::star::uno::Sequence< ::com::sun::star::i18n::CalendarItem > CalendarWrapper::getDays() const +{ + try + { + if ( xC.is() ) + return xC->getDays(); + } + catch ( Exception& e ) + { +#ifndef PRODUCT + ByteString aMsg( "getDays: Exception caught\n" ); + aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); + DBG_ERRORFILE( aMsg.GetBuffer() ); +#else + (void)e; +#endif + } + return ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::CalendarItem > (0); +} + + +String CalendarWrapper::getDisplayName( sal_Int16 nCalendarDisplayIndex, sal_Int16 nIdx, sal_Int16 nNameType ) const +{ + try + { + if ( xC.is() ) + return xC->getDisplayName( nCalendarDisplayIndex, nIdx, nNameType ); + } + catch ( Exception& e ) + { +#ifndef PRODUCT + ByteString aMsg( "getDisplayName: Exception caught\n" ); + aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); + DBG_ERRORFILE( aMsg.GetBuffer() ); +#else + (void)e; +#endif + } + return String(); +} + + +// --- XExtendedCalendar ----------------------------------------------------- + +String CalendarWrapper::getDisplayString( sal_Int32 nCalendarDisplayCode, sal_Int16 nNativeNumberMode ) const +{ + try + { + if ( xC.is() ) + return xC->getDisplayString( nCalendarDisplayCode, nNativeNumberMode ); + } + catch ( Exception& e ) + { +#ifndef PRODUCT + ByteString aMsg( "getDisplayString: Exception caught\n" ); + aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); + DBG_ERRORFILE( aMsg.GetBuffer() ); +#else + (void)e; +#endif + } + return String(); +} + diff --git a/unotools/source/i18n/charclass.cxx b/unotools/source/i18n/charclass.cxx new file mode 100644 index 000000000000..c1b6b4bc155c --- /dev/null +++ b/unotools/source/i18n/charclass.cxx @@ -0,0 +1,585 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: charclass.cxx,v $ + * $Revision: 1.13 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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_unotools.hxx" + +#include <unotools/charclass.hxx> +#include <tools/string.hxx> +#include <tools/debug.hxx> + +#ifndef _COMPHELPER_COMPONENTFACTORY_HXX_ +#include <comphelper/componentfactory.hxx> +#endif +#include <com/sun/star/uno/XInterface.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> + +#define CHARCLASS_LIBRARYNAME "i18n" +#define CHARCLASS_SERVICENAME "com.sun.star.i18n.CharacterClassification" + +using namespace ::com::sun::star; +using namespace ::com::sun::star::i18n; +using namespace ::com::sun::star::uno; + + +CharClass::CharClass( + const Reference< lang::XMultiServiceFactory > & xSF, + const lang::Locale& rLocale + ) + : + xSMgr( xSF ) +{ + setLocale( rLocale ); + if ( xSMgr.is() ) + { + try + { + xCC = Reference< XCharacterClassification > ( xSMgr->createInstance( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( CHARCLASS_SERVICENAME ) ) ), + uno::UNO_QUERY ); + } + catch ( Exception& ) + { + DBG_ERRORFILE( "CharClass ctor: Exception caught!" ); + } + } + else + { // try to get an instance somehow + getComponentInstance(); + } +} + + +CharClass::CharClass( + const ::com::sun::star::lang::Locale& rLocale ) +{ + setLocale( rLocale ); + getComponentInstance(); +} + + +CharClass::~CharClass() +{ +} + + +void CharClass::getComponentInstance() +{ + try + { + // CharClass may be needed by "small tools" like the Setup + // => maybe no service manager => loadLibComponentFactory + Reference < XInterface > xI = ::comphelper::getComponentInstance( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( LLCF_LIBNAME( CHARCLASS_LIBRARYNAME ) ) ), + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( CHARCLASS_SERVICENAME ) ) ); + if ( xI.is() ) + { + Any x = xI->queryInterface( ::getCppuType((const Reference< XCharacterClassification >*)0) ); + x >>= xCC; + } + } + catch ( Exception& ) + { + DBG_ERRORFILE( "getComponentInstance: Exception caught!" ); + } +} + + +void CharClass::setLocale( const ::com::sun::star::lang::Locale& rLocale ) +{ + ::osl::MutexGuard aGuard( aMutex ); + aLocale.Language = rLocale.Language; + aLocale.Country = rLocale.Country; + aLocale.Variant = rLocale.Variant; +} + + +const ::com::sun::star::lang::Locale& CharClass::getLocale() const +{ + ::osl::MutexGuard aGuard( aMutex ); + return aLocale; +} + + +// static +sal_Bool CharClass::isAsciiNumeric( const String& rStr ) +{ + if ( !rStr.Len() ) + return sal_False; + register const sal_Unicode* p = rStr.GetBuffer(); + register const sal_Unicode* const pStop = p + rStr.Len(); + do + { + if ( !isAsciiDigit( *p ) ) + return sal_False; + } while ( ++p < pStop ); + return sal_True; +} + + +// static +sal_Bool CharClass::isAsciiAlpha( const String& rStr ) +{ + if ( !rStr.Len() ) + return sal_False; + register const sal_Unicode* p = rStr.GetBuffer(); + register const sal_Unicode* const pStop = p + rStr.Len(); + do + { + if ( !isAsciiAlpha( *p ) ) + return sal_False; + } while ( ++p < pStop ); + return sal_True; +} + + +// static +sal_Bool CharClass::isAsciiAlphaNumeric( const String& rStr ) +{ + if ( !rStr.Len() ) + return sal_False; + register const sal_Unicode* p = rStr.GetBuffer(); + register const sal_Unicode* const pStop = p + rStr.Len(); + do + { + if ( !isAsciiAlphaNumeric( *p ) ) + return sal_False; + } while ( ++p < pStop ); + return sal_True; +} + + +sal_Bool CharClass::isAlpha( const String& rStr, xub_StrLen nPos ) const +{ + sal_Unicode c = rStr.GetChar( nPos ); + if ( c < 128 ) + return isAsciiAlpha( c ); + + try + { + if ( xCC.is() ) + return (xCC->getCharacterType( rStr, nPos, getLocale() ) & + nCharClassAlphaType) != 0; + else + return sal_False; + } + catch ( Exception& ) + { + DBG_ERRORFILE( "isAlpha: Exception caught!" ); + return sal_False; + } +} + + +sal_Bool CharClass::isAlpha( const String& rStr ) const +{ + try + { + if ( xCC.is() ) + return isAlphaType( xCC->getStringType( rStr, 0, rStr.Len(), getLocale() ) ); + else + return sal_False; + } + catch ( Exception& ) + { + DBG_ERRORFILE( "isAlpha: Exception caught!" ); + return sal_False; + } +} + + +sal_Bool CharClass::isLetter( const String& rStr, xub_StrLen nPos ) const +{ + sal_Unicode c = rStr.GetChar( nPos ); + if ( c < 128 ) + return isAsciiAlpha( c ); + + try + { + if ( xCC.is() ) + return (xCC->getCharacterType( rStr, nPos, getLocale() ) & + nCharClassLetterType) != 0; + else + return sal_False; + } + catch ( Exception& ) + { + DBG_ERRORFILE( "isLetter: Exception caught!" ); + return sal_False; + } +} + + +sal_Bool CharClass::isLetter( const String& rStr ) const +{ + try + { + if ( xCC.is() ) + return isLetterType( xCC->getStringType( rStr, 0, rStr.Len(), getLocale() ) ); + else + return sal_False; + } + catch ( Exception& ) + { + DBG_ERRORFILE( "isLetter: Exception caught!" ); + return sal_False; + } +} + + +sal_Bool CharClass::isDigit( const String& rStr, xub_StrLen nPos ) const +{ + sal_Unicode c = rStr.GetChar( nPos ); + if ( c < 128 ) + return isAsciiDigit( c ); + + try + { + if ( xCC.is() ) + return (xCC->getCharacterType( rStr, nPos, getLocale() ) & + KCharacterType::DIGIT) != 0; + else + return sal_False; + } + catch ( Exception& ) + { + DBG_ERRORFILE( "isDigit: Exception caught!" ); + return sal_False; + } +} + + +sal_Bool CharClass::isNumeric( const String& rStr ) const +{ + try + { + if ( xCC.is() ) + return isNumericType( xCC->getStringType( rStr, 0, rStr.Len(), getLocale() ) ); + else + return sal_False; + } + catch ( Exception& ) + { + DBG_ERRORFILE( "isNumeric: Exception caught!" ); + return sal_False; + } +} + + +sal_Bool CharClass::isAlphaNumeric( const String& rStr, xub_StrLen nPos ) const +{ + sal_Unicode c = rStr.GetChar( nPos ); + if ( c < 128 ) + return isAsciiAlphaNumeric( c ); + + try + { + if ( xCC.is() ) + return (xCC->getCharacterType( rStr, nPos, getLocale() ) & + (nCharClassAlphaType | KCharacterType::DIGIT)) != 0; + else + return sal_False; + } + catch ( Exception& ) + { + DBG_ERRORFILE( "isAlphaNumeric: Exception caught!" ); + return sal_False; + } +} + + +sal_Bool CharClass::isAlphaNumeric( const String& rStr ) const +{ + try + { + if ( xCC.is() ) + return isAlphaNumericType( xCC->getStringType( rStr, 0, rStr.Len(), getLocale() ) ); + else + return sal_False; + } + catch ( Exception& ) + { + DBG_ERRORFILE( "isAlphaNumeric: Exception caught!" ); + return sal_False; + } +} + + +sal_Bool CharClass::isLetterNumeric( const String& rStr, xub_StrLen nPos ) const +{ + sal_Unicode c = rStr.GetChar( nPos ); + if ( c < 128 ) + return isAsciiAlphaNumeric( c ); + + try + { + if ( xCC.is() ) + return (xCC->getCharacterType( rStr, nPos, getLocale() ) & + (nCharClassLetterType | KCharacterType::DIGIT)) != 0; + else + return sal_False; + } + catch ( Exception& ) + { + DBG_ERRORFILE( "isLetterNumeric: Exception caught!" ); + return sal_False; + } +} + + +sal_Bool CharClass::isLetterNumeric( const String& rStr ) const +{ + try + { + if ( xCC.is() ) + return isLetterNumericType( xCC->getStringType( rStr, 0, rStr.Len(), getLocale() ) ); + else + return sal_False; + } + catch ( Exception& ) + { + DBG_ERRORFILE( "isLetterNumeric: Exception caught!" ); + return sal_False; + } +} + + +String CharClass::toUpper( const String& rStr, xub_StrLen nPos, xub_StrLen nCount ) const +{ + return toUpper_rtl(rStr, nPos, nCount); +} + + +String CharClass::toLower( const String& rStr, xub_StrLen nPos, xub_StrLen nCount ) const +{ + return toLower_rtl(::rtl::OUString(rStr), nPos, nCount); +} + + +String CharClass::toTitle( const String& rStr, xub_StrLen nPos, xub_StrLen nCount ) const +{ + try + { + if ( xCC.is() ) + return xCC->toTitle( rStr, nPos, nCount, getLocale() ); + else + return rStr.Copy( nPos, nCount ); + } + catch ( Exception& ) + { + DBG_ERRORFILE( "toTitle: Exception caught!" ); + return rStr.Copy( nPos, nCount ); + } +} + + +::rtl::OUString CharClass::toUpper_rtl( const ::rtl::OUString& rStr, sal_Int32 nPos, sal_Int32 nCount ) const +{ + try + { + if ( xCC.is() ) + return xCC->toUpper( rStr, nPos, nCount, getLocale() ); + else + return rStr.copy( nPos, nCount ); + } + catch ( Exception& ) + { + DBG_ERRORFILE( "toUpper: Exception caught!" ); + return rStr.copy( nPos, nCount ); + } +} + + +::rtl::OUString CharClass::toLower_rtl( const ::rtl::OUString& rStr, sal_Int32 nPos, sal_Int32 nCount ) const +{ + try + { + if ( xCC.is() ) + return xCC->toLower( rStr, nPos, nCount, getLocale() ); + else + return rStr.copy( nPos, nCount ); + } + catch ( Exception& ) + { + DBG_ERRORFILE( "toLower: Exception caught!" ); + return rStr.copy( nPos, nCount ); + } +} + + +sal_Int16 CharClass::getType( const String& rStr, xub_StrLen nPos ) const +{ + try + { + if ( xCC.is() ) + return xCC->getType( rStr, nPos ); + else + return 0; + } + catch ( Exception& ) + { + DBG_ERRORFILE( "getType: Exception caught!" ); + return 0; + } +} + + +sal_Int16 CharClass::getCharacterDirection( const String& rStr, xub_StrLen nPos ) const +{ + try + { + if ( xCC.is() ) + return xCC->getCharacterDirection( rStr, nPos ); + else + return 0; + } + catch ( Exception& ) + { + DBG_ERRORFILE( "getCharacterDirection: Exception caught!" ); + return 0; + } +} + + +sal_Int16 CharClass::getScript( const String& rStr, xub_StrLen nPos ) const +{ + try + { + if ( xCC.is() ) + return xCC->getScript( rStr, nPos ); + else + return 0; + } + catch ( Exception& ) + { + DBG_ERRORFILE( "getScript: Exception caught!" ); + return 0; + } +} + + +sal_Int32 CharClass::getCharacterType( const String& rStr, xub_StrLen nPos ) const +{ + try + { + if ( xCC.is() ) + return xCC->getCharacterType( rStr, nPos, getLocale() ); + else + return 0; + } + catch ( Exception& ) + { + DBG_ERRORFILE( "getCharacterType: Exception caught!" ); + return 0; + } +} + + +sal_Int32 CharClass::getStringType( const String& rStr, xub_StrLen nPos, xub_StrLen nCount ) const +{ + try + { + if ( xCC.is() ) + return xCC->getStringType( rStr, nPos, nCount, getLocale() ); + else + return 0; + } + catch ( Exception& ) + { + DBG_ERRORFILE( "getStringType: Exception caught!" ); + return 0; + } +} + + +::com::sun::star::i18n::ParseResult CharClass::parseAnyToken( + const String& rStr, + sal_Int32 nPos, + sal_Int32 nStartCharFlags, + const String& userDefinedCharactersStart, + sal_Int32 nContCharFlags, + const String& userDefinedCharactersCont ) const +{ + try + { + if ( xCC.is() ) + return xCC->parseAnyToken( rStr, nPos, getLocale(), + nStartCharFlags, userDefinedCharactersStart, + nContCharFlags, userDefinedCharactersCont ); + else + return ParseResult(); + } + catch ( Exception& e ) + { +#ifndef PRODUCT + ByteString aMsg( "parseAnyToken: Exception caught\n" ); + aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); + DBG_ERRORFILE( aMsg.GetBuffer() ); +#else + (void)e; +#endif + return ParseResult(); + } +} + + +::com::sun::star::i18n::ParseResult CharClass::parsePredefinedToken( + sal_Int32 nTokenType, + const String& rStr, + sal_Int32 nPos, + sal_Int32 nStartCharFlags, + const String& userDefinedCharactersStart, + sal_Int32 nContCharFlags, + const String& userDefinedCharactersCont ) const +{ + try + { + if ( xCC.is() ) + return xCC->parsePredefinedToken( nTokenType, rStr, nPos, getLocale(), + nStartCharFlags, userDefinedCharactersStart, + nContCharFlags, userDefinedCharactersCont ); + else + return ParseResult(); + } + catch ( Exception& e ) + { +#ifndef PRODUCT + ByteString aMsg( "parsePredefinedToken: Exception caught\n" ); + aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); + DBG_ERRORFILE( aMsg.GetBuffer() ); +#else + (void)e; +#endif + return ParseResult(); + } +} + + + diff --git a/unotools/source/i18n/collatorwrapper.cxx b/unotools/source/i18n/collatorwrapper.cxx new file mode 100644 index 000000000000..99bb28cf6171 --- /dev/null +++ b/unotools/source/i18n/collatorwrapper.cxx @@ -0,0 +1,217 @@ +/************************************************************************* + * + * 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: collatorwrapper.cxx,v $ + * $Revision: 1.8 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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_unotools.hxx" +#include <unotools/collatorwrapper.hxx> +#include <tools/debug.hxx> + +#ifndef _COMPHELPER_COMPONENTFACTORY_HXX_ +#include <comphelper/componentfactory.hxx> +#endif +#include <com/sun/star/uno/XInterface.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> + +using namespace ::com::sun::star; + +CollatorWrapper::CollatorWrapper ( + const uno::Reference< lang::XMultiServiceFactory > &xServiceFactory) + : mxServiceFactory (xServiceFactory) +{ + ::rtl::OUString aService (RTL_CONSTASCII_USTRINGPARAM("com.sun.star.i18n.Collator")); + + if (mxServiceFactory.is()) + { + try + { + mxInternationalCollator = uno::Reference< i18n::XCollator > ( + mxServiceFactory->createInstance(aService), uno::UNO_QUERY); + } + catch (uno::Exception& rException) + { + (void)rException; + DBG_ERRORFILE ("CollatorWrapper: failed to create instance"); + } + } + else + { + ::rtl::OUString aLibrary (RTL_CONSTASCII_USTRINGPARAM(LLCF_LIBNAME("i18n"))); + + try + { + uno::Reference< uno::XInterface > xInstance = + ::comphelper::getComponentInstance (aLibrary, aService); + + if (xInstance.is()) + { + uno::Any xInterface = xInstance->queryInterface ( + ::getCppuType((const uno::Reference< i18n::XCollator >*)0) ); + xInterface >>= mxInternationalCollator; + } + } + catch (uno::Exception& rException) + { + (void)rException; + DBG_ERRORFILE ("CollatorWrapper: failed to get component instance!"); + } + } + + DBG_ASSERT (mxInternationalCollator.is(), "CollatorWrapper: no i18n collator"); +} + +CollatorWrapper::~CollatorWrapper() +{ +} + +sal_Int32 +CollatorWrapper::compareSubstring ( + const ::rtl::OUString& s1, sal_Int32 off1, sal_Int32 len1, + const ::rtl::OUString& s2, sal_Int32 off2, sal_Int32 len2) const +{ + try + { + if (mxInternationalCollator.is()) + return mxInternationalCollator->compareSubstring ( + s1, off1, len1, s2, off2, len2); + } + catch (uno::RuntimeException& rRuntimeException) + { + (void)rRuntimeException; + DBG_ERRORFILE ("CollatorWrapper: compareSubstring failed"); + } + + return 0; +} + +sal_Int32 +CollatorWrapper::compareString (const ::rtl::OUString& s1, const ::rtl::OUString& s2) const +{ + try + { + if (mxInternationalCollator.is()) + return mxInternationalCollator->compareString (s1, s2); + } + catch (uno::RuntimeException& rRuntimeException) + { + (void)rRuntimeException; + DBG_ERRORFILE ("CollatorWrapper: compareString failed"); + } + + return 0; +} + +uno::Sequence< ::rtl::OUString > +CollatorWrapper::listCollatorAlgorithms (const lang::Locale& rLocale) const +{ + try + { + if (mxInternationalCollator.is()) + return mxInternationalCollator->listCollatorAlgorithms (rLocale); + } + catch (uno::RuntimeException& rRuntimeException) + { + (void)rRuntimeException; + DBG_ERRORFILE ("CollatorWrapper: listCollatorAlgorithms failed"); + } + + return uno::Sequence< ::rtl::OUString > (); +} + +uno::Sequence< sal_Int32 > +CollatorWrapper::listCollatorOptions (const ::rtl::OUString& rAlgorithm) const +{ + try + { + if (mxInternationalCollator.is()) + return mxInternationalCollator->listCollatorOptions (rAlgorithm); + } + catch (uno::RuntimeException& rRuntimeException) + { + (void)rRuntimeException; + DBG_ERRORFILE ("CollatorWrapper: listCollatorOptions failed"); + } + + return uno::Sequence< sal_Int32 > (); +} + +sal_Int32 +CollatorWrapper::loadDefaultCollator (const lang::Locale& rLocale, sal_Int32 nOptions) +{ + try + { + if (mxInternationalCollator.is()) + return mxInternationalCollator->loadDefaultCollator (rLocale, nOptions); + } + catch (uno::RuntimeException& rRuntimeException) + { + (void)rRuntimeException; + DBG_ERRORFILE ("CollatorWrapper: loadDefaultCollator failed"); + } + + return 0; +} + +sal_Int32 +CollatorWrapper::loadCollatorAlgorithm (const ::rtl::OUString& rAlgorithm, + const lang::Locale& rLocale, sal_Int32 nOptions) +{ + try + { + if (mxInternationalCollator.is()) + return mxInternationalCollator->loadCollatorAlgorithm ( + rAlgorithm, rLocale, nOptions); + } + catch (uno::RuntimeException& rRuntimeException) + { + (void)rRuntimeException; + DBG_ERRORFILE ("CollatorWrapper: loadCollatorAlgorithm failed"); + } + + return 0; + +} + +void +CollatorWrapper::loadCollatorAlgorithmWithEndUserOption ( + const ::rtl::OUString& rAlgorithm, + const lang::Locale& rLocale, const uno::Sequence< sal_Int32 >& rOption) +{ + try + { + if (mxInternationalCollator.is()) + mxInternationalCollator->loadCollatorAlgorithmWithEndUserOption ( + rAlgorithm, rLocale, rOption); + } + catch (uno::RuntimeException& rRuntimeException) + { + (void)rRuntimeException; + DBG_ERRORFILE ("CollatorWrapper: loadCollatorAlgorithmWithEndUserOption failed"); + } +} diff --git a/unotools/source/i18n/intlwrapper.cxx b/unotools/source/i18n/intlwrapper.cxx new file mode 100644 index 000000000000..e961861da824 --- /dev/null +++ b/unotools/source/i18n/intlwrapper.cxx @@ -0,0 +1,113 @@ +/************************************************************************* + * + * 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: intlwrapper.cxx,v $ + * $Revision: 1.7 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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_unotools.hxx" + +#include "unotools/intlwrapper.hxx" +#include <com/sun/star/i18n/CollatorOptions.hpp> +#include <i18npool/mslangid.hxx> + +IntlWrapper::IntlWrapper( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > & xSF, + const ::com::sun::star::lang::Locale& rLocale ) + : + aLocale( rLocale ), + xSMgr( xSF ), + pCharClass( NULL ), + pLocaleData( NULL ), + pCalendar( NULL ), + pCollator( NULL ), + pCaseCollator( NULL ) +{ + eLanguage = MsLangId::convertLocaleToLanguage( aLocale ); +} + + +IntlWrapper::IntlWrapper( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > & xSF, + LanguageType eLang ) + : + xSMgr( xSF ), + pCharClass( NULL ), + pLocaleData( NULL ), + pCalendar( NULL ), + pCollator( NULL ), + pCaseCollator( NULL ), + eLanguage( eLang ) +{ + MsLangId::convertLanguageToLocale( eLanguage, aLocale ); +} + + +IntlWrapper::~IntlWrapper() +{ + delete pCharClass; + delete pLocaleData; + delete pCalendar; + delete pCollator; + delete pCaseCollator; +} + + +void IntlWrapper::ImplNewCharClass() const +{ + ((IntlWrapper*)this)->pCharClass = new CharClass( xSMgr, aLocale ); +} + + +void IntlWrapper::ImplNewLocaleData() const +{ + ((IntlWrapper*)this)->pLocaleData = new LocaleDataWrapper( xSMgr, aLocale ); +} + + +void IntlWrapper::ImplNewCalendar() const +{ + CalendarWrapper* p = new CalendarWrapper( xSMgr ); + p->loadDefaultCalendar( aLocale ); + ((IntlWrapper*)this)->pCalendar = p; +} + + +void IntlWrapper::ImplNewCollator( BOOL bCaseSensitive ) const +{ + CollatorWrapper* p = new CollatorWrapper( xSMgr ); + if ( bCaseSensitive ) + { + p->loadDefaultCollator( aLocale, 0 ); + ((IntlWrapper*)this)->pCaseCollator = p; + } + else + { + p->loadDefaultCollator( aLocale, ::com::sun::star::i18n::CollatorOptions::CollatorOptions_IGNORE_CASE ); + ((IntlWrapper*)this)->pCollator = p; + } +} diff --git a/unotools/source/i18n/localedatawrapper.cxx b/unotools/source/i18n/localedatawrapper.cxx new file mode 100644 index 000000000000..074ff7af716a --- /dev/null +++ b/unotools/source/i18n/localedatawrapper.cxx @@ -0,0 +1,2010 @@ +/************************************************************************* + * + * 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: localedatawrapper.cxx,v $ + * $Revision: 1.43 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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_unotools.hxx" + +#include <string.h> // memcpy() +#include <stdio.h> // fprintf(), stderr + +#include <unotools/localedatawrapper.hxx> +#include <unotools/numberformatcodewrapper.hxx> +#include <unotools/calendarwrapper.hxx> +#include <unotools/digitgroupingiterator.hxx> +#include <tools/string.hxx> +#include <tools/debug.hxx> +#include <i18npool/mslangid.hxx> + +#ifndef _COMPHELPER_COMPONENTFACTORY_HXX_ +#include <comphelper/componentfactory.hxx> +#endif +#include <unotools/processfactory.hxx> +#include <com/sun/star/uno/XInterface.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/i18n/KNumberFormatUsage.hpp> +#include <com/sun/star/i18n/KNumberFormatType.hpp> +#include <com/sun/star/i18n/CalendarFieldIndex.hpp> +#include <com/sun/star/i18n/CalendarDisplayIndex.hpp> + +#ifndef _COM_SUN_STAR_I18N_NUMBERFORMATINDEX_HPP_ +#include <com/sun/star/i18n/NumberFormatIndex.hdl> +#endif +#include <rtl/instance.hxx> + +#define LOCALEDATA_LIBRARYNAME "i18npool" +#define LOCALEDATA_SERVICENAME "com.sun.star.i18n.LocaleData" + +static const int nDateFormatInvalid = -1; +static const USHORT nCurrFormatInvalid = 0xffff; +static const USHORT nCurrFormatDefault = 0; + +using namespace ::com::sun::star; +using namespace ::com::sun::star::i18n; +using namespace ::com::sun::star::uno; + +namespace +{ + struct InstalledLocales + : public rtl::Static< + uno::Sequence< lang::Locale >, InstalledLocales > + {}; + + struct InstalledLanguageTypes + : public rtl::Static< + uno::Sequence< sal_uInt16 >, InstalledLanguageTypes > + {}; +} + +BYTE LocaleDataWrapper::nLocaleDataChecking = 0; + +LocaleDataWrapper::LocaleDataWrapper( + const Reference< lang::XMultiServiceFactory > & xSF, + const lang::Locale& rLocale + ) + : + xSMgr( xSF ), + bLocaleDataItemValid( FALSE ), + bReservedWordValid( FALSE ) +{ + setLocale( rLocale ); + if ( xSMgr.is() ) + { + try + { + xLD = Reference< XLocaleData2 > ( xSMgr->createInstance( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( LOCALEDATA_SERVICENAME ) ) ), + uno::UNO_QUERY ); + } + catch ( Exception& e ) + { +#ifdef DBG_UTIL + ByteString aMsg( "LocaleDataWrapper ctor: Exception caught\n" ); + aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); + DBG_ERRORFILE( aMsg.GetBuffer() ); +#else + (void)e; +#endif + } + } + else + { // try to get an instance somehow + DBG_ERRORFILE( "LocaleDataWrapper: no service manager, trying own" ); + try + { + Reference< XInterface > xI = ::comphelper::getComponentInstance( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( LLCF_LIBNAME( LOCALEDATA_LIBRARYNAME ) ) ), + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( LOCALEDATA_SERVICENAME ) ) ); + if ( xI.is() ) + { + Any x = xI->queryInterface( ::getCppuType((const Reference< XLocaleData2 >*)0) ); + x >>= xLD; + } + } + catch ( Exception& e ) + { +#ifdef DBG_UTIL + ByteString aMsg( "getComponentInstance: Exception caught\n" ); + aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); + DBG_ERRORFILE( aMsg.GetBuffer() ); +#else + (void)e; +#endif + } + } +} + + +LocaleDataWrapper::~LocaleDataWrapper() +{ +} + + +void LocaleDataWrapper::setLocale( const ::com::sun::star::lang::Locale& rLocale ) +{ + ::utl::ReadWriteGuard aGuard( aMutex, ::utl::ReadWriteGuardMode::nCriticalChange ); + aLocale = rLocale; + invalidateData(); +} + + +const ::com::sun::star::lang::Locale& LocaleDataWrapper::getLocale() const +{ + ::utl::ReadWriteGuard aGuard( aMutex ); + return aLocale; +} + + +void LocaleDataWrapper::invalidateData() +{ + aCurrSymbol.Erase(); + aCurrBankSymbol.Erase(); + nDateFormat = nLongDateFormat = nDateFormatInvalid; + nCurrPositiveFormat = nCurrNegativeFormat = nCurrDigits = nCurrFormatInvalid; + if ( bLocaleDataItemValid ) + { + for ( sal_Int32 j=0; j<LocaleItem::COUNT; j++ ) + { + aLocaleItem[j].Erase(); + } + bLocaleDataItemValid = FALSE; + } + if ( bReservedWordValid ) + { + for ( sal_Int16 j=0; j<reservedWords::COUNT; j++ ) + { + aReservedWord[j].Erase(); + } + bReservedWordValid = FALSE; + } + xDefaultCalendar.reset(); + if (aGrouping.getLength()) + aGrouping[0] = 0; + // dummies + cCurrZeroChar = '0'; +} + + +::com::sun::star::i18n::LanguageCountryInfo LocaleDataWrapper::getLanguageCountryInfo() const +{ + try + { + if ( xLD.is() ) + return xLD->getLanguageCountryInfo( getLocale() ); + } + catch ( Exception& e ) + { +#ifdef DBG_UTIL + ByteString aMsg( "getLanguageCountryInfo: Exception caught\n" ); + aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); + DBG_ERRORFILE( aMsg.GetBuffer() ); +#else + (void)e; +#endif + } + return ::com::sun::star::i18n::LanguageCountryInfo(); +} + + +::com::sun::star::i18n::LocaleDataItem LocaleDataWrapper::getLocaleItem() const +{ + try + { + if ( xLD.is() ) + return xLD->getLocaleItem( getLocale() ); + } + catch ( Exception& e ) + { +#ifdef DBG_UTIL + ByteString aMsg( "getLocaleItem: Exception caught\n" ); + aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); + DBG_ERRORFILE( aMsg.GetBuffer() ); +#else + (void)e; +#endif + } + return ::com::sun::star::i18n::LocaleDataItem(); +} + + +::com::sun::star::uno::Sequence< ::com::sun::star::i18n::Calendar > LocaleDataWrapper::getAllCalendars() const +{ + try + { + if ( xLD.is() ) + return xLD->getAllCalendars( getLocale() ); + } + catch ( Exception& e ) + { +#ifdef DBG_UTIL + ByteString aMsg( "getAllCalendars: Exception caught\n" ); + aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); + DBG_ERRORFILE( aMsg.GetBuffer() ); +#else + (void)e; +#endif + } + return ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::Calendar >(0); +} + + +::com::sun::star::uno::Sequence< ::com::sun::star::i18n::Currency2 > LocaleDataWrapper::getAllCurrencies() const +{ + try + { + if ( xLD.is() ) + return xLD->getAllCurrencies2( getLocale() ); + } + catch ( Exception& e ) + { +#ifdef DBG_UTIL + ByteString aMsg( "getAllCurrencies: Exception caught\n" ); + aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); + DBG_ERRORFILE( aMsg.GetBuffer() ); +#else + (void)e; +#endif + } + return ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::Currency2 >(0); +} + + +::com::sun::star::uno::Sequence< ::com::sun::star::i18n::FormatElement > LocaleDataWrapper::getAllFormats() const +{ + try + { + if ( xLD.is() ) + return xLD->getAllFormats( getLocale() ); + } + catch ( Exception& e ) + { +#ifdef DBG_UTIL + ByteString aMsg( "getAllFormats: Exception caught\n" ); + aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); + DBG_ERRORFILE( aMsg.GetBuffer() ); +#else + (void)e; +#endif + } + return ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::FormatElement >(0); +} + + +::com::sun::star::uno::Sequence< ::com::sun::star::i18n::Implementation > LocaleDataWrapper::getCollatorImplementations() const +{ + try + { + if ( xLD.is() ) + return xLD->getCollatorImplementations( getLocale() ); + } + catch ( Exception& e ) + { +#ifdef DBG_UTIL + ByteString aMsg( "getCollatorImplementations: Exception caught\n" ); + aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); + DBG_ERRORFILE( aMsg.GetBuffer() ); +#else + (void)e; +#endif + } + return ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::Implementation >(0); +} + + +::com::sun::star::uno::Sequence< ::rtl::OUString > LocaleDataWrapper::getTransliterations() const +{ + try + { + if ( xLD.is() ) + return xLD->getTransliterations( getLocale() ); + } + catch ( Exception& e ) + { +#ifdef DBG_UTIL + ByteString aMsg( "getTransliterations: Exception caught\n" ); + aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); + DBG_ERRORFILE( aMsg.GetBuffer() ); +#else + (void)e; +#endif + } + return ::com::sun::star::uno::Sequence< ::rtl::OUString >(0); +} + + +::com::sun::star::i18n::ForbiddenCharacters LocaleDataWrapper::getForbiddenCharacters() const +{ + try + { + if ( xLD.is() ) + return xLD->getForbiddenCharacters( getLocale() ); + } + catch ( Exception& e ) + { +#ifdef DBG_UTIL + ByteString aMsg( "getForbiddenCharacters: Exception caught\n" ); + aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); + DBG_ERRORFILE( aMsg.GetBuffer() ); +#else + (void)e; +#endif + } + return ::com::sun::star::i18n::ForbiddenCharacters(); +} + + +::com::sun::star::uno::Sequence< ::rtl::OUString > LocaleDataWrapper::getReservedWord() const +{ + try + { + if ( xLD.is() ) + return xLD->getReservedWord( getLocale() ); + } + catch ( Exception& e ) + { +#ifdef DBG_UTIL + ByteString aMsg( "getReservedWord: Exception caught\n" ); + aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); + DBG_ERRORFILE( aMsg.GetBuffer() ); +#else + (void)e; +#endif + } + return ::com::sun::star::uno::Sequence< ::rtl::OUString >(0); +} + + +::com::sun::star::uno::Sequence< ::com::sun::star::lang::Locale > LocaleDataWrapper::getAllInstalledLocaleNames() const +{ + uno::Sequence< lang::Locale > &rInstalledLocales = InstalledLocales::get(); + + if ( rInstalledLocales.getLength() ) + return rInstalledLocales; + + try + { + if ( xLD.is() ) + rInstalledLocales = xLD->getAllInstalledLocaleNames(); + } + catch ( Exception& e ) + { +#ifdef DBG_UTIL + ByteString aMsg( "getAllInstalledLocaleNames: Exception caught\n" ); + aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); + DBG_ERRORFILE( aMsg.GetBuffer() ); +#else + (void)e; +#endif + } + return rInstalledLocales; +} + + +// --- Impl and helpers ---------------------------------------------------- + +// static +::com::sun::star::uno::Sequence< ::com::sun::star::lang::Locale > LocaleDataWrapper::getInstalledLocaleNames() +{ + const uno::Sequence< lang::Locale > &rInstalledLocales = + InstalledLocales::get(); + + if ( !rInstalledLocales.getLength() ) + { + LocaleDataWrapper aLDW( ::comphelper::getProcessServiceFactory(), lang::Locale() ); + aLDW.getAllInstalledLocaleNames(); + } + return rInstalledLocales; +} + +// static +::com::sun::star::uno::Sequence< sal_uInt16 > LocaleDataWrapper::getInstalledLanguageTypes() +{ + uno::Sequence< sal_uInt16 > &rInstalledLanguageTypes = + InstalledLanguageTypes::get(); + + if ( rInstalledLanguageTypes.getLength() ) + return rInstalledLanguageTypes; + + ::com::sun::star::uno::Sequence< ::com::sun::star::lang::Locale > xLoc = + getInstalledLocaleNames(); + sal_Int32 nCount = xLoc.getLength(); + ::com::sun::star::uno::Sequence< sal_uInt16 > xLang( nCount ); + sal_Int32 nLanguages = 0; + for ( sal_Int32 i=0; i<nCount; i++ ) + { + String aDebugLocale; + if (areChecksEnabled()) + { + aDebugLocale = xLoc[i].Language; + if ( xLoc[i].Country.getLength() ) + { + aDebugLocale += '_'; + aDebugLocale += String( xLoc[i].Country); + if ( xLoc[i].Variant.getLength() ) + { + aDebugLocale += '_'; + aDebugLocale += String( xLoc[i].Variant); + } + } + } + + if ( xLoc[i].Variant.getLength() ) + { + if (areChecksEnabled()) + { + String aMsg( RTL_CONSTASCII_USTRINGPARAM( + "LocaleDataWrapper::getInstalledLanguageTypes: Variants not supported, locale\n")); + aMsg += aDebugLocale; + outputCheckMessage( aMsg ); + } + continue; + } + LanguageType eLang = MsLangId::convertLocaleToLanguage( xLoc[i] ); + + // In checks, exclude known problems because no MS-LCID defined. + if (areChecksEnabled() && eLang == LANGUAGE_DONTKNOW +// && !aDebugLocale.EqualsAscii( "br_AE" ) // ?!? Breton in United Arabic Emirates + ) + { + String aMsg( RTL_CONSTASCII_USTRINGPARAM( + "ConvertIsoNamesToLanguage: unknown MS-LCID for locale\n")); + aMsg += aDebugLocale; + outputCheckMessage( aMsg ); + } + + switch ( eLang ) + { + case LANGUAGE_NORWEGIAN : // no_NO, not Bokmal (nb_NO), not Nynorsk (nn_NO) + eLang = LANGUAGE_DONTKNOW; // don't offer "Unknown" language + break; + } + if ( eLang != LANGUAGE_DONTKNOW ) + { + rtl::OUString aLanguage, aCountry; + MsLangId::convertLanguageToIsoNames( eLang, aLanguage, aCountry ); + if ( xLoc[i].Language != aLanguage || + xLoc[i].Country != aCountry ) + { + // In checks, exclude known problems because no MS-LCID defined + // and default for Language found. + if ( areChecksEnabled() + && !aDebugLocale.EqualsAscii( "ar_SD" ) // Sudan/ar + && !aDebugLocale.EqualsAscii( "en_CB" ) // Carribean is not a country +// && !aDebugLocale.EqualsAscii( "en_BG" ) // ?!? Bulgaria/en +// && !aDebugLocale.EqualsAscii( "es_BR" ) // ?!? Brazil/es + ) + { + String aMsg( RTL_CONSTASCII_USTRINGPARAM( + "ConvertIsoNamesToLanguage/ConvertLanguageToIsoNames: ambiguous locale (MS-LCID?)\n")); + aMsg += aDebugLocale; + aMsg.AppendAscii( RTL_CONSTASCII_STRINGPARAM( " -> 0x" ) ); + aMsg += String::CreateFromInt32( eLang, 16 ); + aMsg.AppendAscii( RTL_CONSTASCII_STRINGPARAM( " -> " ) ); + aMsg += String( aLanguage); + if ( aCountry.getLength() ) + { + aMsg += '_'; + aMsg += String( aCountry); + } + outputCheckMessage( aMsg ); + } + eLang = LANGUAGE_DONTKNOW; + } + } + if ( eLang != LANGUAGE_DONTKNOW ) + xLang[ nLanguages++ ] = eLang; + } + if ( nLanguages < nCount ) + xLang.realloc( nLanguages ); + rInstalledLanguageTypes = xLang; + + return rInstalledLanguageTypes; +} + +const String& LocaleDataWrapper::getOneLocaleItem( sal_Int16 nItem ) const +{ + ::utl::ReadWriteGuard aGuard( aMutex ); + if ( nItem >= LocaleItem::COUNT ) + { + DBG_ERRORFILE( "getOneLocaleItem: bounds" ); + return aLocaleItem[0]; + } + if ( aLocaleItem[nItem].Len() == 0 ) + { // no cached content + aGuard.changeReadToWrite(); + ((LocaleDataWrapper*)this)->getOneLocaleItemImpl( nItem ); + } + return aLocaleItem[nItem]; +} + + +void LocaleDataWrapper::getOneLocaleItemImpl( sal_Int16 nItem ) +{ + if ( !bLocaleDataItemValid ) + { + aLocaleDataItem = getLocaleItem(); + bLocaleDataItemValid = TRUE; + } + switch ( nItem ) + { + case LocaleItem::DATE_SEPARATOR : + aLocaleItem[nItem] = aLocaleDataItem.dateSeparator; + break; + case LocaleItem::THOUSAND_SEPARATOR : + aLocaleItem[nItem] = aLocaleDataItem.thousandSeparator; + break; + case LocaleItem::DECIMAL_SEPARATOR : + aLocaleItem[nItem] = aLocaleDataItem.decimalSeparator; + break; + case LocaleItem::TIME_SEPARATOR : + aLocaleItem[nItem] = aLocaleDataItem.timeSeparator; + break; + case LocaleItem::TIME_100SEC_SEPARATOR : + aLocaleItem[nItem] = aLocaleDataItem.time100SecSeparator; + break; + case LocaleItem::LIST_SEPARATOR : + aLocaleItem[nItem] = aLocaleDataItem.listSeparator; + break; + case LocaleItem::SINGLE_QUOTATION_START : + aLocaleItem[nItem] = aLocaleDataItem.quotationStart; + break; + case LocaleItem::SINGLE_QUOTATION_END : + aLocaleItem[nItem] = aLocaleDataItem.quotationEnd; + break; + case LocaleItem::DOUBLE_QUOTATION_START : + aLocaleItem[nItem] = aLocaleDataItem.doubleQuotationStart; + break; + case LocaleItem::DOUBLE_QUOTATION_END : + aLocaleItem[nItem] = aLocaleDataItem.doubleQuotationEnd; + break; + case LocaleItem::MEASUREMENT_SYSTEM : + aLocaleItem[nItem] = aLocaleDataItem.measurementSystem; + break; + case LocaleItem::TIME_AM : + aLocaleItem[nItem] = aLocaleDataItem.timeAM; + break; + case LocaleItem::TIME_PM : + aLocaleItem[nItem] = aLocaleDataItem.timePM; + break; + case LocaleItem::LONG_DATE_DAY_OF_WEEK_SEPARATOR : + aLocaleItem[nItem] = aLocaleDataItem.LongDateDayOfWeekSeparator; + break; + case LocaleItem::LONG_DATE_DAY_SEPARATOR : + aLocaleItem[nItem] = aLocaleDataItem.LongDateDaySeparator; + break; + case LocaleItem::LONG_DATE_MONTH_SEPARATOR : + aLocaleItem[nItem] = aLocaleDataItem.LongDateMonthSeparator; + break; + case LocaleItem::LONG_DATE_YEAR_SEPARATOR : + aLocaleItem[nItem] = aLocaleDataItem.LongDateYearSeparator; + break; + default: + DBG_ERRORFILE( "getOneLocaleItemImpl: which one?" ); + } +} + + +void LocaleDataWrapper::getOneReservedWordImpl( sal_Int16 nWord ) +{ + if ( !bReservedWordValid ) + { + aReservedWordSeq = getReservedWord(); + bReservedWordValid = TRUE; + } + DBG_ASSERT( nWord < aReservedWordSeq.getLength(), "getOneReservedWordImpl: which one?" ); + if ( nWord < aReservedWordSeq.getLength() ) + aReservedWord[nWord] = aReservedWordSeq[nWord]; +} + + +const String& LocaleDataWrapper::getOneReservedWord( sal_Int16 nWord ) const +{ + ::utl::ReadWriteGuard aGuard( aMutex ); + if ( nWord < 0 || nWord >= reservedWords::COUNT ) + { + DBG_ERRORFILE( "getOneReservedWord: bounds" ); + nWord = reservedWords::FALSE_WORD; + } + if ( aReservedWord[nWord].Len() == 0 ) + { // no cached content + aGuard.changeReadToWrite(); + ((LocaleDataWrapper*)this)->getOneReservedWordImpl( nWord ); + } + return aReservedWord[nWord]; +} + + +MeasurementSystem LocaleDataWrapper::mapMeasurementStringToEnum( const String& rMS ) const +{ +//! TODO: could be cached too + if ( rMS.EqualsIgnoreCaseAscii( "metric" ) ) + return MEASURE_METRIC; +//! TODO: other measurement systems? => extend enum MeasurementSystem + return MEASURE_US; +} + + +void LocaleDataWrapper::getDefaultCalendarImpl() +{ + if (!xDefaultCalendar) + { + Sequence< Calendar > xCals = getAllCalendars(); + sal_Int32 nCount = xCals.getLength(); + sal_Int32 nDef = 0; + if (nCount > 1) + { + const Calendar* pArr = xCals.getArray(); + for (sal_Int32 i=0; i<nCount; ++i) + { + if (pArr[i].Default) + { + nDef = i; + break; + } + } + } + xDefaultCalendar.reset( new Calendar( xCals[nDef])); + } +} + + +const ::boost::shared_ptr< ::com::sun::star::i18n::Calendar > LocaleDataWrapper::getDefaultCalendar() const +{ + ::utl::ReadWriteGuard aGuard( aMutex ); + if (!xDefaultCalendar) + { // no cached content + aGuard.changeReadToWrite(); + ((LocaleDataWrapper*)this)->getDefaultCalendarImpl(); + } + return xDefaultCalendar; +} + + +const ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::CalendarItem > LocaleDataWrapper::getDefaultCalendarDays() const +{ + return getDefaultCalendar()->Days; +} + + +const ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::CalendarItem > LocaleDataWrapper::getDefaultCalendarMonths() const +{ + return getDefaultCalendar()->Months; +} + + +// --- currencies ----------------------------------------------------- + +const String& LocaleDataWrapper::getCurrSymbol() const +{ + ::utl::ReadWriteGuard aGuard( aMutex ); + if ( !aCurrSymbol.Len() ) + { + aGuard.changeReadToWrite(); + ((LocaleDataWrapper*)this)->getCurrSymbolsImpl(); + } + return aCurrSymbol; +} + + +const String& LocaleDataWrapper::getCurrBankSymbol() const +{ + ::utl::ReadWriteGuard aGuard( aMutex ); + if ( !aCurrBankSymbol.Len() ) + { + aGuard.changeReadToWrite(); + ((LocaleDataWrapper*)this)->getCurrSymbolsImpl(); + } + return aCurrBankSymbol; +} + + +USHORT LocaleDataWrapper::getCurrPositiveFormat() const +{ + ::utl::ReadWriteGuard aGuard( aMutex ); + if ( nCurrPositiveFormat == nCurrFormatInvalid ) + { + aGuard.changeReadToWrite(); + ((LocaleDataWrapper*)this)->getCurrFormatsImpl(); + } + return nCurrPositiveFormat; +} + + +USHORT LocaleDataWrapper::getCurrNegativeFormat() const +{ + ::utl::ReadWriteGuard aGuard( aMutex ); + if ( nCurrNegativeFormat == nCurrFormatInvalid ) + { + aGuard.changeReadToWrite(); + ((LocaleDataWrapper*)this)->getCurrFormatsImpl(); + } + return nCurrNegativeFormat; +} + + +USHORT LocaleDataWrapper::getCurrDigits() const +{ + ::utl::ReadWriteGuard aGuard( aMutex ); + if ( nCurrDigits == nCurrFormatInvalid ) + { + aGuard.changeReadToWrite(); + ((LocaleDataWrapper*)this)->getCurrSymbolsImpl(); + } + return nCurrDigits; +} + + +void LocaleDataWrapper::getCurrSymbolsImpl() +{ + Sequence< Currency2 > aCurrSeq = getAllCurrencies(); + sal_Int32 nCnt = aCurrSeq.getLength(); + Currency2 const * const pCurrArr = aCurrSeq.getArray(); + sal_Int32 nElem; + for ( nElem = 0; nElem < nCnt; nElem++ ) + { + if ( pCurrArr[nElem].Default ) + break; + } + if ( nElem >= nCnt ) + { + if (areChecksEnabled()) + { + String aMsg( RTL_CONSTASCII_USTRINGPARAM( + "LocaleDataWrapper::getCurrSymbolsImpl: no default currency")); + outputCheckMessage( appendLocaleInfo( aMsg ) ); + } + nElem = 0; + if ( nElem >= nCnt ) + { + if (areChecksEnabled()) + outputCheckMessage( String( RTL_CONSTASCII_USTRINGPARAM( + "LocaleDataWrapper::getCurrSymbolsImpl: no currency at all, using ShellsAndPebbles"))); + aCurrSymbol.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "ShellsAndPebbles" ) ); + aCurrBankSymbol = aCurrSymbol; + nCurrPositiveFormat = nCurrNegativeFormat = nCurrFormatDefault; + nCurrDigits = 2; + return ; + } + } + aCurrSymbol = pCurrArr[nElem].Symbol; + aCurrBankSymbol = pCurrArr[nElem].BankSymbol; + nCurrDigits = pCurrArr[nElem].DecimalPlaces; +} + + +void LocaleDataWrapper::scanCurrFormatImpl( const String& rCode, + xub_StrLen nStart, xub_StrLen& nSign, xub_StrLen& nPar, + xub_StrLen& nNum, xub_StrLen& nBlank, xub_StrLen& nSym ) +{ + nSign = nPar = nNum = nBlank = nSym = STRING_NOTFOUND; + const sal_Unicode* const pStr = rCode.GetBuffer(); + const sal_Unicode* const pStop = pStr + rCode.Len(); + const sal_Unicode* p = pStr + nStart; + int nInSection = 0; + BOOL bQuote = FALSE; + while ( p < pStop ) + { + if ( bQuote ) + { + if ( *p == '"' && *(p-1) != '\\' ) + bQuote = FALSE; + } + else + { + switch ( *p ) + { + case '"' : + if ( pStr == p || *(p-1) != '\\' ) + bQuote = TRUE; + break; + case '-' : + if ( !nInSection && nSign == STRING_NOTFOUND ) + nSign = (xub_StrLen)(p - pStr); + break; + case '(' : + if ( !nInSection && nPar == STRING_NOTFOUND ) + nPar = (xub_StrLen)(p - pStr); + break; + case '0' : + case '#' : + if ( !nInSection && nNum == STRING_NOTFOUND ) + nNum = (xub_StrLen)(p - pStr); + break; + case '[' : + nInSection++; + break; + case ']' : + if ( nInSection ) + { + nInSection--; + if ( !nInSection && nBlank == STRING_NOTFOUND + && nSym != STRING_NOTFOUND && p < pStop-1 && *(p+1) == ' ' ) + nBlank = (xub_StrLen)(p - pStr + 1); + } + break; + case '$' : + if ( nSym == STRING_NOTFOUND && nInSection && *(p-1) == '[' ) + { + nSym = (xub_StrLen)(p - pStr + 1); + if ( nNum != STRING_NOTFOUND && *(p-2) == ' ' ) + nBlank = (xub_StrLen)(p - pStr - 2); + } + break; + case ';' : + if ( !nInSection ) + p = pStop; + break; + default: + if ( !nInSection && nSym == STRING_NOTFOUND && rCode.Equals( aCurrSymbol, (xub_StrLen)(p-pStr), aCurrSymbol.Len() ) ) + { // currency symbol not surrounded by [$...] + nSym = (xub_StrLen)(p - pStr); + if ( nBlank == STRING_NOTFOUND && pStr < p && *(p-1) == ' ' ) + nBlank = (xub_StrLen)(p - pStr - 1); + p += aCurrSymbol.Len() - 1; + if ( nBlank == STRING_NOTFOUND && p < pStop-2 && *(p+2) == ' ' ) + nBlank = (xub_StrLen)(p - pStr + 2); + } + } + } + p++; + } +} + + +void LocaleDataWrapper::getCurrFormatsImpl() +{ + NumberFormatCodeWrapper aNumberFormatCode( xSMgr, getLocale() ); + uno::Sequence< NumberFormatCode > aFormatSeq + = aNumberFormatCode.getAllFormatCode( KNumberFormatUsage::CURRENCY ); + sal_Int32 nCnt = aFormatSeq.getLength(); + if ( !nCnt ) + { // bad luck + if (areChecksEnabled()) + { + String aMsg( RTL_CONSTASCII_USTRINGPARAM( + "LocaleDataWrapper::getCurrFormatsImpl: no currency formats")); + outputCheckMessage( appendLocaleInfo( aMsg ) ); + } + nCurrPositiveFormat = nCurrNegativeFormat = nCurrFormatDefault; + return ; + } + // find a negative code (medium preferred) and a default (medium preferred) (not necessarily the same) + NumberFormatCode const * const pFormatArr = aFormatSeq.getArray(); + sal_Int32 nElem, nDef, nNeg, nMedium; + nDef = nNeg = nMedium = -1; + for ( nElem = 0; nElem < nCnt; nElem++ ) + { + if ( pFormatArr[nElem].Type == KNumberFormatType::MEDIUM ) + { + if ( pFormatArr[nElem].Default ) + { + nDef = nElem; + nMedium = nElem; + if ( pFormatArr[nElem].Code.indexOf( ';' ) >= 0 ) + nNeg = nElem; + } + else + { + if ( (nNeg == -1 || nMedium == -1) && pFormatArr[nElem].Code.indexOf( ';' ) >= 0 ) + nNeg = nElem; + if ( nMedium == -1 ) + nMedium = nElem; + } + } + else + { + if ( nDef == -1 && pFormatArr[nElem].Default ) + nDef = nElem; + if ( nNeg == -1 && pFormatArr[nElem].Code.indexOf( ';' ) >= 0 ) + nNeg = nElem; + } + } + + // make sure it's loaded + getCurrSymbol(); + + xub_StrLen nSign, nPar, nNum, nBlank, nSym; + + // positive format + nElem = (nDef >= 0 ? nDef : (nNeg >= 0 ? nNeg : 0)); + scanCurrFormatImpl( pFormatArr[nElem].Code, 0, nSign, nPar, nNum, nBlank, nSym ); + if (areChecksEnabled() && (nNum == STRING_NOTFOUND || nSym == STRING_NOTFOUND)) + { + String aMsg( RTL_CONSTASCII_USTRINGPARAM( + "LocaleDataWrapper::getCurrFormatsImpl: CurrPositiveFormat?")); + outputCheckMessage( appendLocaleInfo( aMsg ) ); + } + if ( nBlank == STRING_NOTFOUND ) + { + if ( nSym < nNum ) + nCurrPositiveFormat = 0; // $1 + else + nCurrPositiveFormat = 1; // 1$ + } + else + { + if ( nSym < nNum ) + nCurrPositiveFormat = 2; // $ 1 + else + nCurrPositiveFormat = 3; // 1 $ + } + + // negative format + if ( nNeg < 0 ) + nCurrNegativeFormat = nCurrFormatDefault; + else + { + const ::rtl::OUString& rCode = pFormatArr[nNeg].Code; + xub_StrLen nDelim = (xub_StrLen)rCode.indexOf( ';' ); + scanCurrFormatImpl( rCode, nDelim+1, nSign, nPar, nNum, nBlank, nSym ); + if (areChecksEnabled() && (nNum == STRING_NOTFOUND || + nSym == STRING_NOTFOUND || (nPar == STRING_NOTFOUND && + nSign == STRING_NOTFOUND))) + { + String aMsg( RTL_CONSTASCII_USTRINGPARAM( + "LocaleDataWrapper::getCurrFormatsImpl: CurrNegativeFormat?")); + outputCheckMessage( appendLocaleInfo( aMsg ) ); + } + if ( nBlank == STRING_NOTFOUND ) + { + if ( nSym < nNum ) + { + if ( nPar < nSym ) + nCurrNegativeFormat = 0; // ($1) + else if ( nSign < nSym ) + nCurrNegativeFormat = 1; // -$1 + else if ( nNum < nSign ) + nCurrNegativeFormat = 3; // $1- + else + nCurrNegativeFormat = 2; // $-1 + } + else + { + if ( nPar < nNum ) + nCurrNegativeFormat = 4; // (1$) + else if ( nSign < nNum ) + nCurrNegativeFormat = 5; // -1$ + else if ( nSym < nSign ) + nCurrNegativeFormat = 7; // 1$- + else + nCurrNegativeFormat = 6; // 1-$ + } + } + else + { + if ( nSym < nNum ) + { + if ( nPar < nSym ) + nCurrNegativeFormat = 14; // ($ 1) + else if ( nSign < nSym ) + nCurrNegativeFormat = 9; // -$ 1 + else if ( nNum < nSign ) + nCurrNegativeFormat = 12; // $ 1- + else + nCurrNegativeFormat = 11; // $ -1 + } + else + { + if ( nPar < nNum ) + nCurrNegativeFormat = 15; // (1 $) + else if ( nSign < nNum ) + nCurrNegativeFormat = 8; // -1 $ + else if ( nSym < nSign ) + nCurrNegativeFormat = 10; // 1 $- + else + nCurrNegativeFormat = 13; // 1- $ + } + } + } +} + + +// --- date ----------------------------------------------------------- + +DateFormat LocaleDataWrapper::getDateFormat() const +{ + ::utl::ReadWriteGuard aGuard( aMutex ); + if ( nDateFormat == nDateFormatInvalid ) + { + aGuard.changeReadToWrite(); + ((LocaleDataWrapper*)this)->getDateFormatsImpl(); + } + return (DateFormat) nDateFormat; +} + + +DateFormat LocaleDataWrapper::getLongDateFormat() const +{ + ::utl::ReadWriteGuard aGuard( aMutex ); + if ( nLongDateFormat == nDateFormatInvalid ) + { + aGuard.changeReadToWrite(); + ((LocaleDataWrapper*)this)->getDateFormatsImpl(); + } + return (DateFormat) nLongDateFormat; +} + + +DateFormat LocaleDataWrapper::scanDateFormatImpl( const String& rCode ) +{ + // Only some european versions were translated, the ones with different + // keyword combinations are: + // English DMY, German TMJ, Spanish DMA, French JMA, Italian GMA, + // Dutch DMJ, Finnish PKV + + // default is English keywords for every other language + xub_StrLen nDay = rCode.Search( 'D' ); + xub_StrLen nMonth = rCode.Search( 'M' ); + xub_StrLen nYear = rCode.Search( 'Y' ); + if ( nDay == STRING_NOTFOUND || nMonth == STRING_NOTFOUND || nYear == STRING_NOTFOUND ) + { // This algorithm assumes that all three parts (DMY) are present + if ( nMonth == STRING_NOTFOUND ) + { // only Finnish has something else than 'M' for month + nMonth = rCode.Search( 'K' ); + if ( nMonth != STRING_NOTFOUND ) + { + nDay = rCode.Search( 'P' ); + nYear = rCode.Search( 'V' ); + } + } + else if ( nDay == STRING_NOTFOUND ) + { // We have a month 'M' if we reach this branch. + // Possible languages containing 'M' but no 'D': + // German, French, Italian + nDay = rCode.Search( 'T' ); // German + if ( nDay != STRING_NOTFOUND ) + nYear = rCode.Search( 'J' ); + else + { + nYear = rCode.Search( 'A' ); // French, Italian + if ( nYear != STRING_NOTFOUND ) + { + nDay = rCode.Search( 'J' ); // French + if ( nDay == STRING_NOTFOUND ) + nDay = rCode.Search( 'G' ); // Italian + } + } + } + else + { // We have a month 'M' and a day 'D'. + // Possible languages containing 'D' and 'M' but not 'Y': + // Spanish, Dutch + nYear = rCode.Search( 'A' ); // Spanish + if ( nYear == STRING_NOTFOUND ) + nYear = rCode.Search( 'J' ); // Dutch + } + if ( nDay == STRING_NOTFOUND || nMonth == STRING_NOTFOUND || nYear == STRING_NOTFOUND ) + { + if (areChecksEnabled()) + { + String aMsg( RTL_CONSTASCII_USTRINGPARAM( + "LocaleDataWrapper::scanDateFormat: not all DMY present")); + outputCheckMessage( appendLocaleInfo( aMsg ) ); + } + if ( nDay == STRING_NOTFOUND ) + nDay = rCode.Len(); + if ( nMonth == STRING_NOTFOUND ) + nMonth = rCode.Len(); + if ( nYear == STRING_NOTFOUND ) + nYear = rCode.Len(); + } + } + // compare with <= because each position may equal rCode.Len() + if ( nDay <= nMonth && nMonth <= nYear ) + return DMY; // also if every position equals rCode.Len() + else if ( nMonth <= nDay && nDay <= nYear ) + return MDY; + else if ( nYear <= nMonth && nMonth <= nDay ) + return YMD; + else + { + if (areChecksEnabled()) + { + String aMsg( RTL_CONSTASCII_USTRINGPARAM( + "LocaleDataWrapper::scanDateFormat: no magic applyable")); + outputCheckMessage( appendLocaleInfo( aMsg ) ); + } + return DMY; + } +} + + +void LocaleDataWrapper::getDateFormatsImpl() +{ + NumberFormatCodeWrapper aNumberFormatCode( xSMgr, getLocale() ); + uno::Sequence< NumberFormatCode > aFormatSeq + = aNumberFormatCode.getAllFormatCode( KNumberFormatUsage::DATE ); + sal_Int32 nCnt = aFormatSeq.getLength(); + if ( !nCnt ) + { // bad luck + if (areChecksEnabled()) + { + String aMsg( RTL_CONSTASCII_USTRINGPARAM( + "LocaleDataWrapper::getDateFormatsImpl: no date formats")); + outputCheckMessage( appendLocaleInfo( aMsg ) ); + } + nDateFormat = nLongDateFormat = DMY; + return ; + } + // find the edit (21), a default (medium preferred), + // a medium (default preferred), and a long (default preferred) + NumberFormatCode const * const pFormatArr = aFormatSeq.getArray(); + sal_Int32 nElem, nEdit, nDef, nMedium, nLong; + nEdit = nDef = nMedium = nLong = -1; + for ( nElem = 0; nElem < nCnt; nElem++ ) + { + if ( nEdit == -1 && pFormatArr[nElem].Index == NumberFormatIndex::DATE_SYS_DDMMYYYY ) + nEdit = nElem; + if ( nDef == -1 && pFormatArr[nElem].Default ) + nDef = nElem; + switch ( pFormatArr[nElem].Type ) + { + case KNumberFormatType::MEDIUM : + { + if ( pFormatArr[nElem].Default ) + { + nDef = nElem; + nMedium = nElem; + } + else if ( nMedium == -1 ) + nMedium = nElem; + } + break; + case KNumberFormatType::LONG : + { + if ( pFormatArr[nElem].Default ) + nLong = nElem; + else if ( nLong == -1 ) + nLong = nElem; + } + break; + } + } + if ( nEdit == -1 ) + { + if (areChecksEnabled()) + { + String aMsg( RTL_CONSTASCII_USTRINGPARAM( + "LocaleDataWrapper::getDateFormatsImpl: no edit")); + outputCheckMessage( appendLocaleInfo( aMsg ) ); + } + if ( nDef == -1 ) + { + if (areChecksEnabled()) + { + String aMsg( RTL_CONSTASCII_USTRINGPARAM( + "LocaleDataWrapper::getDateFormatsImpl: no default")); + outputCheckMessage( appendLocaleInfo( aMsg ) ); + } + if ( nMedium != -1 ) + nDef = nMedium; + else if ( nLong != -1 ) + nDef = nLong; + else + nDef = 0; + } + nEdit = nDef; + } + DateFormat nDF = scanDateFormatImpl( pFormatArr[nEdit].Code ); + if ( pFormatArr[nEdit].Type == KNumberFormatType::LONG ) + { // normally this is not the case + nLongDateFormat = nDateFormat = nDF; + } + else + { + nDateFormat = nDF; + if ( nLong == -1 ) + nLongDateFormat = nDF; + else + nLongDateFormat = scanDateFormatImpl( pFormatArr[nLong].Code ); + } +} + + +// --- digit grouping ------------------------------------------------- + +void LocaleDataWrapper::getDigitGroupingImpl() +{ + /* TODO: This is a very simplified grouping setup that only serves its + * current purpose for Indian locales. A free-form flexible one would + * obtain grouping from locale data where it could be specified using, for + * example, codes like #,### and #,##,### that would generate the integer + * sequence. Needed additional API and a locale data element. + */ + + if (!aGrouping.getLength()) + { + aGrouping.realloc(3); // room for {3,2,0} + aGrouping[0] = 0; // invalidate + } + if (!aGrouping[0]) + { + i18n::LanguageCountryInfo aLCInfo( getLanguageCountryInfo()); + if (aLCInfo.Country.equalsIgnoreAsciiCaseAscii( "IN") || // India + aLCInfo.Country.equalsIgnoreAsciiCaseAscii( "BT")) // Bhutan + { + aGrouping[0] = 3; + aGrouping[1] = 2; + aGrouping[2] = 0; + } + else + { + aGrouping[0] = 3; + aGrouping[1] = 0; + } + } +} + + +const ::com::sun::star::uno::Sequence< sal_Int32 > LocaleDataWrapper::getDigitGrouping() const +{ + ::utl::ReadWriteGuard aGuard( aMutex ); + if (!aGrouping.getLength() || aGrouping[0] == 0) + { // no cached content + aGuard.changeReadToWrite(); + ((LocaleDataWrapper*)this)->getDigitGroupingImpl(); + } + return aGrouping; +} + + +// --- simple number formatting helpers ------------------------------- + +// The ImplAdd... methods are taken from class International and modified to +// suit the needs. + +static sal_Unicode* ImplAddUNum( sal_Unicode* pBuf, sal_uInt64 nNumber ) +{ + // fill temp buffer with digits + sal_Unicode aTempBuf[64]; + sal_Unicode* pTempBuf = aTempBuf; + do + { + *pTempBuf = (sal_Unicode)(nNumber % 10) + '0'; + pTempBuf++; + nNumber /= 10; + } + while ( nNumber ); + + // copy temp buffer to buffer passed + do + { + pTempBuf--; + *pBuf = *pTempBuf; + pBuf++; + } + while ( pTempBuf != aTempBuf ); + + return pBuf; +} + + +static sal_Unicode* ImplAddUNum( sal_Unicode* pBuf, sal_uInt64 nNumber, int nMinLen ) +{ + // fill temp buffer with digits + sal_Unicode aTempBuf[64]; + sal_Unicode* pTempBuf = aTempBuf; + do + { + *pTempBuf = (sal_Unicode)(nNumber % 10) + '0'; + pTempBuf++; + nNumber /= 10; + nMinLen--; + } + while ( nNumber ); + + // fill with zeros up to the minimal length + while ( nMinLen > 0 ) + { + *pBuf = '0'; + pBuf++; + nMinLen--; + } + + // copy temp buffer to real buffer + do + { + pTempBuf--; + *pBuf = *pTempBuf; + pBuf++; + } + while ( pTempBuf != aTempBuf ); + + return pBuf; +} + + +static sal_Unicode* ImplAdd2UNum( sal_Unicode* pBuf, USHORT nNumber, int bLeading ) +{ + DBG_ASSERT( nNumber < 100, "ImplAdd2UNum() - Number >= 100" ); + + if ( nNumber < 10 ) + { + if ( bLeading ) + { + *pBuf = '0'; + pBuf++; + } + *pBuf = nNumber + '0'; + } + else + { + USHORT nTemp = nNumber % 10; + nNumber /= 10; + *pBuf = nNumber + '0'; + pBuf++; + *pBuf = nTemp + '0'; + } + + pBuf++; + return pBuf; +} + + +inline sal_Unicode* ImplAddString( sal_Unicode* pBuf, const String& rStr ) +{ + if ( rStr.Len() == 1 ) + *pBuf++ = rStr.GetChar(0); + else if ( rStr.Len() == 0 ) + ; + else + { + memcpy( pBuf, rStr.GetBuffer(), rStr.Len() * sizeof(sal_Unicode) ); + pBuf += rStr.Len(); + } + return pBuf; +} + + +inline sal_Unicode* ImplAddString( sal_Unicode* pBuf, sal_Unicode c ) +{ + *pBuf = c; + pBuf++; + return pBuf; +} + + +inline sal_Unicode* ImplAddString( sal_Unicode* pBuf, const sal_Unicode* pCopyBuf, xub_StrLen nLen ) +{ + memcpy( pBuf, pCopyBuf, nLen * sizeof(sal_Unicode) ); + return pBuf + nLen; +} + + +sal_Unicode* LocaleDataWrapper::ImplAddFormatNum( sal_Unicode* pBuf, + sal_Int64 nNumber, USHORT nDecimals, BOOL bUseThousandSep, + BOOL bTrailingZeros ) const +{ + sal_Unicode aNumBuf[64]; + sal_Unicode* pNumBuf; + USHORT nNumLen; + USHORT i = 0; + BOOL bNeg; + + // negative number + if ( nNumber < 0 ) + { + nNumber *= -1; + bNeg = TRUE; + *pBuf = '-'; + pBuf++; + } + else + bNeg = FALSE; + + // convert number + pNumBuf = ImplAddUNum( aNumBuf, (sal_uInt64)nNumber ); + nNumLen = (USHORT)(ULONG)(pNumBuf-aNumBuf); + pNumBuf = aNumBuf; + + if ( nNumLen <= nDecimals ) + { + // strip .0 in decimals? + if ( !nNumber && !bTrailingZeros ) + { + *pBuf = '0'; + pBuf++; + } + else + { + // LeadingZero, insert 0 + if ( isNumLeadingZero() ) + { + *pBuf = '0'; + pBuf++; + } + + // append decimal separator + pBuf = ImplAddString( pBuf, getNumDecimalSep() ); + + // fill with zeros + while ( i < (nDecimals-nNumLen) ) + { + *pBuf = '0'; + pBuf++; + i++; + } + + // append decimals + while ( nNumLen ) + { + *pBuf = *pNumBuf; + pBuf++; + pNumBuf++; + nNumLen--; + } + } + } + else + { + const String& rThoSep = getNumThousandSep(); + + // copy number to buffer (excluding decimals) + USHORT nNumLen2 = nNumLen-nDecimals; + uno::Sequence< sal_Bool > aGroupPos; + if (bUseThousandSep) + aGroupPos = utl::DigitGroupingIterator::createForwardSequence( + nNumLen2, getDigitGrouping()); + for ( ; i < nNumLen2; ++i ) + { + *pBuf = *pNumBuf; + pBuf++; + pNumBuf++; + + // add thousand separator? + if ( bUseThousandSep && aGroupPos[i] ) + pBuf = ImplAddString( pBuf, rThoSep ); + } + + // append decimals + if ( nDecimals ) + { + pBuf = ImplAddString( pBuf, getNumDecimalSep() ); + + BOOL bNullEnd = TRUE; + while ( i < nNumLen ) + { + if ( *pNumBuf != '0' ) + bNullEnd = FALSE; + + *pBuf = *pNumBuf; + pBuf++; + pNumBuf++; + i++; + } + + // strip .0 in decimals? + if ( bNullEnd && !bTrailingZeros ) + pBuf -= nDecimals+1; + } + } + + return pBuf; +} + + +// --- simple date and time formatting -------------------------------- + +String LocaleDataWrapper::getDate( const Date& rDate ) const +{ + ::utl::ReadWriteGuard aGuard( aMutex, ::utl::ReadWriteGuardMode::nBlockCritical ); +//!TODO: leading zeros et al + sal_Unicode aBuf[128]; + sal_Unicode* pBuf = aBuf; + USHORT nDay = rDate.GetDay(); + USHORT nMonth = rDate.GetMonth(); + USHORT nYear = rDate.GetYear(); + USHORT nYearLen; + + if ( TRUE /* IsDateCentury() */ ) + nYearLen = 4; + else + { + nYearLen = 2; + nYear %= 100; + } + + switch ( getDateFormat() ) + { + case DMY : + pBuf = ImplAdd2UNum( pBuf, nDay, TRUE /* IsDateDayLeadingZero() */ ); + pBuf = ImplAddString( pBuf, getDateSep() ); + pBuf = ImplAdd2UNum( pBuf, nMonth, TRUE /* IsDateMonthLeadingZero() */ ); + pBuf = ImplAddString( pBuf, getDateSep() ); + pBuf = ImplAddUNum( pBuf, nYear, nYearLen ); + break; + case MDY : + pBuf = ImplAdd2UNum( pBuf, nMonth, TRUE /* IsDateMonthLeadingZero() */ ); + pBuf = ImplAddString( pBuf, getDateSep() ); + pBuf = ImplAdd2UNum( pBuf, nDay, TRUE /* IsDateDayLeadingZero() */ ); + pBuf = ImplAddString( pBuf, getDateSep() ); + pBuf = ImplAddUNum( pBuf, nYear, nYearLen ); + break; + default: + pBuf = ImplAddUNum( pBuf, nYear, nYearLen ); + pBuf = ImplAddString( pBuf, getDateSep() ); + pBuf = ImplAdd2UNum( pBuf, nMonth, TRUE /* IsDateMonthLeadingZero() */ ); + pBuf = ImplAddString( pBuf, getDateSep() ); + pBuf = ImplAdd2UNum( pBuf, nDay, TRUE /* IsDateDayLeadingZero() */ ); + } + + return String( aBuf, (xub_StrLen)(ULONG)(pBuf-aBuf) ); +} + + +String LocaleDataWrapper::getTime( const Time& rTime, BOOL bSec, BOOL b100Sec ) const +{ + ::utl::ReadWriteGuard aGuard( aMutex, ::utl::ReadWriteGuardMode::nBlockCritical ); +//!TODO: leading zeros et al + sal_Unicode aBuf[128]; + sal_Unicode* pBuf = aBuf; + USHORT nHour = rTime.GetHour(); + BOOL bHour12 = FALSE; //!TODO: AM/PM from default time format code + + if ( bHour12 ) + { + nHour %= 12; + // 0:00 -> 12:00 + if ( !nHour ) + nHour = 12; + } + else + nHour %= 24; + + pBuf = ImplAdd2UNum( pBuf, nHour, TRUE /* IsTimeLeadingZero() */ ); + pBuf = ImplAddString( pBuf, getTimeSep() ); + pBuf = ImplAdd2UNum( pBuf, rTime.GetMin(), TRUE ); + if ( bSec ) + { + pBuf = ImplAddString( pBuf, getTimeSep() ); + pBuf = ImplAdd2UNum( pBuf, rTime.GetSec(), TRUE ); + + if ( b100Sec ) + { + pBuf = ImplAddString( pBuf, getTime100SecSep() ); + pBuf = ImplAdd2UNum( pBuf, rTime.Get100Sec(), TRUE ); + } + } + + String aStr( aBuf, (xub_StrLen)(ULONG)(pBuf-aBuf) ); + + if ( bHour12 ) + { + if ( (rTime.GetHour() % 24) >= 12 ) + aStr += getTimePM(); + else + aStr += getTimeAM(); + } +#if 0 +//!TODO: do we need a time string? like "o'clock" or "Uhr" or similar + else + aStr += getTimeStr(); +#endif + + return aStr; +} + + +String LocaleDataWrapper::getLongDate( const Date& rDate, CalendarWrapper& rCal, + sal_Int16 nDisplayDayOfWeek, sal_Bool bDayOfMonthWithLeadingZero, + sal_Int16 nDisplayMonth, sal_Bool bTwoDigitYear ) const +{ + ::utl::ReadWriteGuard aGuard( aMutex, ::utl::ReadWriteGuardMode::nBlockCritical ); + using namespace ::com::sun::star::i18n; + sal_Unicode aBuf[20]; + sal_Unicode* pBuf; + String aStr; + sal_Int16 nVal; + rCal.setGregorianDateTime( rDate ); + // day of week + nVal = rCal.getValue( CalendarFieldIndex::DAY_OF_WEEK ); + aStr += rCal.getDisplayName( CalendarDisplayIndex::DAY, nVal, nDisplayDayOfWeek ); + aStr += getLongDateDayOfWeekSep(); + // day of month + nVal = rCal.getValue( CalendarFieldIndex::DAY_OF_MONTH ); + pBuf = ImplAdd2UNum( aBuf, nVal, bDayOfMonthWithLeadingZero ); + String aDay( aBuf, (xub_StrLen)(ULONG)(pBuf-aBuf) ); + // month of year + nVal = rCal.getValue( CalendarFieldIndex::MONTH ); + String aMonth( rCal.getDisplayName( CalendarDisplayIndex::MONTH, nVal, nDisplayMonth ) ); + // year + nVal = rCal.getValue( CalendarFieldIndex::YEAR ); + if ( bTwoDigitYear ) + pBuf = ImplAddUNum( aBuf, nVal % 100, 2 ); + else + pBuf = ImplAddUNum( aBuf, nVal ); + String aYear( aBuf, (xub_StrLen)(ULONG)(pBuf-aBuf) ); + // concatenate + switch ( getLongDateFormat() ) + { + case DMY : + aStr += aDay; + aStr += getLongDateDaySep(); + aStr += aMonth; + aStr += getLongDateMonthSep(); + aStr += aYear; + break; + case MDY : + aStr += aMonth; + aStr += getLongDateMonthSep(); + aStr += aDay; + aStr += getLongDateDaySep(); + aStr += aYear; + break; + default: // YMD + aStr += aYear; + aStr += getLongDateYearSep(); + aStr += aMonth; + aStr += getLongDateMonthSep(); + aStr += aDay; + } + return aStr; +} + + +String LocaleDataWrapper::getDuration( const Time& rTime, BOOL bSec, BOOL b100Sec ) const +{ + ::utl::ReadWriteGuard aGuard( aMutex, ::utl::ReadWriteGuardMode::nBlockCritical ); + sal_Unicode aBuf[128]; + sal_Unicode* pBuf = aBuf; + + if ( rTime < Time( 0 ) ) + pBuf = ImplAddString( pBuf, ' ' ); + + if ( TRUE /* IsTimeLeadingZero() */ ) + pBuf = ImplAddUNum( pBuf, rTime.GetHour(), 2 ); + else + pBuf = ImplAddUNum( pBuf, rTime.GetHour() ); + pBuf = ImplAddString( pBuf, getTimeSep() ); + pBuf = ImplAdd2UNum( pBuf, rTime.GetMin(), TRUE ); + if ( bSec ) + { + pBuf = ImplAddString( pBuf, getTimeSep() ); + pBuf = ImplAdd2UNum( pBuf, rTime.GetSec(), TRUE ); + + if ( b100Sec ) + { + pBuf = ImplAddString( pBuf, getTime100SecSep() ); + pBuf = ImplAdd2UNum( pBuf, rTime.Get100Sec(), TRUE ); + } + } + + return String( aBuf, (xub_StrLen)(ULONG)(pBuf-aBuf) ); +} + + +// --- simple number formatting --------------------------------------- + +inline size_t ImplGetNumberStringLengthGuess( const LocaleDataWrapper& rLoc, USHORT nDecimals ) +{ + // approximately 3.2 bits per digit + const size_t nDig = ((sizeof(sal_Int64) * 8) / 3) + 1; + // digits, separators (pessimized for insane "every digit may be grouped"), leading zero, sign + size_t nGuess = ((nDecimals < nDig) ? + (((nDig - nDecimals) * rLoc.getNumThousandSep().Len()) + nDig) : + nDecimals) + rLoc.getNumDecimalSep().Len() + 3; + return nGuess; +} + + +String LocaleDataWrapper::getNum( sal_Int64 nNumber, USHORT nDecimals, + BOOL bUseThousandSep, BOOL bTrailingZeros ) const +{ + ::utl::ReadWriteGuard aGuard( aMutex, ::utl::ReadWriteGuardMode::nBlockCritical ); + sal_Unicode aBuf[128]; // big enough for 64-bit long and crazy grouping + // check if digits and separators will fit into fixed buffer or allocate + size_t nGuess = ImplGetNumberStringLengthGuess( *this, nDecimals ); + sal_Unicode* const pBuffer = (nGuess < 118 ? aBuf : + new sal_Unicode[nGuess + 16]); + + sal_Unicode* pBuf = ImplAddFormatNum( pBuffer, nNumber, nDecimals, + bUseThousandSep, bTrailingZeros ); + String aStr( pBuffer, (xub_StrLen)(ULONG)(pBuf-pBuffer) ); + + if ( pBuffer != aBuf ) + delete [] pBuffer; + return aStr; +} + + +String LocaleDataWrapper::getCurr( sal_Int64 nNumber, USHORT nDecimals, + const String& rCurrencySymbol, BOOL bUseThousandSep ) const +{ + ::utl::ReadWriteGuard aGuard( aMutex, ::utl::ReadWriteGuardMode::nBlockCritical ); + sal_Unicode aBuf[192]; + sal_Unicode aNumBuf[128]; // big enough for 64-bit long and crazy grouping + sal_Unicode cZeroChar = getCurrZeroChar(); + + // check if digits and separators will fit into fixed buffer or allocate + size_t nGuess = ImplGetNumberStringLengthGuess( *this, nDecimals ); + sal_Unicode* const pNumBuffer = (nGuess < 118 ? aNumBuf : + new sal_Unicode[nGuess + 16]); + + sal_Unicode* const pBuffer = + ((size_t(rCurrencySymbol.Len()) + nGuess + 20) < sizeof(aBuf)/sizeof(aBuf[0]) ? aBuf : + new sal_Unicode[ rCurrencySymbol.Len() + nGuess + 20 ]); + sal_Unicode* pBuf = pBuffer; + + BOOL bNeg; + if ( nNumber < 0 ) + { + bNeg = TRUE; + nNumber *= -1; + } + else + bNeg = FALSE; + + // convert number + sal_Unicode* pEndNumBuf = ImplAddFormatNum( pNumBuffer, nNumber, nDecimals, + bUseThousandSep, TRUE ); + xub_StrLen nNumLen = (xub_StrLen)(ULONG)(pEndNumBuf-pNumBuffer); + + // replace zeros with zero character + if ( (cZeroChar != '0') && nDecimals /* && IsNumTrailingZeros() */ ) + { + sal_Unicode* pTempBuf; + USHORT i; + BOOL bZero = TRUE; + + pTempBuf = pNumBuffer+nNumLen-nDecimals; + i = 0; + do + { + if ( *pTempBuf != '0' ) + { + bZero = FALSE; + break; + } + + pTempBuf++; + i++; + } + while ( i < nDecimals ); + + if ( bZero ) + { + pTempBuf = pNumBuffer+nNumLen-nDecimals; + i = 0; + do + { + *pTempBuf = cZeroChar; + pTempBuf++; + i++; + } + while ( i < nDecimals ); + } + } + + if ( !bNeg ) + { + switch( getCurrPositiveFormat() ) + { + case 0: + pBuf = ImplAddString( pBuf, rCurrencySymbol ); + pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen ); + break; + case 1: + pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen ); + pBuf = ImplAddString( pBuf, rCurrencySymbol ); + break; + case 2: + pBuf = ImplAddString( pBuf, rCurrencySymbol ); + pBuf = ImplAddString( pBuf, ' ' ); + pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen ); + break; + case 3: + pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen ); + pBuf = ImplAddString( pBuf, ' ' ); + pBuf = ImplAddString( pBuf, rCurrencySymbol ); + break; + } + } + else + { + switch( getCurrNegativeFormat() ) + { + case 0: + pBuf = ImplAddString( pBuf, '(' ); + pBuf = ImplAddString( pBuf, rCurrencySymbol ); + pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen ); + pBuf = ImplAddString( pBuf, ')' ); + break; + case 1: + pBuf = ImplAddString( pBuf, '-' ); + pBuf = ImplAddString( pBuf, rCurrencySymbol ); + pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen ); + break; + case 2: + pBuf = ImplAddString( pBuf, rCurrencySymbol ); + pBuf = ImplAddString( pBuf, '-' ); + pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen ); + break; + case 3: + pBuf = ImplAddString( pBuf, rCurrencySymbol ); + pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen ); + pBuf = ImplAddString( pBuf, '-' ); + break; + case 4: + pBuf = ImplAddString( pBuf, '(' ); + pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen ); + pBuf = ImplAddString( pBuf, rCurrencySymbol ); + pBuf = ImplAddString( pBuf, ')' ); + break; + case 5: + pBuf = ImplAddString( pBuf, '-' ); + pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen ); + pBuf = ImplAddString( pBuf, rCurrencySymbol ); + break; + case 6: + pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen ); + pBuf = ImplAddString( pBuf, '-' ); + pBuf = ImplAddString( pBuf, rCurrencySymbol ); + break; + case 7: + pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen ); + pBuf = ImplAddString( pBuf, rCurrencySymbol ); + pBuf = ImplAddString( pBuf, '-' ); + break; + case 8: + pBuf = ImplAddString( pBuf, '-' ); + pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen ); + pBuf = ImplAddString( pBuf, ' ' ); + pBuf = ImplAddString( pBuf, rCurrencySymbol ); + break; + case 9: + pBuf = ImplAddString( pBuf, '-' ); + pBuf = ImplAddString( pBuf, rCurrencySymbol ); + pBuf = ImplAddString( pBuf, ' ' ); + pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen ); + break; + case 10: + pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen ); + pBuf = ImplAddString( pBuf, ' ' ); + pBuf = ImplAddString( pBuf, rCurrencySymbol ); + pBuf = ImplAddString( pBuf, '-' ); + break; + case 11: + pBuf = ImplAddString( pBuf, rCurrencySymbol ); + pBuf = ImplAddString( pBuf, ' ' ); + pBuf = ImplAddString( pBuf, '-' ); + pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen ); + break; + case 12: + pBuf = ImplAddString( pBuf, rCurrencySymbol ); + pBuf = ImplAddString( pBuf, ' ' ); + pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen ); + pBuf = ImplAddString( pBuf, '-' ); + break; + case 13: + pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen ); + pBuf = ImplAddString( pBuf, '-' ); + pBuf = ImplAddString( pBuf, ' ' ); + pBuf = ImplAddString( pBuf, rCurrencySymbol ); + break; + case 14: + pBuf = ImplAddString( pBuf, '(' ); + pBuf = ImplAddString( pBuf, rCurrencySymbol ); + pBuf = ImplAddString( pBuf, ' ' ); + pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen ); + pBuf = ImplAddString( pBuf, ')' ); + break; + case 15: + pBuf = ImplAddString( pBuf, '(' ); + pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen ); + pBuf = ImplAddString( pBuf, ' ' ); + pBuf = ImplAddString( pBuf, rCurrencySymbol ); + pBuf = ImplAddString( pBuf, ')' ); + break; + } + } + + String aNumber( pBuffer, (xub_StrLen)(ULONG)(pBuf-pBuffer) ); + + if ( pBuffer != aBuf ) + delete [] pBuffer; + if ( pNumBuffer != aNumBuf ) + delete [] pNumBuffer; + + return aNumber; +} + + +// --- mixed ---------------------------------------------------------- + +::com::sun::star::lang::Locale LocaleDataWrapper::getLoadedLocale() const +{ + LanguageCountryInfo aLCInfo = getLanguageCountryInfo(); + return lang::Locale( aLCInfo.Language, aLCInfo.Country, aLCInfo.Variant ); +} + + +String& LocaleDataWrapper::appendLocaleInfo( String& rDebugMsg ) const +{ + ::utl::ReadWriteGuard aGuard( aMutex, ::utl::ReadWriteGuardMode::nBlockCritical ); + rDebugMsg += '\n'; + rDebugMsg += String( aLocale.Language); + rDebugMsg += '_'; + rDebugMsg += String( aLocale.Country); + rDebugMsg.AppendAscii( RTL_CONSTASCII_STRINGPARAM( " requested\n" ) ); + lang::Locale aLoaded = getLoadedLocale(); + rDebugMsg += String( aLoaded.Language); + rDebugMsg += '_'; + rDebugMsg += String( aLoaded.Country); + rDebugMsg.AppendAscii( RTL_CONSTASCII_STRINGPARAM( " loaded" ) ); + return rDebugMsg; +} + + +// static +void LocaleDataWrapper::outputCheckMessage( const String& rMsg ) +{ + outputCheckMessage( ByteString( rMsg, RTL_TEXTENCODING_UTF8).GetBuffer()); +} + + +// static +void LocaleDataWrapper::outputCheckMessage( const char* pStr ) +{ + fprintf( stderr, "\n%s\n", pStr); + fflush( stderr); + DBG_ERROR( pStr); +} + + +// static +void LocaleDataWrapper::evaluateLocaleDataChecking() +{ + // Using the rtl_Instance template here wouldn't solve all threaded write + // accesses, since we want to assign the result to the static member + // variable and would need to dereference the pointer returned and assign + // the value unguarded. This is the same pattern manually coded. + BYTE nCheck = nLocaleDataChecking; + if (!nCheck) + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex()); + nCheck = nLocaleDataChecking; + if (!nCheck) + { +#ifndef PRODUCT + nCheck = 1; +#else + const char* pEnv = getenv( "OOO_ENABLE_LOCALE_DATA_CHECKS"); + if (pEnv && (pEnv[0] == 'Y' || pEnv[0] == 'y' || pEnv[0] == '1')) + nCheck = 1; + else + nCheck = 2; +#endif + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + nLocaleDataChecking = nCheck; + } + } + else { + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + } +} diff --git a/unotools/source/i18n/makefile.mk b/unotools/source/i18n/makefile.mk new file mode 100644 index 000000000000..eab1aeb8dc48 --- /dev/null +++ b/unotools/source/i18n/makefile.mk @@ -0,0 +1,61 @@ +#************************************************************************* +# +# 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.21 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General 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=..$/.. +PRJINC=..$/..$/inc +PRJNAME=unotools +TARGET=i18n + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ---------------------------------- + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/util$/makefile.pmk + +# --- Files ------------------------------------- + +SLOFILES= \ + $(SLO)$/charclass.obj \ + $(SLO)$/calendarwrapper.obj \ + $(SLO)$/collatorwrapper.obj \ + $(SLO)$/intlwrapper.obj \ + $(SLO)$/localedatawrapper.obj \ + $(SLO)$/nativenumberwrapper.obj \ + $(SLO)$/numberformatcodewrapper.obj \ + $(SLO)$/readwritemutexguard.obj \ + $(SLO)$/transliterationwrapper.obj \ + $(SLO)$/textsearch.obj + +# --- Targets ---------------------------------- + +.INCLUDE : target.mk + diff --git a/unotools/source/i18n/nativenumberwrapper.cxx b/unotools/source/i18n/nativenumberwrapper.cxx new file mode 100644 index 000000000000..f0efd10920d7 --- /dev/null +++ b/unotools/source/i18n/nativenumberwrapper.cxx @@ -0,0 +1,173 @@ +/************************************************************************* + * + * 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: nativenumberwrapper.cxx,v $ + * $Revision: 1.6 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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_unotools.hxx" + +#include <unotools/nativenumberwrapper.hxx> +#include <tools/debug.hxx> + +#ifndef _COMPHELPER_COMPONENTFACTORY_HXX_ +#include <comphelper/componentfactory.hxx> +#endif +#include <com/sun/star/uno/XInterface.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> + +#define LOCALEDATA_LIBRARYNAME "i18npool" +#define LOCALEDATA_SERVICENAME "com.sun.star.i18n.NativeNumberSupplier" + +using namespace ::com::sun::star; + + +NativeNumberWrapper::NativeNumberWrapper( + const uno::Reference< lang::XMultiServiceFactory > & xSF + ) + : + xSMgr( xSF ) +{ + if ( xSMgr.is() ) + { + try + { + xNNS = uno::Reference< i18n::XNativeNumberSupplier > ( xSMgr->createInstance( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( LOCALEDATA_SERVICENAME ) ) ), + uno::UNO_QUERY ); + } + catch ( uno::Exception& e ) + { + (void)e; + DBG_ERRORFILE( "NativeNumberWrapper ctor: Exception caught!" ); + } + } + else + { // try to get an instance somehow + DBG_ERRORFILE( "NativeNumberWrapper: no service manager, trying own" ); + try + { + uno::Reference< uno::XInterface > xI = ::comphelper::getComponentInstance( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( LLCF_LIBNAME( LOCALEDATA_LIBRARYNAME ) ) ), + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( LOCALEDATA_SERVICENAME ) ) ); + if ( xI.is() ) + { + uno::Any x = xI->queryInterface( ::getCppuType((const uno::Reference< i18n::XNativeNumberSupplier >*)0) ); + x >>= xNNS; + } + } + catch ( uno::Exception& e ) + { + (void)e; + DBG_ERRORFILE( "getComponentInstance: Exception caught!" ); + } + } + DBG_ASSERT( xNNS.is(), "NativeNumberWrapper: no NativeNumberSupplier" ); +} + + +NativeNumberWrapper::~NativeNumberWrapper() +{ +} + + +::rtl::OUString +NativeNumberWrapper::getNativeNumberString( + const ::rtl::OUString& rNumberString, + const ::com::sun::star::lang::Locale& rLocale, + sal_Int16 nNativeNumberMode ) const +{ + try + { + if ( xNNS.is() ) + return xNNS->getNativeNumberString( rNumberString, rLocale, nNativeNumberMode ); + } + catch ( uno::Exception& e ) + { + (void)e; + DBG_ERRORFILE( "getNativeNumberString: Exception caught!" ); + } + return ::rtl::OUString(); +} + + +sal_Bool +NativeNumberWrapper::isValidNatNum( + const ::com::sun::star::lang::Locale& rLocale, + sal_Int16 nNativeNumberMode ) const +{ + try + { + if ( xNNS.is() ) + return xNNS->isValidNatNum( rLocale, nNativeNumberMode ); + } + catch ( uno::Exception& e ) + { + (void)e; + DBG_ERRORFILE( "isValidNatNum: Exception caught!" ); + } + return sal_False; +} + + +i18n::NativeNumberXmlAttributes +NativeNumberWrapper::convertToXmlAttributes( + const ::com::sun::star::lang::Locale& rLocale, + sal_Int16 nNativeNumberMode ) const +{ + try + { + if ( xNNS.is() ) + return xNNS->convertToXmlAttributes( rLocale, nNativeNumberMode ); + } + catch ( uno::Exception& e ) + { + (void)e; + DBG_ERRORFILE( "convertToXmlAttributes: Exception caught!" ); + } + return i18n::NativeNumberXmlAttributes(); +} + + +sal_Int16 +NativeNumberWrapper::convertFromXmlAttributes( + const i18n::NativeNumberXmlAttributes& rAttr ) const +{ + try + { + if ( xNNS.is() ) + return xNNS->convertFromXmlAttributes( rAttr ); + } + catch ( uno::Exception& e ) + { + (void)e; + DBG_ERRORFILE( "convertFromXmlAttributes: Exception caught!" ); + } + return 0; +} + + diff --git a/unotools/source/i18n/numberformatcodewrapper.cxx b/unotools/source/i18n/numberformatcodewrapper.cxx new file mode 100644 index 000000000000..15280b345431 --- /dev/null +++ b/unotools/source/i18n/numberformatcodewrapper.cxx @@ -0,0 +1,173 @@ +/************************************************************************* + * + * 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: numberformatcodewrapper.cxx,v $ + * $Revision: 1.12 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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_unotools.hxx" + +#include <unotools/numberformatcodewrapper.hxx> +#include <tools/debug.hxx> + +#ifndef _COMPHELPER_COMPONENTFACTORY_HXX_ +#include <comphelper/componentfactory.hxx> +#endif +#include <com/sun/star/uno/XInterface.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> + +#define LOCALEDATA_LIBRARYNAME "i18npool" +#define LOCALEDATA_SERVICENAME "com.sun.star.i18n.NumberFormatMapper" + +using namespace ::com::sun::star; +using namespace ::com::sun::star::i18n; +using namespace ::com::sun::star::uno; + + +NumberFormatCodeWrapper::NumberFormatCodeWrapper( + const Reference< lang::XMultiServiceFactory > & xSF, + const lang::Locale& rLocale + ) + : + xSMgr( xSF ) +{ + setLocale( rLocale ); + if ( xSMgr.is() ) + { + try + { + xNFC = Reference< XNumberFormatCode > ( xSMgr->createInstance( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( LOCALEDATA_SERVICENAME ) ) ), + uno::UNO_QUERY ); + } + catch ( Exception& e ) + { + (void)e; + DBG_ERRORFILE( "NumberFormatCodeWrapper ctor: Exception caught!" ); + } + } + else + { // try to get an instance somehow + DBG_ERRORFILE( "NumberFormatCodeWrapper: no service manager, trying own" ); + try + { + Reference< XInterface > xI = ::comphelper::getComponentInstance( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( LLCF_LIBNAME( LOCALEDATA_LIBRARYNAME ) ) ), + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( LOCALEDATA_SERVICENAME ) ) ); + if ( xI.is() ) + { + Any x = xI->queryInterface( ::getCppuType((const Reference< XNumberFormatCode >*)0) ); + x >>= xNFC; + } + } + catch ( Exception& e ) + { + (void)e; + DBG_ERRORFILE( "getComponentInstance: Exception caught!" ); + } + } + DBG_ASSERT( xNFC.is(), "NumberFormatCodeWrapper: no NumberFormatMapper" ); +} + + +NumberFormatCodeWrapper::~NumberFormatCodeWrapper() +{ +} + + +void NumberFormatCodeWrapper::setLocale( const ::com::sun::star::lang::Locale& rLocale ) +{ + aLocale = rLocale; +} + + +::com::sun::star::i18n::NumberFormatCode +NumberFormatCodeWrapper::getDefault( sal_Int16 formatType, sal_Int16 formatUsage ) const +{ + try + { + if ( xNFC.is() ) + return xNFC->getDefault( formatType, formatUsage, aLocale ); + } + catch ( Exception& e ) + { + (void)e; + DBG_ERRORFILE( "getDefault: Exception caught!" ); + } + return ::com::sun::star::i18n::NumberFormatCode(); +} + + +::com::sun::star::i18n::NumberFormatCode +NumberFormatCodeWrapper::getFormatCode( sal_Int16 formatIndex ) const +{ + try + { + if ( xNFC.is() ) + return xNFC->getFormatCode( formatIndex, aLocale ); + } + catch ( Exception& e ) + { + (void)e; + DBG_ERRORFILE( "getFormatCode: Exception caught!" ); + } + return ::com::sun::star::i18n::NumberFormatCode(); +} + + +::com::sun::star::uno::Sequence< ::com::sun::star::i18n::NumberFormatCode > +NumberFormatCodeWrapper::getAllFormatCode( sal_Int16 formatUsage ) const +{ + try + { + if ( xNFC.is() ) + return xNFC->getAllFormatCode( formatUsage, aLocale ); + } + catch ( Exception& e ) + { + (void)e; + DBG_ERRORFILE( "getAllFormatCode: Exception caught!" ); + } + return ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::NumberFormatCode > (0); +} + + +::com::sun::star::uno::Sequence< ::com::sun::star::i18n::NumberFormatCode > +NumberFormatCodeWrapper::getAllFormatCodes() const +{ + try + { + if ( xNFC.is() ) + return xNFC->getAllFormatCodes( aLocale ); + } + catch ( Exception& e ) + { + (void)e; + DBG_ERRORFILE( "getAllFormatCodes: Exception caught!" ); + } + return ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::NumberFormatCode > (0); +} diff --git a/unotools/source/i18n/readwritemutexguard.cxx b/unotools/source/i18n/readwritemutexguard.cxx new file mode 100644 index 000000000000..de614d120e5d --- /dev/null +++ b/unotools/source/i18n/readwritemutexguard.cxx @@ -0,0 +1,123 @@ +/************************************************************************* + * + * 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: readwritemutexguard.cxx,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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_unotools.hxx" +#include "unotools/readwritemutexguard.hxx" +#include <tools/debug.hxx> + + +namespace utl { + +ReadWriteGuard::ReadWriteGuard( ReadWriteMutex& rMutexP, + sal_Int32 nRequestMode ) + : rMutex( rMutexP ) +{ + // don't do anything until a pending write completed (or another + // ReadWriteGuard leaves the ctor phase) + ::osl::MutexGuard aGuard( rMutex.pWriteMutex ); + nMode = nRequestMode; + if ( nMode & ReadWriteGuardMode::nWrite ) + { + rMutex.pWriteMutex->acquire(); + // wait for any read to complete +// TODO: set up a waiting thread instead of a loop + sal_Bool bWait = sal_True; + do + { + rMutex.pMutex->acquire(); + bWait = (rMutex.nReadCount != 0); + if ( nMode & ReadWriteGuardMode::nCriticalChange ) + bWait |= (rMutex.nBlockCriticalCount != 0); + rMutex.pMutex->release(); + } while ( bWait ); + } + else if ( nMode & ReadWriteGuardMode::nBlockCritical ) + { + rMutex.pMutex->acquire(); + ++rMutex.nBlockCriticalCount; + rMutex.pMutex->release(); + } + else + { + rMutex.pMutex->acquire(); + ++rMutex.nReadCount; + rMutex.pMutex->release(); + } +} + + +ReadWriteGuard::~ReadWriteGuard() +{ + if ( nMode & ReadWriteGuardMode::nWrite ) + rMutex.pWriteMutex->release(); + else if ( nMode & ReadWriteGuardMode::nBlockCritical ) + { + rMutex.pMutex->acquire(); + --rMutex.nBlockCriticalCount; + rMutex.pMutex->release(); + } + else + { + rMutex.pMutex->acquire(); + --rMutex.nReadCount; + rMutex.pMutex->release(); + } +} + + +void ReadWriteGuard::changeReadToWrite() +{ + sal_Bool bOk = !(nMode & (ReadWriteGuardMode::nWrite | ReadWriteGuardMode::nBlockCritical)); + DBG_ASSERT( bOk, "ReadWriteGuard::changeReadToWrite: can't" ); + if ( bOk ) + { + // MUST release read before acquiring write mutex or dead lock would + // occur if there was a write in another thread waiting for this read + // to complete. + rMutex.pMutex->acquire(); + --rMutex.nReadCount; + rMutex.pMutex->release(); + + rMutex.pWriteMutex->acquire(); + nMode |= ReadWriteGuardMode::nWrite; + // wait for any other read to complete +// TODO: set up a waiting thread instead of a loop + sal_Bool bWait = sal_True; + do + { + rMutex.pMutex->acquire(); + bWait = (rMutex.nReadCount != 0); + rMutex.pMutex->release(); + } while ( bWait ); + } +} + +} // namespace utl diff --git a/unotools/source/i18n/textsearch.cxx b/unotools/source/i18n/textsearch.cxx new file mode 100644 index 000000000000..10909dd32307 --- /dev/null +++ b/unotools/source/i18n/textsearch.cxx @@ -0,0 +1,401 @@ +/************************************************************************* + * + * 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: textsearch.cxx,v $ + * $Revision: 1.18 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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_unotools.hxx" +#include <i18npool/mslangid.hxx> +#include <tools/debug.hxx> +#ifndef _INTN_HXX //autogen +//#include <tools/intn.hxx> +#endif +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#ifndef _COM_SUN_STAR_UTIL_SEARCHFLAGS_HDL_ +#include <com/sun/star/util/SearchFlags.hdl> +#endif +#include <com/sun/star/i18n/TransliterationModules.hpp> +#include <unotools/charclass.hxx> +#include <comphelper/processfactory.hxx> +#include <unotools/textsearch.hxx> + +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; + +// ............................................................................ +namespace utl +{ +// ............................................................................ + +SearchParam::SearchParam( const String &rText, + SearchType eType, + BOOL bCaseSensitive, + BOOL bWrdOnly, + BOOL bSearchInSel ) +{ + sSrchStr = rText; + eSrchType = eType; + + bWordOnly = bWrdOnly; + bSrchInSel = bSearchInSel; + bCaseSense = bCaseSensitive; + + nTransliterationFlags = 0; + + // Werte fuer "Gewichtete Levenshtein-Distanz" + bLEV_Relaxed = TRUE; + nLEV_OtherX = 2; + nLEV_ShorterY = 1; + nLEV_LongerZ = 3; +} + +SearchParam::SearchParam( const SearchParam& rParam ) +{ + sSrchStr = rParam.sSrchStr; + sReplaceStr = rParam.sReplaceStr; + eSrchType = rParam.eSrchType; + + bWordOnly = rParam.bWordOnly; + bSrchInSel = rParam.bSrchInSel; + bCaseSense = rParam.bCaseSense; + + bLEV_Relaxed = rParam.bLEV_Relaxed; + nLEV_OtherX = rParam.nLEV_OtherX; + nLEV_ShorterY = rParam.nLEV_ShorterY; + nLEV_LongerZ = rParam.nLEV_LongerZ; + + nTransliterationFlags = rParam.nTransliterationFlags; +} + +// Klasse zum Suchen eines Strings in einem Text. Es wird genau nach +// dem String gesucht. +// ( Die Unterscheidung der Gross/Klein-Schreibung kann mit einen Flag +// unterdrueckt werden ) + +TextSearch::CachedTextSearch TextSearch::maCache; + +static bool lcl_Equals( const SearchOptions& rSO1, const SearchOptions& rSO2 ) +{ + return rSO1.algorithmType == rSO2.algorithmType && + rSO1.searchFlag == rSO2.searchFlag && + rSO1.searchString.equals(rSO2.searchString) && + rSO1.replaceString.equals(rSO2.replaceString) && + rSO1.changedChars == rSO2.changedChars && + rSO1.deletedChars == rSO2.deletedChars && + rSO1.insertedChars == rSO2.insertedChars && + rSO1.Locale.Language == rSO2.Locale.Language && + rSO1.Locale.Country == rSO2.Locale.Country && + rSO1.Locale.Variant == rSO2.Locale.Variant && + rSO1.transliterateFlags == rSO2.transliterateFlags; +} + +Reference<XTextSearch> TextSearch::getXTextSearch( const SearchOptions& rPara ) +{ + osl::MutexGuard aGuard(maCache.mutex); + + if ( lcl_Equals(maCache.Options, rPara) ) + return maCache.xTextSearch; + + try + { + Reference< XMultiServiceFactory > xMSF = ::comphelper::getProcessServiceFactory(); + maCache.xTextSearch.set( xMSF->createInstance( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.util.TextSearch" ) ) ), UNO_QUERY_THROW ); + maCache.xTextSearch->setOptions( rPara ); + maCache.Options = rPara; + } + catch ( Exception& ) + { + DBG_ERRORFILE( "TextSearch ctor: Exception caught!" ); + } + return maCache.xTextSearch; +} + +TextSearch::TextSearch(const SearchParam & rParam, LanguageType eLang ) +{ + if( LANGUAGE_NONE == eLang ) + eLang = LANGUAGE_SYSTEM; + ::com::sun::star::lang::Locale aLocale( + MsLangId::convertLanguageToLocale( LanguageType(eLang))); + + Init( rParam, aLocale); +} + +TextSearch::TextSearch(const SearchParam & rParam, const CharClass& rCClass ) +{ + Init( rParam, rCClass.getLocale() ); +} + +TextSearch::TextSearch( const SearchOptions& rPara ) +{ + xTextSearch = getXTextSearch( rPara ); +} + +void TextSearch::Init( const SearchParam & rParam, + const ::com::sun::star::lang::Locale& rLocale ) +{ + // convert SearchParam to the UNO SearchOptions + SearchOptions aSOpt; + + switch( rParam.GetSrchType() ) + { + case SearchParam::SRCH_REGEXP: + aSOpt.algorithmType = SearchAlgorithms_REGEXP; + if( rParam.IsSrchInSelection() ) + aSOpt.searchFlag |= SearchFlags::REG_NOT_BEGINOFLINE | + SearchFlags::REG_NOT_ENDOFLINE; + break; + + case SearchParam::SRCH_LEVDIST: + aSOpt.algorithmType = SearchAlgorithms_APPROXIMATE; + aSOpt.changedChars = rParam.GetLEVOther(); + aSOpt.deletedChars = rParam.GetLEVLonger(); + aSOpt.insertedChars = rParam.GetLEVShorter(); + if( rParam.IsSrchRelaxed() ) + aSOpt.searchFlag |= SearchFlags::LEV_RELAXED; + break; + +// case SearchParam::SRCH_NORMAL: + default: + aSOpt.algorithmType = SearchAlgorithms_ABSOLUTE; + if( rParam.IsSrchWordOnly() ) + aSOpt.searchFlag |= SearchFlags::NORM_WORD_ONLY; + break; + } + aSOpt.searchString = rParam.GetSrchStr(); + aSOpt.replaceString = rParam.GetReplaceStr(); + aSOpt.Locale = rLocale; + aSOpt.transliterateFlags = rParam.GetTransliterationFlags(); + if( !rParam.IsCaseSensitive() ) + { + aSOpt.searchFlag |= SearchFlags::ALL_IGNORE_CASE; + aSOpt.transliterateFlags |= ::com::sun::star::i18n::TransliterationModules_IGNORE_CASE; + } + + xTextSearch = getXTextSearch( aSOpt ); +} + +void TextSearch::SetLocale( const ::com::sun::star::util::SearchOptions& rOptions, + const ::com::sun::star::lang::Locale& rLocale ) +{ + // convert SearchParam to the UNO SearchOptions + SearchOptions aSOpt( rOptions ); + aSOpt.Locale = rLocale; + + xTextSearch = getXTextSearch( aSOpt ); +} + + +TextSearch::~TextSearch() +{ +} + +/* + * Die allgemeinen Methoden zu Suchen. Diese rufen dann die entpsrecheden + * Methoden fuer die normale Suche oder der Suche nach Regular-Expressions + * ueber die MethodenPointer auf. + */ +#if defined _MSC_VER +#pragma optimize("", off) +#pragma warning(push) +#pragma warning(disable: 4748) +#endif +int TextSearch::SearchFrwrd( const String & rStr, xub_StrLen* pStart, + xub_StrLen* pEnde, SearchResult* pRes ) +{ + int nRet = 0; + try + { + if( xTextSearch.is() ) + { + SearchResult aRet( xTextSearch->searchForward( + rStr, *pStart, *pEnde )); + if( aRet.subRegExpressions > 0 ) + { + nRet = 1; + // the XTextsearch returns in startOffset the higher position + // and the endposition is allways exclusive. + // The caller of this function will have in startPos the + // lower pos. and end + *pStart = (xub_StrLen)aRet.startOffset[ 0 ]; + *pEnde = (xub_StrLen)aRet.endOffset[ 0 ]; + if( pRes ) + *pRes = aRet; + } + } + } + catch ( Exception& ) + { + DBG_ERRORFILE( "SearchForward: Exception caught!" ); + } + return nRet; +} + +int TextSearch::SearchBkwrd( const String & rStr, xub_StrLen* pStart, + xub_StrLen* pEnde, SearchResult* pRes ) +{ + int nRet = 0; + try + { + if( xTextSearch.is() ) + { + SearchResult aRet( xTextSearch->searchBackward( + rStr, *pStart, *pEnde )); + if( aRet.subRegExpressions ) + { + nRet = 1; + // the XTextsearch returns in startOffset the higher position + // and the endposition is allways exclusive. + // The caller of this function will have in startPos the + // lower pos. and end + *pEnde = (xub_StrLen)aRet.startOffset[ 0 ]; + *pStart = (xub_StrLen)aRet.endOffset[ 0 ]; + if( pRes ) + *pRes = aRet; + } + } + } + catch ( Exception& ) + { + DBG_ERRORFILE( "SearchBackward: Exception caught!" ); + } + return nRet; +} + +void TextSearch::ReplaceBackReferences( String& rReplaceStr, const String &rStr, const SearchResult& rResult ) +{ + if( rResult.subRegExpressions > 0 ) + { + String sTab( '\t' ); + sal_Unicode sSrchChrs[] = {'\\', '&', '$', 0}; + String sTmp; + xub_StrLen nPos = 0; + sal_Unicode sFndChar; + while( STRING_NOTFOUND != ( nPos = rReplaceStr.SearchChar( sSrchChrs, nPos )) ) + { + if( rReplaceStr.GetChar( nPos ) == '&') + { + USHORT nStart = (USHORT)(rResult.startOffset[0]); + USHORT nLength = (USHORT)(rResult.endOffset[0] - rResult.startOffset[0]); + rReplaceStr.Erase( nPos, 1 ); // delete ampersand + // replace by found string + rReplaceStr.Insert( rStr, nStart, nLength, nPos ); + // jump over + nPos = nPos + nLength; + } + else if( rReplaceStr.GetChar( nPos ) == '$') + { + if( nPos + 1 < rReplaceStr.Len()) + { + sFndChar = rReplaceStr.GetChar( nPos + 1 ); + switch(sFndChar) + { // placeholder for a backward reference? + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + rReplaceStr.Erase( nPos, 2 ); // delete both + int i = sFndChar - '0'; // index + if(i < rResult.subRegExpressions) + { + USHORT nSttReg = (USHORT)(rResult.startOffset[i]); + USHORT nRegLen = (USHORT)(rResult.endOffset[i]); + if( nRegLen > nSttReg ) + nRegLen = nRegLen - nSttReg; + else + { + nRegLen = nSttReg - nRegLen; + nSttReg = (USHORT)(rResult.endOffset[i]); + } + // Copy reference from found string + sTmp = rStr.Copy((USHORT)nSttReg, (USHORT)nRegLen); + // insert + rReplaceStr.Insert( sTmp, nPos ); + // and step over + nPos = nPos + sTmp.Len(); + } + } + break; + default: + nPos += 2; // leave both chars unchanged + break; + } + } + else + ++nPos; + } + else + { + // at least another character? + if( nPos + 1 < rReplaceStr.Len()) + { + sFndChar = rReplaceStr.GetChar( nPos + 1 ); + switch(sFndChar) + { + case '\\': + case '&': + case '$': + rReplaceStr.Erase( nPos, 1 ); + nPos++; + break; + case 't': + rReplaceStr.Erase( nPos, 2 ); // delete both + rReplaceStr.Insert( sTab, nPos ); // insert tabulator + nPos++; // step over + break; + default: + nPos += 2; // ignore both characters + break; + } + } + else + ++nPos; + } + } + } +} + + +#if defined _MSC_VER +#pragma optimize("", on) +#pragma warning(pop) +#endif + +// ............................................................................ +} // namespace utl +// ............................................................................ + diff --git a/unotools/source/i18n/transliterationwrapper.cxx b/unotools/source/i18n/transliterationwrapper.cxx new file mode 100644 index 000000000000..bd33e447471f --- /dev/null +++ b/unotools/source/i18n/transliterationwrapper.cxx @@ -0,0 +1,326 @@ +/************************************************************************* + * + * 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: transliterationwrapper.cxx,v $ + * $Revision: 1.17 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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_unotools.hxx" + +#include <unotools/transliterationwrapper.hxx> +#include <tools/debug.hxx> +#include <i18npool/mslangid.hxx> +#ifndef _COMPHELPER_COMPONENTFACTORY_HXX_ +#include <comphelper/componentfactory.hxx> +#endif +#include <com/sun/star/uno/XInterface.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> + +#define TRANSLIT_LIBRARYNAME "i18n" +#define TRANSLIT_SERVICENAME "com.sun.star.i18n.Transliteration" + +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::i18n; +using namespace ::com::sun::star::uno; +using namespace ::utl; + +TransliterationWrapper::TransliterationWrapper( + const Reference< XMultiServiceFactory > & xSF, + sal_uInt32 nTyp ) + : xSMgr( xSF ), nType( nTyp ), nLanguage( 0 ), bFirstCall( sal_True ) +{ + if( xSMgr.is() ) + { + try { + xTrans = Reference< XExtendedTransliteration > ( + xSMgr->createInstance( ::rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + TRANSLIT_SERVICENAME))), UNO_QUERY ); + } + catch ( Exception& ) + { + DBG_ERRORFILE( "TransliterationWrapper: Exception caught!" ); + } + } + else + { // try to get an instance somehow + DBG_ERRORFILE( "TransliterationWrapper: no service manager, trying own" ); + try + { + Reference< XInterface > xI = ::comphelper::getComponentInstance( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( LLCF_LIBNAME( + TRANSLIT_LIBRARYNAME ))), + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + TRANSLIT_SERVICENAME))); + if ( xI.is() ) + { + Any x = xI->queryInterface( + ::getCppuType((const Reference< XExtendedTransliteration>*)0) ); + x >>= xTrans ; + } + } + catch ( Exception& ) + { + DBG_ERRORFILE( "getComponentInstance: Exception caught!" ); + } + } + DBG_ASSERT( xTrans.is(), "TransliterationWrapper: no Transliteraion available" ); +} + + +TransliterationWrapper::~TransliterationWrapper() +{ +} + + +String TransliterationWrapper::transliterate( + const String& rStr, sal_uInt16 nLang, + xub_StrLen nStart, xub_StrLen nLen, + Sequence <sal_Int32>* pOffset ) +{ + String sRet; + if( xTrans.is() ) + { + try + { + loadModuleIfNeeded( nLang ); + + if ( pOffset ) + sRet = xTrans->transliterate( rStr, nStart, nLen, *pOffset ); + else + sRet = xTrans->transliterateString2String( rStr, nStart, nLen); + } + catch( Exception& ) + { + DBG_ERRORFILE( "transliterate: Exception caught!" ); + } + } + return sRet; +} + + +String TransliterationWrapper::transliterate( + const String& rStr, + xub_StrLen nStart, xub_StrLen nLen, + Sequence <sal_Int32>* pOffset ) const +{ + String sRet( rStr ); + if( xTrans.is() ) + { + try + { + if ( pOffset ) + sRet = xTrans->transliterate( rStr, nStart, nLen, *pOffset ); + else + sRet = xTrans->transliterateString2String( rStr, nStart, nLen); + } + catch( Exception& ) + { + DBG_ERRORFILE( "transliterate: Exception caught!" ); + } + } + return sRet; +} + +sal_Bool TransliterationWrapper::needLanguageForTheMode() const +{ + return TransliterationModules_UPPERCASE_LOWERCASE == nType || + TransliterationModules_LOWERCASE_UPPERCASE == nType || + TransliterationModules_IGNORE_CASE == nType; +} + + +void TransliterationWrapper::setLanguageLocaleImpl( sal_uInt16 nLang ) +{ + nLanguage = nLang; + if( LANGUAGE_NONE == nLanguage ) + nLanguage = LANGUAGE_SYSTEM; + MsLangId::convertLanguageToLocale( nLanguage, aLocale); +} + + +void TransliterationWrapper::loadModuleIfNeeded( sal_uInt16 nLang ) +{ + sal_Bool bLoad = bFirstCall; + bFirstCall = sal_False; + + if( nLanguage != nLang ) + { + setLanguageLocaleImpl( nLang ); + if( !bLoad ) + bLoad = needLanguageForTheMode(); + } + if( bLoad ) + loadModuleImpl(); +} + + +void TransliterationWrapper::loadModuleImpl() const +{ + if ( bFirstCall ) + ((TransliterationWrapper*)this)->setLanguageLocaleImpl( LANGUAGE_SYSTEM ); + + try + { + if ( xTrans.is() ) + xTrans->loadModule( (TransliterationModules)nType, aLocale ); + } + catch ( Exception& e ) + { +#ifndef PRODUCT + ByteString aMsg( "loadModuleImpl: Exception caught\n" ); + aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); + DBG_ERRORFILE( aMsg.GetBuffer() ); +#else + (void)e; +#endif + } + + bFirstCall = sal_False; +} + + +void TransliterationWrapper::loadModuleByImplName( + const String& rModuleName, sal_uInt16 nLang ) +{ + try + { + setLanguageLocaleImpl( nLang ); + // Reset LanguageType, so the next call to loadModuleIfNeeded() forces + // new settings. + nLanguage = LANGUAGE_DONTKNOW; + if ( xTrans.is() ) + xTrans->loadModuleByImplName( rModuleName, aLocale ); + } + catch ( Exception& e ) + { +#ifndef PRODUCT + ByteString aMsg( "loadModuleByImplName: Exception caught\n" ); + aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); + DBG_ERRORFILE( aMsg.GetBuffer() ); +#else + (void)e; +#endif + } + + bFirstCall = sal_False; +} + + +sal_Bool TransliterationWrapper::equals( + const String& rStr1, sal_Int32 nPos1, sal_Int32 nCount1, sal_Int32& nMatch1, + const String& rStr2, sal_Int32 nPos2, sal_Int32 nCount2, sal_Int32& nMatch2 ) const +{ + try + { + if( bFirstCall ) + loadModuleImpl(); + if ( xTrans.is() ) + return xTrans->equals( rStr1, nPos1, nCount1, nMatch1, rStr2, nPos2, nCount2, nMatch2 ); + } + catch ( Exception& e ) + { +#ifndef PRODUCT + ByteString aMsg( "equals: Exception caught\n" ); + aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); + DBG_ERRORFILE( aMsg.GetBuffer() ); +#else + (void)e; +#endif + } + return sal_False; +} + + +sal_Int32 TransliterationWrapper::compareSubstring( + const String& rStr1, sal_Int32 nOff1, sal_Int32 nLen1, + const String& rStr2, sal_Int32 nOff2, sal_Int32 nLen2 ) const +{ + try + { + if( bFirstCall ) + loadModuleImpl(); + if ( xTrans.is() ) + return xTrans->compareSubstring( rStr1, nOff1, nLen1, rStr2, nOff2, nLen2 ); + } + catch ( Exception& e ) + { +#ifndef PRODUCT + ByteString aMsg( "compareSubstring: Exception caught\n" ); + aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); + DBG_ERRORFILE( aMsg.GetBuffer() ); +#else + (void)e; +#endif + } + return 0; +} + + +sal_Int32 TransliterationWrapper::compareString( const String& rStr1, const String& rStr2 ) const +{ + try + { + if( bFirstCall ) + loadModuleImpl(); + if ( xTrans.is() ) + return xTrans->compareString( rStr1, rStr2 ); + } + catch ( Exception& e ) + { +#ifndef PRODUCT + ByteString aMsg( "compareString: Exception caught\n" ); + aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); + DBG_ERRORFILE( aMsg.GetBuffer() ); +#else + (void)e; +#endif + } + return 0; +} + + +// --- helpers -------------------------------------------------------- + +sal_Bool TransliterationWrapper::isEqual( const String& rStr1, const String& rStr2 ) const +{ + sal_Int32 nMatch1, nMatch2; + sal_Bool bMatch = equals( + rStr1, 0, rStr1.Len(), nMatch1, + rStr2, 0, rStr2.Len(), nMatch2 ); + return bMatch; +} + + +sal_Bool TransliterationWrapper::isMatch( const String& rStr1, const String& rStr2 ) const +{ + sal_Int32 nMatch1, nMatch2; + equals( + rStr1, 0, rStr1.Len(), nMatch1, + rStr2, 0, rStr2.Len(), nMatch2 ); + return (nMatch1 <= nMatch2) && (nMatch1 == rStr1.Len()); +} diff --git a/unotools/source/misc/atom.cxx b/unotools/source/misc/atom.cxx new file mode 100644 index 000000000000..03a459326d08 --- /dev/null +++ b/unotools/source/misc/atom.cxx @@ -0,0 +1,386 @@ +/************************************************************************* + * + * 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: atom.cxx,v $ + * $Revision: 1.10 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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_unotools.hxx" + +#include <unotools/atom.hxx> + +using namespace utl; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::util; +#define NMSP_UTIL ::com::sun::star::util + +AtomProvider::AtomProvider() +{ + m_nAtoms = 1; +} + +AtomProvider::~AtomProvider() +{ +} + +int AtomProvider::getAtom( const ::rtl::OUString& rString, sal_Bool bCreate ) +{ + ::std::hash_map< ::rtl::OUString, int, ::rtl::OUStringHash >::iterator it = m_aAtomMap.find( rString ); + if( it != m_aAtomMap.end() ) + return it->second; + if( ! bCreate ) + return INVALID_ATOM; + m_aAtomMap[ rString ] = m_nAtoms; + m_aStringMap[ m_nAtoms ] = rString; + m_nAtoms++; + return m_nAtoms-1; +} + +void AtomProvider::getAll( ::std::list< ::utl::AtomDescription >& atoms ) +{ + atoms.clear(); + ::std::hash_map< ::rtl::OUString, int, ::rtl::OUStringHash >::const_iterator it = m_aAtomMap.begin(); + + ::utl::AtomDescription aDesc; + while( it != m_aAtomMap.end() ) + { + aDesc.atom = it->second; + aDesc.description = it->first; + atoms.push_back( aDesc ); + ++it; + } +} + +void AtomProvider::getRecent( int atom, ::std::list< ::utl::AtomDescription >& atoms ) +{ + atoms.clear(); + + ::std::hash_map< ::rtl::OUString, int, ::rtl::OUStringHash >::const_iterator it = m_aAtomMap.begin(); + + ::utl::AtomDescription aDesc; + while( it != m_aAtomMap.end() ) + { + if( it->second > atom ) + { + aDesc.atom = it->second; + aDesc.description = it->first; + atoms.push_back( aDesc ); + } + ++it; + } +} + +const ::rtl::OUString& AtomProvider::getString( int nAtom ) const +{ + static ::rtl::OUString aEmpty; + ::std::hash_map< int, ::rtl::OUString, ::std::hash< int > >::const_iterator it = m_aStringMap.find( nAtom ); + + return it == m_aStringMap.end() ? aEmpty : it->second; +} + +void AtomProvider::overrideAtom( int atom, const ::rtl::OUString& description ) +{ + m_aAtomMap[ description ] = atom; + m_aStringMap[ atom ] = description; + if( m_nAtoms <= atom ) + m_nAtoms=atom+1; +} + +sal_Bool AtomProvider::hasAtom( int atom ) const +{ + return m_aStringMap.find( atom ) != m_aStringMap.end() ? sal_True : sal_False; +} + +// ----------------------------------------------------------------------- + +MultiAtomProvider::MultiAtomProvider() +{ +} + +MultiAtomProvider::~MultiAtomProvider() +{ + for( ::std::hash_map< int, AtomProvider*, ::std::hash< int > >::iterator it = m_aAtomLists.begin(); it != m_aAtomLists.end(); ++it ) + delete it->second; +} + + +sal_Bool MultiAtomProvider::insertAtomClass( int atomClass ) +{ + ::std::hash_map< int, AtomProvider*, ::std::hash< int > >::iterator it = + m_aAtomLists.find( atomClass ); + if( it != m_aAtomLists.end() ) + return sal_False; + m_aAtomLists[ atomClass ] = new AtomProvider(); + return sal_True; +} + +int MultiAtomProvider::getAtom( int atomClass, const ::rtl::OUString& rString, sal_Bool bCreate ) +{ + ::std::hash_map< int, AtomProvider*, ::std::hash< int > >::iterator it = + m_aAtomLists.find( atomClass ); + if( it != m_aAtomLists.end() ) + return it->second->getAtom( rString, bCreate ); + + if( bCreate ) + { + AtomProvider* pNewClass; + m_aAtomLists[ atomClass ] = pNewClass = new AtomProvider(); + return pNewClass->getAtom( rString, bCreate ); + } + return INVALID_ATOM; +} + +int MultiAtomProvider::getLastAtom( int atomClass ) const +{ + ::std::hash_map< int, AtomProvider*, ::std::hash< int > >::const_iterator it = + m_aAtomLists.find( atomClass ); + + return it != m_aAtomLists.end() ? it->second->getLastAtom() : INVALID_ATOM; +} + +void MultiAtomProvider::getRecent( int atomClass, int atom, ::std::list< ::utl::AtomDescription >& atoms ) +{ + ::std::hash_map< int, AtomProvider*, ::std::hash< int > >::const_iterator it = + m_aAtomLists.find( atomClass ); + if( it != m_aAtomLists.end() ) + it->second->getRecent( atom, atoms ); + else + atoms.clear(); +} + +const ::rtl::OUString& MultiAtomProvider::getString( int atomClass, int atom ) const +{ + ::std::hash_map< int, AtomProvider*, ::std::hash< int > >::const_iterator it = + m_aAtomLists.find( atomClass ); + if( it != m_aAtomLists.end() ) + return it->second->getString( atom ); + + static ::rtl::OUString aEmpty; + return aEmpty; +} + +sal_Bool MultiAtomProvider::hasAtom( int atomClass, int atom ) const +{ + ::std::hash_map< int, AtomProvider*, ::std::hash< int > >::const_iterator it = m_aAtomLists.find( atomClass ); + return it != m_aAtomLists.end() ? it->second->hasAtom( atom ) : sal_False; +} + +void MultiAtomProvider::getClass( int atomClass, ::std::list< ::utl::AtomDescription >& atoms) const +{ + ::std::hash_map< int, AtomProvider*, ::std::hash< int > >::const_iterator it = m_aAtomLists.find( atomClass ); + + if( it != m_aAtomLists.end() ) + it->second->getAll( atoms ); + else + atoms.clear(); +} + +void MultiAtomProvider::overrideAtom( int atomClass, int atom, const ::rtl::OUString& description ) +{ + ::std::hash_map< int, AtomProvider*, ::std::hash< int > >::const_iterator it = m_aAtomLists.find( atomClass ); + if( it == m_aAtomLists.end() ) + m_aAtomLists[ atomClass ] = new AtomProvider(); + m_aAtomLists[ atomClass ]->overrideAtom( atom, description ); +} + +// ----------------------------------------------------------------------- + +AtomServer::AtomServer() +{ +} + +AtomServer::~AtomServer() +{ +} + +sal_Int32 AtomServer::getAtom( sal_Int32 atomClass, const ::rtl::OUString& description, sal_Bool create ) throw() +{ + ::osl::Guard< ::osl::Mutex > guard( m_aMutex ); + + return m_aProvider.getAtom( atomClass, description, create ); +} + +Sequence< Sequence< NMSP_UTIL::AtomDescription > > AtomServer::getClasses( const Sequence< sal_Int32 >& atomClasses ) throw() +{ + ::osl::Guard< ::osl::Mutex > guard( m_aMutex ); + + Sequence< Sequence< NMSP_UTIL::AtomDescription > > aRet( atomClasses.getLength() ); + for( int i = 0; i < atomClasses.getLength(); i++ ) + { + aRet.getArray()[i] = getClass( atomClasses.getConstArray()[i] ); + } + return aRet; +} + +Sequence< NMSP_UTIL::AtomDescription > AtomServer::getClass( sal_Int32 atomClass ) throw() +{ + ::osl::Guard< ::osl::Mutex > guard( m_aMutex ); + + ::std::list< ::utl::AtomDescription > atoms; + m_aProvider.getClass( atomClass, atoms ); + + Sequence< NMSP_UTIL::AtomDescription > aRet( atoms.size() ); + for( int i = aRet.getLength()-1; i >= 0; i-- ) + { + aRet.getArray()[i].atom = atoms.back().atom; + aRet.getArray()[i].description = atoms.back().description; + atoms.pop_back(); + } + + return aRet; +} + +Sequence< NMSP_UTIL::AtomDescription > AtomServer::getRecentAtoms( sal_Int32 atomClass, sal_Int32 atom ) throw() +{ + ::osl::Guard< ::osl::Mutex > guard( m_aMutex ); + + ::std::list< ::utl::AtomDescription > atoms; + m_aProvider.getRecent( atomClass, atom, atoms ); + + Sequence< NMSP_UTIL::AtomDescription > aRet( atoms.size() ); + for( int i = aRet.getLength()-1; i >= 0; i-- ) + { + aRet.getArray()[i].atom = atoms.back().atom; + aRet.getArray()[i].description = atoms.back().description; + atoms.pop_back(); + } + + return aRet; +} + +Sequence< ::rtl::OUString > AtomServer::getAtomDescriptions( const Sequence< AtomClassRequest >& atoms ) throw() +{ + ::osl::Guard< ::osl::Mutex > guard( m_aMutex ); + + int nStrings = 0, i; + for( i = 0; i < atoms.getLength(); i++ ) + nStrings += atoms.getConstArray()[ i ].atoms.getLength(); + Sequence< ::rtl::OUString > aRet( nStrings ); + for( i = 0, nStrings = 0; i < atoms.getLength(); i++ ) + { + const AtomClassRequest& rRequest = atoms.getConstArray()[i]; + for( int n = 0; n < rRequest.atoms.getLength(); n++ ) + aRet.getArray()[ nStrings++ ] = m_aProvider.getString( rRequest.atomClass, rRequest.atoms.getConstArray()[ n ] ); + } + return aRet; +} + +// ----------------------------------------------------------------------- + +AtomClient::AtomClient( const Reference< XAtomServer >& xServer ) : + m_xServer( xServer ) +{ +} + +AtomClient::~AtomClient() +{ +} + +int AtomClient::getAtom( int atomClass, const ::rtl::OUString& description, sal_Bool bCreate ) +{ + int nAtom = m_aProvider.getAtom( atomClass, description, sal_False ); + if( nAtom == INVALID_ATOM && bCreate ) + { + try + { + nAtom = m_xServer->getAtom( atomClass, description, bCreate ); + } + catch( RuntimeException& ) + { + return INVALID_ATOM; + } + if( nAtom != INVALID_ATOM ) + m_aProvider.overrideAtom( atomClass, nAtom, description ); + } + return nAtom; +} + +const ::rtl::OUString& AtomClient::getString( int atomClass, int atom ) +{ + static ::rtl::OUString aEmpty; + + if( ! m_aProvider.hasAtom( atomClass, atom ) ) + { + Sequence< NMSP_UTIL::AtomDescription > aSeq; + try + { + aSeq = m_xServer->getRecentAtoms( atomClass, m_aProvider.getLastAtom( atomClass ) ); + } + catch( RuntimeException& ) + { + return aEmpty; + } + const NMSP_UTIL::AtomDescription* pDescriptions = aSeq.getConstArray(); + for( int i = 0; i < aSeq.getLength(); i++ ) + m_aProvider.overrideAtom( atomClass, + pDescriptions[i].atom, + pDescriptions[i].description + ); + + if( ! m_aProvider.hasAtom( atomClass, atom ) ) + { + // holes may occur by the above procedure! + Sequence< AtomClassRequest > aReq( 1 ); + aReq.getArray()[0].atomClass = atomClass; + aReq.getArray()[0].atoms.realloc( 1 ); + aReq.getArray()[0].atoms.getArray()[0] = atom; + Sequence< ::rtl::OUString > aRet; + try + { + aRet = m_xServer->getAtomDescriptions( aReq ); + } + catch( RuntimeException& ) + { + return aEmpty; + } + if( aRet.getLength() == 1 ) + m_aProvider.overrideAtom( atomClass, atom, aRet.getConstArray()[0] ); + } + } + return m_aProvider.getString( atomClass, atom ); +} + +void AtomClient::updateAtomClasses( const Sequence< sal_Int32 >& atomClasses ) +{ + Sequence< Sequence< NMSP_UTIL::AtomDescription > > aUpdate; + try + { + aUpdate = m_xServer->getClasses( atomClasses ); + } + catch( RuntimeException& ) + { + return; + } + for( int i = 0; i < atomClasses.getLength(); i++ ) + { + int nClass = atomClasses.getConstArray()[i]; + const Sequence< NMSP_UTIL::AtomDescription >& rClass = aUpdate.getConstArray()[i]; + const NMSP_UTIL::AtomDescription* pDesc = rClass.getConstArray(); + for( int n = 0; n < rClass.getLength(); n++, pDesc++ ) + m_aProvider.overrideAtom( nClass, pDesc->atom, pDesc->description ); + } +} diff --git a/unotools/source/misc/componentresmodule.cxx b/unotools/source/misc/componentresmodule.cxx new file mode 100644 index 000000000000..9f0eaa055da8 --- /dev/null +++ b/unotools/source/misc/componentresmodule.cxx @@ -0,0 +1,149 @@ +/************************************************************************* + * + * 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: componentresmodule.cxx,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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_unotools.hxx" +#include <unotools/componentresmodule.hxx> + +/** === begin UNO includes === **/ +/** === end UNO includes === **/ +#include <tools/resmgr.hxx> +#include <osl/diagnose.h> + +//........................................................................ +namespace utl +{ +//........................................................................ + + //==================================================================== + //= OComponentResModuleImpl + //==================================================================== + /** PIMPL-class for OComponentResourceModule + + not threadsafe! + */ + class OComponentResModuleImpl + { + private: + ResMgr* m_pRessources; + bool m_bInitialized; + ::rtl::OString m_sResFilePrefix; + + public: + OComponentResModuleImpl( const ::rtl::OString& _rResFilePrefix ) + :m_pRessources( NULL ) + ,m_bInitialized( false ) + ,m_sResFilePrefix( _rResFilePrefix ) + { + } + + ~OComponentResModuleImpl() + { + freeResManager(); + } + + /** releases our resource manager + */ + void freeResManager(); + + /** retrieves our resource manager + */ + ResMgr* getResManager(); + + private: + OComponentResModuleImpl(); // never implemented + OComponentResModuleImpl( const OComponentResModuleImpl& ); // never implemented + OComponentResModuleImpl& operator=( const OComponentResModuleImpl& ); // never implemented + }; + + //-------------------------------------------------------------------- + void OComponentResModuleImpl::freeResManager() + { + delete m_pRessources, m_pRessources = NULL; + m_bInitialized = false; + } + + //-------------------------------------------------------------------- + ResMgr* OComponentResModuleImpl::getResManager() + { + if ( !m_pRessources && !m_bInitialized ) + { + // create a manager with a fixed prefix + ByteString aMgrName = m_sResFilePrefix; + + m_pRessources = ResMgr::CreateResMgr( aMgrName.GetBuffer() ); + OSL_ENSURE( m_pRessources, + ( ByteString( "OModuleImpl::getResManager: could not create the resource manager (file name: " ) + += aMgrName + += ByteString( ")!" ) ).GetBuffer() ); + + m_bInitialized = sal_True; + } + return m_pRessources; + } + + //==================================================================== + //= OComponentResourceModule + //==================================================================== + //-------------------------------------------------------------------- + OComponentResourceModule::OComponentResourceModule( const ::rtl::OString& _rResFilePrefix ) + :BaseClass() + ,m_pImpl( new OComponentResModuleImpl( _rResFilePrefix ) ) + { + } + + //-------------------------------------------------------------------- + OComponentResourceModule::~OComponentResourceModule() + { + } + + //------------------------------------------------------------------------- + ResMgr* OComponentResourceModule::getResManager() + { + ::osl::MutexGuard aGuard( m_aMutex ); + return m_pImpl->getResManager(); + } + + //-------------------------------------------------------------------------- + void OComponentResourceModule::onFirstClient() + { + BaseClass::onFirstClient(); + } + + //-------------------------------------------------------------------------- + void OComponentResourceModule::onLastClient() + { + m_pImpl->freeResManager(); + BaseClass::onLastClient(); + } + +//........................................................................ +} // namespace utl +//........................................................................ diff --git a/unotools/source/misc/datetime.cxx b/unotools/source/misc/datetime.cxx new file mode 100644 index 000000000000..cab276309542 --- /dev/null +++ b/unotools/source/misc/datetime.cxx @@ -0,0 +1,124 @@ +/************************************************************************* + * + * 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: datetime.cxx,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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_unotools.hxx" +#include <unotools/datetime.hxx> +#include <tools/date.hxx> +#include <tools/time.hxx> +#include <tools/datetime.hxx> + +//......................................................................... +namespace utl +{ +//......................................................................... + +//------------------------------------------------------------------ +void typeConvert(const Time& _rTime, starutil::Time& _rOut) +{ + _rOut.Hours = _rTime.GetHour(); + _rOut.Minutes = _rTime.GetMin(); + _rOut.Seconds = _rTime.GetSec(); + _rOut.HundredthSeconds = _rTime.Get100Sec(); +} + +//------------------------------------------------------------------ +void typeConvert(const starutil::Time& _rTime, Time& _rOut) +{ + _rOut = Time(_rTime.Hours, _rTime.Minutes, _rTime.Seconds, _rTime.HundredthSeconds); +} + +//------------------------------------------------------------------ +void typeConvert(const Date& _rDate, starutil::Date& _rOut) +{ + _rOut.Day = _rDate.GetDay(); + _rOut.Month = _rDate.GetMonth(); + _rOut.Year = _rDate.GetYear(); +} + +//------------------------------------------------------------------ +void typeConvert(const starutil::Date& _rDate, Date& _rOut) +{ + _rOut = Date(_rDate.Day, _rDate.Month, _rDate.Year); +} + +//------------------------------------------------------------------ +void typeConvert(const DateTime& _rDateTime, starutil::DateTime& _rOut) +{ + _rOut.Year = _rDateTime.GetYear(); + _rOut.Month = _rDateTime.GetMonth(); + _rOut.Day = _rDateTime.GetDay(); + _rOut.Hours = _rDateTime.GetHour(); + _rOut.Minutes = _rDateTime.GetMin(); + _rOut.Seconds = _rDateTime.GetSec(); + _rOut.HundredthSeconds = _rDateTime.Get100Sec(); +} + +//------------------------------------------------------------------ +void typeConvert(const starutil::DateTime& _rDateTime, DateTime& _rOut) +{ + Date aDate(_rDateTime.Day, _rDateTime.Month, _rDateTime.Year); + Time aTime(_rDateTime.Hours, _rDateTime.Minutes, _rDateTime.Seconds, _rDateTime.HundredthSeconds); + _rOut = DateTime(aDate, aTime); +} + +//------------------------------------------------------------------------- +sal_Bool operator ==(const starutil::DateTime& _rLeft, const starutil::DateTime& _rRight) +{ + return ( _rLeft.HundredthSeconds == _rRight.HundredthSeconds) && + ( _rLeft.Seconds == _rRight.Seconds) && + ( _rLeft.Minutes == _rRight.Minutes) && + ( _rLeft.Hours == _rRight.Hours) && + ( _rLeft.Day == _rRight.Day) && + ( _rLeft.Month == _rRight.Month) && + ( _rLeft.Year == _rRight.Year) ; +} + +//------------------------------------------------------------------------- +sal_Bool operator ==(const starutil::Date& _rLeft, const starutil::Date& _rRight) +{ + return ( _rLeft.Day == _rRight.Day) && + ( _rLeft.Month == _rRight.Month) && + ( _rLeft.Year == _rRight.Year) ; +} + +//------------------------------------------------------------------------- +sal_Bool operator ==(const starutil::Time& _rLeft, const starutil::Time& _rRight) +{ + return ( _rLeft.HundredthSeconds == _rRight.HundredthSeconds) && + ( _rLeft.Seconds == _rRight.Seconds) && + ( _rLeft.Minutes == _rRight.Minutes) && + ( _rLeft.Hours == _rRight.Hours) ; +} + +//......................................................................... +} // namespace utl +//......................................................................... + diff --git a/unotools/source/misc/desktopterminationobserver.cxx b/unotools/source/misc/desktopterminationobserver.cxx new file mode 100644 index 000000000000..d30ea7cc281d --- /dev/null +++ b/unotools/source/misc/desktopterminationobserver.cxx @@ -0,0 +1,240 @@ +/************************************************************************* + * + * 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: desktopterminationobserver.cxx,v $ + * $Revision: 1.6 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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_unotools.hxx" +#include <unotools/desktopterminationobserver.hxx> + +/** === begin UNO includes === **/ +#include <com/sun/star/frame/XTerminateListener.hpp> +#include <com/sun/star/frame/XDesktop.hpp> +/** === end UNO includes === **/ +#include <cppuhelper/implbase1.hxx> +#include <comphelper/processfactory.hxx> + +#include <list> + +//........................................................................ +namespace utl +{ +//........................................................................ + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::frame; + + namespace + { + //................................................................ + typedef ::std::list< ITerminationListener* > Listeners; + + struct ListenerAdminData + { + Listeners aListeners; + bool bAlreadyTerminated; + bool bCreatedAdapter; + + ListenerAdminData() : bAlreadyTerminated( false ), bCreatedAdapter( false ) { } + }; + + //................................................................ + ListenerAdminData& getListenerAdminData() + { + static ListenerAdminData s_aData; + return s_aData; + } + + //================================================================ + //= OObserverImpl + //================================================================ + class OObserverImpl : public ::cppu::WeakImplHelper1< XTerminateListener > + { + public: + static void ensureObservation(); + + protected: + OObserverImpl(); + ~OObserverImpl(); + + private: + // XTerminateListener + virtual void SAL_CALL queryTermination( const EventObject& Event ) throw (TerminationVetoException, RuntimeException); + virtual void SAL_CALL notifyTermination( const EventObject& Event ) throw (RuntimeException); + + // XEventListener + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException); + }; + + //-------------------------------------------------------------------- + OObserverImpl::OObserverImpl() + { + } + + //-------------------------------------------------------------------- + OObserverImpl::~OObserverImpl() + { + } + + //-------------------------------------------------------------------- + void OObserverImpl::ensureObservation() + { + { + if ( getListenerAdminData().bCreatedAdapter ) + return; + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if ( getListenerAdminData().bCreatedAdapter ) + return; + + getListenerAdminData().bCreatedAdapter = true; + } + + try + { + Reference< XDesktop > xDesktop; + xDesktop = xDesktop.query( ::comphelper::getProcessServiceFactory()->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.Desktop" ) ) ) ); + OSL_ENSURE( xDesktop.is(), "OObserverImpl::ensureObservation: could not ensureObservation the desktop!" ); + if ( xDesktop.is() ) + xDesktop->addTerminateListener( new OObserverImpl ); + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "OObserverImpl::ensureObservation: caught an exception!" ); + } + } + + //-------------------------------------------------------------------- + void SAL_CALL OObserverImpl::queryTermination( const EventObject& /*Event*/ ) throw (TerminationVetoException, RuntimeException) + { + Listeners aToNotify; + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + aToNotify = getListenerAdminData().aListeners; + } + + for ( Listeners::const_iterator listener = aToNotify.begin(); + listener != aToNotify.end(); + ++listener + ) + { + if ( !(*listener)->queryTermination() ) + throw TerminationVetoException(); + } + } + + //-------------------------------------------------------------------- + void SAL_CALL OObserverImpl::notifyTermination( const EventObject& /*Event*/ ) throw (RuntimeException) + { + // get the listeners + Listeners aToNotify; + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + OSL_ENSURE( !getListenerAdminData().bAlreadyTerminated, "OObserverImpl::notifyTermination: terminated twice?" ); + aToNotify = getListenerAdminData().aListeners; + getListenerAdminData().bAlreadyTerminated = true; + } + + // notify the listeners + for ( Listeners::const_iterator listener = aToNotify.begin(); + listener != aToNotify.end(); + ++listener + ) + { + (*listener)->notifyTermination(); + } + + // clear the listener container + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + getListenerAdminData().aListeners.clear(); + } + } + + //-------------------------------------------------------------------- + void SAL_CALL OObserverImpl::disposing( const EventObject& /*Event*/ ) throw (RuntimeException) + { +#if OSL_DEBUG_LEVEL > 0 + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + OSL_ENSURE( getListenerAdminData().bAlreadyTerminated, "OObserverImpl::disposing: disposing without terminated?" ); +#endif + // not interested in + } + } + + //==================================================================== + //= DesktopTerminationObserver + //==================================================================== + //-------------------------------------------------------------------- + void DesktopTerminationObserver::registerTerminationListener( ITerminationListener* _pListener ) + { + if ( !_pListener ) + return; + + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if ( getListenerAdminData().bAlreadyTerminated ) + { + _pListener->notifyTermination(); + return; + } + + getListenerAdminData().aListeners.push_back( _pListener ); + } + + OObserverImpl::ensureObservation(); + } + + //-------------------------------------------------------------------- + void DesktopTerminationObserver::revokeTerminationListener( ITerminationListener* _pListener ) + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if ( getListenerAdminData().bAlreadyTerminated ) + { + _pListener->notifyTermination(); + return; + } + + Listeners& rListeners = getListenerAdminData().aListeners; + for ( Listeners::iterator lookup = rListeners.begin(); + lookup != rListeners.end(); + ++lookup + ) + { + if ( *lookup == _pListener ) + { + rListeners.erase( lookup ); + break; + } + } + } + +//........................................................................ +} // namespace utl +//........................................................................ + diff --git a/unotools/source/misc/eventlisteneradapter.cxx b/unotools/source/misc/eventlisteneradapter.cxx new file mode 100644 index 000000000000..b4c344e2cfd3 --- /dev/null +++ b/unotools/source/misc/eventlisteneradapter.cxx @@ -0,0 +1,185 @@ +/************************************************************************* + * + * 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: eventlisteneradapter.cxx,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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_unotools.hxx" +#include <unotools/eventlisteneradapter.hxx> +#include <osl/diagnose.h> +#include <cppuhelper/implbase1.hxx> +#include <comphelper/stl_types.hxx> + +//......................................................................... +namespace utl +{ +//......................................................................... + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::lang; + + //===================================================================== + //= OEventListenerImpl + //===================================================================== + class OEventListenerImpl : public ::cppu::WeakImplHelper1< XEventListener > + { + protected: + OEventListenerAdapter* m_pAdapter; + Reference< XEventListener > m_xKeepMeAlive; + // imagine an implementation of XComponent which holds it's listeners with a weak reference ... + // would be very bad if we don't hold ourself + Reference< XComponent > m_xComponent; + + public: + OEventListenerImpl( OEventListenerAdapter* _pAdapter, const Reference< XComponent >& _rxComp ); + + void dispose(); + const Reference< XComponent >& getComponent() const { return m_xComponent; } + + protected: + virtual void SAL_CALL disposing( const EventObject& _rSource ) throw (RuntimeException); + }; + + //--------------------------------------------------------------------- + OEventListenerImpl::OEventListenerImpl( OEventListenerAdapter* _pAdapter, const Reference< XComponent >& _rxComp ) + :m_pAdapter(_pAdapter) + { + OSL_ENSURE(m_pAdapter, "OEventListenerImpl::OEventListenerImpl: invalid adapter!"); + // no checks of _rxComp !! + // (OEventListenerAdapter is responsible for this) + + // just in case addEventListener throws an exception ... don't initialize m_xKeepMeAlive before this + // is done + Reference< XEventListener > xMeMyselfAndI = this; + _rxComp->addEventListener(xMeMyselfAndI); + + m_xComponent = _rxComp; + m_xKeepMeAlive = xMeMyselfAndI; + } + + //--------------------------------------------------------------------- + void OEventListenerImpl::dispose() + { + if (m_xComponent.is()) + { + m_xComponent->removeEventListener(m_xKeepMeAlive); + m_xComponent.clear(); + m_xKeepMeAlive.clear(); + } + } + + //--------------------------------------------------------------------- + void SAL_CALL OEventListenerImpl::disposing( const EventObject& _rSource ) throw (RuntimeException) + { + Reference< XEventListener > xDeleteUponLeaving = m_xKeepMeAlive; + m_xKeepMeAlive.clear(); + m_xComponent.clear(); + + m_pAdapter->_disposing(_rSource); + } + + //===================================================================== + //= OEventListenerAdapterImpl + //===================================================================== + struct OEventListenerAdapterImpl + { + public: + ::std::vector< void* > aListeners; + }; + + //===================================================================== + //= OEventListenerAdapter + //===================================================================== + //--------------------------------------------------------------------- + OEventListenerAdapter::OEventListenerAdapter() + :m_pImpl(new OEventListenerAdapterImpl) + { + } + + //--------------------------------------------------------------------- + OEventListenerAdapter::~OEventListenerAdapter() + { + stopAllComponentListening( ); + delete m_pImpl; + m_pImpl = NULL; + } + + //--------------------------------------------------------------------- + void OEventListenerAdapter::stopComponentListening( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent >& _rxComp ) + { + if ( m_pImpl->aListeners.empty() ) + return; + + ::std::vector< void* >::iterator dispose = m_pImpl->aListeners.begin(); + do + { + OEventListenerImpl* pListenerImpl = static_cast< OEventListenerImpl* >( *dispose ); + if ( pListenerImpl->getComponent().get() == _rxComp.get() ) + { + pListenerImpl->dispose(); + pListenerImpl->release(); + dispose = m_pImpl->aListeners.erase( dispose ); + } + else + ++dispose; + } + while ( dispose != m_pImpl->aListeners.end() ); + } + + //--------------------------------------------------------------------- + void OEventListenerAdapter::stopAllComponentListening( ) + { + for ( ::std::vector< void* >::const_iterator aDisposeLoop = m_pImpl->aListeners.begin(); + aDisposeLoop != m_pImpl->aListeners.end(); + ++aDisposeLoop + ) + { + OEventListenerImpl* pListenerImpl = static_cast< OEventListenerImpl* >(*aDisposeLoop); + pListenerImpl->dispose(); + pListenerImpl->release(); + } + m_pImpl->aListeners.clear(); + } + + //--------------------------------------------------------------------- + void OEventListenerAdapter::startComponentListening( const Reference< XComponent >& _rxComp ) + { + if (!_rxComp.is()) + { + OSL_ENSURE(sal_False, "OEventListenerAdapter::startComponentListening: invalid component!"); + return; + } + + OEventListenerImpl* pListenerImpl = new OEventListenerImpl(this, _rxComp); + pListenerImpl->acquire(); + m_pImpl->aListeners.push_back(pListenerImpl); + } + +//......................................................................... +} // namespace utl +//......................................................................... diff --git a/unotools/source/misc/makefile.mk b/unotools/source/misc/makefile.mk new file mode 100644 index 000000000000..8e505e41aaac --- /dev/null +++ b/unotools/source/misc/makefile.mk @@ -0,0 +1,56 @@ +#************************************************************************* +# +# 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.18 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General 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=..$/.. +PRJINC=..$/..$/inc +PRJNAME=unotools +TARGET=misc + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ---------------------------------- + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/util$/makefile.pmk + +# --- Files ------------------------------------- + +SLOFILES= $(SLO)$/atom.obj \ + $(SLO)$/datetime.obj \ + $(SLO)$/eventlisteneradapter.obj \ + $(SLO)$/desktopterminationobserver.obj \ + $(SLO)$/sharedunocomponent.obj \ + $(SLO)$/componentresmodule.obj + +# --- Targets ---------------------------------- + +.INCLUDE : target.mk + diff --git a/unotools/source/misc/sharedunocomponent.cxx b/unotools/source/misc/sharedunocomponent.cxx new file mode 100644 index 000000000000..a426a6662fa5 --- /dev/null +++ b/unotools/source/misc/sharedunocomponent.cxx @@ -0,0 +1,249 @@ +/************************************************************************* + * + * 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: sharedunocomponent.cxx,v $ + * $Revision: 1.7 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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_unotools.hxx" +#include <unotools/sharedunocomponent.hxx> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/util/XCloseable.hpp> +#include <cppuhelper/implbase1.hxx> +#include <tools/debug.hxx> + +//............................................................................ +namespace utl +{ +//............................................................................ + + using ::com::sun::star::uno::XInterface; + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::uno::UNO_QUERY; + using ::com::sun::star::uno::RuntimeException; + using ::com::sun::star::lang::XComponent; + using ::com::sun::star::lang::EventObject; + using ::com::sun::star::util::XCloseable; + using ::com::sun::star::util::XCloseListener; + using ::com::sun::star::util::CloseVetoException; + + //======================================================================== + //= DisposableComponent + //======================================================================== + //------------------------------------------------------------------------ + DisposableComponent::DisposableComponent( const Reference< XInterface >& _rxComponent ) + :m_xComponent( _rxComponent, UNO_QUERY ) + { + DBG_ASSERT( m_xComponent.is() || !_rxComponent.is(), "DisposableComponent::DisposableComponent: should be an XComponent!" ); + } + + //------------------------------------------------------------------------ + DisposableComponent::~DisposableComponent() + { + if ( m_xComponent.is() ) + { + try + { + m_xComponent->dispose(); + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "DisposableComponent::~DisposableComponent: caught an exception!" ); + } + m_xComponent.clear(); + } + } + + //======================================================================== + //= CloseableComponentImpl + //======================================================================== + DBG_NAME( CloseableComponentImpl ) + typedef ::cppu::WeakImplHelper1 < XCloseListener + > CloseableComponentImpl_Base; + class CloseableComponentImpl : public CloseableComponentImpl_Base + { + private: + Reference< XCloseable > m_xCloseable; + + public: + CloseableComponentImpl( const Reference< XInterface >& _rxComponent ); + + /** closes the component + + @nofail + */ + void nf_closeComponent(); + + protected: + virtual ~CloseableComponentImpl(); + + // XCloseListener overridables + virtual void SAL_CALL queryClosing( const EventObject& Source, ::sal_Bool GetsOwnership ) throw (CloseVetoException, RuntimeException); + virtual void SAL_CALL notifyClosing( const EventObject& Source ) throw (RuntimeException); + + // XEventListener overridables + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException); + + private: + /** starts or stops being a CloseListener at the component + + Only to be called upon construction of the instance, or when the component + is to be closed. + + @nofail + */ + void impl_nf_switchListening( bool _bListen ); + + + private: + CloseableComponentImpl(); // never implemented + CloseableComponentImpl( const CloseableComponentImpl& ); // never implemented + CloseableComponentImpl& operator=( const CloseableComponentImpl& ); // never implemented + }; + + //------------------------------------------------------------------------ + CloseableComponentImpl::CloseableComponentImpl( const Reference< XInterface >& _rxComponent ) + :m_xCloseable( _rxComponent, UNO_QUERY ) + { + DBG_CTOR( CloseableComponentImpl, NULL ); + DBG_ASSERT( m_xCloseable.is() || !_rxComponent.is(), "CloseableComponentImpl::CloseableComponentImpl: component is not an XCloseable!" ); + impl_nf_switchListening( true ); + } + //------------------------------------------------------------------------ + CloseableComponentImpl::~CloseableComponentImpl() + { + nf_closeComponent(); + DBG_DTOR( CloseableComponentImpl, NULL ); + } + + //------------------------------------------------------------------------ + void CloseableComponentImpl::nf_closeComponent() + { + if ( !m_xCloseable.is() ) + // nothing to do + return; + + // stop listening + impl_nf_switchListening( false ); + + // close + try + { + m_xCloseable->close( sal_True ); + } + catch( const CloseVetoException& ) { /* fine */ } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "CloseableComponentImpl::nf_closeComponent: caught an unexpected exception!" ); + } + + // reset + m_xCloseable.clear(); + } + + //------------------------------------------------------------------------ + void CloseableComponentImpl::impl_nf_switchListening( bool _bListen ) + { + if ( !m_xCloseable.is() ) + return; + + try + { + if ( _bListen ) + m_xCloseable->addCloseListener( this ); + else + m_xCloseable->removeCloseListener( this ); + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "CloseableComponentImpl::impl_nf_switchListening: caught an exception!" ); + } + } + + //-------------------------------------------------------------------- + void SAL_CALL CloseableComponentImpl::queryClosing( const EventObject& + #ifdef DBG_UTIL + Source + #endif + , ::sal_Bool /*GetsOwnership*/ ) throw (CloseVetoException, RuntimeException) + { + // as long as we live, somebody wants to keep the object alive. So, veto the + // closing + DBG_ASSERT( Source.Source == m_xCloseable, "CloseableComponentImpl::queryClosing: where did this come from?" ); + throw CloseVetoException(); + } + + //-------------------------------------------------------------------- + void SAL_CALL CloseableComponentImpl::notifyClosing( const EventObject& + #ifdef DBG_UTIL + Source + #endif + ) throw (RuntimeException) + { + DBG_ASSERT( Source.Source == m_xCloseable, "CloseableComponentImpl::notifyClosing: where did this come from?" ); + + // this should be unreachable: As long as we're a CloseListener, we veto the closing. If we're going + // to close the component ourself, then we revoke ourself as listener *before* the close call. So, + // if this here fires, something went definately wrong. + DBG_ERROR( "CloseableComponentImpl::notifyClosing: unreachable!" ); + } + + //-------------------------------------------------------------------- + void SAL_CALL CloseableComponentImpl::disposing( const EventObject& + #ifdef DBG_UTIL + Source + #endif + ) throw (RuntimeException) + { + DBG_ASSERT( Source.Source == m_xCloseable, "CloseableComponentImpl::disposing: where did this come from?" ); + DBG_ERROR( "CloseableComponentImpl::disposing: unreachable!" ); + // same reasoning for this assertion as in ->notifyClosing + } + + //======================================================================== + //= CloseableComponentImpl + //======================================================================== + DBG_NAME( CloseableComponent ) + //------------------------------------------------------------------------ + CloseableComponent::CloseableComponent( const Reference< XInterface >& _rxComponent ) + :m_pImpl( new CloseableComponentImpl( _rxComponent ) ) + { + DBG_CTOR( CloseableComponent, NULL ); + } + + //------------------------------------------------------------------------ + CloseableComponent::~CloseableComponent() + { + // close the component, deliver ownership to anybody who wants to veto the close + m_pImpl->nf_closeComponent(); + DBG_DTOR( CloseableComponent, NULL ); + } + +//............................................................................ +} // namespace utl +//............................................................................ diff --git a/unotools/source/processfactory/componentfactory.cxx b/unotools/source/processfactory/componentfactory.cxx new file mode 100644 index 000000000000..690cd86b8124 --- /dev/null +++ b/unotools/source/processfactory/componentfactory.cxx @@ -0,0 +1,189 @@ +/************************************************************************* + * + * 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: componentfactory.cxx,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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_unotools.hxx" + +#include <unotools/componentfactory.hxx> +#include <comphelper/processfactory.hxx> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> + +#ifndef _COM_SUN_STAR_REGISTRY_XREGISTRYKEY_HDL_ +#include <com/sun/star/registry/XRegistryKey.hpp> +#endif + +#include <cppuhelper/factory.hxx> + +#include <uno/environment.h> +#include <uno/mapping.hxx> + +#include <rtl/ustring.hxx> +#include <osl/module.h> + + + + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::registry; +using namespace ::rtl; + + +namespace utl +{ + +Reference< XInterface > getComponentInstance( + const OUString & rLibraryName, + const OUString & rImplementationName + ) +{ + Reference< XInterface > xI; + Reference< XMultiServiceFactory > xMSF = ::comphelper::getProcessServiceFactory(); + if ( xMSF.is() ) + xI = xMSF->createInstance( rImplementationName ); + if( !xI.is() ) + { + Reference< XSingleServiceFactory > xSSF = + loadLibComponentFactory( rLibraryName, rImplementationName, + Reference< XMultiServiceFactory >(), Reference< XRegistryKey >() ); + xI = xSSF->createInstance(); + } + return xI; +} + + +Reference< XSingleServiceFactory > loadLibComponentFactory( + const OUString & rLibName, + const OUString & rImplName, + const Reference< XMultiServiceFactory > & xSF, + const Reference< XRegistryKey > & xKey + ) +{ + Reference< XSingleServiceFactory > xRet; + + oslModule lib = osl_loadModule( rLibName.pData, SAL_LOADMODULE_LAZY | SAL_LOADMODULE_GLOBAL ); + if (lib) + { + void * pSym; + + // ========================= LATEST VERSION ========================= + OUString aGetEnvName( RTL_CONSTASCII_USTRINGPARAM(COMPONENT_GETENV) ); + if (pSym = osl_getSymbol( lib, aGetEnvName.pData )) + { + uno_Environment * pCurrentEnv = 0; + uno_Environment * pEnv = 0; + const sal_Char * pEnvTypeName = 0; + (*((component_getImplementationEnvironmentFunc)pSym))( &pEnvTypeName, &pEnv ); + + sal_Bool bNeedsMapping = + (pEnv || 0 != rtl_str_compare( pEnvTypeName, CPPU_CURRENT_LANGUAGE_BINDING_NAME )); + + OUString aEnvTypeName( OUString::createFromAscii( pEnvTypeName ) ); + + if (bNeedsMapping) + { + if (! pEnv) + uno_getEnvironment( &pEnv, aEnvTypeName.pData, 0 ); + if (pEnv) + { + OUString aCppEnvTypeName( RTL_CONSTASCII_USTRINGPARAM(CPPU_CURRENT_LANGUAGE_BINDING_NAME) ); + uno_getEnvironment( &pCurrentEnv, aCppEnvTypeName.pData, 0 ); + if (pCurrentEnv) + bNeedsMapping = (pEnv != pCurrentEnv); + } + } + + OUString aGetFactoryName( RTL_CONSTASCII_USTRINGPARAM(COMPONENT_GETFACTORY) ); + if (pSym = osl_getSymbol( lib, aGetFactoryName.pData )) + { + OString aImplName( OUStringToOString( rImplName, RTL_TEXTENCODING_ASCII_US ) ); + + if (bNeedsMapping) + { + if (pEnv && pCurrentEnv) + { + Mapping aCurrent2Env( pCurrentEnv, pEnv ); + Mapping aEnv2Current( pEnv, pCurrentEnv ); + + if (aCurrent2Env.is() && aEnv2Current.is()) + { + void * pSMgr = aCurrent2Env.mapInterface( + xSF.get(), ::getCppuType( (const Reference< XMultiServiceFactory > *)0 ) ); + void * pKey = aCurrent2Env.mapInterface( + xKey.get(), ::getCppuType( (const Reference< XRegistryKey > *)0 ) ); + + void * pSSF = (*((component_getFactoryFunc)pSym))( + aImplName.getStr(), pSMgr, pKey ); + + if (pKey) + (*pEnv->pExtEnv->releaseInterface)( pEnv->pExtEnv, pKey ); + if (pSMgr) + (*pEnv->pExtEnv->releaseInterface)( pEnv->pExtEnv, pSMgr ); + + if (pSSF) + { + aEnv2Current.mapInterface( + reinterpret_cast< void ** >( &xRet ), + pSSF, ::getCppuType( (const Reference< XSingleServiceFactory > *)0 ) ); + (*pEnv->pExtEnv->releaseInterface)( pEnv->pExtEnv, pSSF ); + } + } + } + } + else + { + XSingleServiceFactory * pRet = (XSingleServiceFactory *) + (*((component_getFactoryFunc)pSym))( + aImplName.getStr(), xSF.get(), xKey.get() ); + if (pRet) + { + xRet = pRet; + pRet->release(); + } + } + } + + if (pEnv) + (*pEnv->release)( pEnv ); + if (pCurrentEnv) + (*pCurrentEnv->release)( pCurrentEnv ); + } + + + if (! xRet.is()) + osl_unloadModule( lib ); + } + + return xRet; +} + +} // namespace utl diff --git a/unotools/source/processfactory/makefile.mk b/unotools/source/processfactory/makefile.mk new file mode 100644 index 000000000000..de27f67c982f --- /dev/null +++ b/unotools/source/processfactory/makefile.mk @@ -0,0 +1,54 @@ +#************************************************************************* +# +# 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.6 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General 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=..$/.. +PRJINC=..$/..$/inc +PRJNAME=unotools +TARGET=procfact + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings common for the whole project ----- + + +# --- Settings ---------------------------------- + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/util$/makefile.pmk + +# --- Files ------------------------------------- + +SLOFILES= $(SLO)$/processfactory.obj + +# --- Targets ---------------------------------- + +.INCLUDE : target.mk + diff --git a/unotools/source/processfactory/processfactory.cxx b/unotools/source/processfactory/processfactory.cxx new file mode 100644 index 000000000000..c8124bf106c8 --- /dev/null +++ b/unotools/source/processfactory/processfactory.cxx @@ -0,0 +1,57 @@ +/************************************************************************* + * + * 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: processfactory.cxx,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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_unotools.hxx" +#include <osl/mutex.hxx> +#include <unotools/processfactory.hxx> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> + +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace osl; + +namespace utl +{ + // just use the comphelper versions of both functions. The versions here in unotools will become obsolete + // from SRC610 on. + + void setProcessServiceFactory(const Reference< XMultiServiceFactory >& xSMgr) + { + ::comphelper::setProcessServiceFactory(xSMgr); + } + + Reference< XMultiServiceFactory > getProcessServiceFactory() + { + return ::comphelper::getProcessServiceFactory(); + } + +} // namesapce utl + diff --git a/unotools/source/property/makefile.mk b/unotools/source/property/makefile.mk new file mode 100644 index 000000000000..292ef8cad062 --- /dev/null +++ b/unotools/source/property/makefile.mk @@ -0,0 +1,52 @@ +#************************************************************************* +# +# 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.10 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General 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=..$/.. +PRJINC=..$/..$/inc +PRJNAME=unotools +TARGET=property + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ---------------------------------- + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/util$/makefile.pmk + +# --- Files ------------------------------------- + +SLOFILES= $(SLO)$/propertysetinfo.obj \ + $(SLO)$/propertysethelper.obj + +# --- Targets ---------------------------------- + +.INCLUDE : target.mk + diff --git a/unotools/source/property/propertysethelper.cxx b/unotools/source/property/propertysethelper.cxx new file mode 100644 index 000000000000..28dc143873d6 --- /dev/null +++ b/unotools/source/property/propertysethelper.cxx @@ -0,0 +1,304 @@ +/************************************************************************* + * + * 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: propertysethelper.cxx,v $ + * $Revision: 1.6 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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_unotools.hxx" +#include <tools/debug.hxx> + +#include "unotools/propertysetinfo.hxx" +#include "unotools/propertysethelper.hxx" + +/////////////////////////////////////////////////////////////////////// + +using namespace ::utl; +using namespace ::rtl; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::lang; + +namespace utl +{ +class PropertySetHelperImpl +{ +public: + PropertyMapEntry* find( const OUString& aName ) const throw(); + + PropertySetInfo* mpInfo; +}; +} + +PropertyMapEntry* PropertySetHelperImpl::find( const OUString& aName ) const throw() +{ + PropertyMap::const_iterator aIter = mpInfo->getPropertyMap()->find( aName ); + + if( mpInfo->getPropertyMap()->end() != aIter ) + { + return (*aIter).second; + } + else + { + return NULL; + } +} + +/////////////////////////////////////////////////////////////////////// + +PropertySetHelper::PropertySetHelper( utl::PropertySetInfo* pInfo ) throw() +{ + mp = new PropertySetHelperImpl; + mp->mpInfo = pInfo; + pInfo->acquire(); +} + +PropertySetHelper::~PropertySetHelper() throw() +{ + mp->mpInfo->release(); + delete mp; +} + +// XPropertySet +Reference< XPropertySetInfo > SAL_CALL PropertySetHelper::getPropertySetInfo( ) throw(RuntimeException) +{ + return mp->mpInfo; +} + +void SAL_CALL PropertySetHelper::setPropertyValue( const ::rtl::OUString& aPropertyName, const Any& aValue ) throw(UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException) +{ + PropertyMapEntry* aEntries[2]; + aEntries[0] = mp->find( aPropertyName ); + + if( NULL == aEntries[0] ) + throw UnknownPropertyException(); + + aEntries[1] = NULL; + + _setPropertyValues( (const PropertyMapEntry**)aEntries, &aValue ); +} + +Any SAL_CALL PropertySetHelper::getPropertyValue( const ::rtl::OUString& PropertyName ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException) +{ + PropertyMapEntry* aEntries[2]; + aEntries[0] = mp->find( PropertyName ); + + if( NULL == aEntries[0] ) + throw UnknownPropertyException(); + + aEntries[1] = NULL; + + Any aAny; + _getPropertyValues( (const PropertyMapEntry**)aEntries, &aAny ); + + return aAny; +} + +void SAL_CALL PropertySetHelper::addPropertyChangeListener( const ::rtl::OUString& /*aPropertyName*/, const Reference< XPropertyChangeListener >& /*xListener*/ ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException) +{ + // todo +} + +void SAL_CALL PropertySetHelper::removePropertyChangeListener( const ::rtl::OUString& /*aPropertyName*/, const Reference< XPropertyChangeListener >& /*aListener*/ ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException) +{ + // todo +} + +void SAL_CALL PropertySetHelper::addVetoableChangeListener( const ::rtl::OUString& /*PropertyName*/, const Reference< XVetoableChangeListener >& /*aListener*/ ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException) +{ + // todo +} + +void SAL_CALL PropertySetHelper::removeVetoableChangeListener( const ::rtl::OUString& /*PropertyName*/, const Reference< XVetoableChangeListener >& /*aListener*/ ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException) +{ + // todo +} + +// XMultiPropertySet +void SAL_CALL PropertySetHelper::setPropertyValues( const Sequence< ::rtl::OUString >& aPropertyNames, const Sequence< Any >& aValues ) throw(PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException) +{ + const sal_Int32 nCount = aPropertyNames.getLength(); + + if( nCount != aValues.getLength() ) + throw IllegalArgumentException(); + + if( nCount ) + { + PropertyMapEntry** pEntries = new PropertyMapEntry*[nCount+1]; + const OUString* pNames = aPropertyNames.getConstArray(); + + sal_Bool bUnknown = sal_False; + sal_Int32 n; + for( n = 0; !bUnknown && ( n < nCount ); n++, pNames++ ) + { + pEntries[n] = mp->find( *pNames ); + bUnknown = NULL == pEntries[n]; + } + + if( !bUnknown ) + _setPropertyValues( (const PropertyMapEntry**)pEntries, aValues.getConstArray() ); + + delete [] pEntries; + + if( bUnknown ) + throw UnknownPropertyException(); + } +} + +Sequence< Any > SAL_CALL PropertySetHelper::getPropertyValues( const Sequence< ::rtl::OUString >& aPropertyNames ) throw(RuntimeException) +{ + const sal_Int32 nCount = aPropertyNames.getLength(); + + Sequence< Any > aValues; + if( nCount ) + { + PropertyMapEntry** pEntries = new PropertyMapEntry*[nCount+1]; + const OUString* pNames = aPropertyNames.getConstArray(); + + sal_Bool bUnknown = sal_False; + sal_Int32 n; + for( n = 0; !bUnknown && ( n < nCount ); n++, pNames++ ) + { + pEntries[n] = mp->find( *pNames ); + bUnknown = NULL == pEntries[n]; + } + + if( !bUnknown ) + _getPropertyValues( (const PropertyMapEntry**)pEntries, aValues.getArray() ); + + delete [] pEntries; + + if( bUnknown ) + throw UnknownPropertyException(); + } + + return aValues; +} + +void SAL_CALL PropertySetHelper::addPropertiesChangeListener( const Sequence< ::rtl::OUString >& /*aPropertyNames*/, const Reference< XPropertiesChangeListener >& /*xListener*/ ) throw(RuntimeException) +{ + // todo +} + +void SAL_CALL PropertySetHelper::removePropertiesChangeListener( const Reference< XPropertiesChangeListener >& /*xListener*/ ) throw(RuntimeException) +{ + // todo +} + +void SAL_CALL PropertySetHelper::firePropertiesChangeEvent( const Sequence< ::rtl::OUString >& /*aPropertyNames*/, const Reference< XPropertiesChangeListener >& /*xListener*/ ) throw(RuntimeException) +{ + // todo +} + +// XPropertyState +PropertyState SAL_CALL PropertySetHelper::getPropertyState( const ::rtl::OUString& PropertyName ) throw(UnknownPropertyException, RuntimeException) +{ + PropertyMapEntry* aEntries[2]; + + aEntries[0] = mp->find( PropertyName ); + if( aEntries[0] == NULL ) + throw UnknownPropertyException(); + + aEntries[1] = NULL; + + PropertyState aState; + _getPropertyStates( (const PropertyMapEntry**)aEntries, &aState ); + + return aState; +} + +Sequence< PropertyState > SAL_CALL PropertySetHelper::getPropertyStates( const Sequence< ::rtl::OUString >& aPropertyName ) throw(UnknownPropertyException, RuntimeException) +{ + const sal_Int32 nCount = aPropertyName.getLength(); + + Sequence< PropertyState > aStates( nCount ); + + if( nCount ) + { + const OUString* pNames = aPropertyName.getConstArray(); + + sal_Bool bUnknown = sal_False; + + PropertyMapEntry** pEntries = new PropertyMapEntry*[nCount+1]; + + sal_Int32 n; + for( n = 0; !bUnknown && (n < nCount); n++, pNames++ ) + { + pEntries[n] = mp->find( *pNames ); + bUnknown = NULL == pEntries[n]; + } + + pEntries[nCount] = NULL; + + if( !bUnknown ) + _getPropertyStates( (const PropertyMapEntry**)pEntries, aStates.getArray() ); + + delete [] pEntries; + + if( bUnknown ) + throw UnknownPropertyException(); + } + + return aStates; +} + +void SAL_CALL PropertySetHelper::setPropertyToDefault( const ::rtl::OUString& PropertyName ) throw(UnknownPropertyException, RuntimeException) +{ + PropertyMapEntry *pEntry = mp->find( PropertyName ); + if( NULL == pEntry ) + throw UnknownPropertyException(); + + _setPropertyToDefault( pEntry ); +} + +Any SAL_CALL PropertySetHelper::getPropertyDefault( const ::rtl::OUString& aPropertyName ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException) +{ + PropertyMapEntry* pEntry = mp->find( aPropertyName ); + if( NULL == pEntry ) + throw UnknownPropertyException(); + + return _getPropertyDefault( pEntry ); +} + +void PropertySetHelper::_getPropertyStates( const utl::PropertyMapEntry** /*ppEntries*/, PropertyState* /*pStates*/ ) throw(UnknownPropertyException ) +{ + DBG_ERROR( "you have to implement this yourself!" ); +} + +void PropertySetHelper::_setPropertyToDefault( const utl::PropertyMapEntry* /*pEntry*/ ) throw(UnknownPropertyException ) +{ + DBG_ERROR( "you have to implement this yourself!" ); +} + +Any PropertySetHelper::_getPropertyDefault( const utl::PropertyMapEntry* /*pEntry*/ ) throw(UnknownPropertyException, WrappedTargetException ) +{ + DBG_ERROR( "you have to implement this yourself!" ); + + Any aAny; + return aAny; +} diff --git a/unotools/source/property/propertysetinfo.cxx b/unotools/source/property/propertysetinfo.cxx new file mode 100644 index 000000000000..b8b5f8bb5125 --- /dev/null +++ b/unotools/source/property/propertysetinfo.cxx @@ -0,0 +1,202 @@ +/************************************************************************* + * + * 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: propertysetinfo.cxx,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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_unotools.hxx" +#include <tools/debug.hxx> + +#include "unotools/propertysetinfo.hxx" + +using namespace ::utl; +using namespace ::rtl; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::lang; + +namespace utl +{ +class PropertyMapImpl +{ +public: + PropertyMapImpl() throw(); + virtual ~PropertyMapImpl() throw(); + + void add( PropertyMapEntry* pMap ) throw(); + void remove( const OUString& aName ) throw(); + + Sequence< Property > getProperties() throw(); + + const PropertyMap* getPropertyMap() const throw(); + + Property getPropertyByName( const OUString& aName ) throw( UnknownPropertyException ); + sal_Bool hasPropertyByName( const OUString& aName ) throw(); + +private: + PropertyMap maPropertyMap; + Sequence< Property > maProperties; +}; +} + +PropertyMapImpl::PropertyMapImpl() throw() +{ +} + +PropertyMapImpl::~PropertyMapImpl() throw() +{ +} + +void PropertyMapImpl::add( PropertyMapEntry* pMap ) throw() +{ + while( pMap->mpName ) + { + OUString aName( pMap->mpName, pMap->mnNameLen, RTL_TEXTENCODING_ASCII_US ); + +#ifndef PRODUCT + PropertyMap::iterator aIter = maPropertyMap.find( aName ); + if( aIter != maPropertyMap.end() ) + { + DBG_ERROR( "Warning: PropertyMapEntry added twice, possible error!" ); + } +#endif + if( NULL == pMap->mpType ) + { + DBG_ERROR( "No type in PropertyMapEntry!" ); + pMap->mpType = &::getCppuType((const sal_Int32*)0); + } + + maPropertyMap[aName] = pMap; + + if( maProperties.getLength() ) + maProperties.realloc( 0 ); + + pMap = &pMap[1]; + } +} + +void PropertyMapImpl::remove( const OUString& aName ) throw() +{ + maPropertyMap.erase( aName ); + + if( maProperties.getLength() ) + maProperties.realloc( 0 ); +} + +Sequence< Property > PropertyMapImpl::getProperties() throw() +{ + // maybe we have to generate the properties after + // a change in the property map or at first call + // to getProperties + if( maProperties.getLength() != (sal_Int32)maPropertyMap.size() ) + { + maProperties = Sequence< Property >( maPropertyMap.size() ); + Property* pProperties = maProperties.getArray(); + + PropertyMap::iterator aIter = maPropertyMap.begin(); + const PropertyMap::iterator aEnd = maPropertyMap.end(); + while( aIter != aEnd ) + { + PropertyMapEntry* pEntry = (*aIter).second; + + pProperties->Name = OUString( pEntry->mpName, pEntry->mnNameLen, RTL_TEXTENCODING_ASCII_US ); + pProperties->Handle = pEntry->mnWhich; + pProperties->Type = *pEntry->mpType; + pProperties->Attributes = pEntry->mnFlags; + pProperties++; + aIter++; + } + } + + return maProperties; +} + +const PropertyMap* PropertyMapImpl::getPropertyMap() const throw() +{ + return &maPropertyMap; +} + +Property PropertyMapImpl::getPropertyByName( const OUString& aName ) throw( UnknownPropertyException ) +{ + PropertyMap::iterator aIter = maPropertyMap.find( aName ); + + if( maPropertyMap.end() == aIter ) + throw UnknownPropertyException(); + + PropertyMapEntry* pEntry = (*aIter).second; + + return Property( aName, pEntry->mnWhich, *pEntry->mpType, pEntry->mnFlags ); +} + +sal_Bool PropertyMapImpl::hasPropertyByName( const OUString& aName ) throw() +{ + return maPropertyMap.find( aName ) != maPropertyMap.end(); +} + +/////////////////////////////////////////////////////////////////////// + +PropertySetInfo::PropertySetInfo() throw() +{ + mpMap = new PropertyMapImpl(); +} + +PropertySetInfo::~PropertySetInfo() throw() +{ + delete mpMap; +} + +void PropertySetInfo::add( PropertyMapEntry* pMap ) throw() +{ + mpMap->add( pMap ); +} + +void PropertySetInfo::remove( const rtl::OUString& aName ) throw() +{ + mpMap->remove( aName ); +} + +Sequence< ::com::sun::star::beans::Property > SAL_CALL PropertySetInfo::getProperties() throw(::com::sun::star::uno::RuntimeException) +{ + return mpMap->getProperties(); +} + +Property SAL_CALL PropertySetInfo::getPropertyByName( const ::rtl::OUString& aName ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException) +{ + return mpMap->getPropertyByName( aName ); +} + +sal_Bool SAL_CALL PropertySetInfo::hasPropertyByName( const ::rtl::OUString& Name ) throw(::com::sun::star::uno::RuntimeException) +{ + return mpMap->hasPropertyByName( Name ); +} + +const PropertyMap* PropertySetInfo::getPropertyMap() const throw() +{ + return mpMap->getPropertyMap(); +} diff --git a/unotools/source/streaming/makefile.mk b/unotools/source/streaming/makefile.mk new file mode 100644 index 000000000000..db53632a7170 --- /dev/null +++ b/unotools/source/streaming/makefile.mk @@ -0,0 +1,52 @@ +#************************************************************************* +# +# 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.8 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General 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=..$/.. +PRJINC=..$/..$/inc +PRJNAME=unotools +TARGET=streaming + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ---------------------------------- + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/util$/makefile.pmk + +# --- Files ------------------------------------- + +SLOFILES= $(SLO)$/streamhelper.obj \ + $(SLO)$/streamwrap.obj + +# --- Targets ---------------------------------- + +.INCLUDE : target.mk + diff --git a/unotools/source/streaming/streamhelper.cxx b/unotools/source/streaming/streamhelper.cxx new file mode 100644 index 000000000000..f21872c67a5b --- /dev/null +++ b/unotools/source/streaming/streamhelper.cxx @@ -0,0 +1,207 @@ +/************************************************************************* + * + * 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: streamhelper.cxx,v $ + * $Revision: 1.8 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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_unotools.hxx" +#include <unotools/streamhelper.hxx> +#include <tools/debug.hxx> + +namespace utl +{ + +//------------------------------------------------------------------------------ +void SAL_CALL OInputStreamHelper::acquire() throw () +{ + InputStreamHelper_Base::acquire(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OInputStreamHelper::release() throw () +{ + InputStreamHelper_Base::release(); +} + +//------------------------------------------------------------------------------ +sal_Int32 SAL_CALL OInputStreamHelper::readBytes(staruno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead) + throw(stario::NotConnectedException, stario::BufferSizeExceededException, stario::IOException, staruno::RuntimeException) +{ + if (!m_xLockBytes.Is()) + throw stario::NotConnectedException(::rtl::OUString(), static_cast<staruno::XWeak*>(this)); + + if (nBytesToRead < 0) + throw stario::BufferSizeExceededException(::rtl::OUString(), static_cast<staruno::XWeak*>(this)); + + ::osl::MutexGuard aGuard( m_aMutex ); + aData.realloc(nBytesToRead); + + sal_Size nRead; + ErrCode nError = m_xLockBytes->ReadAt(m_nActPos, (void*)aData.getArray(), nBytesToRead, &nRead); + // FIXME nRead could be truncated on 64-bit arches + m_nActPos += (sal_uInt32)nRead; + + if (nError != ERRCODE_NONE) + throw stario::IOException(::rtl::OUString(), static_cast<staruno::XWeak*>(this)); + + // adjust sequence if data read is lower than the desired data + if (nRead < (sal_uInt32)nBytesToRead) + aData.realloc( nRead ); + + return nRead; +} + +void SAL_CALL OInputStreamHelper::seek( sal_Int64 location ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + // cast is truncating, but position would be truncated as soon as + // put into SvLockBytes anyway + m_nActPos = sal::static_int_cast<sal_uInt32>(location); +} + +sal_Int64 SAL_CALL OInputStreamHelper::getPosition( ) throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException) +{ + return m_nActPos; +} + +sal_Int64 SAL_CALL OInputStreamHelper::getLength( ) throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException) +{ + if (!m_xLockBytes.Is()) + return 0; + + ::osl::MutexGuard aGuard( m_aMutex ); + SvLockBytesStat aStat; + m_xLockBytes->Stat( &aStat, SVSTATFLAG_DEFAULT ); + return aStat.nSize; +} + +//------------------------------------------------------------------------------ +sal_Int32 SAL_CALL OInputStreamHelper::readSomeBytes(staruno::Sequence< sal_Int8 >& aData, + sal_Int32 nMaxBytesToRead) + throw (stario::NotConnectedException, stario::BufferSizeExceededException, stario::IOException, staruno::RuntimeException) +{ + // read all data desired + return readBytes(aData, nMaxBytesToRead); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OInputStreamHelper::skipBytes(sal_Int32 nBytesToSkip) + throw (stario::NotConnectedException, stario::BufferSizeExceededException, stario::IOException, staruno::RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + if (!m_xLockBytes.Is()) + throw stario::NotConnectedException(::rtl::OUString(), static_cast<staruno::XWeak*>(this)); + + if (nBytesToSkip < 0) + throw stario::BufferSizeExceededException(::rtl::OUString(), static_cast<staruno::XWeak*>(this)); + + m_nActPos += nBytesToSkip; +} + +//------------------------------------------------------------------------------ +sal_Int32 SAL_CALL OInputStreamHelper::available() + throw (stario::NotConnectedException, stario::IOException, staruno::RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + if (!m_xLockBytes.Is()) + throw stario::NotConnectedException(::rtl::OUString(), static_cast<staruno::XWeak*>(this)); + + return m_nAvailable; +} + +//------------------------------------------------------------------------------ +void SAL_CALL OInputStreamHelper::closeInput() + throw (stario::NotConnectedException, stario::IOException, staruno::RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + if (!m_xLockBytes.Is()) + throw stario::NotConnectedException(::rtl::OUString(), static_cast<staruno::XWeak*>(this)); + + m_xLockBytes = NULL; +} + +/*************************************************************************/ +//------------------------------------------------------------------------------ +void SAL_CALL OOutputStreamHelper::acquire() throw () +{ + OutputStreamHelper_Base::acquire(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OOutputStreamHelper::release() throw () +{ + OutputStreamHelper_Base::release(); +} +// stario::XOutputStream +//------------------------------------------------------------------------------ +void SAL_CALL OOutputStreamHelper::writeBytes(const staruno::Sequence< sal_Int8 >& aData) + throw (stario::NotConnectedException, stario::BufferSizeExceededException, stario::IOException, staruno::RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + if (!m_xLockBytes.Is()) + throw stario::NotConnectedException(::rtl::OUString(), static_cast<staruno::XWeak*>(this)); + + sal_Size nWritten; + ErrCode nError = m_xLockBytes->WriteAt( m_nActPos, aData.getConstArray(), aData.getLength(), &nWritten ); + // FIXME nWritten could be truncated on 64-bit arches + m_nActPos += (sal_uInt32)nWritten; + + if (nError != ERRCODE_NONE || + sal::static_int_cast<sal_Int32>(nWritten) != aData.getLength()) + { + throw stario::IOException(::rtl::OUString(),static_cast<staruno::XWeak*>(this)); + } +} + +//------------------------------------------------------------------ +void SAL_CALL OOutputStreamHelper::flush() + throw (stario::NotConnectedException, stario::BufferSizeExceededException, stario::IOException, staruno::RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + if (!m_xLockBytes.Is()) + throw stario::NotConnectedException(::rtl::OUString(), static_cast<staruno::XWeak*>(this)); + + ErrCode nError = m_xLockBytes->Flush(); + if (nError != ERRCODE_NONE) + throw stario::IOException(::rtl::OUString(),static_cast<staruno::XWeak*>(this)); +} + +//------------------------------------------------------------------ +void SAL_CALL OOutputStreamHelper::closeOutput( ) + throw(stario::NotConnectedException, stario::BufferSizeExceededException, stario::IOException, staruno::RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + if (!m_xLockBytes.Is()) + throw stario::NotConnectedException(::rtl::OUString(), static_cast<staruno::XWeak*>(this)); + + m_xLockBytes = NULL; +} + +} // namespace utl + + diff --git a/unotools/source/streaming/streamwrap.cxx b/unotools/source/streaming/streamwrap.cxx new file mode 100644 index 000000000000..b9f03b022d6e --- /dev/null +++ b/unotools/source/streaming/streamwrap.cxx @@ -0,0 +1,382 @@ +/************************************************************************* + * + * 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: streamwrap.cxx,v $ + * $Revision: 1.8 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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_unotools.hxx" +#include <unotools/streamwrap.hxx> +#include <tools/stream.hxx> +#include <tools/debug.hxx> + +namespace utl +{ + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::lang; + +//================================================================== +//= OInputStreamWrapper +//================================================================== +DBG_NAME(OInputStreamWrapper) +//------------------------------------------------------------------ +OInputStreamWrapper::OInputStreamWrapper( SvStream& _rStream ) + :m_pSvStream(&_rStream) + ,m_bSvStreamOwner(sal_False) +{ + DBG_CTOR(OInputStreamWrapper,NULL); + +} + +//------------------------------------------------------------------ +OInputStreamWrapper::OInputStreamWrapper( SvStream* pStream, sal_Bool bOwner ) + :m_pSvStream( pStream ) + ,m_bSvStreamOwner( bOwner ) +{ + DBG_CTOR(OInputStreamWrapper,NULL); + +} + +//------------------------------------------------------------------ +OInputStreamWrapper::~OInputStreamWrapper() +{ + if( m_bSvStreamOwner ) + delete m_pSvStream; + + DBG_DTOR(OInputStreamWrapper,NULL); +} + +//------------------------------------------------------------------------------ +sal_Int32 SAL_CALL OInputStreamWrapper::readBytes(staruno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead) + throw( stario::NotConnectedException, stario::BufferSizeExceededException, staruno::RuntimeException ) +{ + checkConnected(); + + if (nBytesToRead < 0) + throw stario::BufferSizeExceededException(::rtl::OUString(),static_cast<staruno::XWeak*>(this)); + + ::osl::MutexGuard aGuard( m_aMutex ); + + aData.realloc(nBytesToRead); + + sal_uInt32 nRead = m_pSvStream->Read((void*)aData.getArray(), nBytesToRead); + checkError(); + + // Wenn gelesene Zeichen < MaxLength, staruno::Sequence anpassen + if (nRead < (sal_uInt32)nBytesToRead) + aData.realloc( nRead ); + + return nRead; +} + +//------------------------------------------------------------------------------ +sal_Int32 SAL_CALL OInputStreamWrapper::readSomeBytes(staruno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead) throw( stario::NotConnectedException, stario::BufferSizeExceededException, staruno::RuntimeException ) +{ + checkError(); + + if (nMaxBytesToRead < 0) + throw stario::BufferSizeExceededException(::rtl::OUString(),static_cast<staruno::XWeak*>(this)); + + if (m_pSvStream->IsEof()) + { + aData.realloc(0); + return 0; + } + else + return readBytes(aData, nMaxBytesToRead); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OInputStreamWrapper::skipBytes(sal_Int32 nBytesToSkip) throw( stario::NotConnectedException, stario::BufferSizeExceededException, staruno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkError(); + +#ifdef DBG_UTIL + sal_uInt32 nCurrentPos = m_pSvStream->Tell(); +#endif + + m_pSvStream->SeekRel(nBytesToSkip); + checkError(); + +#ifdef DBG_UTIL + nCurrentPos = m_pSvStream->Tell(); +#endif +} + +//------------------------------------------------------------------------------ +sal_Int32 SAL_CALL OInputStreamWrapper::available() throw( stario::NotConnectedException, staruno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkConnected(); + + sal_uInt32 nPos = m_pSvStream->Tell(); + checkError(); + + m_pSvStream->Seek(STREAM_SEEK_TO_END); + checkError(); + + sal_Int32 nAvailable = (sal_Int32)m_pSvStream->Tell() - nPos; + m_pSvStream->Seek(nPos); + checkError(); + + return nAvailable; +} + +//------------------------------------------------------------------------------ +void SAL_CALL OInputStreamWrapper::closeInput() throw( stario::NotConnectedException, staruno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkConnected(); + + if (m_bSvStreamOwner) + delete m_pSvStream; + + m_pSvStream = NULL; +} + +//------------------------------------------------------------------------------ +void OInputStreamWrapper::checkConnected() const +{ + if (!m_pSvStream) + throw stario::NotConnectedException(::rtl::OUString(), const_cast<staruno::XWeak*>(static_cast<const staruno::XWeak*>(this))); +} + +//------------------------------------------------------------------------------ +void OInputStreamWrapper::checkError() const +{ + checkConnected(); + + if (m_pSvStream->SvStream::GetError() != ERRCODE_NONE) + // TODO: really evaluate the error + throw stario::NotConnectedException(::rtl::OUString(), const_cast<staruno::XWeak*>(static_cast<const staruno::XWeak*>(this))); +} + +//================================================================== +//= OSeekableInputStreamWrapper +//================================================================== +//------------------------------------------------------------------------------ +OSeekableInputStreamWrapper::OSeekableInputStreamWrapper(SvStream& _rStream) +{ + SetStream( &_rStream, FALSE ); +} + +//------------------------------------------------------------------------------ +OSeekableInputStreamWrapper::OSeekableInputStreamWrapper(SvStream* _pStream, sal_Bool _bOwner) +{ + SetStream( _pStream, _bOwner ); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OSeekableInputStreamWrapper::seek( sal_Int64 _nLocation ) throw (IllegalArgumentException, IOException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkConnected(); + + m_pSvStream->Seek((sal_uInt32)_nLocation); + checkError(); +} + +//------------------------------------------------------------------------------ +sal_Int64 SAL_CALL OSeekableInputStreamWrapper::getPosition( ) throw (IOException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkConnected(); + + sal_uInt32 nPos = m_pSvStream->Tell(); + checkError(); + return (sal_Int64)nPos; +} + +//------------------------------------------------------------------------------ +sal_Int64 SAL_CALL OSeekableInputStreamWrapper::getLength( ) throw (IOException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkConnected(); + + sal_uInt32 nCurrentPos = m_pSvStream->Tell(); + checkError(); + + m_pSvStream->Seek(STREAM_SEEK_TO_END); + sal_uInt32 nEndPos = m_pSvStream->Tell(); + m_pSvStream->Seek(nCurrentPos); + + checkError(); + + return (sal_Int64)nEndPos; +} + +//================================================================== +//= OOutputStreamWrapper +//================================================================== +//------------------------------------------------------------------------------ +void SAL_CALL OOutputStreamWrapper::writeBytes(const staruno::Sequence< sal_Int8 >& aData) throw( stario::NotConnectedException, stario::BufferSizeExceededException, staruno::RuntimeException ) +{ + sal_uInt32 nWritten = rStream.Write(aData.getConstArray(),aData.getLength()); + ErrCode err = rStream.GetError(); + if ( (ERRCODE_NONE != err) + || (nWritten != (sal_uInt32)aData.getLength()) + ) + { + throw stario::BufferSizeExceededException(::rtl::OUString(),static_cast<staruno::XWeak*>(this)); + } +} + +//------------------------------------------------------------------ +void SAL_CALL OOutputStreamWrapper::flush() throw( stario::NotConnectedException, stario::BufferSizeExceededException, staruno::RuntimeException ) +{ + rStream.Flush(); + checkError(); +} + +//------------------------------------------------------------------ +void SAL_CALL OOutputStreamWrapper::closeOutput() throw( stario::NotConnectedException, stario::BufferSizeExceededException, staruno::RuntimeException ) +{ +} + +//------------------------------------------------------------------------------ +void OOutputStreamWrapper::checkError() const +{ + if (rStream.GetError() != ERRCODE_NONE) + // TODO: really evaluate the error + throw stario::NotConnectedException(::rtl::OUString(), const_cast<staruno::XWeak*>(static_cast<const staruno::XWeak*>(this))); +} + +//================================================================== +//= OSeekableOutputStreamWrapper +//================================================================== +//------------------------------------------------------------------------------ +OSeekableOutputStreamWrapper::OSeekableOutputStreamWrapper(SvStream& _rStream) + :OOutputStreamWrapper(_rStream) +{ +} + +//------------------------------------------------------------------------------ +Any SAL_CALL OSeekableOutputStreamWrapper::queryInterface( const Type& _rType ) throw (RuntimeException) +{ + Any aReturn = OOutputStreamWrapper::queryInterface(_rType); + if (!aReturn.hasValue()) + aReturn = OSeekableOutputStreamWrapper_Base::queryInterface(_rType); + return aReturn; +} + +//------------------------------------------------------------------------------ +void SAL_CALL OSeekableOutputStreamWrapper::acquire( ) throw () +{ + OOutputStreamWrapper::acquire(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OSeekableOutputStreamWrapper::release( ) throw () +{ + OOutputStreamWrapper::release(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OSeekableOutputStreamWrapper::seek( sal_Int64 _nLocation ) throw (IllegalArgumentException, IOException, RuntimeException) +{ + rStream.Seek((sal_uInt32)_nLocation); + checkError(); +} + +//------------------------------------------------------------------------------ +sal_Int64 SAL_CALL OSeekableOutputStreamWrapper::getPosition( ) throw (IOException, RuntimeException) +{ + sal_uInt32 nPos = rStream.Tell(); + checkError(); + return (sal_Int64)nPos; +} + +//------------------------------------------------------------------------------ +sal_Int64 SAL_CALL OSeekableOutputStreamWrapper::getLength( ) throw (IOException, RuntimeException) +{ + sal_uInt32 nCurrentPos = rStream.Tell(); + checkError(); + + rStream.Seek(STREAM_SEEK_TO_END); + sal_uInt32 nEndPos = rStream.Tell(); + rStream.Seek(nCurrentPos); + + checkError(); + + return (sal_Int64)nEndPos; +} + +//------------------------------------------------------------------------------ +OStreamWrapper::OStreamWrapper(SvStream& _rStream) +{ + SetStream( &_rStream, FALSE ); +} + +//------------------------------------------------------------------------------ +::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL OStreamWrapper::getInputStream( ) throw (::com::sun::star::uno::RuntimeException) +{ + return this; +} + +//------------------------------------------------------------------------------ +::com::sun::star::uno::Reference< ::com::sun::star::io::XOutputStream > SAL_CALL OStreamWrapper::getOutputStream( ) throw (::com::sun::star::uno::RuntimeException) +{ + return this; +} + +//------------------------------------------------------------------------------ +void SAL_CALL OStreamWrapper::writeBytes(const staruno::Sequence< sal_Int8 >& aData) throw(stario::NotConnectedException, stario::BufferSizeExceededException, staruno::RuntimeException) +{ + sal_uInt32 nWritten = m_pSvStream->Write(aData.getConstArray(),aData.getLength()); + ErrCode err = m_pSvStream->GetError(); + if ( (ERRCODE_NONE != err) + || (nWritten != (sal_uInt32)aData.getLength()) + ) + { + throw stario::BufferSizeExceededException(::rtl::OUString(),static_cast<staruno::XWeak*>(this)); + } +} + +//------------------------------------------------------------------------------ +void SAL_CALL OStreamWrapper::flush() throw(stario::NotConnectedException, stario::BufferSizeExceededException, staruno::RuntimeException) +{ + m_pSvStream->Flush(); + if (m_pSvStream->GetError() != ERRCODE_NONE) + throw stario::NotConnectedException(::rtl::OUString(),static_cast<staruno::XWeak*>(this)); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OStreamWrapper::closeOutput() throw(stario::NotConnectedException, stario::BufferSizeExceededException, staruno::RuntimeException) +{ +} + +//------------------------------------------------------------------------------ +void SAL_CALL OStreamWrapper::truncate() throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException) +{ + m_pSvStream->SetStreamSize(0); +} + +} // namespace utl + diff --git a/unotools/source/ucbhelper/XTempFile.hxx b/unotools/source/ucbhelper/XTempFile.hxx new file mode 100644 index 000000000000..34aa18f04829 --- /dev/null +++ b/unotools/source/ucbhelper/XTempFile.hxx @@ -0,0 +1,156 @@ +/************************************************************************* + * + * 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: XTempFile.hxx,v $ + * $Revision: 1.11 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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 _XTEMPFILE_HXX_ +#define _XTEMPFILE_HXX_ + +#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/XTempFile.hpp> +#include <com/sun/star/io/XTruncate.hpp> +#include <com/sun/star/lang/XSingleComponentFactory.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <cppuhelper/implbase5.hxx> +#ifndef _CPPUHELPER_PROPERTYSETMIXIN_HXX_ +#include <cppuhelper/propertysetmixin.hxx> +#endif +#include <osl/mutex.hxx> + +class SvStream; +namespace utl { class TempFile; } + +typedef ::cppu::WeakImplHelper5< ::com::sun::star::io::XTempFile + , ::com::sun::star::io::XInputStream + , ::com::sun::star::io::XOutputStream + , ::com::sun::star::io::XTruncate + , ::com::sun::star::lang::XServiceInfo + > + OTempFileBase; + +class OTempFileService : + public OTempFileBase, + public ::cppu::PropertySetMixin< ::com::sun::star::io::XTempFile > +{ +protected: + ::utl::TempFile* mpTempFile; + ::osl::Mutex maMutex; + SvStream* mpStream; + sal_Bool mbRemoveFile; + sal_Bool mbInClosed; + sal_Bool mbOutClosed; + + sal_Int64 mnCachedPos; + sal_Bool mbHasCachedPos; + + void checkError () const; + void checkConnected (); + +public: + OTempFileService (::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > const & context); + + //Methods + // 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 + 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); + + // XTempFile + virtual ::sal_Bool SAL_CALL getRemoveFile() + throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setRemoveFile( ::sal_Bool _removefile ) + throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getUri() + throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getResourceName() + 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( ) + 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); + // 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::BufferSizeExceededException, ::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); + // 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() + throw (::com::sun::star::io::IOException, ::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); + + //::com::sun::star::uno::Reference < ::com::sun::star::uno::XInterface > SAL_CALL XTempFile_createInstance( ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > const & context); + 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::XSingleComponentFactory > createServiceFactory_Static( com::sun::star::uno::Reference < com::sun::star::lang::XMultiServiceFactory > const & rServiceFactory ); + +private: + OTempFileService( OTempFileService & ); + virtual ~OTempFileService (); + +}; +#endif diff --git a/unotools/source/ucbhelper/localfilehelper.cxx b/unotools/source/ucbhelper/localfilehelper.cxx new file mode 100644 index 000000000000..81ee866eda2b --- /dev/null +++ b/unotools/source/ucbhelper/localfilehelper.cxx @@ -0,0 +1,245 @@ +/************************************************************************* + * + * 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: localfilehelper.cxx,v $ + * $Revision: 1.19 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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_unotools.hxx" +#include <com/sun/star/sdbc/XResultSet.hpp> +#include <com/sun/star/ucb/XContentAccess.hpp> +#include <com/sun/star/ucb/CommandAbortedException.hpp> + +#include <unotools/localfilehelper.hxx> +#include <ucbhelper/fileidentifierconverter.hxx> +#include <ucbhelper/contentbroker.hxx> +#include <rtl/ustring.hxx> +#include <osl/file.hxx> +#include <tools/debug.hxx> +#include <tools/list.hxx> +#include <tools/urlobj.hxx> +#include <ucbhelper/content.hxx> + +using namespace ::osl; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::ucb; + +namespace utl +{ + +sal_Bool LocalFileHelper::ConvertSystemPathToURL( const String& rName, const String& rBaseURL, String& rReturn ) +{ + rReturn = ::rtl::OUString(); + + ::ucbhelper::ContentBroker* pBroker = ::ucbhelper::ContentBroker::get(); + if ( !pBroker ) + { + rtl::OUString aRet; + if ( FileBase::getFileURLFromSystemPath( rName, aRet ) == FileBase::E_None ) + rReturn = aRet; + } + else + { + ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContentProviderManager > xManager = + pBroker->getContentProviderManagerInterface(); + try + { + rReturn = ::ucbhelper::getFileURLFromSystemPath( xManager, rBaseURL, rName ); + } + catch ( ::com::sun::star::uno::RuntimeException& ) + { + return sal_False; + } + } + + return ( rReturn.Len() != 0 ); +} + +sal_Bool LocalFileHelper::ConvertURLToSystemPath( const String& rName, String& rReturn ) +{ + rReturn = ::rtl::OUString(); + ::ucbhelper::ContentBroker* pBroker = ::ucbhelper::ContentBroker::get(); + if ( !pBroker ) + { + rtl::OUString aRet; + if( FileBase::getSystemPathFromFileURL( rName, aRet ) == FileBase::E_None ) + rReturn = aRet; + } + else + { + ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContentProviderManager > xManager = + pBroker->getContentProviderManagerInterface(); + try + { + rReturn = ::ucbhelper::getSystemPathFromFileURL( xManager, rName ); + } + catch ( ::com::sun::star::uno::RuntimeException& ) + { + } + } + + return ( rReturn.Len() != 0 ); +} + +sal_Bool LocalFileHelper::ConvertPhysicalNameToURL( const String& rName, String& rReturn ) +{ + rReturn = ::rtl::OUString(); + ::ucbhelper::ContentBroker* pBroker = ::ucbhelper::ContentBroker::get(); + if ( !pBroker ) + { + rtl::OUString aRet; + if ( FileBase::getFileURLFromSystemPath( rName, aRet ) == FileBase::E_None ) + rReturn = aRet; + } + else + { + ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContentProviderManager > xManager = + pBroker->getContentProviderManagerInterface(); + + try + { + rtl::OUString aBase( ::ucbhelper::getLocalFileURL( xManager ) ); + rReturn = ::ucbhelper::getFileURLFromSystemPath( xManager, aBase, rName ); + } + catch ( ::com::sun::star::uno::RuntimeException& ) + { + } + } + + return ( rReturn.Len() != 0 ); +} + +sal_Bool LocalFileHelper::ConvertURLToPhysicalName( const String& rName, String& rReturn ) +{ + rReturn = ::rtl::OUString(); + ::ucbhelper::ContentBroker* pBroker = ::ucbhelper::ContentBroker::get(); + if ( !pBroker ) + { + ::rtl::OUString aRet; + if ( FileBase::getSystemPathFromFileURL( rName, aRet ) == FileBase::E_None ) + rReturn = aRet; + } + else + { + ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContentProviderManager > xManager = + pBroker->getContentProviderManagerInterface(); + try + { + INetURLObject aObj( rName ); + INetURLObject aLocal( ::ucbhelper::getLocalFileURL( xManager ) ); + if ( aObj.GetProtocol() == aLocal.GetProtocol() ) + rReturn = ::ucbhelper::getSystemPathFromFileURL( xManager, rName ); + } + catch ( ::com::sun::star::uno::RuntimeException& ) + { + } + } + + return ( rReturn.Len() != 0 ); +} + +sal_Bool LocalFileHelper::IsLocalFile( const String& rName ) +{ + String aTmp; + return ConvertURLToPhysicalName( rName, aTmp ); +} + +sal_Bool LocalFileHelper::IsFileContent( const String& rName ) +{ + String aTmp; + return ConvertURLToSystemPath( rName, aTmp ); +} + +DECLARE_LIST( StringList_Impl, ::rtl::OUString* ) + +::com::sun::star::uno::Sequence < ::rtl::OUString > LocalFileHelper::GetFolderContents( const ::rtl::OUString& rFolder, sal_Bool bFolder ) +{ + StringList_Impl* pFiles = NULL; + try + { + ::ucbhelper::Content aCnt( rFolder, Reference< XCommandEnvironment > () ); + Reference< ::com::sun::star::sdbc::XResultSet > xResultSet; + ::com::sun::star::uno::Sequence< ::rtl::OUString > aProps(1); + ::rtl::OUString* pProps = aProps.getArray(); + pProps[0] = ::rtl::OUString::createFromAscii( "Url" ); + + try + { + ::ucbhelper::ResultSetInclude eInclude = bFolder ? ::ucbhelper::INCLUDE_FOLDERS_AND_DOCUMENTS : ::ucbhelper::INCLUDE_DOCUMENTS_ONLY; + xResultSet = aCnt.createCursor( aProps, eInclude ); + } + catch( ::com::sun::star::ucb::CommandAbortedException& ) + { + } + catch( Exception& ) + { + } + + if ( xResultSet.is() ) + { + pFiles = new StringList_Impl; + Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY ); + try + { + while ( xResultSet->next() ) + { + ::rtl::OUString aId = xContentAccess->queryContentIdentifierString(); + ::rtl::OUString* pFile = new ::rtl::OUString( aId ); + pFiles->Insert( pFile, LIST_APPEND ); + } + } + catch( ::com::sun::star::ucb::CommandAbortedException& ) + { + } + catch( Exception& ) + { + } + } + } + catch( Exception& ) + { + } + + if ( pFiles ) + { + ULONG nCount = pFiles->Count(); + Sequence < ::rtl::OUString > aRet( nCount ); + ::rtl::OUString* pRet = aRet.getArray(); + for ( USHORT i = 0; i < nCount; ++i ) + { + ::rtl::OUString* pFile = pFiles->GetObject(i); + pRet[i] = *( pFile ); + delete pFile; + } + delete pFiles; + return aRet; + } + else + return Sequence < ::rtl::OUString > (); +} + +} diff --git a/unotools/source/ucbhelper/makefile.mk b/unotools/source/ucbhelper/makefile.mk new file mode 100644 index 000000000000..850a6ea532a3 --- /dev/null +++ b/unotools/source/ucbhelper/makefile.mk @@ -0,0 +1,58 @@ +#************************************************************************* +# +# 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.17 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General 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=..$/.. +PRJINC=..$/..$/inc +PRJNAME=unotools +TARGET=ucbhelp + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ---------------------------------- + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/util$/makefile.pmk + +# --- Files ------------------------------------- + +SLOFILES=\ + $(SLO)$/ucblockbytes.obj \ + $(SLO)$/localfilehelper.obj \ + $(SLO)$/ucbhelper.obj \ + $(SLO)$/ucbstreamhelper.obj \ + $(SLO)$/tempfile.obj \ + $(SLO)$/xtempfile.obj \ + $(SLO)$/progresshandlerwrap.obj + +# --- Targets ---------------------------------- + +.INCLUDE : target.mk + diff --git a/unotools/source/ucbhelper/progresshandlerwrap.cxx b/unotools/source/ucbhelper/progresshandlerwrap.cxx new file mode 100644 index 000000000000..540ded03e90b --- /dev/null +++ b/unotools/source/ucbhelper/progresshandlerwrap.cxx @@ -0,0 +1,101 @@ +/************************************************************************* + * + * 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: progresshandlerwrap.cxx,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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_unotools.hxx" +#include <unotools/progresshandlerwrap.hxx> + +namespace utl +{ + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::task; +using namespace ::com::sun::star::ucb; + +ProgressHandlerWrap::ProgressHandlerWrap( ::com::sun::star::uno::Reference< ::com::sun::star::task::XStatusIndicator > xSI ) +: m_xStatusIndicator( xSI ) +{ +} + +sal_Bool getStatusFromAny_Impl( const Any& aAny, ::rtl::OUString& aText, sal_Int32& nNum ) +{ + sal_Bool bNumIsSet = sal_False; + + Sequence< Any > aSetList; + if( ( aAny >>= aSetList ) && aSetList.getLength() ) + for( int ind = 0; ind < aSetList.getLength(); ind++ ) + { + if( !bNumIsSet && ( aSetList[ind] >>= nNum ) ) + bNumIsSet = sal_True; + else + !aText.getLength() && ( aSetList[ind] >>= aText ); + } + + return bNumIsSet; +} + +void SAL_CALL ProgressHandlerWrap::push( const Any& Status ) + throw( RuntimeException ) +{ + if( !m_xStatusIndicator.is() ) + return; + + ::rtl::OUString aText; + sal_Int32 nRange; + + if( getStatusFromAny_Impl( Status, aText, nRange ) ) + m_xStatusIndicator->start( aText, nRange ); +} + +void SAL_CALL ProgressHandlerWrap::update( const Any& Status ) + throw( RuntimeException ) +{ + if( !m_xStatusIndicator.is() ) + return; + + ::rtl::OUString aText; + sal_Int32 nValue; + + if( getStatusFromAny_Impl( Status, aText, nValue ) ) + { + if( aText.getLength() ) m_xStatusIndicator->setText( aText ); + m_xStatusIndicator->setValue( nValue ); + } +} + +void SAL_CALL ProgressHandlerWrap::pop() + throw( RuntimeException ) +{ + if( m_xStatusIndicator.is() ) + m_xStatusIndicator->end(); +} + +} // namespace utl + diff --git a/unotools/source/ucbhelper/tempfile.cxx b/unotools/source/ucbhelper/tempfile.cxx new file mode 100644 index 000000000000..36d738042400 --- /dev/null +++ b/unotools/source/ucbhelper/tempfile.cxx @@ -0,0 +1,496 @@ +/************************************************************************* + * + * 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: tempfile.cxx,v $ + * $Revision: 1.28 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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_unotools.hxx" + +#include <unotools/tempfile.hxx> +#include <tools/tempfile.hxx> +#include <unotools/localfilehelper.hxx> +#include <unotools/ucbstreamhelper.hxx> +#include <ucbhelper/fileidentifierconverter.hxx> +#include <ucbhelper/contentbroker.hxx> +#include <rtl/ustring.hxx> +#include <rtl/instance.hxx> +#include <osl/file.hxx> +#include <tools/time.hxx> +#include <tools/debug.hxx> +#include <stdio.h> + +#ifdef UNX +#include <sys/stat.h> +#endif + +using namespace osl; + +namespace +{ + struct TempNameBase_Impl + : public rtl::Static< ::rtl::OUString, TempNameBase_Impl > {}; +} + +namespace utl +{ + +struct TempFile_Impl +{ + String aName; + String aURL; + SvStream* pStream; + sal_Bool bIsDirectory; + + TempFile_Impl() + : pStream(0) + {} +}; + +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; +} + +sal_Bool ensuredir( const rtl::OUString& rUnqPath ) +{ + rtl::OUString aPath; + if ( rUnqPath.getLength() < 1 ) + return sal_False; + + // remove trailing slash + 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 ); +#ifdef UNX +/* RW permission for the user only! */ + mode_t old_mode = umask(077); +#endif + osl::FileBase::RC nError = aDirectory.open(); +#ifdef UNX +umask(old_mode); +#endif + aDirectory.close(); + if( nError == osl::File::E_None ) + return sal_True; + + // try to create the directory + nError = osl::Directory::create( aPath ); + sal_Bool bSuccess = ( nError == osl::File::E_None || nError == osl::FileBase::E_EXIST ); + if( !bSuccess ) + { + // perhaps parent(s) don't exist + rtl::OUString aParentDir = getParentName( aPath ); + if ( aParentDir != aPath ) + { + bSuccess = ensuredir( getParentName( aPath ) ); + + // After parent directory structure exists try it one's more + if ( bSuccess ) + { + // Parent directory exists, retry creation of directory + nError = osl::Directory::create( aPath ); + bSuccess =( nError == osl::File::E_None || nError == osl::FileBase::E_EXIST ); + } + } + } + + return bSuccess; +} + +#define TMPNAME_SIZE ( 1 + 5 + 5 + 4 + 1 ) +String ConstructTempDir_Impl( const String* pParent ) +{ + String aName; + if ( pParent && pParent->Len() ) + { + ::ucbhelper::ContentBroker* pBroker = ::ucbhelper::ContentBroker::get(); + if ( pBroker ) + { + ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContentProviderManager > xManager = + pBroker->getContentProviderManagerInterface(); + + // if parent given try to use it + rtl::OUString aTmp( *pParent ); + + // test for valid filename + rtl::OUString aRet; + ::osl::FileBase::getFileURLFromSystemPath( + ::ucbhelper::getSystemPathFromFileURL( xManager, aTmp ), + aRet ); + if ( aRet.getLength() ) + { + ::osl::DirectoryItem aItem; + sal_Int32 i = aRet.getLength(); + if ( aRet[i-1] == '/' ) + i--; + + if ( DirectoryItem::get( ::rtl::OUString( aRet, i ), aItem ) == FileBase::E_None ) + aName = aRet; + } + } + else + { + DBG_WARNING( "::unotools::TempFile : UCB not present or not initialized!" ); + } + } + + if ( !aName.Len() ) + { + ::rtl::OUString &rTempNameBase_Impl = TempNameBase_Impl::get(); + if (rTempNameBase_Impl.getLength() == 0) + { + ::rtl::OUString ustrTempDirURL; + ::osl::FileBase::RC rc = ::osl::File::getTempDirURL( + ustrTempDirURL ); + if (rc == ::osl::FileBase::E_None) + rTempNameBase_Impl = ustrTempDirURL; + } + // if no parent or invalid parent : use default directory + DBG_ASSERT( rTempNameBase_Impl.getLength(), "No TempDir!" ); + aName = rTempNameBase_Impl; + ensuredir( aName ); + } + + // Make sure that directory ends with a separator + xub_StrLen i = aName.Len(); + if( i>0 && aName.GetChar(i-1) != '/' ) + aName += '/'; + + return aName; +} + +void CreateTempName_Impl( String& rName, sal_Bool bKeep, sal_Bool bDir = sal_True ) +{ + // add a suitable tempname + // Prefix can have 5 chars, leaving 3 for numbers. 26 ** 3 == 17576 + // ER 13.07.00 why not radix 36 [0-9A-Z] ?!? + const unsigned nRadix = 26; + String aName( rName ); + aName += String::CreateFromAscii( "sv" ); + + rName.Erase(); + static unsigned long u = Time::GetSystemTicks(); + for ( unsigned long nOld = u; ++u != nOld; ) + { + u %= (nRadix*nRadix*nRadix); + String aTmp( aName ); + aTmp += String::CreateFromInt32( (sal_Int32) (unsigned) u, nRadix ); + aTmp += String::CreateFromAscii( ".tmp" ); + + if ( bDir ) + { + FileBase::RC err = Directory::create( aTmp ); + if ( err == FileBase::E_None ) + { + // !bKeep: only for creating a name, not a file or directory + if ( bKeep || Directory::remove( aTmp ) == FileBase::E_None ) + rName = aTmp; + break; + } + else if ( err != FileBase::E_EXIST ) + { + // if f.e. name contains invalid chars stop trying to create dirs + break; + } + } + else + { + DBG_ASSERT( bKeep, "Too expensive, use directory for creating name!" ); + File aFile( aTmp ); +#ifdef UNX +/* RW permission for the user only! */ + mode_t old_mode = umask(077); +#endif + FileBase::RC err = aFile.open(osl_File_OpenFlag_Create); +#ifdef UNX +umask(old_mode); +#endif + if ( err == FileBase::E_None ) + { + rName = aTmp; + aFile.close(); + break; + } + else if ( err != FileBase::E_EXIST ) + { + // if f.e. name contains invalid chars stop trying to create files + // but if there is a folder with such name proceed further + + DirectoryItem aTmpItem; + FileStatus aTmpStatus( FileStatusMask_Type ); + if ( DirectoryItem::get( aTmp, aTmpItem ) != FileBase::E_None + || aTmpItem.getFileStatus( aTmpStatus ) != FileBase::E_None + || aTmpStatus.getFileType() != FileStatus::Directory ) + break; + } + } + } +} + +void lcl_createName(TempFile_Impl& _rImpl,const String& rLeadingChars,sal_Bool _bStartWithZero, const String* pExtension, const String* pParent, sal_Bool bDirectory) +{ + _rImpl.bIsDirectory = bDirectory; + + // get correct directory + String aName = ConstructTempDir_Impl( pParent ); + + sal_Bool bUseNumber = _bStartWithZero; + // now use special naming scheme ( name takes leading chars and an index counting up from zero + aName += rLeadingChars; + for ( sal_Int32 i=0;; i++ ) + { + String aTmp( aName ); + if ( bUseNumber ) + aTmp += String::CreateFromInt32( i ); + bUseNumber = sal_True; + if ( pExtension ) + aTmp += *pExtension; + else + aTmp += String::CreateFromAscii( ".tmp" ); + if ( bDirectory ) + { + FileBase::RC err = Directory::create( aTmp ); + if ( err == FileBase::E_None ) + { + _rImpl.aName = aTmp; + break; + } + else if ( err != FileBase::E_EXIST ) + // if f.e. name contains invalid chars stop trying to create dirs + break; + } + else + { + File aFile( aTmp ); +#ifdef UNX +/* RW permission for the user only! */ + mode_t old_mode = umask(077); +#endif + FileBase::RC err = aFile.open(osl_File_OpenFlag_Create); +#ifdef UNX +umask(old_mode); +#endif + if ( err == FileBase::E_None ) + { + _rImpl.aName = aTmp; + aFile.close(); + break; + } + else if ( err != FileBase::E_EXIST ) + { + // if f.e. name contains invalid chars stop trying to create dirs + // but if there is a folder with such name proceed further + + DirectoryItem aTmpItem; + FileStatus aTmpStatus( FileStatusMask_Type ); + if ( DirectoryItem::get( aTmp, aTmpItem ) != FileBase::E_None + || aTmpItem.getFileStatus( aTmpStatus ) != FileBase::E_None + || aTmpStatus.getFileType() != FileStatus::Directory ) + break; + } + } + if ( !_bStartWithZero ) + aTmp += String::CreateFromInt32( i ); + } +} + + +String TempFile::CreateTempName( const String* pParent ) +{ + // get correct directory + String aName = ConstructTempDir_Impl( pParent ); + + // get TempFile name with default naming scheme + CreateTempName_Impl( aName, sal_False ); + + // convert to file URL + rtl::OUString aTmp; + if ( aName.Len() ) + FileBase::getSystemPathFromFileURL( aName, aTmp ); + return aTmp; +} + +TempFile::TempFile( const String* pParent, sal_Bool bDirectory ) + : pImp( new TempFile_Impl ) + , bKillingFileEnabled( sal_False ) +{ + pImp->bIsDirectory = bDirectory; + + // get correct directory + pImp->aName = ConstructTempDir_Impl( pParent ); + + // get TempFile with default naming scheme + CreateTempName_Impl( pImp->aName, sal_True, bDirectory ); +} + +TempFile::TempFile( const String& rLeadingChars, const String* pExtension, const String* pParent, sal_Bool bDirectory) + : pImp( new TempFile_Impl ) + , bKillingFileEnabled( sal_False ) +{ + lcl_createName(*pImp,rLeadingChars,sal_True, pExtension, pParent, bDirectory); +} +TempFile::TempFile( const String& rLeadingChars,sal_Bool _bStartWithZero, const String* pExtension, const String* pParent, sal_Bool bDirectory) + : pImp( new TempFile_Impl ) + , bKillingFileEnabled( sal_False ) +{ + lcl_createName(*pImp,rLeadingChars,_bStartWithZero, pExtension, pParent, bDirectory); +} + +TempFile::~TempFile() +{ + delete pImp->pStream; + if ( bKillingFileEnabled ) + { + if ( pImp->bIsDirectory ) + { + // at the moment no recursiv algorithm present + Directory::remove( pImp->aName ); + } + else + { + File::remove( pImp->aName ); + } + } + + delete pImp; +} + +sal_Bool TempFile::IsValid() const +{ + return pImp->aName.Len() != 0; +} + +String TempFile::GetFileName() const +{ + rtl::OUString aTmp; + FileBase::getSystemPathFromFileURL( pImp->aName, aTmp ); + return aTmp; +} + +String TempFile::GetURL() const +{ + if ( !pImp->aURL.Len() ) + { + String aTmp; + LocalFileHelper::ConvertPhysicalNameToURL( GetFileName(), aTmp ); + pImp->aURL = aTmp; + } + + return pImp->aURL; +} + +SvStream* TempFile::GetStream( StreamMode eMode ) +{ + if ( !pImp->pStream ) + { + if ( GetURL().Len() ) + pImp->pStream = UcbStreamHelper::CreateStream( pImp->aURL, eMode, sal_True /* bFileExists */ ); + else + pImp->pStream = new SvMemoryStream( eMode ); + } + + return pImp->pStream; +} + +void TempFile::CloseStream() +{ + if ( pImp->pStream ) + { + delete pImp->pStream; + pImp->pStream = NULL; + } +} + +String TempFile::SetTempNameBaseDirectory( const String &rBaseName ) +{ + if( !rBaseName.Len() ) + return String(); + + rtl::OUString aUnqPath( rBaseName ); + + // remove trailing slash + if ( rBaseName.GetChar( rBaseName.Len() - 1 ) == sal_Unicode( '/' ) ) + aUnqPath = rBaseName.Copy( 0, rBaseName.Len() - 1 ); + + // try to create the directory + sal_Bool bRet = sal_False; + osl::FileBase::RC err = osl::Directory::create( aUnqPath ); + if ( err != FileBase::E_None && err != FileBase::E_EXIST ) + // perhaps parent(s) don't exist + bRet = ensuredir( aUnqPath ); + else + bRet = sal_True; + + // failure to create base directory means returning an empty string + rtl::OUString aTmp; + if ( bRet ) + { + // append own internal directory + bRet = sal_True; + ::rtl::OUString &rTempNameBase_Impl = TempNameBase_Impl::get(); + rTempNameBase_Impl = rBaseName; + rTempNameBase_Impl += String( '/' ); + + TempFile aBase( NULL, sal_True ); + if ( aBase.IsValid() ) + // use it in case of success + rTempNameBase_Impl = aBase.pImp->aName; + + // return system path of used directory + FileBase::getSystemPathFromFileURL( rTempNameBase_Impl, aTmp ); + } + + return aTmp; +} + +String TempFile::GetTempNameBaseDirectory() +{ + const ::rtl::OUString &rTempNameBase_Impl = TempNameBase_Impl::get(); + if ( !rTempNameBase_Impl.getLength() ) + return String(); + + rtl::OUString aTmp; + FileBase::getSystemPathFromFileURL( rTempNameBase_Impl, aTmp ); + return aTmp; +} + +} diff --git a/unotools/source/ucbhelper/ucbhelper.cxx b/unotools/source/ucbhelper/ucbhelper.cxx new file mode 100644 index 000000000000..2b301efc4e52 --- /dev/null +++ b/unotools/source/ucbhelper/ucbhelper.cxx @@ -0,0 +1,889 @@ +/************************************************************************* + * + * 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: ucbhelper.cxx,v $ + * $Revision: 1.24 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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_unotools.hxx" + +#include "unotools/ucbhelper.hxx" +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/sdbc/XResultSet.hpp> +#include <com/sun/star/sdbc/XRow.hpp> +#include <com/sun/star/ucb/XContentIdentifierFactory.hpp> +#include <com/sun/star/ucb/XCommandProcessor.hpp> +#include <com/sun/star/ucb/CommandAbortedException.hpp> +#include <com/sun/star/ucb/IllegalIdentifierException.hpp> +#include <com/sun/star/ucb/NameClashException.hpp> +#include <com/sun/star/ucb/NameClash.hpp> +#include <com/sun/star/ucb/NumberedSortingInfo.hpp> +#include <com/sun/star/ucb/TransferInfo.hpp> +#include <com/sun/star/ucb/XAnyCompareFactory.hpp> +#include <com/sun/star/ucb/XCommandInfo.hpp> +#include <com/sun/star/ucb/XContentAccess.hpp> +#include <com/sun/star/ucb/ContentInfoAttribute.hpp> +#include <com/sun/star/ucb/XContentCreator.hpp> +#include <com/sun/star/ucb/XDynamicResultSet.hpp> +#include <com/sun/star/ucb/XSortedDynamicResultSetFactory.hpp> +#include <com/sun/star/util/DateTime.hpp> +#include <com/sun/star/container/XChild.hpp> +#ifndef _COM_SUN_STAR_UCB_INTERACTIVEIODEXCEPTION_HPP_ +#include <com/sun/star/ucb/InteractiveIOException.hpp> +#endif +#include <com/sun/star/task/XInteractionHandler.hpp> +#include <ucbhelper/commandenvironment.hxx> +#include <ucbhelper/content.hxx> +#include <comphelper/processfactory.hxx> +#include <osl/file.hxx> + +#include <tools/wldcrd.hxx> +#include <tools/ref.hxx> +#include <tools/debug.hxx> +#include <tools/urlobj.hxx> +#include <tools/datetime.hxx> +#include <ucbhelper/contentbroker.hxx> + +#include "unotools/localfilehelper.hxx" + +using namespace ucbhelper; +using namespace com::sun::star; +using namespace com::sun::star::beans; +using namespace com::sun::star::container; +using namespace com::sun::star::lang; +using namespace com::sun::star::sdbc; +using namespace com::sun::star::task; +using namespace com::sun::star::uno; +using namespace com::sun::star::ucb; +using namespace rtl; +using namespace comphelper; +using namespace osl; + +DECLARE_LIST( StringList_Impl, OUString* ) + +#define CONVERT_DATETIME( aUnoDT, aToolsDT ) \ + aToolsDT = DateTime( Date( aUnoDT.Day, aUnoDT.Month, aUnoDT.Year ), \ + Time( aUnoDT.Hours, aUnoDT.Minutes, aUnoDT.Seconds, aUnoDT.HundredthSeconds ) ); + +namespace utl +{ + +sal_Bool UCBContentHelper::Transfer_Impl( const String& rSource, const String& rDest, sal_Bool bMoveData, sal_Int32 nNameClash ) +{ + sal_Bool bRet = sal_True, bKillSource = sal_False; + INetURLObject aSourceObj( rSource ); + DBG_ASSERT( aSourceObj.GetProtocol() != INET_PROT_NOT_VALID, "Invalid URL!" ); + + INetURLObject aDestObj( rDest ); + DBG_ASSERT( aDestObj.GetProtocol() != INET_PROT_NOT_VALID, "Invalid URL!" ); + if ( bMoveData && aSourceObj.GetProtocol() != aDestObj.GetProtocol() ) + { + bMoveData = sal_False; + bKillSource = sal_True; + } + String aName = aDestObj.getName(); + aDestObj.removeSegment(); + aDestObj.setFinalSlash(); + + try + { + Content aDestPath( aDestObj.GetMainURL( INetURLObject::NO_DECODE ), uno::Reference< ::com::sun::star::ucb::XCommandEnvironment > () ); + uno::Reference< ::com::sun::star::ucb::XCommandInfo > xInfo = aDestPath.getCommands(); + OUString aTransferName = OUString::createFromAscii( "transfer" ); + if ( xInfo->hasCommandByName( aTransferName ) ) + { + aDestPath.executeCommand( aTransferName, makeAny( + ::com::sun::star::ucb::TransferInfo( bMoveData, aSourceObj.GetMainURL( INetURLObject::NO_DECODE ), aName, nNameClash ) ) ); + } + else + { + DBG_ERRORFILE( "transfer command not available" ); + } + } + catch( ::com::sun::star::ucb::CommandAbortedException& ) + { + bRet = sal_False; + } + catch( ::com::sun::star::uno::Exception& ) + { + bRet = sal_False; + } + + if ( bKillSource ) + UCBContentHelper::Kill( rSource ); + + return bRet; +} + +// ----------------------------------------------------------------------- + +sal_Bool UCBContentHelper::IsDocument( const String& rContent ) +{ + sal_Bool bRet = sal_False; + INetURLObject aObj( rContent ); + DBG_ASSERT( aObj.GetProtocol() != INET_PROT_NOT_VALID, "Invalid URL!" ); + + try + { + Content aCnt( aObj.GetMainURL( INetURLObject::NO_DECODE ), uno::Reference< ::com::sun::star::ucb::XCommandEnvironment > () ); + bRet = aCnt.isDocument(); + } + catch( ::com::sun::star::ucb::CommandAbortedException& ) + { + DBG_WARNING( "CommandAbortedException" ); + } + catch( ::com::sun::star::ucb::IllegalIdentifierException& ) + { + DBG_WARNING( "IllegalIdentifierException" ); + } + catch( ContentCreationException& ) + { + DBG_WARNING( "IllegalIdentifierException" ); + } + catch( ::com::sun::star::uno::Exception& ) + { + DBG_WARNING( "Any other exception" ); + } + + return bRet; +} + +// ----------------------------------------------------------------------- + +Any UCBContentHelper::GetProperty( const String& rContent, const ::rtl::OUString& rName ) +{ + INetURLObject aObj( rContent ); + DBG_ASSERT( aObj.GetProtocol() != INET_PROT_NOT_VALID, "Invalid URL!" ); + try + { + Content aCnt( aObj.GetMainURL( INetURLObject::NO_DECODE ), uno::Reference< ::com::sun::star::ucb::XCommandEnvironment > () ); + return aCnt.getPropertyValue( rName ); + } + catch( ::com::sun::star::ucb::CommandAbortedException& ) + { + DBG_WARNING( "CommandAbortedException" ); + } + catch( ::com::sun::star::ucb::IllegalIdentifierException& ) + { + DBG_WARNING( "IllegalIdentifierException" ); + } + catch( ContentCreationException& ) + { + DBG_WARNING( "IllegalIdentifierException" ); + } + catch( ::com::sun::star::uno::Exception& ) + { + DBG_WARNING( "Any other exception" ); + } + + return Any(); +} + +sal_Bool UCBContentHelper::IsFolder( const String& rContent ) +{ + sal_Bool bRet = sal_False; + INetURLObject aObj( rContent ); + DBG_ASSERT( aObj.GetProtocol() != INET_PROT_NOT_VALID, "Invalid URL!" ); + try + { + Content aCnt( aObj.GetMainURL( INetURLObject::NO_DECODE ), uno::Reference< ::com::sun::star::ucb::XCommandEnvironment > () ); + bRet = aCnt.isFolder(); + } + catch( ::com::sun::star::ucb::CommandAbortedException& ) + { + DBG_WARNING( "CommandAbortedException" ); + } + catch( ::com::sun::star::ucb::IllegalIdentifierException& ) + { + DBG_WARNING( "IllegalIdentifierException" ); + } + catch( ContentCreationException& ) + { + DBG_WARNING( "IllegalIdentifierException" ); + } + catch( ::com::sun::star::uno::Exception& ) + { + DBG_WARNING( "Any other exception" ); + } + + return bRet; +} + +// ----------------------------------------------------------------------- + +sal_Bool UCBContentHelper::GetTitle( const String& rContent, String& rTitle ) +{ + sal_Bool bRet = sal_False; + INetURLObject aObj( rContent ); + DBG_ASSERT( aObj.GetProtocol() != INET_PROT_NOT_VALID, "Invalid URL!" ); + try + { + Content aCnt( aObj.GetMainURL( INetURLObject::NO_DECODE ), uno::Reference< ::com::sun::star::ucb::XCommandEnvironment > () ); + OUString aTemp; + if ( aCnt.getPropertyValue( OUString::createFromAscii( "Title" ) ) >>= aTemp ) + { + rTitle = String( aTemp ); + bRet = sal_True; + } + } + catch( ::com::sun::star::ucb::CommandAbortedException& ) + { + } + catch( ::com::sun::star::uno::Exception& ) + { + } + return bRet; +} + +// ----------------------------------------------------------------------- + +sal_Bool UCBContentHelper::Kill( const String& rContent ) +{ + sal_Bool bRet = sal_True; + INetURLObject aDeleteObj( rContent ); + DBG_ASSERT( aDeleteObj.GetProtocol() != INET_PROT_NOT_VALID, "Invalid URL!" ); + + try + { + Content aCnt( aDeleteObj.GetMainURL( INetURLObject::NO_DECODE ), uno::Reference< ::com::sun::star::ucb::XCommandEnvironment > () ); + aCnt.executeCommand( OUString::createFromAscii( "delete" ), makeAny( sal_Bool( sal_True ) ) ); + } + catch( ::com::sun::star::ucb::CommandAbortedException& ) + { + DBG_WARNING( "CommandAbortedException" ); + bRet = sal_False; + } + catch( ::com::sun::star::uno::Exception& ) + { + DBG_WARNING( "Any other exception" ); + bRet = sal_False; + } + + return bRet; +} + +// ----------------------------------------------------------------------- + +Sequence < OUString > UCBContentHelper::GetFolderContents( const String& rFolder, sal_Bool bFolder, sal_Bool bSorted ) +{ + StringList_Impl* pFiles = NULL; + INetURLObject aFolderObj( rFolder ); + DBG_ASSERT( aFolderObj.GetProtocol() != INET_PROT_NOT_VALID, "Invalid URL!" ); + try + { + Content aCnt( aFolderObj.GetMainURL( INetURLObject::NO_DECODE ), uno::Reference< ::com::sun::star::ucb::XCommandEnvironment > () ); + uno::Reference< XResultSet > xResultSet; + Sequence< OUString > aProps( bSorted ? 2 : 1 ); + OUString* pProps = aProps.getArray(); + pProps[0] = OUString::createFromAscii( "Title" ); + if ( bSorted ) + pProps[1] = OUString::createFromAscii( "IsFolder" ); + + try + { + ResultSetInclude eInclude = bFolder ? INCLUDE_FOLDERS_AND_DOCUMENTS : INCLUDE_DOCUMENTS_ONLY; + if ( !bSorted ) + { + xResultSet = aCnt.createCursor( aProps, eInclude ); + } + else + { + uno::Reference< com::sun::star::ucb::XDynamicResultSet > xDynResultSet; + xDynResultSet = aCnt.createDynamicCursor( aProps, eInclude ); + + uno::Reference < com::sun::star::ucb::XAnyCompareFactory > xFactory; + uno::Reference < XMultiServiceFactory > xMgr = getProcessServiceFactory(); + uno::Reference < com::sun::star::ucb::XSortedDynamicResultSetFactory > xSRSFac( + xMgr->createInstance( ::rtl::OUString::createFromAscii("com.sun.star.ucb.SortedDynamicResultSetFactory") ), UNO_QUERY ); + + Sequence< com::sun::star::ucb::NumberedSortingInfo > aSortInfo( 2 ); + com::sun::star::ucb::NumberedSortingInfo* pInfo = aSortInfo.getArray(); + pInfo[ 0 ].ColumnIndex = 2; + pInfo[ 0 ].Ascending = sal_False; + pInfo[ 1 ].ColumnIndex = 1; + pInfo[ 1 ].Ascending = sal_True; + + uno::Reference< com::sun::star::ucb::XDynamicResultSet > xDynamicResultSet; + xDynamicResultSet = + xSRSFac->createSortedDynamicResultSet( xDynResultSet, aSortInfo, xFactory ); + if ( xDynamicResultSet.is() ) + { + xResultSet = xDynamicResultSet->getStaticResultSet(); + } + } + } + catch( ::com::sun::star::ucb::CommandAbortedException& ) + { + // folder not exists? + } + catch( ::com::sun::star::uno::Exception& ) + { + } + + if ( xResultSet.is() ) + { + pFiles = new StringList_Impl; + uno::Reference< com::sun::star::ucb::XContentAccess > xContentAccess( xResultSet, UNO_QUERY ); + try + { + while ( xResultSet->next() ) + { + OUString aId = xContentAccess->queryContentIdentifierString(); + OUString* pFile = new OUString( aId ); + pFiles->Insert( pFile, LIST_APPEND ); + } + } + catch( ::com::sun::star::ucb::CommandAbortedException& ) + { + } + catch( ::com::sun::star::uno::Exception& ) + { + } + } + } + catch( ::com::sun::star::uno::Exception& ) + { + } + + if ( pFiles ) + { + ULONG nCount = pFiles->Count(); + Sequence < OUString > aRet( nCount ); + OUString* pRet = aRet.getArray(); + for ( ULONG i = 0; i < nCount; ++i ) + { + OUString* pFile = pFiles->GetObject(i); + pRet[i] = *( pFile ); + delete pFile; + } + delete pFiles; + return aRet; + } + else + return Sequence < OUString > (); +} + +// ----------------------------------------------------------------------- + +Sequence < OUString > UCBContentHelper::GetResultSet( const String& rURL ) +{ + StringList_Impl* pList = NULL; + try + { + Content aCnt( rURL, uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >() ); + uno::Reference< XResultSet > xResultSet; + uno::Reference< com::sun::star::ucb::XDynamicResultSet > xDynResultSet; + Sequence< OUString > aProps(3); + OUString* pProps = aProps.getArray(); + pProps[0] = OUString::createFromAscii( "Title" ); + pProps[1] = OUString::createFromAscii( "ContentType" ); + // TODO: can be optimized, property never used: + pProps[2] = OUString::createFromAscii( "IsFolder" ); + + try + { + xDynResultSet = aCnt.createDynamicCursor( aProps, INCLUDE_FOLDERS_AND_DOCUMENTS ); + if ( xDynResultSet.is() ) + xResultSet = xDynResultSet->getStaticResultSet(); + } + catch( ::com::sun::star::ucb::CommandAbortedException& ) + { + } + catch( ::com::sun::star::uno::Exception& ) + { + } + + if ( xResultSet.is() ) + { + pList = new StringList_Impl; + uno::Reference< com::sun::star::sdbc::XRow > xRow( xResultSet, UNO_QUERY ); + uno::Reference< com::sun::star::ucb::XContentAccess > xContentAccess( xResultSet, UNO_QUERY ); + + try + { + while ( xResultSet->next() ) + { + String aTitle( xRow->getString(1) ); + String aType( xRow->getString(2) ); + String aRow = aTitle; + aRow += '\t'; + aRow += aType; + aRow += '\t'; + aRow += String( xContentAccess->queryContentIdentifierString() ); + OUString* pRow = new OUString( aRow ); + pList->Insert( pRow, LIST_APPEND ); + } + } + catch( ::com::sun::star::ucb::CommandAbortedException& ) + { + } + catch( ::com::sun::star::uno::Exception& ) + { + } + } + } + catch( ::com::sun::star::uno::Exception& ) + { + } + + if ( pList ) + { + ULONG nCount = pList->Count(); + Sequence < OUString > aRet( nCount ); + OUString* pRet = aRet.getArray(); + for ( ULONG i = 0; i < nCount; ++i ) + { + OUString* pEntry = pList->GetObject(i); + pRet[i] = *( pEntry ); + delete pEntry; + } + delete pList; + return aRet; + } + else + return Sequence < OUString > (); +} + +// ----------------------------------------------------------------------- + +sal_Bool UCBContentHelper::CopyTo( const String& rSource, const String& rDest ) +{ + return Transfer_Impl( rSource, rDest, sal_False, NameClash::ERROR ); +} + +// ----------------------------------------------------------------------- + +sal_Bool UCBContentHelper::MoveTo( const String& rSource, const String& rDest, sal_Int32 nNameClash ) +{ + return Transfer_Impl( rSource, rDest, sal_True, nNameClash ); +} + +// ----------------------------------------------------------------------- + +sal_Bool UCBContentHelper::CanMakeFolder( const String& rFolder ) +{ + try + { + Content aCnt( rFolder, uno::Reference< XCommandEnvironment > () ); + uno::Reference< XContentCreator > xCreator = uno::Reference< XContentCreator >( aCnt.get(), UNO_QUERY ); + if ( !xCreator.is() ) + return sal_False; + + Sequence< ContentInfo > aInfo = xCreator->queryCreatableContentsInfo(); + sal_Int32 nCount = aInfo.getLength(); + if ( nCount == 0 ) + return sal_False; + + for ( sal_Int32 i = 0; i < nCount; ++i ) + { + // Simply look for the first KIND_FOLDER... + const ContentInfo & rCurr = aInfo[i]; + if ( rCurr.Attributes & ContentInfoAttribute::KIND_FOLDER ) + return sal_True; + } + } + catch( ::com::sun::star::ucb::CommandAbortedException& ) {} + catch( RuntimeException& ) {} + catch( Exception& ) {} + + return sal_False; +} + +// ----------------------------------------------------------------------- + +sal_Bool UCBContentHelper::MakeFolder( const String& rFolder, sal_Bool bNewOnly ) +{ + INetURLObject aURL( rFolder ); + DBG_ASSERT( aURL.GetProtocol() != INET_PROT_NOT_VALID, "Invalid URL!" ); + String aTitle = aURL.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET ); + aURL.removeSegment(); + Content aCnt; + Content aNew; + uno::Reference< XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory(); + uno::Reference< XInteractionHandler > xInteractionHandler = uno::Reference< XInteractionHandler > ( + xFactory->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uui.InteractionHandler") ) ), UNO_QUERY ); + if ( Content::create( aURL.GetMainURL( INetURLObject::NO_DECODE ), new CommandEnvironment( xInteractionHandler, uno::Reference< XProgressHandler >() ), aCnt ) ) + return MakeFolder( aCnt, aTitle, aNew, bNewOnly ); + else + return sal_False; +} + +sal_Bool UCBContentHelper::MakeFolder( Content& aCnt, const String& aTitle, Content& rNew, sal_Bool bNewOnly ) +{ + sal_Bool bAlreadyExists = sal_False; + + try + { + uno::Reference< XContentCreator > xCreator( aCnt.get(), UNO_QUERY ); + if ( !xCreator.is() ) + return sal_False; + + Sequence< ContentInfo > aInfo = xCreator->queryCreatableContentsInfo(); + sal_Int32 nCount = aInfo.getLength(); + if ( nCount == 0 ) + return sal_False; + + for ( sal_Int32 i = 0; i < nCount; ++i ) + { + // Simply look for the first KIND_FOLDER... + const ContentInfo & rCurr = aInfo[i]; + if ( rCurr.Attributes & ContentInfoAttribute::KIND_FOLDER ) + { + // Make sure the only required bootstrap property is "Title", + const Sequence< Property > & rProps = rCurr.Properties; + if ( rProps.getLength() != 1 ) + continue; + + if ( !rProps[ 0 ].Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "Title" ) ) ) + continue; + + Sequence<OUString> aNames(1); + OUString* pNames = aNames.getArray(); + pNames[0] = OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ); + Sequence<Any> aValues(1); + Any* pValues = aValues.getArray(); + pValues[0] = makeAny( OUString( aTitle ) ); + + if ( !aCnt.insertNewContent( rCurr.Type, aNames, aValues, rNew ) ) + continue; + + return sal_True; + } + } + } + catch ( InteractiveIOException& r ) + { + if ( r.Code == IOErrorCode_ALREADY_EXISTING ) + { + bAlreadyExists = sal_True; + } + } + catch ( NameClashException& ) + { + bAlreadyExists = sal_True; + } + catch( ::com::sun::star::ucb::CommandAbortedException& ) + { + } + catch( RuntimeException& ) + { + } + catch( Exception& ) + { + } + + if( bAlreadyExists && !bNewOnly ) + { + INetURLObject aObj( aCnt.getURL() ); + aObj.Append( aTitle ); + rNew = Content( aObj.GetMainURL( INetURLObject::NO_DECODE ), uno::Reference < XCommandEnvironment >() ); + return sal_True; + } + + return sal_False; +} + +// ----------------------------------------------------------------------- + +sal_Bool UCBContentHelper::HasParentFolder( const String& rFolder ) +{ + sal_Bool bRet = sal_False; + try + { + Content aCnt( rFolder, uno::Reference< XCommandEnvironment > () ); + uno::Reference< XChild > xChild( aCnt.get(), UNO_QUERY ); + if ( xChild.is() ) + { + uno::Reference< XContent > xParent( xChild->getParent(), UNO_QUERY ); + if ( xParent.is() ) + { + String aParentURL = String( xParent->getIdentifier()->getContentIdentifier() ); + bRet = ( aParentURL.Len() > 0 && aParentURL != rFolder ); + } + } + } + catch( ::com::sun::star::ucb::CommandAbortedException& ) + { + } + catch( ::com::sun::star::uno::Exception& ) + { + } + + return bRet; +} + +// ----------------------------------------------------------------------- + +ULONG UCBContentHelper::GetSize( const String& rContent ) +{ + ULONG nSize = 0; + sal_Int64 nTemp = 0; + INetURLObject aObj( rContent ); + DBG_ASSERT( aObj.GetProtocol() != INET_PROT_NOT_VALID, "Invalid URL!" ); + try + { + Content aCnt( aObj.GetMainURL( INetURLObject::NO_DECODE ), uno::Reference< ::com::sun::star::ucb::XCommandEnvironment > () ); + aCnt.getPropertyValue( OUString::createFromAscii( "Size" ) ) >>= nTemp; + } + catch( ::com::sun::star::ucb::CommandAbortedException& ) + { + } + catch( ::com::sun::star::uno::Exception& ) + { + } + nSize = (UINT32)nTemp; + return nSize; +} + +// ----------------------------------------------------------------------- + +sal_Bool UCBContentHelper::IsYounger( const String& rIsYoung, const String& rIsOlder ) +{ + DateTime aYoungDate, aOlderDate; + INetURLObject aYoungObj( rIsYoung ); + DBG_ASSERT( aYoungObj.GetProtocol() != INET_PROT_NOT_VALID, "Invalid URL!" ); + INetURLObject aOlderObj( rIsOlder ); + DBG_ASSERT( aOlderObj.GetProtocol() != INET_PROT_NOT_VALID, "Invalid URL!" ); + try + { + uno::Reference< ::com::sun::star::ucb::XCommandEnvironment > aCmdEnv; + Content aYoung( aYoungObj.GetMainURL( INetURLObject::NO_DECODE ), aCmdEnv ); + ::com::sun::star::util::DateTime aTempYoungDate; + aYoung.getPropertyValue( OUString::createFromAscii( "DateModified" ) ) >>= aTempYoungDate; + CONVERT_DATETIME( aTempYoungDate, aYoungDate ); + Content aOlder( aOlderObj.GetMainURL( INetURLObject::NO_DECODE ), aCmdEnv ); + ::com::sun::star::util::DateTime aTempOlderDate; + aOlder.getPropertyValue( OUString::createFromAscii( "DateModified" ) ) >>= aTempOlderDate; + CONVERT_DATETIME( aTempOlderDate, aOlderDate ); + } + catch( ::com::sun::star::ucb::CommandAbortedException& ) + { + } + catch( ::com::sun::star::uno::Exception& ) + { + } + + return ( aYoungDate > aOlderDate ); +} + +// ----------------------------------------------------------------------- +sal_Bool UCBContentHelper::Find( const String& rFolder, const String& rName, String& rFile, BOOL bAllowWildCards ) +{ + BOOL bWild = bAllowWildCards && ( rName.Search( '*' ) != STRING_NOTFOUND || rName.Search( '?' ) != STRING_NOTFOUND ); + + sal_Bool bRet = sal_False; + + // get a list of URLs for all children of rFolder + Sequence< ::rtl::OUString > aFiles = GetFolderContents( rFolder, sal_False ); + + const ::rtl::OUString* pFiles = aFiles.getConstArray(); + UINT32 i, nCount = aFiles.getLength(); + for ( i = 0; i < nCount; ++i ) + { + // get the last name of the URLs and compare it with rName + INetURLObject aFileObject( pFiles[i] ); + String aFile = aFileObject.getName( + INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET ).toAsciiLowerCase(); + if ( (bWild && WildCard( rName ).Matches( aFile )) || aFile == rName ) + { + // names match + rFile = aFileObject.GetMainURL( INetURLObject::NO_DECODE ); + bRet = sal_True; + break; + } + } + + return bRet; +} + +// ----------------------------------------------------------------------- +sal_Bool UCBContentHelper::Exists( const String& rURL ) +{ + + String sObjectPhysicalName; + sal_Bool bIsLocalFile = ::utl::LocalFileHelper::ConvertURLToPhysicalName( rURL, sObjectPhysicalName ); + // try to create a directory entry for the URL given + if ( bIsLocalFile ) + { + ::rtl::OUString sIn( sObjectPhysicalName ), sOut; + if ( osl_File_E_None == osl_getFileURLFromSystemPath( sIn.pData, &sOut.pData ) ) + { + // #106526 osl_getDirectoryItem is an existence check + // no further osl_getFileStatus call necessary + DirectoryItem aItem; + return (FileBase::E_None == DirectoryItem::get(sOut, aItem)); + } + return sal_False; + } + + // divide URL into folder and name part + sal_Bool bRet = sal_False; + INetURLObject aObj( rURL ); + ::rtl::OUString aFileName = aObj.getName( + INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET ).toAsciiLowerCase(); + aObj.removeSegment(); + aObj.removeFinalSlash(); + + // get a list of URLs for all children of rFolder + Sequence< ::rtl::OUString > aFiles = GetFolderContents( aObj.GetMainURL( INetURLObject::NO_DECODE ), sal_True, sal_False ); + + const ::rtl::OUString* pFiles = aFiles.getConstArray(); + UINT32 i, nCount = aFiles.getLength(); + for ( i = 0; i < nCount; ++i ) + { + // get the last name of the URLs and compare it with rName + INetURLObject aFileObject( pFiles[i] ); + ::rtl::OUString aFile = aFileObject.getName( + INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET ).toAsciiLowerCase(); + if ( aFile == aFileName ) + { + // names match + bRet = sal_True; + break; + } + } + + return bRet; +} + +// ----------------------------------------------------------------------- +sal_Bool UCBContentHelper::FindInPath( const String& rPath, const String& rName, String& rFile, char cDelim, BOOL bAllowWildCards ) +{ + // extract the single folder names from the path variable and try to find the file in one of these folders + USHORT nTokenCount = rPath.GetTokenCount( cDelim ); + for ( USHORT nToken = 0; nToken < nTokenCount; ++nToken ) + { + String aPath = rPath.GetToken( nToken, cDelim ); + if ( Find( aPath, rName, rFile, bAllowWildCards ) ) + return TRUE; + } + + return FALSE; +} + +// ----------------------------------------------------------------------- +sal_Bool UCBContentHelper::IsSubPath( const ::rtl::OUString& rPath, const ::rtl::OUString& rSubfolderCandidate, const uno::Reference< ::com::sun::star::ucb::XContentProvider >& xProv ) +{ + sal_Bool bResult = sal_False; + + uno::Reference< ::com::sun::star::ucb::XContentProvider > xContentProvider = xProv; + + // the comparing is done in the following way: + // - first compare in case sensitive way + // - if name are different try a fallback comparing inf case insensitive way + // - if the last comparing succeeded get casepreserving normalized names for the files and compare them + // ( the second step is required because retrieving of the normalized names might be very expensive in some cases ) + + INetURLObject aCandidate( rSubfolderCandidate ); + INetURLObject aCandidateLowCase( rSubfolderCandidate.toAsciiLowerCase() ); // will be used for case insensitive comparing + INetURLObject aParentFolder( rPath ); + INetURLObject aParentFolderLowCase( rPath.toAsciiLowerCase() ); // will be used for case insensitive comparing + + if ( aCandidate.GetProtocol() == aParentFolder.GetProtocol() ) + { + if ( !xContentProvider.is() ) + { + ::ucbhelper::ContentBroker* pBroker = NULL; + if ( aCandidate.GetProtocol() == INET_PROT_FILE ) + { + pBroker = ::ucbhelper::ContentBroker::get(); + if ( pBroker ) + xContentProvider = pBroker->getContentProviderInterface(); + } + } + + INetURLObject aLastTmpObj; + do + { + if ( aParentFolder == aCandidate ) + { + // if case sensitive comparing succeeded there is no need for additional checks + bResult = sal_True; + } + else if ( xContentProvider.is() && aParentFolderLowCase == aCandidateLowCase ) + { + // the comparing was done using caseinsensitive way + // the case sensitive comparing have failed already + // the normalized urls must be retrieved + try + { + uno::Reference< ::com::sun::star::ucb::XContent > xSecCont = + xContentProvider->queryContent( + uno::Reference< ::com::sun::star::ucb::XContentIdentifierFactory >( + xContentProvider, ::com::sun::star::uno::UNO_QUERY_THROW )->createContentIdentifier( + aParentFolder.GetMainURL( INetURLObject::NO_DECODE ) ) ); + + uno::Reference< ::com::sun::star::ucb::XContent > xLocCont = + xContentProvider->queryContent( + uno::Reference< ::com::sun::star::ucb::XContentIdentifierFactory >( + xContentProvider, ::com::sun::star::uno::UNO_QUERY_THROW )->createContentIdentifier( + aCandidate.GetMainURL( INetURLObject::NO_DECODE ) ) ); + + if ( !xSecCont.is() || !xLocCont.is() ) + throw ::com::sun::star::uno::RuntimeException(); + + ::rtl::OUString aSecNormStr; + ::rtl::OUString aLocNormStr; + + bResult = + ( ( uno::Reference< ::com::sun::star::ucb::XCommandProcessor >( + xSecCont, ::com::sun::star::uno::UNO_QUERY_THROW )->execute( + ::com::sun::star::ucb::Command( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getCasePreservingURL" ) ), + -1, + ::com::sun::star::uno::Any() ), + 0, + uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >() ) + >>= aSecNormStr ) + && ( uno::Reference< ::com::sun::star::ucb::XCommandProcessor >( + xLocCont, ::com::sun::star::uno::UNO_QUERY_THROW )->execute( + ::com::sun::star::ucb::Command( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getCasePreservingURL" ) ), + -1, + ::com::sun::star::uno::Any() ), + 0, + uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >() ) + >>= aLocNormStr ) + && aLocNormStr.equals( aSecNormStr ) ); + } + catch( ::com::sun::star::uno::Exception& ) + {} + } + + // INetURLObject::removeSegment sometimes return true without exchanging URL, + // for example in case of "file:///" + aLastTmpObj = aCandidate; + + } while( aCandidate.removeSegment() && aCandidateLowCase.removeSegment() && aCandidate != aLastTmpObj && !bResult ); + } + + return bResult; +} + +} // namespace utl + diff --git a/unotools/source/ucbhelper/ucblockbytes.cxx b/unotools/source/ucbhelper/ucblockbytes.cxx new file mode 100644 index 000000000000..45ed6e728033 --- /dev/null +++ b/unotools/source/ucbhelper/ucblockbytes.cxx @@ -0,0 +1,1749 @@ +/************************************************************************* + * + * 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: ucblockbytes.cxx,v $ + * $Revision: 1.60 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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_unotools.hxx" + +#include <unotools/ucblockbytes.hxx> +#include <comphelper/processfactory.hxx> +#include <salhelper/condition.hxx> +#ifndef _OSL_THREAD_HXX_ +#include <osl/thread.hxx> +#endif +#include <tools/urlobj.hxx> +#include <ucbhelper/interactionrequest.hxx> +#include <com/sun/star/task/XInteractionAbort.hpp> +#include <com/sun/star/ucb/InteractiveNetworkConnectException.hpp> +#include <com/sun/star/ucb/CommandFailedException.hpp> +#include <com/sun/star/ucb/UnsupportedDataSinkException.hpp> +#ifndef _COM_SUN_STAR_UCB_INTERACTIVEIODEXCEPTION_HPP_ +#include <com/sun/star/ucb/InteractiveIOException.hpp> +#endif +#include <com/sun/star/io/XActiveDataStreamer.hpp> +#include <com/sun/star/ucb/DocumentHeaderField.hpp> +#include <com/sun/star/ucb/XCommandInfo.hpp> +#include <com/sun/star/ucb/XCommandProcessor.hpp> +#include <com/sun/star/task/XInteractionHandler.hpp> +#include <com/sun/star/ucb/OpenCommandArgument2.hpp> +#include <com/sun/star/ucb/PostCommandArgument2.hpp> +#include <com/sun/star/ucb/OpenMode.hpp> +#include <com/sun/star/beans/Property.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/beans/XPropertiesChangeNotifier.hpp> +#include <com/sun/star/beans/XPropertiesChangeListener.hpp> +#include <com/sun/star/sdbc/XRow.hpp> +#include <com/sun/star/io/XActiveDataSink.hpp> +#include <com/sun/star/io/XActiveDataControl.hpp> +#include <com/sun/star/io/XSeekable.hpp> +#include <cppuhelper/implbase1.hxx> +#include <cppuhelper/implbase2.hxx> +#include <tools/inetmsg.hxx> +#include <com/sun/star/io/XTruncate.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> + +#include <comphelper/storagehelper.hxx> + +#include <ucbhelper/contentbroker.hxx> +#include <ucbhelper/content.hxx> + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::ucb; +using namespace ::com::sun::star::task; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; + + +namespace utl +{ + +/** + Helper class for getting a XInputStream when opening a content + */ +class UcbDataSink_Impl : public ::cppu::WeakImplHelper2< XActiveDataControl, XActiveDataSink > +{ + UcbLockBytesRef m_xLockBytes; + +public: + UcbDataSink_Impl( UcbLockBytes* pLockBytes ) + : m_xLockBytes( pLockBytes ) + {} + + SvLockBytes* getLockBytes (void) + { return m_xLockBytes; } + + // XActiveDataControl. + virtual void SAL_CALL addListener ( const Reference<XStreamListener> &/*rxListener*/) throw(RuntimeException) {} + virtual void SAL_CALL removeListener ( const Reference<XStreamListener> &/*rxListener*/) throw(RuntimeException) {} + virtual void SAL_CALL start (void) throw(RuntimeException) {} + virtual void SAL_CALL terminate (void) throw(RuntimeException) + { m_xLockBytes->terminate_Impl(); } + + // XActiveDataSink. + virtual void SAL_CALL setInputStream ( const Reference<XInputStream> &rxInputStream) throw(RuntimeException) + { m_xLockBytes->setInputStream_Impl (rxInputStream); } + virtual Reference<XInputStream> SAL_CALL getInputStream (void) throw(RuntimeException) + { return m_xLockBytes->getInputStream_Impl(); } +}; + +/** + Helper class for getting a XStream when opening a content + */ +class UcbStreamer_Impl : public ::cppu::WeakImplHelper2< XActiveDataStreamer, XActiveDataControl > +{ + Reference < XStream > m_xStream; + UcbLockBytesRef m_xLockBytes; + +public: + + UcbStreamer_Impl( UcbLockBytes* pLockBytes ) + : m_xLockBytes( pLockBytes ) + {} + + // XActiveDataControl. + virtual void SAL_CALL addListener ( const Reference<XStreamListener> &/*rxListener*/) throw(RuntimeException) {} + virtual void SAL_CALL removeListener ( const Reference<XStreamListener> &/*rxListener*/) throw(RuntimeException) {} + virtual void SAL_CALL start (void) throw(RuntimeException) {} + virtual void SAL_CALL terminate (void) throw(RuntimeException) + { m_xLockBytes->terminate_Impl(); } + + // XActiveDataStreamer + virtual void SAL_CALL setStream( const Reference< XStream >& aStream ) throw(RuntimeException) + { m_xStream = aStream; m_xLockBytes->setStream_Impl( aStream ); } + virtual Reference< XStream > SAL_CALL getStream() throw(RuntimeException) + { return m_xStream; } +}; + +/** + Helper class for progress handling while executing UCB commands + */ +class ProgressHandler_Impl: public ::cppu::WeakImplHelper1< XProgressHandler > +{ + Link m_aProgress; + +public: + ProgressHandler_Impl( const Link& rLink ) + : m_aProgress( rLink ) + {} + // XProgressHandler + virtual void SAL_CALL push(const Any & /*rStatus*/) throw (RuntimeException) {} + virtual void SAL_CALL pop() throw (RuntimeException) {} + virtual void SAL_CALL update(const Any & /*rStatus*/) throw (RuntimeException) + { if ( m_aProgress.IsSet() ) m_aProgress.Call( 0 ); } +}; + +/** + Helper class for managing interactions and progress when executing UCB commands + */ +class UcbTaskEnvironment : public ::cppu::WeakImplHelper1< XCommandEnvironment > +{ + Reference< XInteractionHandler > m_xInteractionHandler; + Reference< XProgressHandler > m_xProgressHandler; + +public: + UcbTaskEnvironment( const Reference< XInteractionHandler>& rxInteractionHandler, + const Reference< XProgressHandler>& rxProgressHandler ) + : m_xInteractionHandler( rxInteractionHandler ) + , m_xProgressHandler( rxProgressHandler ) + {} + + + virtual Reference<XInteractionHandler> SAL_CALL getInteractionHandler() throw (RuntimeException) + { return m_xInteractionHandler; } + + virtual Reference<XProgressHandler> SAL_CALL getProgressHandler() throw (RuntimeException) + { return m_xProgressHandler; } +}; + + +/** + Helper class for property change notifies when executing UCB commands +*/ +class UcbPropertiesChangeListener_Impl : public ::cppu::WeakImplHelper1< XPropertiesChangeListener > +{ +public: + UcbLockBytesRef m_xLockBytes; + + UcbPropertiesChangeListener_Impl( UcbLockBytesRef rRef ) + : m_xLockBytes( rRef ) + {} + + virtual void SAL_CALL disposing ( const EventObject &/*rEvent*/) throw(RuntimeException) {} + virtual void SAL_CALL propertiesChange ( const Sequence<PropertyChangeEvent> &rEvent) throw(RuntimeException); +}; + +void SAL_CALL UcbPropertiesChangeListener_Impl::propertiesChange ( const Sequence<PropertyChangeEvent> &rEvent) throw(RuntimeException) +{ + sal_Int32 i, n = rEvent.getLength(); + for (i = 0; i < n; i++) + { + PropertyChangeEvent evt (rEvent[i]); + if (evt.PropertyName == ::rtl::OUString::createFromAscii ("DocumentHeader")) + { + Sequence<DocumentHeaderField> aHead; + if (evt.NewValue >>= aHead) + { + sal_Int32 k, m = aHead.getLength(); + for (k = 0; k < m; k++) + { + String aName( aHead[k].Name ); + String aValue( aHead[k].Value ); + + if (aName.CompareIgnoreCaseToAscii("Expires") == COMPARE_EQUAL) + { + DateTime aExpires (0, 0); + if (INetRFC822Message::ParseDateField (aValue, aExpires)) + { + aExpires.ConvertToLocalTime(); + m_xLockBytes->SetExpireDate_Impl( aExpires ); + } + } + } + } + + m_xLockBytes->SetStreamValid_Impl(); + } + else if (evt.PropertyName == rtl::OUString::createFromAscii ("PresentationURL")) + { + ::rtl::OUString aUrl; + if (evt.NewValue >>= aUrl) + { + ::rtl::OUString aBad (::rtl::OUString::createFromAscii ("private:")); + if (!(aUrl.compareTo (aBad, aBad.getLength()) == 0)) + { + // URL changed (Redirection). + m_xLockBytes->SetRealURL_Impl( aUrl ); + } + } + } + else if (evt.PropertyName == ::rtl::OUString::createFromAscii ("MediaType")) + { + ::rtl::OUString aContentType; + if (evt.NewValue >>= aContentType) + m_xLockBytes->SetContentType_Impl( aContentType ); + } + } +} + + + +class Moderator + : public osl::Thread +{ + // usage restriction: + // It might be possible, that the call to the interactionhandler and/or + // progresshandler is done asynchrounsly, while the 'execute' simply + // returns. This would imply that these class must be refcounted !!! + +public: + + Moderator( + Reference < XContent >& xContent, + Reference < XInteractionHandler >& xInteract, + Reference < XProgressHandler >& xProgress, + const Command& rArg + ) + throw( + ContentCreationException, + RuntimeException + ); + + ~Moderator(); + + + enum ResultType { + NORESULT, + + INTERACTIONREQUEST, // reply expected + + PROGRESSPUSH, + PROGRESSUPDATE, + PROGRESSPOP, + + INPUTSTREAM, + STREAM, + + RESULT, + TIMEDOUT, + COMMANDABORTED, + COMMANDFAILED, + INTERACTIVEIO, + UNSUPPORTED, + GENERAL + }; + + + class ConditionRes + : public salhelper::Condition + { + public: + + ConditionRes(osl::Mutex& aMutex,Moderator& aModerator) + : salhelper::Condition(aMutex), + m_aModerator(aModerator) + { + } + + protected: + + bool applies() const { + return m_aModerator.m_aResultType != NORESULT; + } + + private: + + Moderator& m_aModerator; + }; + + + struct Result { + ResultType type; + Any result; + sal_Int32 ioErrorCode; + }; + + + Result getResult(const sal_uInt32 milliSec); + + + enum ReplyType { + NOREPLY, + EXIT, + RETRY, + REQUESTHANDLED + }; + + + class ConditionRep + : public salhelper::Condition + { + public: + + ConditionRep(osl::Mutex& aMutex,Moderator& aModerator) + : salhelper::Condition(aMutex), + m_aModerator(aModerator) + { + } + + protected: + + bool applies() const { + return m_aModerator.m_aReplyType != NOREPLY; + } + + private: + + Moderator& m_aModerator; + }; + + void setReply(ReplyType); + + + void handle( const Reference<XInteractionRequest >& Request ); + + void push( const Any& Status ); + + void update( const Any& Status ); + + void pop( ); + + void setStream(const Reference< XStream >& aStream); + + void setInputStream(const Reference<XInputStream> &rxInputStream); + + +protected: + + virtual void SAL_CALL run(); + + virtual void SAL_CALL onTerminated(); + +private: + + osl::Mutex m_aMutex; + + friend class ConditionRes; + + ConditionRes m_aRes; + ResultType m_aResultType; + sal_Int32 m_nIOErrorCode; + Any m_aResult; + + friend class ConditionRep; + + ConditionRep m_aRep; + ReplyType m_aReplyType; + + Command m_aArg; + ::ucbhelper::Content m_aContent; +}; + + +class ModeratorsActiveDataStreamer + : public ::cppu::WeakImplHelper1<XActiveDataStreamer> +{ +public: + + ModeratorsActiveDataStreamer(Moderator &theModerator); + + ~ModeratorsActiveDataStreamer(); + + // XActiveDataStreamer + virtual void SAL_CALL + setStream( + const Reference< XStream >& aStream + ) + throw( + RuntimeException + ); + + virtual Reference<XStream> SAL_CALL + getStream ( + void + ) throw( + RuntimeException + ) + { + osl::MutexGuard aGuard(m_aMutex); + return m_xStream; + } + + +private: + + Moderator& m_aModerator; + + osl::Mutex m_aMutex; + Reference<XStream> m_xStream; +}; + + + +class ModeratorsActiveDataSink + : public ::cppu::WeakImplHelper1<XActiveDataSink> +{ +public: + + ModeratorsActiveDataSink(Moderator &theModerator); + + ~ModeratorsActiveDataSink(); + + // XActiveDataSink. + virtual void SAL_CALL + setInputStream ( + const Reference<XInputStream> &rxInputStream + ) + throw( + RuntimeException + ); + + virtual Reference<XInputStream> SAL_CALL + getInputStream ( + void + ) throw( + RuntimeException + ) + { + osl::MutexGuard aGuard(m_aMutex); + return m_xStream; + } + + +private: + + Moderator& m_aModerator; + osl::Mutex m_aMutex; + Reference<XInputStream> m_xStream; +}; + + + +ModeratorsActiveDataSink::ModeratorsActiveDataSink(Moderator &theModerator) + : m_aModerator(theModerator) +{ +} + + +ModeratorsActiveDataSink::~ModeratorsActiveDataSink() +{ +} + +// XActiveDataSink. +void SAL_CALL +ModeratorsActiveDataSink::setInputStream ( + const Reference<XInputStream> &rxInputStream +) + throw( + RuntimeException + ) +{ + m_aModerator.setInputStream(rxInputStream); + osl::MutexGuard aGuard(m_aMutex); + m_xStream = rxInputStream; +} + + +ModeratorsActiveDataStreamer::ModeratorsActiveDataStreamer( + Moderator &theModerator +) + : m_aModerator(theModerator) +{ +} + + +ModeratorsActiveDataStreamer::~ModeratorsActiveDataStreamer() +{ +} + +// XActiveDataStreamer. +void SAL_CALL +ModeratorsActiveDataStreamer::setStream ( + const Reference<XStream> &rxStream +) + throw( + RuntimeException + ) +{ + m_aModerator.setStream(rxStream); + osl::MutexGuard aGuard(m_aMutex); + m_xStream = rxStream; +} + + + +class ModeratorsInteractionHandler + : public ::cppu::WeakImplHelper1<XInteractionHandler> +{ +public: + + ModeratorsInteractionHandler(Moderator &theModerator); + + ~ModeratorsInteractionHandler(); + + virtual void SAL_CALL + handle( const Reference<XInteractionRequest >& Request ) + throw (RuntimeException); + +private: + + Moderator& m_aModerator; +}; + + +class ModeratorsProgressHandler + : public ::cppu::WeakImplHelper1<XProgressHandler> +{ +public: + + ModeratorsProgressHandler(Moderator &theModerator); + + ~ModeratorsProgressHandler(); + + virtual void SAL_CALL push( const Any& Status ) + throw ( + RuntimeException); + + virtual void SAL_CALL update( const Any& Status ) + throw (RuntimeException); + + virtual void SAL_CALL pop( ) + throw (RuntimeException); + + +private: + + Moderator& m_aModerator; +}; + + +ModeratorsProgressHandler::ModeratorsProgressHandler(Moderator &theModerator) + : m_aModerator(theModerator) +{ +} + +ModeratorsProgressHandler::~ModeratorsProgressHandler() +{ +} + + +void SAL_CALL ModeratorsProgressHandler::push( const Any& Status ) + throw ( + RuntimeException) +{ + m_aModerator.push(Status); +} + + +void SAL_CALL ModeratorsProgressHandler::update( const Any& Status ) + throw (RuntimeException) +{ + m_aModerator.update(Status); +} + + +void SAL_CALL ModeratorsProgressHandler::pop( ) + throw (RuntimeException) +{ + m_aModerator.pop(); +} + + + + +ModeratorsInteractionHandler::ModeratorsInteractionHandler( + Moderator &aModerator) + : m_aModerator(aModerator) +{ +} + + +ModeratorsInteractionHandler::~ModeratorsInteractionHandler() +{ +} + + +void SAL_CALL +ModeratorsInteractionHandler::handle( + const Reference<XInteractionRequest >& Request +) + throw ( + RuntimeException + ) +{ + // wakes up the mainthread + m_aModerator.handle(Request); +} + + + + +Moderator::Moderator( + Reference < XContent >& xContent, + Reference < XInteractionHandler >& xInteract, + Reference < XProgressHandler >& xProgress, + const Command& rArg +) + throw( + ::com::sun::star::ucb::ContentCreationException, + ::com::sun::star::uno::RuntimeException + ) + : m_aMutex(), + + m_aRes(m_aMutex,*this), + m_aResultType(NORESULT), + m_nIOErrorCode(0), + m_aResult(), + + m_aRep(m_aMutex,*this), + m_aReplyType(NOREPLY), + + m_aArg(rArg), + m_aContent( + xContent, + new UcbTaskEnvironment( + xInteract.is() ? new ModeratorsInteractionHandler(*this) : 0, + xProgress.is() ? new ModeratorsProgressHandler(*this) : 0 + )) +{ + // now exchange the whole data sink stuff + // with a thread safe version + + Reference<XInterface> *pxSink = NULL; + + PostCommandArgument2 aPostArg; + OpenCommandArgument2 aOpenArg; + + int dec(2); + if(m_aArg.Argument >>= aPostArg) { + pxSink = &aPostArg.Sink; + dec = 0; + } + else if(m_aArg.Argument >>= aOpenArg) { + pxSink = &aOpenArg.Sink; + dec = 1; + } + + if(dec ==2) + throw ContentCreationException(); + + Reference < XActiveDataSink > xActiveSink(*pxSink,UNO_QUERY); + if(xActiveSink.is()) + *pxSink = Reference<XInterface>( + (cppu::OWeakObject*)new ModeratorsActiveDataSink(*this)); + + Reference<XActiveDataStreamer> xStreamer( *pxSink, UNO_QUERY ); + if ( xStreamer.is() ) + *pxSink = Reference<XInterface>( + (cppu::OWeakObject*)new ModeratorsActiveDataStreamer(*this)); + + if(dec == 0) + m_aArg.Argument <<= aPostArg; + else if(dec == 1) + m_aArg.Argument <<= aOpenArg; +} + + +Moderator::~Moderator() +{ +} + + +Moderator::Result Moderator::getResult(const sal_uInt32 milliSec) +{ + Result ret; + try { + salhelper::ConditionWaiter aWaiter(m_aRes,milliSec); + ret.type = m_aResultType; + ret.result = m_aResult; + ret.ioErrorCode = m_nIOErrorCode; + + // reset + m_aResultType = NORESULT; + } + catch(const salhelper::ConditionWaiter::timedout&) + { + ret.type = TIMEDOUT; + } + + return ret; +} + + +void Moderator::setReply(ReplyType aReplyType ) +{ + salhelper::ConditionModifier aMod(m_aRep); + m_aReplyType = aReplyType; +} + + +void Moderator::handle( const Reference<XInteractionRequest >& Request ) +{ + ReplyType aReplyType; + + do { + { + salhelper::ConditionModifier aMod(m_aRes); + m_aResultType = INTERACTIONREQUEST; + m_aResult <<= Request; + } + + { + salhelper::ConditionWaiter aWait(m_aRep); + aReplyType = m_aReplyType; + + // reset + m_aReplyType = NOREPLY; + } + + if(aReplyType == EXIT) { + Sequence<Reference<XInteractionContinuation> > aSeq( + Request->getContinuations()); + for(sal_Int32 i = 0; i < aSeq.getLength(); ++i) { + Reference<XInteractionAbort> aRef(aSeq[i],UNO_QUERY); + if(aRef.is()) { + aRef->select(); + } + } + + // resignal the exitcondition + setReply(EXIT); + break; + } + } while(aReplyType != REQUESTHANDLED); +} + + + +void Moderator::push( const Any& Status ) +{ + { + salhelper::ConditionModifier aMod(m_aRes); + m_aResultType = PROGRESSPUSH; + m_aResult = Status; + } + ReplyType aReplyType; + { + salhelper::ConditionWaiter aWait(m_aRep); + aReplyType = m_aReplyType; + m_aReplyType = NOREPLY; + } + if(aReplyType == EXIT) + setReply(EXIT); +} + + +void Moderator::update( const Any& Status ) +{ + { + salhelper::ConditionModifier aMod(m_aRes); + m_aResultType = PROGRESSUPDATE; + m_aResult = Status; + } + ReplyType aReplyType; + { + salhelper::ConditionWaiter aWait(m_aRep); + aReplyType = m_aReplyType; + m_aReplyType = NOREPLY; + } + if(aReplyType == EXIT) + setReply(EXIT); +} + + +void Moderator::pop( ) +{ + { + salhelper::ConditionModifier aMod(m_aRes); + m_aResultType = PROGRESSPOP; + } + ReplyType aReplyType; + { + salhelper::ConditionWaiter aWait(m_aRep); + aReplyType = m_aReplyType; + m_aReplyType = NOREPLY; + } + if(aReplyType == EXIT) + setReply(EXIT); +} + + +void Moderator::setStream(const Reference< XStream >& aStream) +{ + { + salhelper::ConditionModifier aMod(m_aRes); + m_aResultType = STREAM; + m_aResult <<= aStream; + } + ReplyType aReplyType; + { + salhelper::ConditionWaiter aWait(m_aRep); + aReplyType = m_aReplyType; + m_aReplyType = NOREPLY; + } + if(aReplyType == EXIT) + setReply(EXIT); +} + + +void Moderator::setInputStream(const Reference<XInputStream> &rxInputStream) +{ + { + salhelper::ConditionModifier aMod(m_aRes); + m_aResultType = INPUTSTREAM; + m_aResult <<= rxInputStream; + } + ReplyType aReplyType; + { + salhelper::ConditionWaiter aWait(m_aRep); + aReplyType = m_aReplyType; + m_aReplyType = NOREPLY; + } + if(aReplyType == EXIT) + setReply(EXIT); +} + + + +void SAL_CALL Moderator::run() +{ + ResultType aResultType; + Any aResult; + sal_Int32 nIOErrorCode = 0; + + try + { + aResult = m_aContent.executeCommand(m_aArg.Name,m_aArg.Argument); + aResultType = RESULT; + } + catch ( CommandAbortedException ) + { + aResultType = COMMANDABORTED; + } + catch ( CommandFailedException ) + { + aResultType = COMMANDFAILED; + } + catch ( InteractiveIOException& r ) + { + nIOErrorCode = r.Code; + aResultType = INTERACTIVEIO; + } + catch ( UnsupportedDataSinkException& ) + { + aResultType = UNSUPPORTED; + } + catch ( Exception ) + { + aResultType = GENERAL; + } + + { + salhelper::ConditionModifier aMod(m_aRes); + m_aResultType = aResultType; + m_aResult = aResult; + m_nIOErrorCode = nIOErrorCode; + } +} + + + +void SAL_CALL Moderator::onTerminated() +{ + { + salhelper::ConditionWaiter aWaiter(m_aRep); + } + delete this; +} + + +/** + Function for opening UCB contents synchronously, + but with handled timeout; +*/ + +static sal_Bool _UCBOpenContentSync( + UcbLockBytesRef xLockBytes, + Reference < XContent > xContent, + const Command& rArg, + Reference < XInterface > xSink, + Reference < XInteractionHandler > xInteract, + Reference < XProgressHandler > xProgress, + UcbLockBytesHandlerRef xHandler ); + + +static sal_Bool UCBOpenContentSync( + UcbLockBytesRef xLockBytes, + Reference < XContent > xContent, + const Command& rArg, + Reference < XInterface > xSink, + Reference < XInteractionHandler > xInteract, + Reference < XProgressHandler > xProgress, + UcbLockBytesHandlerRef xHandler ) +{ + // http protocol must be handled in a special way: + // during the opening process the input stream may change + // only the last inputstream after notifying the document + // headers is valid + + Reference<XContentIdentifier> xContId( + xContent.is() ? xContent->getIdentifier() : 0 ); + + rtl::OUString aScheme; + if(xContId.is()) + aScheme = xContId->getContentProviderScheme(); + + // now determine wether we use a timeout or not; + if( ! aScheme.equalsIgnoreAsciiCaseAscii("http") && + ! aScheme.equalsIgnoreAsciiCaseAscii("https") && + ! aScheme.equalsIgnoreAsciiCaseAscii("vnd.sun.star.webdav") && + ! aScheme.equalsIgnoreAsciiCaseAscii("ftp")) + return _UCBOpenContentSync( + xLockBytes,xContent,rArg,xSink,xInteract,xProgress,xHandler); + + if ( (aScheme.compareToAscii( "http" ) != COMPARE_EQUAL) || + (aScheme.compareToAscii( "https" ) != COMPARE_EQUAL) ) + xLockBytes->SetStreamValid_Impl(); + + Reference< XPropertiesChangeListener > xListener; + Reference< XPropertiesChangeNotifier > xProps(xContent,UNO_QUERY); + if(xProps.is()) { + xListener = + new UcbPropertiesChangeListener_Impl(xLockBytes); + xProps->addPropertiesChangeListener( + Sequence< ::rtl::OUString >(), + xListener); + } + + Any aResult; + bool bException(false); + bool bAborted(false); + bool bResultAchieved(false); + + Moderator* pMod = 0; + try { + pMod = new Moderator(xContent,xInteract,xProgress,rArg); + pMod->create(); + } catch(const ContentCreationException&) { + bResultAchieved = bException = true; + xLockBytes->SetError( ERRCODE_IO_GENERAL ); + } + + sal_uInt32 nTimeout(5000); // initially 5000 milliSec + while(!bResultAchieved) { + + Moderator::Result res; + // try to get the result for with timeout + res = pMod->getResult(nTimeout); + + switch(res.type) { + case Moderator::PROGRESSPUSH: + { + if(xProgress.is()) + xProgress->push(res.result); + pMod->setReply(Moderator::REQUESTHANDLED); + break; + } + case Moderator::PROGRESSUPDATE: + { + if(xProgress.is()) + xProgress->update(res.result); + pMod->setReply(Moderator::REQUESTHANDLED); + break; + } + case Moderator::PROGRESSPOP: + { + if(xProgress.is()) + xProgress->pop(); + pMod->setReply(Moderator::REQUESTHANDLED); + break; + } + case Moderator::STREAM: + { + Reference<XStream> result; + if(res.result >>= result) { + Reference < XActiveDataStreamer > xStreamer( + xSink, UNO_QUERY + ); + + if(xStreamer.is()) + xStreamer->setStream(result); + } + pMod->setReply(Moderator::REQUESTHANDLED); + break; + } + case Moderator::INPUTSTREAM: + { + Reference<XInputStream> result; + res.result >>= result; + Reference < XActiveDataSink > xActiveSink( + xSink, UNO_QUERY + ); + + if(xActiveSink.is()) + xActiveSink->setInputStream(result); + pMod->setReply(Moderator::REQUESTHANDLED); + break; + } + case Moderator::TIMEDOUT: + { + Reference<XInteractionRetry> xRet; + if(xInteract.is()) { + InteractiveNetworkConnectException aExcep; + INetURLObject aURL( + xContId.is() ? + xContId->getContentIdentifier() : + rtl::OUString() ); + aExcep.Server = aURL.GetHost(); + aExcep.Classification = InteractionClassification_ERROR; + aExcep.Message = + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "server not responding after five seconds")); + Any request; + request <<= aExcep; + ucbhelper::InteractionRequest *ir = + new ucbhelper::InteractionRequest(request); + Reference<XInteractionRequest> xIR(ir); + Sequence<Reference<XInteractionContinuation> > aSeq(2); + ucbhelper::InteractionRetry *retryP = + new ucbhelper::InteractionRetry(ir); + aSeq[0] = retryP; + ucbhelper::InteractionAbort *abortP = + new ucbhelper::InteractionAbort(ir); + aSeq[1] = abortP; + + ir->setContinuations(aSeq); + xInteract->handle(xIR); + rtl::Reference< ucbhelper::InteractionContinuation > ref + = ir->getSelection(); + if(ref.is()) { + Reference<XInterface> xInt(ref.get()); + xRet = Reference<XInteractionRetry>(xInt,UNO_QUERY); + } + } + + if(!xRet.is()) { + bAborted = true; + xLockBytes->SetError(ERRCODE_ABORT); + } + + break; + } + case Moderator::INTERACTIONREQUEST: + { + Reference<XInteractionRequest> Request; + res.result >>= Request; + xInteract->handle(Request); + pMod->setReply(Moderator::REQUESTHANDLED); + break; + } + case Moderator::RESULT: + { + bResultAchieved = true; + aResult = res.result; + break; + } + case Moderator::COMMANDABORTED: + { + bAborted = true; + xLockBytes->SetError( ERRCODE_ABORT ); + break; + } + case Moderator::COMMANDFAILED: + { + bAborted = true; + xLockBytes->SetError( ERRCODE_ABORT ); + break; + } + case Moderator::INTERACTIVEIO: + { + bException = true; + if ( res.ioErrorCode == IOErrorCode_ACCESS_DENIED || + res.ioErrorCode == IOErrorCode_LOCKING_VIOLATION ) + xLockBytes->SetError( ERRCODE_IO_ACCESSDENIED ); + else if ( res.ioErrorCode == IOErrorCode_NOT_EXISTING ) + xLockBytes->SetError( ERRCODE_IO_NOTEXISTS ); + else if ( res.ioErrorCode == IOErrorCode_CANT_READ ) + xLockBytes->SetError( ERRCODE_IO_CANTREAD ); + else + xLockBytes->SetError( ERRCODE_IO_GENERAL ); + break; + } + case Moderator::UNSUPPORTED: + { + bException = true; + xLockBytes->SetError( ERRCODE_IO_NOTSUPPORTED ); + break; + } + default: + { + bException = true; + xLockBytes->SetError( ERRCODE_IO_GENERAL ); + break; + } + } + + bResultAchieved |= bException; + bResultAchieved |= bAborted; + if(nTimeout == 5000) nTimeout *= 2; + } + + if(pMod) pMod->setReply(Moderator::EXIT); + + if ( bAborted || bException ) + { + if( xHandler.Is() ) + xHandler->Handle( UcbLockBytesHandler::CANCEL, xLockBytes ); + + Reference < XActiveDataSink > xActiveSink( xSink, UNO_QUERY ); + if ( xActiveSink.is() ) + xActiveSink->setInputStream( Reference < XInputStream >() ); + + Reference < XActiveDataStreamer > xStreamer( xSink, UNO_QUERY ); + if ( xStreamer.is() ) + xStreamer->setStream( Reference < XStream >() ); + } + + Reference < XActiveDataControl > xControl( xSink, UNO_QUERY ); + if ( xControl.is() ) + xControl->terminate(); + + if ( xProps.is() ) + xProps->removePropertiesChangeListener( + Sequence< ::rtl::OUString >(), + xListener ); + + return ( bAborted || bException ); +} + +/** + Function for opening UCB contents synchronously + */ +static sal_Bool _UCBOpenContentSync( + UcbLockBytesRef xLockBytes, + Reference < XContent > xContent, + const Command& rArg, + Reference < XInterface > xSink, + Reference < XInteractionHandler > xInteract, + Reference < XProgressHandler > xProgress, + UcbLockBytesHandlerRef xHandler ) +{ + ::ucbhelper::Content aContent( xContent, new UcbTaskEnvironment( xInteract, xProgress ) ); + Reference < XContentIdentifier > xIdent = xContent->getIdentifier(); + ::rtl::OUString aScheme = xIdent->getContentProviderScheme(); + + // http protocol must be handled in a special way: during the opening process the input stream may change + // only the last inputstream after notifying the document headers is valid + if ( aScheme.compareToAscii("http") != COMPARE_EQUAL ) + xLockBytes->SetStreamValid_Impl(); + + Reference< XPropertiesChangeListener > xListener = new UcbPropertiesChangeListener_Impl( xLockBytes ); + Reference< XPropertiesChangeNotifier > xProps ( xContent, UNO_QUERY ); + if ( xProps.is() ) + xProps->addPropertiesChangeListener( Sequence< ::rtl::OUString >(), xListener ); + + Any aResult; + bool bException = false; + bool bAborted = false; + + try + { + aResult = aContent.executeCommand( rArg.Name, rArg.Argument ); + } + catch ( CommandAbortedException ) + { + bAborted = true; + xLockBytes->SetError( ERRCODE_ABORT ); + } + catch ( CommandFailedException ) + { + bAborted = true; + xLockBytes->SetError( ERRCODE_ABORT ); + } + catch ( InteractiveIOException& r ) + { + bException = true; + if ( r.Code == IOErrorCode_ACCESS_DENIED || r.Code == IOErrorCode_LOCKING_VIOLATION ) + xLockBytes->SetError( ERRCODE_IO_ACCESSDENIED ); + else if ( r.Code == IOErrorCode_NOT_EXISTING ) + xLockBytes->SetError( ERRCODE_IO_NOTEXISTS ); + else if ( r.Code == IOErrorCode_CANT_READ ) + xLockBytes->SetError( ERRCODE_IO_CANTREAD ); + else + xLockBytes->SetError( ERRCODE_IO_GENERAL ); + } + catch ( UnsupportedDataSinkException& ) + { + bException = true; + xLockBytes->SetError( ERRCODE_IO_NOTSUPPORTED ); + } + catch ( Exception ) + { + bException = true; + xLockBytes->SetError( ERRCODE_IO_GENERAL ); + } + + if ( bAborted || bException ) + { + if( xHandler.Is() ) + xHandler->Handle( UcbLockBytesHandler::CANCEL, xLockBytes ); + + Reference < XActiveDataSink > xActiveSink( xSink, UNO_QUERY ); + if ( xActiveSink.is() ) + xActiveSink->setInputStream( Reference < XInputStream >() ); + + Reference < XActiveDataStreamer > xStreamer( xSink, UNO_QUERY ); + if ( xStreamer.is() ) + xStreamer->setStream( Reference < XStream >() ); + } + + Reference < XActiveDataControl > xControl( xSink, UNO_QUERY ); + if ( xControl.is() ) + xControl->terminate(); + + + if ( xProps.is() ) + xProps->removePropertiesChangeListener( Sequence< ::rtl::OUString >(), xListener ); + + return ( bAborted || bException ); +} + + +//---------------------------------------------------------------------------- +UcbLockBytes::UcbLockBytes( UcbLockBytesHandler* pHandler ) + : m_xInputStream (NULL) + , m_pCommandThread( NULL ) + , m_xHandler( pHandler ) + , m_nError( ERRCODE_NONE ) + , m_bTerminated (sal_False) + , m_bDontClose( sal_False ) + , m_bStreamValid (sal_False) +{ + SetSynchronMode( TRUE ); +} + +//---------------------------------------------------------------------------- +UcbLockBytes::~UcbLockBytes() +{ + if ( !m_bDontClose ) + { + if ( m_xInputStream.is() ) + { + try + { + m_xInputStream->closeInput(); + } + catch ( RuntimeException const & ) + {} + catch ( IOException const & ) + {} + } + } + + if ( !m_xInputStream.is() && m_xOutputStream.is() ) + { + try + { + m_xOutputStream->closeOutput(); + } + catch ( RuntimeException const & ) + {} + catch ( IOException const & ) + {} + } +} + +Reference < XInputStream > UcbLockBytes::getInputStream() +{ + vos::OClearableGuard aGuard( m_aMutex ); + m_bDontClose = sal_True; + return m_xInputStream; +} + +Reference < XStream > UcbLockBytes::getStream() +{ + vos::OClearableGuard aGuard( m_aMutex ); + Reference < XStream > xStream( m_xSeekable, UNO_QUERY ); + if ( xStream.is() ) + m_bDontClose = sal_True; + return xStream; +} + +//---------------------------------------------------------------------------- + +sal_Bool UcbLockBytes::setStream_Impl( const Reference<XStream>& aStream ) +{ + vos::OClearableGuard aGuard( m_aMutex ); + if ( aStream.is() ) + { + m_xOutputStream = aStream->getOutputStream(); + setInputStream_Impl( aStream->getInputStream(), sal_False ); + m_xSeekable = Reference < XSeekable > ( aStream, UNO_QUERY ); + } + else + { + m_xOutputStream = Reference < XOutputStream >(); + setInputStream_Impl( Reference < XInputStream >() ); + } + + return m_xInputStream.is(); +} + +sal_Bool UcbLockBytes::setInputStream_Impl( const Reference<XInputStream> &rxInputStream, sal_Bool bSetXSeekable ) +{ + sal_Bool bRet = sal_False; + + try + { + vos::OClearableGuard aGuard( m_aMutex ); + + if ( !m_bDontClose && m_xInputStream.is() ) + m_xInputStream->closeInput(); + + m_xInputStream = rxInputStream; + + if( bSetXSeekable ) + { + m_xSeekable = Reference < XSeekable > ( rxInputStream, UNO_QUERY ); + if( !m_xSeekable.is() && rxInputStream.is() ) + { + Reference < XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory(); + Reference< XOutputStream > rxTempOut = Reference < XOutputStream > ( + xFactory->createInstance ( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ), + UNO_QUERY ); + + if( rxTempOut.is() ) + { + ::comphelper::OStorageHelper::CopyInputToOutput( rxInputStream, rxTempOut ); + m_xInputStream = Reference< XInputStream >( rxTempOut, UNO_QUERY ); + m_xSeekable = Reference < XSeekable > ( rxTempOut, UNO_QUERY ); + } + } + } + + bRet = m_xInputStream.is(); + // aGuard.clear(); + } + catch( Exception& ) + {} + + if ( m_bStreamValid && m_xInputStream.is() ) + m_aInitialized.set(); + + return bRet; +} + +void UcbLockBytes::SetStreamValid_Impl() +{ + m_bStreamValid = sal_True; + if ( m_xInputStream.is() ) + m_aInitialized.set(); +} + +//---------------------------------------------------------------------------- +void UcbLockBytes::terminate_Impl() +{ + m_bTerminated = sal_True; + m_aInitialized.set(); + m_aTerminated.set(); + + if ( GetError() == ERRCODE_NONE && !m_xInputStream.is() ) + { + DBG_ERROR("No InputStream, but no error set!" ); + SetError( ERRCODE_IO_NOTEXISTS ); + } + + if ( m_xHandler.Is() ) + m_xHandler->Handle( UcbLockBytesHandler::DONE, this ); +} + +//---------------------------------------------------------------------------- +void UcbLockBytes::SetSynchronMode (BOOL bSynchron) +{ + SvLockBytes::SetSynchronMode (bSynchron); +} + +//---------------------------------------------------------------------------- +ErrCode UcbLockBytes::ReadAt ( ULONG nPos, void *pBuffer, ULONG nCount, ULONG *pRead) const +{ + if ( IsSynchronMode() ) + { + UcbLockBytes* pThis = const_cast < UcbLockBytes* >( this ); + pThis->m_aInitialized.wait(); + } + + Reference <XInputStream> xStream = getInputStream_Impl(); + if ( !xStream.is() ) + { + if ( m_bTerminated ) + return ERRCODE_IO_CANTREAD; + else + return ERRCODE_IO_PENDING; + } + + if ( pRead ) + *pRead = 0; + + Reference <XSeekable> xSeekable = getSeekable_Impl(); + if ( !xSeekable.is() ) + return ERRCODE_IO_CANTREAD; + + try + { + xSeekable->seek( nPos ); + } + catch ( IOException ) + { + return ERRCODE_IO_CANTSEEK; + } + catch (com::sun::star::lang::IllegalArgumentException) + { + return ERRCODE_IO_CANTSEEK; + } + + Sequence<sal_Int8> aData; + sal_Int32 nSize; + + nCount = VOS_MIN(nCount, 0x7FFFFFFF); + try + { + if ( !m_bTerminated && !IsSynchronMode() ) + { + sal_uInt64 nLen = xSeekable->getLength(); + if ( nPos + nCount > nLen ) + return ERRCODE_IO_PENDING; + } + + nSize = xStream->readBytes( aData, sal_Int32(nCount) ); + } + catch (IOException) + { + return ERRCODE_IO_CANTREAD; + } + + rtl_copyMemory (pBuffer, aData.getConstArray(), nSize); + if (pRead) + *pRead = ULONG(nSize); + + return ERRCODE_NONE; +} + +//---------------------------------------------------------------------------- +ErrCode UcbLockBytes::WriteAt ( ULONG nPos, const void *pBuffer, ULONG nCount, ULONG *pWritten) +{ + if ( pWritten ) + *pWritten = 0; + + DBG_ASSERT( IsSynchronMode(), "Writing is only possible in SynchronMode!" ); + DBG_ASSERT( m_aInitialized.check(), "Writing bevor stream is ready!" ); + + Reference <XSeekable> xSeekable = getSeekable_Impl(); + Reference <XOutputStream> xOutputStream = getOutputStream_Impl(); + if ( !xOutputStream.is() || !xSeekable.is() ) + return ERRCODE_IO_CANTWRITE; + + try + { + xSeekable->seek( nPos ); + } + catch ( IOException ) + { + return ERRCODE_IO_CANTSEEK; + } + + sal_Int8* pData = (sal_Int8*) pBuffer; + Sequence<sal_Int8> aData( pData, nCount ); + try + { + xOutputStream->writeBytes( aData ); + if ( pWritten ) + *pWritten = nCount; + } + catch ( Exception ) + { + return ERRCODE_IO_CANTWRITE; + } + + return ERRCODE_NONE; +} + +//---------------------------------------------------------------------------- +ErrCode UcbLockBytes::Flush() const +{ + Reference <XOutputStream > xOutputStream = getOutputStream_Impl(); + if ( !xOutputStream.is() ) + return ERRCODE_IO_CANTWRITE; + xOutputStream->flush(); + return ERRCODE_NONE; +} + +//---------------------------------------------------------------------------- +ErrCode UcbLockBytes::SetSize (ULONG nNewSize) +{ + SvLockBytesStat aStat; + Stat( &aStat, (SvLockBytesStatFlag) 0 ); + ULONG nSize = aStat.nSize; + + if ( nSize > nNewSize ) + { + Reference < XTruncate > xTrunc( getOutputStream_Impl(), UNO_QUERY ); + if ( xTrunc.is() ) + { + xTrunc->truncate(); + nSize = 0; + } + else { + DBG_WARNING("Not truncatable!"); + } + } + + if ( nSize < nNewSize ) + { + ULONG nDiff = nNewSize-nSize, nCount=0; + BYTE* pBuffer = new BYTE[ nDiff ]; + memset(pBuffer, 0, nDiff); // initialize for enhanced security + WriteAt( nSize, pBuffer, nDiff, &nCount ); + delete[] pBuffer; + if ( nCount != nDiff ) + return ERRCODE_IO_CANTWRITE; + } + + return ERRCODE_NONE; +} + +//---------------------------------------------------------------------------- +ErrCode UcbLockBytes::Stat( SvLockBytesStat *pStat, SvLockBytesStatFlag) const +{ + if ( IsSynchronMode() ) + { + UcbLockBytes* pThis = const_cast < UcbLockBytes* >( this ); + pThis->m_aInitialized.wait(); + } + + if (!pStat) + return ERRCODE_IO_INVALIDPARAMETER; + + Reference <XInputStream> xStream = getInputStream_Impl(); + Reference <XSeekable> xSeekable = getSeekable_Impl(); + + if ( !xStream.is() ) + { + if ( m_bTerminated ) + return ERRCODE_IO_INVALIDACCESS; + else + return ERRCODE_IO_PENDING; + } + else if( !xSeekable.is() ) + return ERRCODE_IO_CANTTELL; + + try + { + pStat->nSize = ULONG(xSeekable->getLength()); + } + catch (IOException) + { + return ERRCODE_IO_CANTTELL; + } + + return ERRCODE_NONE; +} + +//---------------------------------------------------------------------------- +void UcbLockBytes::Cancel() +{ + // is alive only for compatibility reasons + OSL_ENSURE( m_bTerminated, "UcbLockBytes is not thread safe so it can be used only syncronously!\n" ); +} + +//---------------------------------------------------------------------------- +IMPL_LINK( UcbLockBytes, DataAvailHdl, void*, EMPTYARG ) +{ + if ( hasInputStream_Impl() && m_xHandler.Is() ) + m_xHandler->Handle( UcbLockBytesHandler::DATA_AVAILABLE, this ); + + return 0; +} + +UcbLockBytesRef UcbLockBytes::CreateInputLockBytes( const Reference< XInputStream >& xInputStream ) +{ + if( !xInputStream.is() ) + return NULL;; + + UcbLockBytesRef xLockBytes = new UcbLockBytes(); + xLockBytes->setDontClose_Impl(); + xLockBytes->setInputStream_Impl( xInputStream ); + xLockBytes->terminate_Impl(); + return xLockBytes; +} + +UcbLockBytesRef UcbLockBytes::CreateLockBytes( const Reference< XStream >& xStream ) +{ + if( !xStream.is() ) + return NULL;; + + UcbLockBytesRef xLockBytes = new UcbLockBytes(); + xLockBytes->setDontClose_Impl(); + xLockBytes->setStream_Impl( xStream ); + xLockBytes->terminate_Impl(); + return xLockBytes; +} + +UcbLockBytesRef UcbLockBytes::CreateLockBytes( const Reference < XContent >& xContent, const ::rtl::OUString& rReferer, const ::rtl::OUString& rMediaType, + const Reference < XInputStream >& xPostData, const Reference < XInteractionHandler >& xInteractionHandler, UcbLockBytesHandler* pHandler ) +{ + if( !xContent.is() ) + return NULL;; + + UcbLockBytesRef xLockBytes = new UcbLockBytes( pHandler ); + xLockBytes->SetSynchronMode( !pHandler ); + Reference< XActiveDataControl > xSink = (XActiveDataControl*) new UcbDataSink_Impl( xLockBytes ); + + PostCommandArgument2 aArgument; + aArgument.Source = xPostData; + aArgument.Sink = xSink; + aArgument.MediaType = rMediaType; + aArgument.Referer = rReferer; + + Command aCommand; + aCommand.Name = ::rtl::OUString::createFromAscii ("post"); + aCommand.Argument <<= aArgument; + + Reference< XProgressHandler > xProgressHdl = new ProgressHandler_Impl( LINK( &xLockBytes, UcbLockBytes, DataAvailHdl ) ); + + sal_Bool bError = UCBOpenContentSync( xLockBytes, + xContent, + aCommand, + xSink, + xInteractionHandler, + xProgressHdl, + pHandler ); + + if ( xLockBytes->GetError() == ERRCODE_NONE && ( bError || !xLockBytes->getInputStream().is() ) ) + { + DBG_ERROR("No InputStream, but no error set!" ); + xLockBytes->SetError( ERRCODE_IO_GENERAL ); + } + + return xLockBytes; +} + +UcbLockBytesRef UcbLockBytes::CreateLockBytes( const Reference < XContent >& xContent, const Sequence < PropertyValue >& rProps, + StreamMode eOpenMode, const Reference < XInteractionHandler >& xInteractionHandler, UcbLockBytesHandler* pHandler ) +{ + if( !xContent.is() ) + return NULL;; + + UcbLockBytesRef xLockBytes = new UcbLockBytes( pHandler ); + xLockBytes->SetSynchronMode( !pHandler ); + Reference< XActiveDataControl > xSink; + if ( eOpenMode & STREAM_WRITE ) + xSink = (XActiveDataControl*) new UcbStreamer_Impl( xLockBytes ); + else + xSink = (XActiveDataControl*) new UcbDataSink_Impl( xLockBytes ); + + if ( rProps.getLength() ) + { + Reference < XCommandProcessor > xProcessor( xContent, UNO_QUERY ); + Command aCommand; + aCommand.Name = ::rtl::OUString::createFromAscii("setPropertyValues"); + aCommand.Handle = -1; /* unknown */ + aCommand.Argument <<= rProps; + xProcessor->execute( aCommand, 0, Reference < XCommandEnvironment >() ); + } + + OpenCommandArgument2 aArgument; + aArgument.Sink = xSink; + aArgument.Mode = OpenMode::DOCUMENT; + + Command aCommand; + aCommand.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("open") ); + aCommand.Argument <<= aArgument; + + Reference< XProgressHandler > xProgressHdl = new ProgressHandler_Impl( LINK( &xLockBytes, UcbLockBytes, DataAvailHdl ) ); + + sal_Bool bError = UCBOpenContentSync( xLockBytes, + xContent, + aCommand, + xSink, + xInteractionHandler, + xProgressHdl, + pHandler ); + + if ( xLockBytes->GetError() == ERRCODE_NONE && ( bError || !xLockBytes->getInputStream().is() ) ) + { + DBG_ERROR("No InputStream, but no error set!" ); + xLockBytes->SetError( ERRCODE_IO_GENERAL ); + } + + return xLockBytes; +} + +} diff --git a/unotools/source/ucbhelper/ucbstreamhelper.cxx b/unotools/source/ucbhelper/ucbstreamhelper.cxx new file mode 100644 index 000000000000..8a574dec66d4 --- /dev/null +++ b/unotools/source/ucbhelper/ucbstreamhelper.cxx @@ -0,0 +1,251 @@ +/************************************************************************* + * + * 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: ucbstreamhelper.cxx,v $ + * $Revision: 1.21 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General 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_unotools.hxx" + +#include <unotools/ucblockbytes.hxx> +#include <unotools/ucbstreamhelper.hxx> +#include <comphelper/processfactory.hxx> +#include <com/sun/star/ucb/CommandAbortedException.hpp> + +#ifndef _COM_SUN_STAR_UCB_XCOMMANDENVIRONMENT_HDL_ +#include <com/sun/star/ucb/XCommandEnvironment.hdl> +#endif +#include <com/sun/star/ucb/InsertCommandArgument.hpp> +#include <com/sun/star/io/XActiveDataStreamer.hpp> + +#include <ucbhelper/contentbroker.hxx> +#include <ucbhelper/content.hxx> +#include <tools/debug.hxx> +#include <unotools/streamwrap.hxx> + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::ucb; +using namespace ::com::sun::star::task; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; + +namespace utl +{ + +static SvStream* lcl_CreateStream( const String& rFileName, StreamMode eOpenMode, + Reference < XInteractionHandler > xInteractionHandler, + UcbLockBytesHandler* pHandler, sal_Bool /*bForceSynchron*/, sal_Bool bEnsureFileExists ) +{ + SvStream* pStream = NULL; + ::ucbhelper::ContentBroker* pBroker = ::ucbhelper::ContentBroker::get(); + if ( pBroker ) + { + UcbLockBytesRef xLockBytes; + if ( eOpenMode & STREAM_WRITE ) + { + sal_Bool bTruncate = ( eOpenMode & STREAM_TRUNC ) != 0; + if ( bTruncate ) + { + try + { + // truncate is implemented with deleting the original file + ::ucbhelper::Content aCnt( rFileName, Reference < XCommandEnvironment >() ); + aCnt.executeCommand( ::rtl::OUString::createFromAscii( "delete" ), makeAny( sal_Bool( sal_True ) ) ); + } + + catch ( CommandAbortedException& ) + { + // couldn't truncate/delete + } + catch ( ContentCreationException& ) + { + } + catch ( Exception& ) + { + } + } + + if ( bEnsureFileExists || bTruncate ) + { + try + { + // make sure that the desired file exists before trying to open + SvMemoryStream aStream(0,0); + ::utl::OInputStreamWrapper* pInput = new ::utl::OInputStreamWrapper( aStream ); + Reference< XInputStream > xInput( pInput ); + + ::ucbhelper::Content aContent( rFileName, Reference < XCommandEnvironment >() ); + InsertCommandArgument aInsertArg; + aInsertArg.Data = xInput; + + aInsertArg.ReplaceExisting = sal_False; + Any aCmdArg; + aCmdArg <<= aInsertArg; + aContent.executeCommand( ::rtl::OUString::createFromAscii( "insert" ), aCmdArg ); + } + + // it is NOT an error when the stream already exists and no truncation was desired + catch ( CommandAbortedException& ) + { + // currently never an error is detected ! + } + catch ( ContentCreationException& ) + { + } + catch ( Exception& ) + { + } + } + } + + try + { + // create LockBytes using UCB + ::ucbhelper::Content aContent( rFileName, Reference < XCommandEnvironment >() ); + xLockBytes = UcbLockBytes::CreateLockBytes( aContent.get(), Sequence < PropertyValue >(), + eOpenMode, xInteractionHandler, pHandler ); + if ( xLockBytes.Is() ) + { + pStream = new SvStream( xLockBytes ); + pStream->SetBufferSize( 4096 ); + pStream->SetError( xLockBytes->GetError() ); + } + } + catch ( CommandAbortedException& ) + { + } + catch ( ContentCreationException& ) + { + } + catch ( Exception& ) + { + } + } + else + // if no UCB is present at least conventional file io is supported + pStream = new SvFileStream( rFileName, eOpenMode ); + + return pStream; +} + +//============================================================================ + +SvStream* UcbStreamHelper::CreateStream( const String& rFileName, StreamMode eOpenMode, + UcbLockBytesHandler* pHandler, sal_Bool bForceSynchron ) +{ + return lcl_CreateStream( rFileName, eOpenMode, Reference < XInteractionHandler >(), pHandler, bForceSynchron, sal_True /* bEnsureFileExists */ ); +} + +SvStream* UcbStreamHelper::CreateStream( const String& rFileName, StreamMode eOpenMode, + Reference < XInteractionHandler > xInteractionHandler, + UcbLockBytesHandler* pHandler, sal_Bool bForceSynchron ) +{ + return lcl_CreateStream( rFileName, eOpenMode, xInteractionHandler, pHandler, bForceSynchron, sal_True /* bEnsureFileExists */ ); +} + +SvStream* UcbStreamHelper::CreateStream( const String& rFileName, StreamMode eOpenMode, + sal_Bool bFileExists, + UcbLockBytesHandler* pHandler, sal_Bool bForceSynchron ) +{ + return lcl_CreateStream( rFileName, eOpenMode, Reference < XInteractionHandler >(), pHandler, bForceSynchron, !bFileExists ); +} + +SvStream* UcbStreamHelper::CreateStream( Reference < XInputStream > xStream ) +{ + SvStream* pStream = NULL; + UcbLockBytesRef xLockBytes = UcbLockBytes::CreateInputLockBytes( xStream ); + if ( xLockBytes.Is() ) + { + pStream = new SvStream( xLockBytes ); + pStream->SetBufferSize( 4096 ); + pStream->SetError( xLockBytes->GetError() ); + } + + return pStream; +} + +SvStream* UcbStreamHelper::CreateStream( Reference < XStream > xStream ) +{ + SvStream* pStream = NULL; + if ( xStream->getOutputStream().is() ) + { + UcbLockBytesRef xLockBytes = UcbLockBytes::CreateLockBytes( xStream ); + if ( xLockBytes.Is() ) + { + pStream = new SvStream( xLockBytes ); + pStream->SetBufferSize( 4096 ); + pStream->SetError( xLockBytes->GetError() ); + } + } + else + return CreateStream( xStream->getInputStream() ); + + return pStream; +} + +SvStream* UcbStreamHelper::CreateStream( Reference < XInputStream > xStream, sal_Bool bCloseStream ) +{ + SvStream* pStream = NULL; + UcbLockBytesRef xLockBytes = UcbLockBytes::CreateInputLockBytes( xStream ); + if ( xLockBytes.Is() ) + { + if ( !bCloseStream ) + xLockBytes->setDontClose_Impl(); + + pStream = new SvStream( xLockBytes ); + pStream->SetBufferSize( 4096 ); + pStream->SetError( xLockBytes->GetError() ); + } + + return pStream; +}; + +SvStream* UcbStreamHelper::CreateStream( Reference < XStream > xStream, sal_Bool bCloseStream ) +{ + SvStream* pStream = NULL; + if ( xStream->getOutputStream().is() ) + { + UcbLockBytesRef xLockBytes = UcbLockBytes::CreateLockBytes( xStream ); + if ( xLockBytes.Is() ) + { + if ( !bCloseStream ) + xLockBytes->setDontClose_Impl(); + + pStream = new SvStream( xLockBytes ); + pStream->SetBufferSize( 4096 ); + pStream->SetError( xLockBytes->GetError() ); + } + } + else + return CreateStream( xStream->getInputStream(), bCloseStream ); + + return pStream; +}; + +} diff --git a/unotools/source/ucbhelper/xtempfile.cxx b/unotools/source/ucbhelper/xtempfile.cxx new file mode 100644 index 000000000000..75024c3c9b35 --- /dev/null +++ b/unotools/source/ucbhelper/xtempfile.cxx @@ -0,0 +1,579 @@ +/************************************************************************* + * + * 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: xtempfile.cxx,v $ + * $Revision: 1.16 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#include "precompiled_unotools.hxx" +#include <XTempFile.hxx> +#include <cppuhelper/factory.hxx> +#include <cppuhelper/typeprovider.hxx> +#ifndef _COM_SUN_STAR_REGISTRY_XREGISTRYKEY_HPP +#include <com/sun/star/registry/XRegistryKey.hpp> +#endif +#ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBUTE_HPP +#include <com/sun/star/beans/PropertyAttribute.hpp> +#endif +#include <unotools/tempfile.hxx> +#include <osl/file.hxx> +#include <unotools/configmgr.hxx> +#include <tools/urlobj.hxx> +#include <tools/debug.hxx> + +namespace css = com::sun::star; + +// copy define from desktop\source\app\appinit.cxx + +#define DESKTOP_TEMPNAMEBASE_DIR "/temp/soffice.tmp" + +OTempFileService::OTempFileService(::css::uno::Reference< ::css::uno::XComponentContext > const & context) +: ::cppu::PropertySetMixin< ::css::io::XTempFile >( + context + , static_cast< Implements >( IMPLEMENTS_PROPERTY_SET | IMPLEMENTS_FAST_PROPERTY_SET | IMPLEMENTS_PROPERTY_ACCESS ) + , com::sun::star::uno::Sequence< rtl::OUString >() ) +, mpStream( NULL ) +, mbRemoveFile( sal_True ) +, mbInClosed( sal_False ) +, mbOutClosed( sal_False ) +, mnCachedPos( 0 ) +, mbHasCachedPos( sal_False ) + +{ + mpTempFile = new ::utl::TempFile; + mpTempFile->EnableKillingFile ( sal_True ); +} + +OTempFileService::~OTempFileService () +{ + if ( mpTempFile ) + delete mpTempFile; +} + + +// XInterface + +::css::uno::Any SAL_CALL OTempFileService::queryInterface( ::css::uno::Type const & aType ) +throw ( ::css::uno::RuntimeException ) +{ + ::css::uno::Any aResult( OTempFileBase::queryInterface( aType ) ); + if (!aResult.hasValue()) + aResult = cppu::PropertySetMixin< ::css::io::XTempFile >::queryInterface( aType ) ; + return aResult; +}; +void SAL_CALL OTempFileService::acquire( ) +throw () +{ + OTempFileBase::acquire(); +} +void SAL_CALL OTempFileService::release( ) +throw () +{ + OTempFileBase::release(); +} + +// XTypeProvider + +::css::uno::Sequence< ::css::uno::Type > SAL_CALL OTempFileService::getTypes( ) +throw ( ::css::uno::RuntimeException ) +{ + static ::cppu::OTypeCollection* pTypeCollection = NULL; + if ( pTypeCollection == NULL ) + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ) ; + + if ( pTypeCollection == NULL ) + { + static ::cppu::OTypeCollection aTypeCollection( + ::getCppuType( ( const ::css::uno::Reference< ::css::beans::XPropertySet >*)NULL ) + ,OTempFileBase::getTypes() ); + pTypeCollection = &aTypeCollection; + } + } + return pTypeCollection->getTypes(); +}; +::css::uno::Sequence< sal_Int8 > SAL_CALL OTempFileService::getImplementationId( ) +throw ( ::css::uno::RuntimeException ) +{ + return OTempFileBase::getImplementationId(); +} + +// XTempFile + +sal_Bool SAL_CALL OTempFileService::getRemoveFile() +throw ( ::css::uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( maMutex ); + + if ( !mpTempFile ) + { + // the stream is already disconnected + throw ::css::uno::RuntimeException(); + } + + return mbRemoveFile; +}; +void SAL_CALL OTempFileService::setRemoveFile( sal_Bool _removefile ) +throw ( ::css::uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( maMutex ); + + if ( !mpTempFile ) + { + // the stream is already disconnected + throw ::css::uno::RuntimeException(); + } + + mbRemoveFile = _removefile; + mpTempFile->EnableKillingFile( mbRemoveFile ); +}; +::rtl::OUString SAL_CALL OTempFileService::getUri() +throw ( ::css::uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( maMutex ); + + if ( !mpTempFile ) + { + throw ::css::uno::RuntimeException(); + } + + return ::rtl::OUString( mpTempFile->GetURL() ); + +}; +::rtl::OUString SAL_CALL OTempFileService::getResourceName() +throw ( ::css::uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( maMutex ); + + if ( !mpTempFile ) + { + throw ::css::uno::RuntimeException(); +} + + return ::rtl::OUString( mpTempFile->GetFileName() ); +}; + + + +// XInputStream + +sal_Int32 SAL_CALL OTempFileService::readBytes( ::css::uno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead ) +throw (::css::io::NotConnectedException, ::css::io::BufferSizeExceededException, ::css::io::IOException, ::css::uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( maMutex ); + if ( mbInClosed ) + throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak * > ( static_cast < const ::css::uno::XWeak * > (this ) ) ); + + checkConnected(); + if (nBytesToRead < 0) + throw ::css::io::BufferSizeExceededException( ::rtl::OUString(), static_cast< ::css::uno::XWeak * >(this)); + + aData.realloc(nBytesToRead); + + sal_uInt32 nRead = mpStream->Read(static_cast < void* > ( aData.getArray() ), nBytesToRead); + checkError(); + + if (nRead < static_cast < sal_uInt32 > ( nBytesToRead ) ) + aData.realloc( nRead ); + + if ( sal::static_int_cast<sal_uInt32>(nBytesToRead) > nRead ) + { + // usually that means that the stream was read till the end + // TODO/LATER: it is better to get rid of this optimization by avoiding using of multiple temporary files ( there should be only one temporary file? ) + mnCachedPos = mpStream->Tell(); + mbHasCachedPos = sal_True; + + mpStream = NULL; + if ( mpTempFile ) + mpTempFile->CloseStream(); + } + + return nRead; +} +sal_Int32 SAL_CALL OTempFileService::readSomeBytes( ::css::uno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead ) +throw ( ::css::io::NotConnectedException, ::css::io::BufferSizeExceededException, ::css::io::IOException, ::css::uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( maMutex ); + if ( mbInClosed ) + throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak * > ( static_cast < const ::css::uno::XWeak * > (this ) ) ); + + checkConnected(); + checkError(); + + if (nMaxBytesToRead < 0) + throw ::css::io::BufferSizeExceededException( ::rtl::OUString(), static_cast < ::css::uno::XWeak * >( this ) ); + + if (mpStream->IsEof()) + { + aData.realloc(0); + return 0; + } + else + return readBytes(aData, nMaxBytesToRead); +} +void SAL_CALL OTempFileService::skipBytes( sal_Int32 nBytesToSkip ) +throw ( ::css::io::NotConnectedException, ::css::io::BufferSizeExceededException, ::css::io::IOException, ::css::uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( maMutex ); + if ( mbInClosed ) + throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak * > ( static_cast < const ::css::uno::XWeak * > (this ) ) ); + + checkConnected(); + checkError(); + mpStream->SeekRel(nBytesToSkip); + checkError(); +} +sal_Int32 SAL_CALL OTempFileService::available( ) +throw ( ::css::io::NotConnectedException, ::css::io::IOException, ::css::uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( maMutex ); + if ( mbInClosed ) + throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak * > ( static_cast < const ::css::uno::XWeak * > (this ) ) ); + + checkConnected(); + + sal_uInt32 nPos = mpStream->Tell(); + checkError(); + + mpStream->Seek(STREAM_SEEK_TO_END); + checkError(); + + sal_Int32 nAvailable = (sal_Int32)mpStream->Tell() - nPos; + mpStream->Seek(nPos); + checkError(); + + return nAvailable; +} +void SAL_CALL OTempFileService::closeInput( ) +throw ( ::css::io::NotConnectedException, ::css::io::IOException, ::css::uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( maMutex ); + if ( mbInClosed ) + throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak * > ( static_cast < const ::css::uno::XWeak * > (this ) ) ); + + mbInClosed = sal_True; + + if ( mbOutClosed ) + { + // stream will be deleted by TempFile implementation + mpStream = NULL; + + if ( mpTempFile ) + { + delete mpTempFile; + mpTempFile = NULL; + } + } +} + +// XOutputStream + +void SAL_CALL OTempFileService::writeBytes( const ::css::uno::Sequence< sal_Int8 >& aData ) +throw ( ::css::io::NotConnectedException, ::css::io::BufferSizeExceededException, ::css::io::IOException, ::css::uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( maMutex ); + if ( mbOutClosed ) + throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak * > ( static_cast < const ::css::uno::XWeak * > (this ) ) ); + + checkConnected(); + sal_uInt32 nWritten = mpStream->Write(aData.getConstArray(),aData.getLength()); + checkError(); + if ( nWritten != (sal_uInt32)aData.getLength()) + throw ::css::io::BufferSizeExceededException( ::rtl::OUString(),static_cast < ::css::uno::XWeak * > ( this ) ); +} +void SAL_CALL OTempFileService::flush( ) +throw ( ::css::io::NotConnectedException, ::css::io::BufferSizeExceededException, ::css::io::IOException, ::css::uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( maMutex ); + if ( mbOutClosed ) + throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak * > ( static_cast < const ::css::uno::XWeak * > (this ) ) ); + + checkConnected(); + mpStream->Flush(); + checkError(); +} +void SAL_CALL OTempFileService::closeOutput( ) +throw ( ::css::io::NotConnectedException, ::css::io::BufferSizeExceededException, ::css::io::IOException, ::css::uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( maMutex ); + if ( mbOutClosed ) + throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak * > ( static_cast < const ::css::uno::XWeak * > (this ) ) ); + + mbOutClosed = sal_True; + + // TODO/LATER: it is better to get rid of this optimization by avoiding using of multiple temporary files ( there should be only one temporary file? ) + if ( mpStream ) + { + mnCachedPos = mpStream->Tell(); + mbHasCachedPos = sal_True; + + mpStream = NULL; + if ( mpTempFile ) + mpTempFile->CloseStream(); + } + + if ( mbInClosed ) + { + // stream will be deleted by TempFile implementation + mpStream = NULL; + + if ( mpTempFile ) + { + delete mpTempFile; + mpTempFile = NULL; + } + } +} + + +void OTempFileService::checkError () const +{ + if (!mpStream || mpStream->SvStream::GetError () != ERRCODE_NONE ) + throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak * > ( static_cast < const ::css::uno::XWeak * > (this ) ) ); +} +void OTempFileService::checkConnected () +{ + if (!mpStream && mpTempFile) + { + mpStream = mpTempFile->GetStream( STREAM_STD_READWRITE ); + if ( mpStream && mbHasCachedPos ) + { + mpStream->Seek( sal::static_int_cast<sal_Size>(mnCachedPos) ); + if ( mpStream->SvStream::GetError () == ERRCODE_NONE ) + { + mbHasCachedPos = sal_False; + mnCachedPos = 0; + } + else + { + mpStream = NULL; + mpTempFile->CloseStream(); + } + } + } + + if (!mpStream) + throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak * > ( static_cast < const ::css::uno::XWeak * > (this ) ) ); +} + +// XSeekable + +void SAL_CALL OTempFileService::seek( sal_Int64 nLocation ) +throw ( ::css::lang::IllegalArgumentException, ::css::io::IOException, ::css::uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( maMutex ); + checkConnected(); + if ( nLocation < 0 || nLocation > getLength() ) + throw ::css::lang::IllegalArgumentException(); + + mpStream->Seek((sal_uInt32) nLocation ); + checkError(); +} +sal_Int64 SAL_CALL OTempFileService::getPosition( ) +throw ( ::css::io::IOException, ::css::uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( maMutex ); + checkConnected(); + + sal_uInt32 nPos = mpStream->Tell(); + checkError(); + return (sal_Int64)nPos; +} +sal_Int64 SAL_CALL OTempFileService::getLength( ) +throw ( ::css::io::IOException, ::css::uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( maMutex ); + checkConnected(); + + sal_uInt32 nCurrentPos = mpStream->Tell(); + checkError(); + + mpStream->Seek(STREAM_SEEK_TO_END); + sal_uInt32 nEndPos = mpStream->Tell(); + mpStream->Seek(nCurrentPos); + + checkError(); + + return (sal_Int64)nEndPos; +} + + +// XStream + +::css::uno::Reference< ::css::io::XInputStream > SAL_CALL OTempFileService::getInputStream() +throw ( ::css::uno::RuntimeException ) + { + return ::css::uno::Reference< ::css::io::XInputStream >( *this, ::css::uno::UNO_QUERY ); +} + +::css::uno::Reference< ::css::io::XOutputStream > SAL_CALL OTempFileService::getOutputStream() +throw ( ::css::uno::RuntimeException ) + { + return ::css::uno::Reference< ::css::io::XOutputStream >( *this, ::css::uno::UNO_QUERY ); + } + +// XTruncate + +void SAL_CALL OTempFileService::truncate() +throw ( ::css::io::IOException, ::css::uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( maMutex ); + checkConnected(); + // SetStreamSize() call does not change the position + mpStream->Seek( 0 ); + mpStream->SetStreamSize( 0 ); + checkError(); +} + +// XServiceInfo + +::rtl::OUString SAL_CALL OTempFileService::getImplementationName() +throw ( ::css::uno::RuntimeException ) +{ + return getImplementationName_Static(); +} + +sal_Bool SAL_CALL OTempFileService::supportsService( ::rtl::OUString const & rServiceName ) +throw ( ::css::uno::RuntimeException ) +{ + ::css::uno::Sequence< ::rtl::OUString > aServices(getSupportedServiceNames_Static()); + return rServiceName == aServices[0]; +} + +::css::uno::Sequence < ::rtl::OUString > SAL_CALL OTempFileService::getSupportedServiceNames() +throw ( ::css::uno::RuntimeException ) +{ + return getSupportedServiceNames_Static(); +} + + + +::rtl::OUString OTempFileService::getImplementationName_Static () +{ + return ::rtl::OUString ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.io.comp.TempFile" ) ); +} +::css::uno::Sequence < ::rtl::OUString > OTempFileService::getSupportedServiceNames_Static() +{ + ::css::uno::Sequence < ::rtl::OUString > aNames ( 1 ); + aNames[0] = ::rtl::OUString ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.io.TempFile" ) ); + return aNames; +} +::css::uno::Reference < ::css::uno::XInterface >SAL_CALL XTempFile_createInstance( + css::uno::Reference< ::css::uno::XComponentContext > const & context) + SAL_THROW( ( css::uno::Exception ) ) +{ + return static_cast< ::cppu::OWeakObject * >( new OTempFileService(context) ); +} + +::css::uno::Reference < ::css::lang::XSingleComponentFactory > OTempFileService::createServiceFactory_Static( ::css::uno::Reference < ::css::lang::XMultiServiceFactory > const & ) +{ + return ::cppu::createSingleComponentFactory( XTempFile_createInstance, getImplementationName_Static(), getSupportedServiceNames_Static() ); +} + +static sal_Bool writeInfo( void * pRegistryKey, + const ::rtl::OUString & rImplementationName, + ::css::uno::Sequence< ::rtl::OUString > const & rServiceNames ) +{ + ::rtl::OUString aKeyName( RTL_CONSTASCII_USTRINGPARAM ( "/" ) ); + aKeyName += rImplementationName; + aKeyName += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "/UNO/SERVICES" ) ); + + ::css::uno::Reference< ::css::registry::XRegistryKey > xKey; + try + { + xKey = static_cast< ::css::registry::XRegistryKey * >( + pRegistryKey )->createKey( aKeyName ); + } + catch ( ::css::registry::InvalidRegistryException const & ) + { + } + + if ( !xKey.is() ) + return sal_False; + + sal_Bool bSuccess = sal_True; + + for ( sal_Int32 n = 0; n < rServiceNames.getLength(); ++n ) + { + try + { + xKey->createKey( rServiceNames[ n ] ); + } + catch ( ::css::registry::InvalidRegistryException const & ) + { + bSuccess = sal_False; + break; + } + } + return bSuccess; +} +// C functions to implement this as a component + +extern "C" SAL_DLLPUBLIC_EXPORT void SAL_CALL component_getImplementationEnvironment( + const sal_Char ** ppEnvTypeName, uno_Environment ** /*ppEnv*/ ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + +/** + * This function creates an implementation section in the registry and another subkey + * for each supported service. + * @param pServiceManager generic uno interface providing a service manager + * @param pRegistryKey generic uno interface providing registry key to write + */ +extern "C" SAL_DLLPUBLIC_EXPORT sal_Bool SAL_CALL component_writeInfo( void* /*pServiceManager*/, void* pRegistryKey ) +{ + return pRegistryKey && + writeInfo (pRegistryKey, + OTempFileService::getImplementationName_Static(), + OTempFileService::getSupportedServiceNames_Static() ); +} + + +/** + * This function is called to get service factories for an implementation. + * @param pImplName name of implementation + * @param pServiceManager generic uno interface providing a service manager to instantiate components + * @param pRegistryKey registry data key to read and write component persistent data + * @return a component factory (generic uno interface) + */ +extern "C" SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory( + const sal_Char * pImplName, void * pServiceManager, void * /*pRegistryKey*/ ) +{ + void * pRet = 0; + ::css::uno::Reference< ::css::lang::XMultiServiceFactory > xSMgr( + reinterpret_cast< ::css::lang::XMultiServiceFactory * >( pServiceManager ) ); + ::css::uno::Reference< ::css::lang::XSingleComponentFactory > xFactory; + + if (OTempFileService::getImplementationName_Static().compareToAscii( pImplName ) == 0) + xFactory = OTempFileService::createServiceFactory_Static ( xSMgr ); + + if ( xFactory.is() ) + { + xFactory->acquire(); + pRet = xFactory.get(); + } + return pRet; +} diff --git a/unotools/util/makefile.mk b/unotools/util/makefile.mk new file mode 100644 index 000000000000..637e58765f83 --- /dev/null +++ b/unotools/util/makefile.mk @@ -0,0 +1,100 @@ +#************************************************************************* +# +# 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.21 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General 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=unotools +TARGET=utl +TARGETTYPE=CUI +USE_LDUMP2=TRUE + +USE_DEFFILE=TRUE + +# --- Settings ---------------------------------- + +.INCLUDE : settings.mk + +# --- Library ----------------------------------- + +LIB1TARGET=$(SLB)$/untools.lib +LIB1FILES=\ + $(SLB)$/i18n.lib \ + $(SLB)$/misc.lib \ + $(SLB)$/streaming.lib \ + $(SLB)$/config.lib \ + $(SLB)$/ucbhelp.lib \ + $(SLB)$/procfact.lib \ + $(SLB)$/property.lib \ + $(SLB)$/accessibility.lib + +SHL1TARGET=$(TARGET)$(DLLPOSTFIX) + +SHL1IMPLIB=iutl +SHL1USE_EXPORTS=name + +SHL1STDLIBS= \ + $(SALHELPERLIB) \ + $(COMPHELPERLIB) \ + $(UCBHELPERLIB) \ + $(CPPUHELPERLIB) \ + $(CPPULIB) \ + $(I18NISOLANGLIB) \ + $(TOOLSLIB) \ + $(VOSLIB) \ + $(SALLIB) + +SHL1LIBS=$(LIB1TARGET) +SHL1DEF=$(MISC)$/$(SHL1TARGET).def + +SHL1DEPN=$(LIB1TARGET) + +DEF1NAME =$(SHL1TARGET) +DEF1DEPN =$(MISC)$/$(SHL1TARGET).flt +DEFLIB1NAME =untools +DEF1DES =unotools + +# --- Targets ---------------------------------- + +.INCLUDE : target.mk + +# --- Filter-Datei --- + +$(MISC)$/$(SHL1TARGET).flt: makefile.mk + @echo ------------------------------ + @echo Making: $@ + @echo CLEAR_THE_FILE > $@ + @echo _TI >> $@ + @echo _real >> $@ + @echo NodeValueAccessor >> $@ + @echo SubNodeAccess >> $@ + @echo UpdateFromConfig >> $@ + @echo UpdateToConfig >> $@ + @echo _Impl >> $@ + diff --git a/unotools/util/makefile.pmk b/unotools/util/makefile.pmk new file mode 100644 index 000000000000..a59b857ac7b2 --- /dev/null +++ b/unotools/util/makefile.pmk @@ -0,0 +1,35 @@ +#************************************************************************* +# +# 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.pmk,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. +# +#************************************************************************* + +# define UNOTOOLS_DLLIMPLEMENTATION (see @ unotoolsdllapi.h) +CDEFS += -DUNOTOOLS_DLLIMPLEMENTATION + +VISIBILITY_HIDDEN=TRUE |