diff options
Diffstat (limited to 'ucb/source/ucp/package')
-rw-r--r-- | ucb/source/ucp/package/makefile.mk | 97 | ||||
-rw-r--r-- | ucb/source/ucp/package/pkgcontent.cxx | 3012 | ||||
-rw-r--r-- | ucb/source/ucp/package/pkgcontent.hxx | 335 | ||||
-rw-r--r-- | ucb/source/ucp/package/pkgcontentcaps.cxx | 562 | ||||
-rw-r--r-- | ucb/source/ucp/package/pkgdatasupplier.cxx | 498 | ||||
-rw-r--r-- | ucb/source/ucp/package/pkgdatasupplier.hxx | 77 | ||||
-rw-r--r-- | ucb/source/ucp/package/pkgprovider.cxx | 330 | ||||
-rw-r--r-- | ucb/source/ucp/package/pkgprovider.hxx | 105 | ||||
-rw-r--r-- | ucb/source/ucp/package/pkgresultset.cxx | 94 | ||||
-rw-r--r-- | ucb/source/ucp/package/pkgresultset.hxx | 59 | ||||
-rw-r--r-- | ucb/source/ucp/package/pkgservices.cxx | 74 | ||||
-rw-r--r-- | ucb/source/ucp/package/pkguri.cxx | 249 | ||||
-rw-r--r-- | ucb/source/ucp/package/pkguri.hxx | 101 | ||||
-rw-r--r-- | ucb/source/ucp/package/ucppkg.xml | 92 | ||||
-rw-r--r-- | ucb/source/ucp/package/ucppkg1.component | 34 |
15 files changed, 5719 insertions, 0 deletions
diff --git a/ucb/source/ucp/package/makefile.mk b/ucb/source/ucp/package/makefile.mk new file mode 100644 index 000000000000..b78150aed2cb --- /dev/null +++ b/ucb/source/ucp/package/makefile.mk @@ -0,0 +1,97 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +# UCP Version - Increase, if UCP libraray becomes incompatible. +UCP_VERSION=1 + +# Name for UCP. Will become part of the library name (See below). +UCP_NAME=pkg + +PRJ=..$/..$/.. + +PRJNAME=ucb + +TARGET=ucp$(UCP_NAME) + +ENABLE_EXCEPTIONS=TRUE +USE_DEFFILE=TRUE +NO_BSYMBOLIC=TRUE + +# --- Settings --------------------------------------------------------- + +.INCLUDE: settings.mk + +# --- General ----------------------------------------------------- +.IF "$(L10N_framework)"=="" + +SLOFILES=\ + $(SLO)$/pkgservices.obj \ + $(SLO)$/pkguri.obj \ + $(SLO)$/pkgprovider.obj \ + $(SLO)$/pkgcontent.obj \ + $(SLO)$/pkgcontentcaps.obj \ + $(SLO)$/pkgresultset.obj \ + $(SLO)$/pkgdatasupplier.obj + +LIB1TARGET=$(SLB)$/_$(TARGET).lib +LIB1OBJFILES=$(SLOFILES) + +# --- Shared-Library --------------------------------------------------- + +SHL1TARGET=$(TARGET)$(UCP_VERSION) +SHL1IMPLIB=i$(TARGET) + +SHL1VERSIONMAP=$(SOLARENV)/src/component.map + +SHL1STDLIBS=\ + $(COMPHELPERLIB) \ + $(CPPUHELPERLIB) \ + $(CPPULIB) \ + $(SALLIB) \ + $(SALHELPERLIB) \ + $(UCBHELPERLIB) + +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +SHL1LIBS=$(LIB1TARGET) + +# --- Def-File --------------------------------------------------------- + +DEF1NAME=$(SHL1TARGET) + +# --- Targets ---------------------------------------------------------- + +.ENDIF # L10N_framework +.INCLUDE: target.mk + + +ALLTAR : $(MISC)/ucppkg1.component + +$(MISC)/ucppkg1.component .ERRREMOVE : $(SOLARENV)/bin/createcomponent.xslt \ + ucppkg1.component + $(XSLTPROC) --nonet --stringparam uri \ + '$(COMPONENTPREFIX_BASIS_NATIVE)$(SHL1TARGETN:f)' -o $@ \ + $(SOLARENV)/bin/createcomponent.xslt ucppkg1.component diff --git a/ucb/source/ucp/package/pkgcontent.cxx b/ucb/source/ucp/package/pkgcontent.cxx new file mode 100644 index 000000000000..8bdebb138467 --- /dev/null +++ b/ucb/source/ucp/package/pkgcontent.cxx @@ -0,0 +1,3012 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + *************************************************************************/ +#include <osl/diagnose.h> + +#include "osl/doublecheckedlocking.h" +#include <rtl/ustring.h> +#include <rtl/ustring.hxx> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/beans/PropertyState.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/beans/XPropertyAccess.hpp> +#include <com/sun/star/container/XEnumerationAccess.hpp> +#include <com/sun/star/container/XHierarchicalNameAccess.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/container/XNamed.hpp> +#include <com/sun/star/io/XActiveDataSink.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/lang/IllegalAccessException.hpp> +#include <com/sun/star/sdbc/XRow.hpp> +#include <com/sun/star/ucb/ContentInfoAttribute.hpp> +#include <com/sun/star/ucb/InsertCommandArgument.hpp> +#include <com/sun/star/ucb/InteractiveBadTransferURLException.hpp> +#include <com/sun/star/ucb/MissingInputStreamException.hpp> +#include <com/sun/star/ucb/NameClash.hpp> +#include <com/sun/star/ucb/NameClashException.hpp> +#include <com/sun/star/ucb/OpenCommandArgument2.hpp> +#include <com/sun/star/ucb/OpenMode.hpp> +#include <com/sun/star/ucb/TransferInfo.hpp> +#include <com/sun/star/ucb/UnsupportedDataSinkException.hpp> +#include <com/sun/star/ucb/UnsupportedNameClashException.hpp> +#include <com/sun/star/ucb/UnsupportedOpenModeException.hpp> +#include <com/sun/star/ucb/XCommandInfo.hpp> +#include <com/sun/star/ucb/XPersistentPropertySet.hpp> +#include <com/sun/star/util/XChangesBatch.hpp> +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/uno/Sequence.hxx> +#include <ucbhelper/contentidentifier.hxx> +#include <ucbhelper/propertyvalueset.hxx> +#include <ucbhelper/cancelcommandexecution.hxx> +#include "pkgcontent.hxx" +#include "pkgprovider.hxx" +#include "pkgresultset.hxx" + +#include "../inc/urihelper.hxx" + +using namespace com::sun::star; +using namespace package_ucp; + +#define NONE_MODIFIED sal_uInt32( 0x00 ) +#define MEDIATYPE_MODIFIED sal_uInt32( 0x01 ) +#define COMPRESSED_MODIFIED sal_uInt32( 0x02 ) +#define ENCRYPTED_MODIFIED sal_uInt32( 0x04 ) +#define ENCRYPTIONKEY_MODIFIED sal_uInt32( 0x08 ) + +//========================================================================= +//========================================================================= +// +// ContentProperties Implementation. +// +//========================================================================= +//========================================================================= + +ContentProperties::ContentProperties( const rtl::OUString& rContentType ) +: aContentType( rContentType ), + nSize( 0 ), + bCompressed( sal_True ), + bEncrypted( sal_False ), + bHasEncryptedEntries( sal_False ) +{ + bIsFolder = rContentType.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( PACKAGE_FOLDER_CONTENT_TYPE ) ) + || rContentType.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( PACKAGE_ZIP_FOLDER_CONTENT_TYPE ) ); + bIsDocument = !bIsFolder; + + OSL_ENSURE( bIsFolder || + rContentType.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( PACKAGE_STREAM_CONTENT_TYPE ) ) + || rContentType.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( PACKAGE_ZIP_STREAM_CONTENT_TYPE ) ), + "ContentProperties::ContentProperties - Unknown type!" ); +} + +//========================================================================= + +uno::Sequence< ucb::ContentInfo > +ContentProperties::getCreatableContentsInfo( PackageUri const & rUri ) const +{ + if ( bIsFolder ) + { + uno::Sequence< beans::Property > aProps( 1 ); + aProps.getArray()[ 0 ] = beans::Property( + rtl::OUString::createFromAscii( "Title" ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND ); + + uno::Sequence< ucb::ContentInfo > aSeq( 2 ); + + // Folder. + aSeq.getArray()[ 0 ].Type + = Content::getContentType( rUri.getScheme(), sal_True ); + aSeq.getArray()[ 0 ].Attributes + = ucb::ContentInfoAttribute::KIND_FOLDER; + aSeq.getArray()[ 0 ].Properties = aProps; + + // Stream. + aSeq.getArray()[ 1 ].Type + = Content::getContentType( rUri.getScheme(), sal_False ); + aSeq.getArray()[ 1 ].Attributes + = ucb::ContentInfoAttribute::INSERT_WITH_INPUTSTREAM + | ucb::ContentInfoAttribute::KIND_DOCUMENT; + aSeq.getArray()[ 1 ].Properties = aProps; + + return aSeq; + } + else + { + return uno::Sequence< ucb::ContentInfo >( 0 ); + } +} + +//========================================================================= +//========================================================================= +// +// Content Implementation. +// +//========================================================================= +//========================================================================= + +// static ( "virtual" ctor ) +Content* Content::create( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + ContentProvider* pProvider, + const uno::Reference< ucb::XContentIdentifier >& Identifier ) +{ + rtl::OUString aURL = Identifier->getContentIdentifier(); + PackageUri aURI( aURL ); + ContentProperties aProps; + uno::Reference< container::XHierarchicalNameAccess > xPackage; + + if ( loadData( pProvider, aURI, aProps, xPackage ) ) + { + // resource exists + + sal_Int32 nLastSlash = aURL.lastIndexOf( '/' ); + if ( ( nLastSlash + 1 ) == aURL.getLength() ) + { + // Client explicitely requested a folder! + if ( !aProps.bIsFolder ) + return 0; + } + + uno::Reference< ucb::XContentIdentifier > xId + = new ::ucbhelper::ContentIdentifier( rxSMgr, aURI.getUri() ); + return new Content( rxSMgr, pProvider, xId, xPackage, aURI, aProps ); + } + else + { + // resource doesn't exist + + sal_Bool bFolder = sal_False; + + // Guess type according to URI. + sal_Int32 nLastSlash = aURL.lastIndexOf( '/' ); + if ( ( nLastSlash + 1 ) == aURL.getLength() ) + bFolder = sal_True; + + uno::Reference< ucb::XContentIdentifier > xId + = new ::ucbhelper::ContentIdentifier( rxSMgr, aURI.getUri() ); + + ucb::ContentInfo aInfo; + if ( bFolder || aURI.isRootFolder() ) + aInfo.Type = getContentType( aURI.getScheme(), sal_True ); + else + aInfo.Type = getContentType( aURI.getScheme(), sal_False ); + + return new Content( rxSMgr, pProvider, xId, xPackage, aURI, aInfo ); + } +} + +//========================================================================= +// static ( "virtual" ctor ) +Content* Content::create( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + ContentProvider* pProvider, + const uno::Reference< ucb::XContentIdentifier >& Identifier, + const ucb::ContentInfo& Info ) +{ + if ( !Info.Type.getLength() ) + return 0; + + PackageUri aURI( Identifier->getContentIdentifier() ); + + if ( !Info.Type.equalsIgnoreAsciiCase( + getContentType( aURI.getScheme(), sal_True ) ) && + !Info.Type.equalsIgnoreAsciiCase( + getContentType( aURI.getScheme(), sal_False ) ) ) + return 0; + + uno::Reference< container::XHierarchicalNameAccess > xPackage; + +#if 0 + // Fail, if content does exist. + if ( hasData( pProvider, aURI, xPackage ) ) + return 0; +#else + xPackage = pProvider->createPackage( aURI.getPackage(), aURI.getParam() ); +#endif + + uno::Reference< ucb::XContentIdentifier > xId + = new ::ucbhelper::ContentIdentifier( rxSMgr, aURI.getUri() ); + return new Content( rxSMgr, pProvider, xId, xPackage, aURI, Info ); +} + +//========================================================================= +// static +::rtl::OUString Content::getContentType( + const ::rtl::OUString& aScheme, sal_Bool bFolder ) +{ + return ( rtl::OUString::createFromAscii( "application/" ) + + aScheme + + ( bFolder + ? rtl::OUString::createFromAscii( "-folder" ) + : rtl::OUString::createFromAscii( "-stream" ) ) ); +} + +//========================================================================= +Content::Content( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + ContentProvider* pProvider, + const uno::Reference< ucb::XContentIdentifier >& Identifier, + const uno::Reference< container::XHierarchicalNameAccess > & Package, + const PackageUri& rUri, + const ContentProperties& rProps ) +: ContentImplHelper( rxSMgr, pProvider, Identifier ), + m_aUri( rUri ), + m_aProps( rProps ), + m_eState( PERSISTENT ), + m_xPackage( Package ), + m_pProvider( pProvider ), + m_nModifiedProps( NONE_MODIFIED ) +{ +} + +//========================================================================= +Content::Content( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + ContentProvider* pProvider, + const uno::Reference< ucb::XContentIdentifier >& Identifier, + const uno::Reference< container::XHierarchicalNameAccess > & Package, + const PackageUri& rUri, + const ucb::ContentInfo& Info ) + : ContentImplHelper( rxSMgr, pProvider, Identifier ), + m_aUri( rUri ), + m_aProps( Info.Type ), + m_eState( TRANSIENT ), + m_xPackage( Package ), + m_pProvider( pProvider ), + m_nModifiedProps( NONE_MODIFIED ) +{ +} + +//========================================================================= +// virtual +Content::~Content() +{ +} + +//========================================================================= +// +// XInterface methods. +// +//========================================================================= + +// virtual +void SAL_CALL Content::acquire() + throw( ) +{ + ContentImplHelper::acquire(); +} + +//========================================================================= +// virtual +void SAL_CALL Content::release() + throw( ) +{ + ContentImplHelper::release(); +} + +//========================================================================= +// virtual +uno::Any SAL_CALL Content::queryInterface( const uno::Type & rType ) + throw ( uno::RuntimeException ) +{ + uno::Any aRet; + + if ( isFolder() ) + aRet = cppu::queryInterface( + rType, static_cast< ucb::XContentCreator * >( this ) ); + + return aRet.hasValue() ? aRet : ContentImplHelper::queryInterface( rType ); +} + +//========================================================================= +// +// XTypeProvider methods. +// +//========================================================================= + +XTYPEPROVIDER_COMMON_IMPL( Content ); + +//========================================================================= +// virtual +uno::Sequence< uno::Type > SAL_CALL Content::getTypes() + throw( uno::RuntimeException ) +{ + cppu::OTypeCollection * pCollection = 0; + + if ( isFolder() ) + { + static cppu::OTypeCollection* pFolderTypes = 0; + + pCollection = pFolderTypes; + if ( !pCollection ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + + pCollection = pFolderTypes; + if ( !pCollection ) + { + static cppu::OTypeCollection aCollection( + CPPU_TYPE_REF( lang::XTypeProvider ), + CPPU_TYPE_REF( lang::XServiceInfo ), + CPPU_TYPE_REF( lang::XComponent ), + CPPU_TYPE_REF( ucb::XContent ), + CPPU_TYPE_REF( ucb::XCommandProcessor ), + CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ), + CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ), + CPPU_TYPE_REF( beans::XPropertyContainer ), + CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ), + CPPU_TYPE_REF( container::XChild ), + CPPU_TYPE_REF( ucb::XContentCreator ) ); // !! + pCollection = &aCollection; + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + pFolderTypes = pCollection; + } + } + else { + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + } + } + else + { + static cppu::OTypeCollection* pDocumentTypes = 0; + + pCollection = pDocumentTypes; + if ( !pCollection ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + + pCollection = pDocumentTypes; + if ( !pCollection ) + { + static cppu::OTypeCollection aCollection( + CPPU_TYPE_REF( lang::XTypeProvider ), + CPPU_TYPE_REF( lang::XServiceInfo ), + CPPU_TYPE_REF( lang::XComponent ), + CPPU_TYPE_REF( ucb::XContent ), + CPPU_TYPE_REF( ucb::XCommandProcessor ), + CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ), + CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ), + CPPU_TYPE_REF( beans::XPropertyContainer ), + CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ), + CPPU_TYPE_REF( container::XChild ) ); + pCollection = &aCollection; + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + pDocumentTypes = pCollection; + } + } + else { + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + } + } + + return (*pCollection).getTypes(); +} + +//========================================================================= +// +// XServiceInfo methods. +// +//========================================================================= + +// virtual +rtl::OUString SAL_CALL Content::getImplementationName() + throw( uno::RuntimeException ) +{ + return rtl::OUString::createFromAscii( + "com.sun.star.comp.ucb.PackageContent" ); +} + +//========================================================================= +// virtual +uno::Sequence< rtl::OUString > SAL_CALL Content::getSupportedServiceNames() + throw( uno::RuntimeException ) +{ + uno::Sequence< rtl::OUString > aSNS( 1 ); + if ( isFolder() ) + aSNS.getArray()[ 0 ] + = rtl::OUString::createFromAscii( + PACKAGE_FOLDER_CONTENT_SERVICE_NAME ); + else + aSNS.getArray()[ 0 ] + = rtl::OUString::createFromAscii( + PACKAGE_STREAM_CONTENT_SERVICE_NAME ); + + return aSNS; +} + +//========================================================================= +// +// XContent methods. +// +//========================================================================= + +// virtual +rtl::OUString SAL_CALL Content::getContentType() + throw( uno::RuntimeException ) +{ + return m_aProps.aContentType; +} + +//========================================================================= +// +// XCommandProcessor methods. +// +//========================================================================= + +// virtual +uno::Any SAL_CALL Content::execute( + const ucb::Command& aCommand, + sal_Int32 /*CommandId*/, + const uno::Reference< ucb::XCommandEnvironment >& Environment ) + throw( uno::Exception, + ucb::CommandAbortedException, + uno::RuntimeException ) +{ + uno::Any aRet; + + if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "getPropertyValues" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // getPropertyValues + ////////////////////////////////////////////////////////////////// + + uno::Sequence< beans::Property > Properties; + if ( !( aCommand.Argument >>= Properties ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Wrong argument type!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + aRet <<= getPropertyValues( Properties ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "setPropertyValues" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // setPropertyValues + ////////////////////////////////////////////////////////////////// + + uno::Sequence< beans::PropertyValue > aProperties; + if ( !( aCommand.Argument >>= aProperties ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Wrong argument type!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + if ( !aProperties.getLength() ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "No properties!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + aRet <<= setPropertyValues( aProperties, Environment ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "getPropertySetInfo" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // getPropertySetInfo + ////////////////////////////////////////////////////////////////// + + // Note: Implemented by base class. + aRet <<= getPropertySetInfo( Environment ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "getCommandInfo" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // getCommandInfo + ////////////////////////////////////////////////////////////////// + + // Note: Implemented by base class. + aRet <<= getCommandInfo( Environment ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "open" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // open + ////////////////////////////////////////////////////////////////// + + ucb::OpenCommandArgument2 aOpenCommand; + if ( !( aCommand.Argument >>= aOpenCommand ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Wrong argument type!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + aRet = open( aOpenCommand, Environment ); + } + else if ( !m_aUri.isRootFolder() + && aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "insert" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // insert + ////////////////////////////////////////////////////////////////// + + ucb::InsertCommandArgument aArg; + if ( !( aCommand.Argument >>= aArg ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Wrong argument type!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + sal_Int32 nNameClash = aArg.ReplaceExisting + ? ucb::NameClash::OVERWRITE + : ucb::NameClash::ERROR; + insert( aArg.Data, nNameClash, Environment ); + } + else if ( !m_aUri.isRootFolder() + && aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "delete" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // delete + ////////////////////////////////////////////////////////////////// + + sal_Bool bDeletePhysical = sal_False; + aCommand.Argument >>= bDeletePhysical; + destroy( bDeletePhysical, Environment ); + + // Remove own and all children's persistent data. + if ( !removeData() ) + { + uno::Any aProps + = uno::makeAny( + beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Uri")), + -1, + uno::makeAny(m_xIdentifier-> + getContentIdentifier()), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_WRITE, + uno::Sequence< uno::Any >(&aProps, 1), + Environment, + rtl::OUString::createFromAscii( + "Cannot remove persistent data!" ), + this ); + // Unreachable + } + + // Remove own and all children's Additional Core Properties. + removeAdditionalPropertySet( sal_True ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "transfer" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // transfer + // ( Not available at stream objects ) + ////////////////////////////////////////////////////////////////// + + ucb::TransferInfo aInfo; + if ( !( aCommand.Argument >>= aInfo ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Wrong argument type!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + transfer( aInfo, Environment ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "createNewContent" ) ) && + isFolder() ) + { + ////////////////////////////////////////////////////////////////// + // createNewContent + // ( Not available at stream objects ) + ////////////////////////////////////////////////////////////////// + + ucb::ContentInfo aInfo; + if ( !( aCommand.Argument >>= aInfo ) ) + { + OSL_ENSURE( sal_False, "Wrong argument type!" ); + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Wrong argument type!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + aRet <<= createNewContent( aInfo ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "flush" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // flush + // ( Not available at stream objects ) + ////////////////////////////////////////////////////////////////// + + if( !flushData() ) + { + uno::Any aProps + = uno::makeAny( + beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Uri")), + -1, + uno::makeAny(m_xIdentifier-> + getContentIdentifier()), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_WRITE, + uno::Sequence< uno::Any >(&aProps, 1), + Environment, + rtl::OUString::createFromAscii( + "Cannot write file to disk!" ), + this ); + // Unreachable + } + } + else + { + ////////////////////////////////////////////////////////////////// + // Unsupported command + ////////////////////////////////////////////////////////////////// + + ucbhelper::cancelCommandExecution( + uno::makeAny( ucb::UnsupportedCommandException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ) ) ), + Environment ); + // Unreachable + } + + return aRet; +} + +//========================================================================= +// virtual +void SAL_CALL Content::abort( sal_Int32 /*CommandId*/ ) + throw( uno::RuntimeException ) +{ + // @@@ Implement logic to abort running commands, if this makes + // sense for your content. +} + +//========================================================================= +// +// XContentCreator methods. +// +//========================================================================= + +// virtual +uno::Sequence< ucb::ContentInfo > SAL_CALL +Content::queryCreatableContentsInfo() + throw( uno::RuntimeException ) +{ + return m_aProps.getCreatableContentsInfo( m_aUri ); +} + +//========================================================================= +// virtual +uno::Reference< ucb::XContent > SAL_CALL +Content::createNewContent( const ucb::ContentInfo& Info ) + throw( uno::RuntimeException ) +{ + if ( isFolder() ) + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + if ( !Info.Type.getLength() ) + return uno::Reference< ucb::XContent >(); + + if ( !Info.Type.equalsIgnoreAsciiCase( + getContentType( m_aUri.getScheme(), sal_True ) ) && + !Info.Type.equalsIgnoreAsciiCase( + getContentType( m_aUri.getScheme(), sal_False ) ) ) + return uno::Reference< ucb::XContent >(); + + rtl::OUString aURL = m_aUri.getUri(); + aURL += rtl::OUString::createFromAscii( "/" ); + + if ( Info.Type.equalsIgnoreAsciiCase( + getContentType( m_aUri.getScheme(), sal_True ) ) ) + aURL += rtl::OUString::createFromAscii( "New_Folder" ); + else + aURL += rtl::OUString::createFromAscii( "New_Stream" ); + + uno::Reference< ucb::XContentIdentifier > xId( + new ::ucbhelper::ContentIdentifier( m_xSMgr, aURL ) ); + + return create( m_xSMgr, m_pProvider, xId, Info ); + } + else + { + OSL_ENSURE( sal_False, + "createNewContent called on non-folder object!" ); + return uno::Reference< ucb::XContent >(); + } +} + +//========================================================================= +// +// Non-interface methods. +// +//========================================================================= + +// virtual +rtl::OUString Content::getParentURL() +{ + return m_aUri.getParentUri(); +} + +//========================================================================= +// static +uno::Reference< sdbc::XRow > Content::getPropertyValues( + const uno::Reference< lang::XMultiServiceFactory >& rSMgr, + const uno::Sequence< beans::Property >& rProperties, + ContentProvider* pProvider, + const rtl::OUString& rContentId ) +{ + ContentProperties aData; + uno::Reference< container::XHierarchicalNameAccess > xPackage; + if ( loadData( pProvider, PackageUri( rContentId ), aData, xPackage ) ) + { + return getPropertyValues( rSMgr, + rProperties, + aData, + rtl::Reference< + ::ucbhelper::ContentProviderImplHelper >( + pProvider ), + rContentId ); + } + else + { + rtl::Reference< ::ucbhelper::PropertyValueSet > xRow + = new ::ucbhelper::PropertyValueSet( rSMgr ); + + sal_Int32 nCount = rProperties.getLength(); + if ( nCount ) + { + const beans::Property* pProps = rProperties.getConstArray(); + for ( sal_Int32 n = 0; n < nCount; ++n ) + xRow->appendVoid( pProps[ n ] ); + } + + return uno::Reference< sdbc::XRow >( xRow.get() ); + } +} + +//========================================================================= +// static +uno::Reference< sdbc::XRow > Content::getPropertyValues( + const uno::Reference< lang::XMultiServiceFactory >& rSMgr, + const uno::Sequence< beans::Property >& rProperties, + const ContentProperties& rData, + const rtl::Reference< ::ucbhelper::ContentProviderImplHelper >& + rProvider, + const rtl::OUString& rContentId ) +{ + // Note: Empty sequence means "get values of all supported properties". + + rtl::Reference< ::ucbhelper::PropertyValueSet > xRow + = new ::ucbhelper::PropertyValueSet( rSMgr ); + + sal_Int32 nCount = rProperties.getLength(); + if ( nCount ) + { + uno::Reference< beans::XPropertySet > xAdditionalPropSet; + sal_Bool bTriedToGetAdditonalPropSet = sal_False; + + const beans::Property* pProps = rProperties.getConstArray(); + for ( sal_Int32 n = 0; n < nCount; ++n ) + { + const beans::Property& rProp = pProps[ n ]; + + // Process Core properties. + + if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) ) + { + xRow->appendString ( rProp, rData.aContentType ); + } + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "Title" ) ) ) + { + xRow->appendString ( rProp, rData.aTitle ); + } + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) ) + { + xRow->appendBoolean( rProp, rData.bIsDocument ); + } + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) ) + { + xRow->appendBoolean( rProp, rData.bIsFolder ); + } + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "CreatableContentsInfo" ) ) ) + { + xRow->appendObject( + rProp, uno::makeAny( + rData.getCreatableContentsInfo( + PackageUri( rContentId ) ) ) ); + } + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "MediaType" ) ) ) + { + xRow->appendString ( rProp, rData.aMediaType ); + } + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "Size" ) ) ) + { + // Property only available for streams. + if ( rData.bIsDocument ) + xRow->appendLong( rProp, rData.nSize ); + else + xRow->appendVoid( rProp ); + } + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "Compressed" ) ) ) + { + // Property only available for streams. + if ( rData.bIsDocument ) + xRow->appendBoolean( rProp, rData.bCompressed ); + else + xRow->appendVoid( rProp ); + } + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "Encrypted" ) ) ) + { + // Property only available for streams. + if ( rData.bIsDocument ) + xRow->appendBoolean( rProp, rData.bEncrypted ); + else + xRow->appendVoid( rProp ); + } + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "HasEncryptedEntries" ) ) ) + { + // Property only available for root folder. + PackageUri aURI( rContentId ); + if ( aURI.isRootFolder() ) + xRow->appendBoolean( rProp, rData.bHasEncryptedEntries ); + else + xRow->appendVoid( rProp ); + } + else + { + // Not a Core Property! Maybe it's an Additional Core Property?! + + if ( !bTriedToGetAdditonalPropSet && !xAdditionalPropSet.is() ) + { + xAdditionalPropSet + = uno::Reference< beans::XPropertySet >( + rProvider->getAdditionalPropertySet( rContentId, + sal_False ), + uno::UNO_QUERY ); + bTriedToGetAdditonalPropSet = sal_True; + } + + if ( xAdditionalPropSet.is() ) + { + if ( !xRow->appendPropertySetValue( + xAdditionalPropSet, + rProp ) ) + { + // Append empty entry. + xRow->appendVoid( rProp ); + } + } + else + { + // Append empty entry. + xRow->appendVoid( rProp ); + } + } + } + } + else + { + // Append all Core Properties. + xRow->appendString ( + beans::Property( + rtl::OUString::createFromAscii( "ContentType" ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ), + rData.aContentType ); + xRow->appendString( + beans::Property( + rtl::OUString::createFromAscii( "Title" ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND ), + rData.aTitle ); + xRow->appendBoolean( + beans::Property( + rtl::OUString::createFromAscii( "IsDocument" ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ), + rData.bIsDocument ); + xRow->appendBoolean( + beans::Property( + rtl::OUString::createFromAscii( "IsFolder" ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ), + rData.bIsFolder ); + xRow->appendObject( + beans::Property( + rtl::OUString::createFromAscii( "CreatableContentsInfo" ), + -1, + getCppuType( static_cast< + const uno::Sequence< ucb::ContentInfo > * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ), + uno::makeAny( + rData.getCreatableContentsInfo( PackageUri( rContentId ) ) ) ); + xRow->appendString( + beans::Property( + rtl::OUString::createFromAscii( "MediaType" ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND ), + rData.aMediaType ); + + // Properties only available for streams. + if ( rData.bIsDocument ) + { + xRow->appendLong( + beans::Property( + rtl::OUString::createFromAscii( "Size" ), + -1, + getCppuType( static_cast< const sal_Int64 * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ), + rData.nSize ); + + xRow->appendBoolean( + beans::Property( + rtl::OUString::createFromAscii( "Compressed" ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND ), + rData.bCompressed ); + + xRow->appendBoolean( + beans::Property( + rtl::OUString::createFromAscii( "Encrypted" ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND ), + rData.bEncrypted ); + } + + // Properties only available for root folder. + PackageUri aURI( rContentId ); + if ( aURI.isRootFolder() ) + { + xRow->appendBoolean( + beans::Property( + rtl::OUString::createFromAscii( "HasEncryptedEntries" ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ), + rData.bHasEncryptedEntries ); + } + + // Append all Additional Core Properties. + + uno::Reference< beans::XPropertySet > xSet( + rProvider->getAdditionalPropertySet( rContentId, sal_False ), + uno::UNO_QUERY ); + xRow->appendPropertySet( xSet ); + } + + return uno::Reference< sdbc::XRow >( xRow.get() ); +} + +//========================================================================= +uno::Reference< sdbc::XRow > Content::getPropertyValues( + const uno::Sequence< beans::Property >& rProperties ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + return getPropertyValues( m_xSMgr, + rProperties, + m_aProps, + rtl::Reference< + ::ucbhelper::ContentProviderImplHelper >( + m_xProvider.get() ), + m_xIdentifier->getContentIdentifier() ); +} + +//========================================================================= +uno::Sequence< uno::Any > Content::setPropertyValues( + const uno::Sequence< beans::PropertyValue >& rValues, + const uno::Reference< ucb::XCommandEnvironment > & xEnv ) + throw( uno::Exception ) +{ + osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); + + uno::Sequence< uno::Any > aRet( rValues.getLength() ); + uno::Sequence< beans::PropertyChangeEvent > aChanges( rValues.getLength() ); + sal_Int32 nChanged = 0; + + beans::PropertyChangeEvent aEvent; + aEvent.Source = static_cast< cppu::OWeakObject * >( this ); + aEvent.Further = sal_False; +// aEvent.PropertyName = + aEvent.PropertyHandle = -1; +// aEvent.OldValue = +// aEvent.NewValue = + + const beans::PropertyValue* pValues = rValues.getConstArray(); + sal_Int32 nCount = rValues.getLength(); + + uno::Reference< ucb::XPersistentPropertySet > xAdditionalPropSet; + sal_Bool bTriedToGetAdditonalPropSet = sal_False; + sal_Bool bExchange = sal_False; + sal_Bool bStore = sal_False; + rtl::OUString aNewTitle; + sal_Int32 nTitlePos = -1; + + for ( sal_Int32 n = 0; n < nCount; ++n ) + { + const beans::PropertyValue& rValue = pValues[ n ]; + + if ( rValue.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) ) + { + // Read-only property! + aRet[ n ] <<= lang::IllegalAccessException( + rtl::OUString::createFromAscii( + "Property is read-only!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + else if ( rValue.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) ) + { + // Read-only property! + aRet[ n ] <<= lang::IllegalAccessException( + rtl::OUString::createFromAscii( + "Property is read-only!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + else if ( rValue.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) ) + { + // Read-only property! + aRet[ n ] <<= lang::IllegalAccessException( + rtl::OUString::createFromAscii( + "Property is read-only!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + else if ( rValue.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "CreatableContentsInfo" ) ) ) + { + // Read-only property! + aRet[ n ] <<= lang::IllegalAccessException( + rtl::OUString::createFromAscii( + "Property is read-only!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + else if ( rValue.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "Title" ) ) ) + { + if ( m_aUri.isRootFolder() ) + { + // Read-only property! + aRet[ n ] <<= lang::IllegalAccessException( + rtl::OUString::createFromAscii( + "Property is read-only!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + else + { + rtl::OUString aNewValue; + if ( rValue.Value >>= aNewValue ) + { + // No empty titles! + if ( aNewValue.getLength() > 0 ) + { + if ( aNewValue != m_aProps.aTitle ) + { + // modified title -> modified URL -> exchange ! + if ( m_eState == PERSISTENT ) + bExchange = sal_True; + + // new value will be set later... + aNewTitle = aNewValue; + + // remember position within sequence of values + // (for error handling). + nTitlePos = n; + } + } + else + { + aRet[ n ] <<= + lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Empty title not allowed!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ); + } + } + else + { + aRet[ n ] <<= + beans::IllegalTypeException( + rtl::OUString::createFromAscii( + "Property value has wrong type!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + } + } + else if ( rValue.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "MediaType" ) ) ) + { + rtl::OUString aNewValue; + if ( rValue.Value >>= aNewValue ) + { + if ( aNewValue != m_aProps.aMediaType ) + { + aEvent.PropertyName = rValue.Name; + aEvent.OldValue = uno::makeAny( m_aProps.aMediaType ); + aEvent.NewValue = uno::makeAny( aNewValue ); + + m_aProps.aMediaType = aNewValue; + nChanged++; + bStore = sal_True; + m_nModifiedProps |= MEDIATYPE_MODIFIED; + } + } + else + { + aRet[ n ] <<= beans::IllegalTypeException( + rtl::OUString::createFromAscii( + "Property value has wrong type!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + } + else if ( rValue.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "Size" ) ) ) + { + // Read-only property! + aRet[ n ] <<= lang::IllegalAccessException( + rtl::OUString::createFromAscii( + "Property is read-only!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + else if ( rValue.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "Compressed" ) ) ) + { + // Property only available for streams. + if ( m_aProps.bIsDocument ) + { + sal_Bool bNewValue; + if ( rValue.Value >>= bNewValue ) + { + if ( bNewValue != m_aProps.bCompressed ) + { + aEvent.PropertyName = rValue.Name; + aEvent.OldValue = uno::makeAny( m_aProps.bCompressed ); + aEvent.NewValue = uno::makeAny( bNewValue ); + + m_aProps.bCompressed = bNewValue; + nChanged++; + bStore = sal_True; + m_nModifiedProps |= COMPRESSED_MODIFIED; + } + } + else + { + aRet[ n ] <<= beans::IllegalTypeException( + rtl::OUString::createFromAscii( + "Property value has wrong type!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + } + else + { + aRet[ n ] <<= beans::UnknownPropertyException( + rtl::OUString::createFromAscii( + "Compressed only supported by streams!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + } + else if ( rValue.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "Encrypted" ) ) ) + { + // Property only available for streams. + if ( m_aProps.bIsDocument ) + { + sal_Bool bNewValue; + if ( rValue.Value >>= bNewValue ) + { + if ( bNewValue != m_aProps.bEncrypted ) + { + aEvent.PropertyName = rValue.Name; + aEvent.OldValue = uno::makeAny( m_aProps.bEncrypted ); + aEvent.NewValue = uno::makeAny( bNewValue ); + + m_aProps.bEncrypted = bNewValue; + nChanged++; + bStore = sal_True; + m_nModifiedProps |= ENCRYPTED_MODIFIED; + } + } + else + { + aRet[ n ] <<= beans::IllegalTypeException( + rtl::OUString::createFromAscii( + "Property value has wrong type!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + } + else + { + aRet[ n ] <<= beans::UnknownPropertyException( + rtl::OUString::createFromAscii( + "Encrypted only supported by streams!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + } + else if ( rValue.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "HasEncryptedEntries" ) ) ) + { + // Read-only property! + aRet[ n ] <<= lang::IllegalAccessException( + rtl::OUString::createFromAscii( + "Property is read-only!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + else if ( rValue.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "EncryptionKey" ) ) ) + { + // @@@ This is a temporary solution. In the future submitting + // the key should be done using an interaction handler! + + // Write-Only property. Only supported by root folder and streams + // (all non-root folders of a package have the same encryption key). + if ( m_aUri.isRootFolder() || m_aProps.bIsDocument ) + { + uno::Sequence < sal_Int8 > aNewValue; + if ( rValue.Value >>= aNewValue ) + { + if ( aNewValue != m_aProps.aEncryptionKey ) + { + aEvent.PropertyName = rValue.Name; + aEvent.OldValue = uno::makeAny( + m_aProps.aEncryptionKey ); + aEvent.NewValue = uno::makeAny( aNewValue ); + + m_aProps.aEncryptionKey = aNewValue; + nChanged++; + bStore = sal_True; + m_nModifiedProps |= ENCRYPTIONKEY_MODIFIED; + } + } + else + { + aRet[ n ] <<= beans::IllegalTypeException( + rtl::OUString::createFromAscii( + "Property value has wrong type!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + } + else + { + aRet[ n ] <<= beans::UnknownPropertyException( + rtl::OUString::createFromAscii( + "EncryptionKey not supported by non-root folder!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + } + else + { + // Not a Core Property! Maybe it's an Additional Core Property?! + + if ( !bTriedToGetAdditonalPropSet && !xAdditionalPropSet.is() ) + { + xAdditionalPropSet = getAdditionalPropertySet( sal_False ); + bTriedToGetAdditonalPropSet = sal_True; + } + + if ( xAdditionalPropSet.is() ) + { + try + { + uno::Any aOldValue + = xAdditionalPropSet->getPropertyValue( rValue.Name ); + if ( aOldValue != rValue.Value ) + { + xAdditionalPropSet->setPropertyValue( + rValue.Name, rValue.Value ); + + aEvent.PropertyName = rValue.Name; + aEvent.OldValue = aOldValue; + aEvent.NewValue = rValue.Value; + + aChanges.getArray()[ nChanged ] = aEvent; + nChanged++; + } + } + catch ( beans::UnknownPropertyException const & e ) + { + aRet[ n ] <<= e; + } + catch ( lang::WrappedTargetException const & e ) + { + aRet[ n ] <<= e; + } + catch ( beans::PropertyVetoException const & e ) + { + aRet[ n ] <<= e; + } + catch ( lang::IllegalArgumentException const & e ) + { + aRet[ n ] <<= e; + } + } + else + { + aRet[ n ] <<= uno::Exception( + rtl::OUString::createFromAscii( + "No property set for storing the value!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + } + } + + if ( bExchange ) + { + uno::Reference< ucb::XContentIdentifier > xOldId = m_xIdentifier; + + // Assemble new content identifier... + rtl::OUString aNewURL = m_aUri.getParentUri(); + aNewURL += rtl::OUString::createFromAscii( "/" ); + aNewURL += ::ucb_impl::urihelper::encodeSegment( aNewTitle ); + uno::Reference< ucb::XContentIdentifier > xNewId + = new ::ucbhelper::ContentIdentifier( m_xSMgr, aNewURL ); + + aGuard.clear(); + if ( exchangeIdentity( xNewId ) ) + { + // Adapt persistent data. + renameData( xOldId, xNewId ); + + // Adapt Additional Core Properties. + renameAdditionalPropertySet( xOldId->getContentIdentifier(), + xNewId->getContentIdentifier(), + sal_True ); + } + else + { + // Do not set new title! + aNewTitle = rtl::OUString(); + + // Set error . + aRet[ nTitlePos ] <<= uno::Exception( + rtl::OUString::createFromAscii( "Exchange failed!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + } + + if ( aNewTitle.getLength() ) + { + aEvent.PropertyName = rtl::OUString::createFromAscii( "Title" ); + aEvent.OldValue = uno::makeAny( m_aProps.aTitle ); + aEvent.NewValue = uno::makeAny( aNewTitle ); + + m_aProps.aTitle = aNewTitle; + + aChanges.getArray()[ nChanged ] = aEvent; + nChanged++; + } + + if ( nChanged > 0 ) + { + // Save changes, if content was already made persistent. + if ( ( m_nModifiedProps & ENCRYPTIONKEY_MODIFIED ) || + ( bStore && ( m_eState == PERSISTENT ) ) ) + { + if ( !storeData( uno::Reference< io::XInputStream >() ) ) + { + uno::Any aProps + = uno::makeAny( + beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Uri")), + -1, + uno::makeAny(m_xIdentifier-> + getContentIdentifier()), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_WRITE, + uno::Sequence< uno::Any >(&aProps, 1), + xEnv, + rtl::OUString::createFromAscii( + "Cannot store persistent data!" ), + this ); + // Unreachable + } + } + + aGuard.clear(); + aChanges.realloc( nChanged ); + notifyPropertiesChange( aChanges ); + } + + return aRet; +} + +//========================================================================= +uno::Any Content::open( + const ucb::OpenCommandArgument2& rArg, + const uno::Reference< ucb::XCommandEnvironment >& xEnv ) + throw( uno::Exception ) +{ + if ( rArg.Mode == ucb::OpenMode::ALL || + rArg.Mode == ucb::OpenMode::FOLDERS || + rArg.Mode == ucb::OpenMode::DOCUMENTS ) + { + ////////////////////////////////////////////////////////////////// + // open command for a folder content + ////////////////////////////////////////////////////////////////// + + uno::Reference< ucb::XDynamicResultSet > xSet + = new DynamicResultSet( m_xSMgr, this, rArg, xEnv ); + return uno::makeAny( xSet ); + } + else + { + ////////////////////////////////////////////////////////////////// + // open command for a document content + ////////////////////////////////////////////////////////////////// + + if ( ( rArg.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_NONE ) || + ( rArg.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE ) ) + { + // Currently(?) unsupported. + ucbhelper::cancelCommandExecution( + uno::makeAny( ucb::UnsupportedOpenModeException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + sal_Int16( rArg.Mode ) ) ), + xEnv ); + // Unreachable + } + + rtl::OUString aURL = m_xIdentifier->getContentIdentifier(); + uno::Reference< io::XOutputStream > xOut( rArg.Sink, uno::UNO_QUERY ); + if ( xOut.is() ) + { + // PUSH: write data into xOut + + uno::Reference< io::XInputStream > xIn = getInputStream(); + if ( !xIn.is() ) + { + // No interaction if we are not persistent! + uno::Any aProps + = uno::makeAny( + beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Uri")), + -1, + uno::makeAny(m_xIdentifier-> + getContentIdentifier()), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_READ, + uno::Sequence< uno::Any >(&aProps, 1), + m_eState == PERSISTENT + ? xEnv + : uno::Reference< ucb::XCommandEnvironment >(), + rtl::OUString::createFromAscii( "Got no data stream!" ), + this ); + // Unreachable + } + + try + { + uno::Sequence< sal_Int8 > aBuffer; + sal_Int32 nRead = xIn->readSomeBytes( aBuffer, 65536 ); + + while ( nRead > 0 ) + { + aBuffer.realloc( nRead ); + xOut->writeBytes( aBuffer ); + aBuffer.realloc( 0 ); + nRead = xIn->readSomeBytes( aBuffer, 65536 ); + } + + xOut->closeOutput(); + } + catch ( io::NotConnectedException const & ) + { + // closeOutput, readSomeBytes, writeBytes + } + catch ( io::BufferSizeExceededException const & ) + { + // closeOutput, readSomeBytes, writeBytes + } + catch ( io::IOException const & ) + { + // closeOutput, readSomeBytes, writeBytes + } + } + else + { + uno::Reference< io::XActiveDataSink > xDataSink( + rArg.Sink, uno::UNO_QUERY ); + if ( xDataSink.is() ) + { + // PULL: wait for client read + + uno::Reference< io::XInputStream > xIn = getInputStream(); + if ( !xIn.is() ) + { + // No interaction if we are not persistent! + uno::Any aProps + = uno::makeAny( + beans::PropertyValue( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("Uri")), + -1, + uno::makeAny(m_xIdentifier-> + getContentIdentifier()), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_READ, + uno::Sequence< uno::Any >(&aProps, 1), + m_eState == PERSISTENT + ? xEnv + : uno::Reference< + ucb::XCommandEnvironment >(), + rtl::OUString::createFromAscii( + "Got no data stream!" ), + this ); + // Unreachable + } + + // Done. + xDataSink->setInputStream( xIn ); + } + else + { + // Note: aOpenCommand.Sink may contain an XStream + // implementation. Support for this type of + // sink is optional... + ucbhelper::cancelCommandExecution( + uno::makeAny( + ucb::UnsupportedDataSinkException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + rArg.Sink ) ), + xEnv ); + // Unreachable + } + } + } + + return uno::Any(); +} + +//========================================================================= +void Content::insert( + const uno::Reference< io::XInputStream >& xStream, + sal_Int32 nNameClashResolve, + const uno::Reference< ucb::XCommandEnvironment >& xEnv ) + throw( uno::Exception ) +{ + osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); + + // Check, if all required properties were set. + if ( isFolder() ) + { + // Required: Title + + if ( !m_aProps.aTitle.getLength() ) + m_aProps.aTitle = m_aUri.getName(); + } + else + { + // Required: rArg.Data + + if ( !xStream.is() ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( ucb::MissingInputStreamException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ) ) ), + xEnv ); + // Unreachable + } + + // Required: Title + + if ( !m_aProps.aTitle.getLength() ) + m_aProps.aTitle = m_aUri.getName(); + } + + rtl::OUString aNewURL = m_aUri.getParentUri(); + if (1 + aNewURL.lastIndexOf('/') != aNewURL.getLength()) + aNewURL += rtl::OUString::createFromAscii( "/" ); + aNewURL += ::ucb_impl::urihelper::encodeSegment( m_aProps.aTitle ); + PackageUri aNewUri( aNewURL ); + + // Handle possible name clash... + switch ( nNameClashResolve ) + { + // fail. + case ucb::NameClash::ERROR: + if ( hasData( aNewUri ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( ucb::NameClashException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + task::InteractionClassification_ERROR, + m_aProps.aTitle ) ), + xEnv ); + // Unreachable + } + break; + + // replace (possibly) existing object. + case ucb::NameClash::OVERWRITE: + break; + + // "invent" a new valid title. + case ucb::NameClash::RENAME: + if ( hasData( aNewUri ) ) + { + sal_Int32 nTry = 0; + + do + { + rtl::OUString aNew = aNewUri.getUri(); + aNew += rtl::OUString::createFromAscii( "_" ); + aNew += rtl::OUString::valueOf( ++nTry ); + aNewUri.setUri( aNew ); + } + while ( hasData( aNewUri ) && ( nTry < 1000 ) ); + + if ( nTry == 1000 ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( + ucb::UnsupportedNameClashException( + rtl::OUString::createFromAscii( + "Unable to resolve name clash!" ), + static_cast< cppu::OWeakObject * >( this ), + nNameClashResolve ) ), + xEnv ); + // Unreachable + } + else + { + m_aProps.aTitle += rtl::OUString::createFromAscii( "_" ); + m_aProps.aTitle += rtl::OUString::valueOf( nTry ); + } + } + break; + + case ucb::NameClash::KEEP: // deprecated + case ucb::NameClash::ASK: + default: + if ( hasData( aNewUri ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( + ucb::UnsupportedNameClashException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + nNameClashResolve ) ), + xEnv ); + // Unreachable + } + break; + } + + // Identifier changed? + sal_Bool bNewId = ( m_aUri.getUri() != aNewUri.getUri() ); + + if ( bNewId ) + { + m_xIdentifier = new ::ucbhelper::ContentIdentifier( m_xSMgr, aNewURL ); + m_aUri = aNewUri; + } + + if ( !storeData( xStream ) ) + { + uno::Any aProps + = uno::makeAny(beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Uri")), + -1, + uno::makeAny(m_xIdentifier-> + getContentIdentifier()), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_WRITE, + uno::Sequence< uno::Any >(&aProps, 1), + xEnv, + rtl::OUString::createFromAscii( "Cannot store persistent data!" ), + this ); + // Unreachable + } + + m_eState = PERSISTENT; + + if ( bNewId ) + { + // Take over correct default values from underlying packager... + uno::Reference< container::XHierarchicalNameAccess > xXHierarchicalNameAccess; + loadData( m_pProvider, + m_aUri, + m_aProps, + xXHierarchicalNameAccess ); + + aGuard.clear(); + inserted(); + } +} + +//========================================================================= +void Content::destroy( + sal_Bool bDeletePhysical, + const uno::Reference< ucb::XCommandEnvironment >& xEnv ) + throw( uno::Exception ) +{ + // @@@ take care about bDeletePhysical -> trashcan support + + osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); + + uno::Reference< ucb::XContent > xThis = this; + + // Persistent? + if ( m_eState != PERSISTENT ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( ucb::UnsupportedCommandException( + rtl::OUString::createFromAscii( + "Not persistent!" ), + static_cast< cppu::OWeakObject * >( this ) ) ), + xEnv ); + // Unreachable + } + + m_eState = DEAD; + + aGuard.clear(); + deleted(); + + if ( isFolder() ) + { + // Process instanciated children... + + ContentRefList aChildren; + queryChildren( aChildren ); + + ContentRefList::const_iterator it = aChildren.begin(); + ContentRefList::const_iterator end = aChildren.end(); + + while ( it != end ) + { + (*it)->destroy( bDeletePhysical, xEnv ); + ++it; + } + } +} + +//========================================================================= +void Content::transfer( + const ucb::TransferInfo& rInfo, + const uno::Reference< ucb::XCommandEnvironment > & xEnv ) + throw( uno::Exception ) +{ + osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); + + // Persistent? + if ( m_eState != PERSISTENT ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( ucb::UnsupportedCommandException( + rtl::OUString::createFromAscii( + "Not persistent!" ), + static_cast< cppu::OWeakObject * >( this ) ) ), + xEnv ); + // Unreachable + } + + // Is source a package content? + if ( ( rInfo.SourceURL.getLength() == 0 ) || + ( rInfo.SourceURL.compareTo( + m_aUri.getUri(), PACKAGE_URL_SCHEME_LENGTH + 3 ) != 0 ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( ucb::InteractiveBadTransferURLException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ) ) ), + xEnv ); + // Unreachable + } + + // Is source not a parent of me / not me? + rtl::OUString aId = m_aUri.getParentUri(); + aId += rtl::OUString::createFromAscii( "/" ); + + if ( rInfo.SourceURL.getLength() <= aId.getLength() ) + { + if ( aId.compareTo( + rInfo.SourceURL, rInfo.SourceURL.getLength() ) == 0 ) + { + uno::Any aProps + = uno::makeAny(beans::PropertyValue( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("Uri")), + -1, + uno::makeAny(rInfo.SourceURL), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_RECURSIVE, + uno::Sequence< uno::Any >(&aProps, 1), + xEnv, + rtl::OUString::createFromAscii( + "Target is equal to or is a child of source!" ), + this ); + // Unreachable + } + } + + ////////////////////////////////////////////////////////////////////// + // 0) Obtain content object for source. + ////////////////////////////////////////////////////////////////////// + + uno::Reference< ucb::XContentIdentifier > xId + = new ::ucbhelper::ContentIdentifier( m_xSMgr, rInfo.SourceURL ); + + // Note: The static cast is okay here, because its sure that + // m_xProvider is always the PackageContentProvider. + rtl::Reference< Content > xSource; + + try + { + xSource = static_cast< Content * >( + m_xProvider->queryContent( xId ).get() ); + } + catch ( ucb::IllegalIdentifierException const & ) + { + // queryContent + } + + if ( !xSource.is() ) + { + uno::Any aProps + = uno::makeAny(beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Uri")), + -1, + uno::makeAny(xId->getContentIdentifier()), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_READ, + uno::Sequence< uno::Any >(&aProps, 1), + xEnv, + rtl::OUString::createFromAscii( + "Cannot instanciate source object!" ), + this ); + // Unreachable + } + + ////////////////////////////////////////////////////////////////////// + // 1) Create new child content. + ////////////////////////////////////////////////////////////////////// + + rtl::OUString aType = xSource->isFolder() + ? getContentType( m_aUri.getScheme(), sal_True ) + : getContentType( m_aUri.getScheme(), sal_False ); + ucb::ContentInfo aContentInfo; + aContentInfo.Type = aType; + aContentInfo.Attributes = 0; + + // Note: The static cast is okay here, because its sure that + // createNewContent always creates a Content. + rtl::Reference< Content > xTarget + = static_cast< Content * >( createNewContent( aContentInfo ).get() ); + if ( !xTarget.is() ) + { + uno::Any aProps + = uno::makeAny(beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Folder")), + -1, + uno::makeAny(aId), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_CREATE, + uno::Sequence< uno::Any >(&aProps, 1), + xEnv, + rtl::OUString::createFromAscii( + "XContentCreator::createNewContent failed!" ), + this ); + // Unreachable + } + + ////////////////////////////////////////////////////////////////////// + // 2) Copy data from source content to child content. + ////////////////////////////////////////////////////////////////////// + + uno::Sequence< beans::Property > aSourceProps + = xSource->getPropertySetInfo( xEnv )->getProperties(); + sal_Int32 nCount = aSourceProps.getLength(); + + if ( nCount ) + { + sal_Bool bHadTitle = ( rInfo.NewTitle.getLength() == 0 ); + + // Get all source values. + uno::Reference< sdbc::XRow > xRow + = xSource->getPropertyValues( aSourceProps ); + + uno::Sequence< beans::PropertyValue > aValues( nCount ); + beans::PropertyValue* pValues = aValues.getArray(); + + const beans::Property* pProps = aSourceProps.getConstArray(); + for ( sal_Int32 n = 0; n < nCount; ++n ) + { + const beans::Property& rProp = pProps[ n ]; + beans::PropertyValue& rValue = pValues[ n ]; + + rValue.Name = rProp.Name; + rValue.Handle = rProp.Handle; + + if ( !bHadTitle && rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "Title" ) ) ) + { + // Set new title instead of original. + bHadTitle = sal_True; + rValue.Value <<= rInfo.NewTitle; + } + else + rValue.Value + = xRow->getObject( n + 1, + uno::Reference< + container::XNameAccess >() ); + + rValue.State = beans::PropertyState_DIRECT_VALUE; + + if ( rProp.Attributes & beans::PropertyAttribute::REMOVABLE ) + { + // Add Additional Core Property. + try + { + xTarget->addProperty( rProp.Name, + rProp.Attributes, + rValue.Value ); + } + catch ( beans::PropertyExistException const & ) + { + } + catch ( beans::IllegalTypeException const & ) + { + } + catch ( lang::IllegalArgumentException const & ) + { + } + } + } + + // Set target values. + xTarget->setPropertyValues( aValues, xEnv ); + } + + ////////////////////////////////////////////////////////////////////// + // 3) Commit (insert) child. + ////////////////////////////////////////////////////////////////////// + + xTarget->insert( xSource->getInputStream(), rInfo.NameClash, xEnv ); + + ////////////////////////////////////////////////////////////////////// + // 4) Transfer (copy) children of source. + ////////////////////////////////////////////////////////////////////// + + if ( xSource->isFolder() ) + { + uno::Reference< container::XEnumeration > xIter + = xSource->getIterator(); + if ( xIter.is() ) + { + while ( xIter->hasMoreElements() ) + { + try + { + uno::Reference< container::XNamed > xNamed; + xIter->nextElement() >>= xNamed; + + if ( !xNamed.is() ) + { + OSL_ENSURE( sal_False, + "Content::transfer - Got no XNamed!" ); + break; + } + + rtl::OUString aName = xNamed->getName(); + + if ( !aName.getLength() ) + { + OSL_ENSURE( sal_False, + "Content::transfer - Empty name!" ); + break; + } + + rtl::OUString aChildId = xId->getContentIdentifier(); + if ( ( aChildId.lastIndexOf( '/' ) + 1 ) + != aChildId.getLength() ) + aChildId += rtl::OUString::createFromAscii( "/" ); + + aChildId += ::ucb_impl::urihelper::encodeSegment( aName ); + + ucb::TransferInfo aInfo; + aInfo.MoveData = sal_False; + aInfo.NewTitle = rtl::OUString(); + aInfo.SourceURL = aChildId; + aInfo.NameClash = rInfo.NameClash; + + // Transfer child to target. + xTarget->transfer( aInfo, xEnv ); + } + catch ( container::NoSuchElementException const & ) + { + } + catch ( lang::WrappedTargetException const & ) + { + } + } + } + } + + ////////////////////////////////////////////////////////////////////// + // 5) Destroy source ( when moving only ) . + ////////////////////////////////////////////////////////////////////// + + if ( rInfo.MoveData ) + { + xSource->destroy( sal_True, xEnv ); + + // Remove all persistent data of source and its children. + if ( !xSource->removeData() ) + { + uno::Any aProps + = uno::makeAny( + beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Uri")), + -1, + uno::makeAny( + xSource->m_xIdentifier-> + getContentIdentifier()), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_WRITE, + uno::Sequence< uno::Any >(&aProps, 1), + xEnv, + rtl::OUString::createFromAscii( + "Cannot remove persistent data of source object!" ), + this ); + // Unreachable + } + + // Remove own and all children's Additional Core Properties. + xSource->removeAdditionalPropertySet( sal_True ); + } +} + +//========================================================================= +sal_Bool Content::exchangeIdentity( + const uno::Reference< ucb::XContentIdentifier >& xNewId ) +{ + if ( !xNewId.is() ) + return sal_False; + + osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); + + uno::Reference< ucb::XContent > xThis = this; + + // Already persistent? + if ( m_eState != PERSISTENT ) + { + OSL_ENSURE( sal_False, + "Content::exchangeIdentity - Not persistent!" ); + return sal_False; + } + + // Exchange own identitity. + + // Fail, if a content with given id already exists. + PackageUri aNewUri( xNewId->getContentIdentifier() ); + if ( !hasData( aNewUri ) ) + { + rtl::OUString aOldURL = m_xIdentifier->getContentIdentifier(); + + aGuard.clear(); + if ( exchange( xNewId ) ) + { + m_aUri = aNewUri; + if ( isFolder() ) + { + // Process instanciated children... + + ContentRefList aChildren; + queryChildren( aChildren ); + + ContentRefList::const_iterator it = aChildren.begin(); + ContentRefList::const_iterator end = aChildren.end(); + + while ( it != end ) + { + ContentRef xChild = (*it); + + // Create new content identifier for the child... + uno::Reference< ucb::XContentIdentifier > xOldChildId + = xChild->getIdentifier(); + rtl::OUString aOldChildURL + = xOldChildId->getContentIdentifier(); + rtl::OUString aNewChildURL + = aOldChildURL.replaceAt( + 0, + aOldURL.getLength(), + xNewId->getContentIdentifier() ); + uno::Reference< ucb::XContentIdentifier > xNewChildId + = new ::ucbhelper::ContentIdentifier( + m_xSMgr, aNewChildURL ); + + if ( !xChild->exchangeIdentity( xNewChildId ) ) + return sal_False; + + ++it; + } + } + return sal_True; + } + } + + OSL_ENSURE( sal_False, + "Content::exchangeIdentity - Panic! Cannot exchange identity!" ); + return sal_False; +} + +//========================================================================= +void Content::queryChildren( ContentRefList& rChildren ) +{ + // Obtain a list with a snapshot of all currently instanciated contents + // from provider and extract the contents which are direct children + // of this content. + + ::ucbhelper::ContentRefList aAllContents; + m_xProvider->queryExistingContents( aAllContents ); + + rtl::OUString aURL = m_xIdentifier->getContentIdentifier(); + + OSL_ENSURE( aURL.lastIndexOf( '/' ) != ( aURL.getLength() - 1 ), + "Content::queryChildren - Invalid URL!" ); + + aURL += rtl::OUString::createFromAscii( "/" ); + + sal_Int32 nLen = aURL.getLength(); + + ::ucbhelper::ContentRefList::const_iterator it = aAllContents.begin(); + ::ucbhelper::ContentRefList::const_iterator end = aAllContents.end(); + + while ( it != end ) + { + ::ucbhelper::ContentImplHelperRef xChild = (*it); + rtl::OUString aChildURL + = xChild->getIdentifier()->getContentIdentifier(); + + // Is aURL a prefix of aChildURL? + if ( ( aChildURL.getLength() > nLen ) && + ( aChildURL.compareTo( aURL, nLen ) == 0 ) ) + { + if ( aChildURL.indexOf( '/', nLen ) == -1 ) + { + // No further slashes. It's a child! + rChildren.push_back( + ContentRef( + static_cast< Content * >( xChild.get() ) ) ); + } + } + ++it; + } +} + +//========================================================================= +uno::Reference< container::XHierarchicalNameAccess > Content::getPackage( + const PackageUri& rURI ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + uno::Reference< container::XHierarchicalNameAccess > xPackage; + if ( rURI.getPackage() == m_aUri.getPackage() ) + { + if ( !m_xPackage.is() ) + m_xPackage = m_pProvider->createPackage( m_aUri.getPackage(), m_aUri.getParam() ); + + return m_xPackage; + } + + return m_pProvider->createPackage( rURI.getPackage(), rURI.getParam() ); +} + +//========================================================================= +uno::Reference< container::XHierarchicalNameAccess > Content::getPackage() +{ + return getPackage( m_aUri ); +} + +//========================================================================= +// static +sal_Bool Content::hasData( + ContentProvider* pProvider, + const PackageUri& rURI, + uno::Reference< container::XHierarchicalNameAccess > & rxPackage ) +{ + rxPackage = pProvider->createPackage( rURI.getPackage(), rURI.getParam() ); + if ( !rxPackage.is() ) + return sal_False; + + return rxPackage->hasByHierarchicalName( rURI.getPath() ); +} + +//========================================================================= +sal_Bool Content::hasData( const PackageUri& rURI ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + uno::Reference< container::XHierarchicalNameAccess > xPackage; + if ( rURI.getPackage() == m_aUri.getPackage() ) + { + xPackage = getPackage(); + if ( !xPackage.is() ) + return sal_False; + + return xPackage->hasByHierarchicalName( rURI.getPath() ); + } + + return hasData( m_pProvider, rURI, xPackage ); +} + +//========================================================================= +//static +sal_Bool Content::loadData( + ContentProvider* pProvider, + const PackageUri& rURI, + ContentProperties& rProps, + uno::Reference< container::XHierarchicalNameAccess > & rxPackage ) +{ + rxPackage = pProvider->createPackage( rURI.getPackage(), rURI.getParam() ); + if ( !rxPackage.is() ) + return sal_False; + + if ( rURI.isRootFolder() ) + { + // Properties available only from package + uno::Reference< beans::XPropertySet > xPackagePropSet( + rxPackage, uno::UNO_QUERY ); + + OSL_ENSURE( xPackagePropSet.is(), + "Content::loadData - " + "Got no XPropertySet interface from package!" ); + + if ( xPackagePropSet.is() ) + { + // HasEncryptedEntries ( only avalibale at root folder ) + try + { + uno::Any aHasEncryptedEntries + = xPackagePropSet->getPropertyValue( + rtl::OUString::createFromAscii( + "HasEncryptedEntries" ) ); + if ( !( aHasEncryptedEntries >>= rProps.bHasEncryptedEntries ) ) + { + OSL_ENSURE( sal_False, + "Content::loadData - " + "Got no HasEncryptedEntries value!" ); + return sal_False; + } + } + catch ( beans::UnknownPropertyException const & ) + { + OSL_ENSURE( sal_False, + "Content::loadData - " + "Got no HasEncryptedEntries value!" ); + return sal_False; + } + catch ( lang::WrappedTargetException const & ) + { + OSL_ENSURE( sal_False, + "Content::loadData - " + "Got no HasEncryptedEntries value!" ); + return sal_False; + } + } + } + + if ( !rxPackage->hasByHierarchicalName( rURI.getPath() ) ) + return sal_False; + + try + { + uno::Any aEntry = rxPackage->getByHierarchicalName( rURI.getPath() ); + if ( aEntry.hasValue() ) + { + uno::Reference< beans::XPropertySet > xPropSet; + aEntry >>= xPropSet; + + if ( !xPropSet.is() ) + { + OSL_ENSURE( sal_False, + "Content::loadData - Got no XPropertySet interface!" ); + return sal_False; + } + + // Title + rProps.aTitle = rURI.getName(); + + // MediaType + try + { + uno::Any aMediaType + = xPropSet->getPropertyValue( + rtl::OUString::createFromAscii( "MediaType" ) ); + if ( !( aMediaType >>= rProps.aMediaType ) ) + { + OSL_ENSURE( sal_False, + "Content::loadData - Got no MediaType value!" ); + return sal_False; + } + } + catch ( beans::UnknownPropertyException const & ) + { + OSL_ENSURE( sal_False, + "Content::loadData - Got no MediaType value!" ); + return sal_False; + } + catch ( lang::WrappedTargetException const & ) + { + OSL_ENSURE( sal_False, + "Content::loadData - Got no MediaType value!" ); + return sal_False; + } + + uno::Reference< container::XEnumerationAccess > xEnumAccess; + aEntry >>= xEnumAccess; + + // ContentType / IsFolder / IsDocument + if ( xEnumAccess.is() ) + { + // folder + rProps.aContentType = getContentType( rURI.getScheme(), sal_True ); + rProps.bIsDocument = sal_False; + rProps.bIsFolder = sal_True; + } + else + { + // stream + rProps.aContentType = getContentType( rURI.getScheme(), sal_False ); + rProps.bIsDocument = sal_True; + rProps.bIsFolder = sal_False; + } + + if ( rProps.bIsDocument ) + { + // Size ( only available for streams ) + try + { + uno::Any aSize + = xPropSet->getPropertyValue( + rtl::OUString::createFromAscii( "Size" ) ); + if ( !( aSize >>= rProps.nSize ) ) + { + OSL_ENSURE( sal_False, + "Content::loadData - Got no Size value!" ); + return sal_False; + } + } + catch ( beans::UnknownPropertyException const & ) + { + OSL_ENSURE( sal_False, + "Content::loadData - Got no Size value!" ); + return sal_False; + } + catch ( lang::WrappedTargetException const & ) + { + OSL_ENSURE( sal_False, + "Content::loadData - Got no Size value!" ); + return sal_False; + } + + // Compressed ( only available for streams ) + try + { + uno::Any aCompressed + = xPropSet->getPropertyValue( + rtl::OUString::createFromAscii( "Compressed" ) ); + if ( !( aCompressed >>= rProps.bCompressed ) ) + { + OSL_ENSURE( sal_False, + "Content::loadData - Got no Compressed value!" ); + return sal_False; + } + } + catch ( beans::UnknownPropertyException const & ) + { + OSL_ENSURE( sal_False, + "Content::loadData - Got no Compressed value!" ); + return sal_False; + } + catch ( lang::WrappedTargetException const & ) + { + OSL_ENSURE( sal_False, + "Content::loadData - Got no Compressed value!" ); + return sal_False; + } + + // Encrypted ( only available for streams ) + try + { + uno::Any aEncrypted + = xPropSet->getPropertyValue( + rtl::OUString::createFromAscii( "Encrypted" ) ); + if ( !( aEncrypted >>= rProps.bEncrypted ) ) + { + OSL_ENSURE( sal_False, + "Content::loadData - Got no Encrypted value!" ); + return sal_False; + } + } + catch ( beans::UnknownPropertyException const & ) + { + OSL_ENSURE( sal_False, + "Content::loadData - Got no Encrypted value!" ); + return sal_False; + } + catch ( lang::WrappedTargetException const & ) + { + OSL_ENSURE( sal_False, + "Content::loadData - Got no Encrypted value!" ); + return sal_False; + } + } + return sal_True; + } + } + catch ( container::NoSuchElementException const & ) + { + // getByHierarchicalName + } + + return sal_False; +} + +//========================================================================= +sal_Bool Content::renameData( + const uno::Reference< ucb::XContentIdentifier >& xOldId, + const uno::Reference< ucb::XContentIdentifier >& xNewId ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + PackageUri aURI( xOldId->getContentIdentifier() ); + uno::Reference< container::XHierarchicalNameAccess > xNA = getPackage( + aURI ); + if ( !xNA.is() ) + return sal_False; + + if ( !xNA->hasByHierarchicalName( aURI.getPath() ) ) + return sal_False; + + try + { + uno::Any aEntry = xNA->getByHierarchicalName( aURI.getPath() ); + uno::Reference< container::XNamed > xNamed; + aEntry >>= xNamed; + + if ( !xNamed.is() ) + { + OSL_ENSURE( sal_False, + "Content::renameData - Got no XNamed interface!" ); + return sal_False; + } + + PackageUri aNewURI( xNewId->getContentIdentifier() ); + + // No success indicator!? No return value / exceptions specified. + xNamed->setName( aNewURI.getName() ); + + return sal_True; + } + catch ( container::NoSuchElementException const & ) + { + // getByHierarchicalName + } + + return sal_False; +} + +//========================================================================= +sal_Bool Content::storeData( const uno::Reference< io::XInputStream >& xStream ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + uno::Reference< container::XHierarchicalNameAccess > xNA = getPackage(); + if ( !xNA.is() ) + return sal_False; + + uno::Reference< beans::XPropertySet > xPackagePropSet( + xNA, uno::UNO_QUERY ); + OSL_ENSURE( xPackagePropSet.is(), + "Content::storeData - " + "Got no XPropertySet interface from package!" ); + + if ( !xPackagePropSet.is() ) + return sal_False; + + if ( m_nModifiedProps & ENCRYPTIONKEY_MODIFIED ) + { + if ( m_aUri.isRootFolder() ) + { + // Property available only from package and from streams (see below) + try + { + xPackagePropSet->setPropertyValue( + rtl::OUString::createFromAscii( "EncryptionKey" ), + uno::makeAny( m_aProps.aEncryptionKey ) ); + m_nModifiedProps &= ~ENCRYPTIONKEY_MODIFIED; + } + catch ( beans::UnknownPropertyException const & ) + { + // setPropertyValue + } + catch ( beans::PropertyVetoException const & ) + { + // setPropertyValue + } + catch ( lang::IllegalArgumentException const & ) + { + // setPropertyValue + } + catch ( lang::WrappedTargetException const & ) + { + // setPropertyValue + } + } + } + + if ( !xNA->hasByHierarchicalName( m_aUri.getPath() ) ) + { +// if ( !bCreate ) +// return sal_True; + + try + { + // Create new resource... + uno::Reference< lang::XSingleServiceFactory > xFac( + xNA, uno::UNO_QUERY ); + if ( !xFac.is() ) + { + OSL_ENSURE( sal_False, + "Content::storeData - " + "Got no XSingleServiceFactory interface!" ); + return sal_False; + } + + uno::Sequence< uno::Any > aArgs( 1 ); + aArgs[ 0 ] <<= isFolder(); + + uno::Reference< uno::XInterface > xNew + = xFac->createInstanceWithArguments( aArgs ); + + if ( !xNew.is() ) + { + OSL_ENSURE( sal_False, + "Content::storeData - createInstance failed!" ); + return sal_False; + } + + PackageUri aParentUri( getParentURL() ); + uno::Any aEntry + = xNA->getByHierarchicalName( aParentUri.getPath() ); + uno::Reference< container::XNameContainer > xParentContainer; + aEntry >>= xParentContainer; + + if ( !xParentContainer.is() ) + { + OSL_ENSURE( sal_False, + "Content::storeData - " + "Got no XNameContainer interface!" ); + return sal_False; + } + + xParentContainer->insertByName( m_aProps.aTitle, + uno::makeAny( xNew ) ); + } + catch ( uno::RuntimeException const & ) + { + throw; + } + catch ( lang::IllegalArgumentException const & ) + { + // insertByName + OSL_ENSURE( sal_False, + "Content::storeData - insertByName failed!" ); + return sal_False; + } + catch ( container::ElementExistException const & ) + { + // insertByName + OSL_ENSURE( sal_False, + "Content::storeData - insertByName failed!" ); + return sal_False; + } + catch ( lang::WrappedTargetException const & ) + { + // insertByName + OSL_ENSURE( sal_False, + "Content::storeData - insertByName failed!" ); + return sal_False; + } + catch ( container::NoSuchElementException const & ) + { + // getByHierarchicalName + OSL_ENSURE( sal_False, + "Content::storeData - getByHierarchicalName failed!" ); + return sal_False; + } + catch ( uno::Exception const & ) + { + // createInstanceWithArguments + OSL_ENSURE( sal_False, "Content::storeData - Error!" ); + return sal_False; + } + } + + if ( !xNA->hasByHierarchicalName( m_aUri.getPath() ) ) + return sal_False; + + try + { + uno::Reference< beans::XPropertySet > xPropSet; + xNA->getByHierarchicalName( m_aUri.getPath() ) >>= xPropSet; + + if ( !xPropSet.is() ) + { + OSL_ENSURE( sal_False, + "Content::storeData - Got no XPropertySet interface!" ); + return sal_False; + } + + ////////////////////////////////////////////////////////////////// + // Store property values... + ////////////////////////////////////////////////////////////////// + + if ( m_nModifiedProps & MEDIATYPE_MODIFIED ) + { + xPropSet->setPropertyValue( + rtl::OUString::createFromAscii( "MediaType" ), + uno::makeAny( m_aProps.aMediaType ) ); + m_nModifiedProps &= ~MEDIATYPE_MODIFIED; + } + + if ( m_nModifiedProps & COMPRESSED_MODIFIED ) + { + if ( !isFolder() ) + xPropSet->setPropertyValue( + rtl::OUString::createFromAscii( "Compressed" ), + uno::makeAny( m_aProps.bCompressed ) ); + + m_nModifiedProps &= ~COMPRESSED_MODIFIED; + } + + if ( m_nModifiedProps & ENCRYPTED_MODIFIED ) + { + if ( !isFolder() ) + xPropSet->setPropertyValue( + rtl::OUString::createFromAscii( "Encrypted" ), + uno::makeAny( m_aProps.bEncrypted ) ); + + m_nModifiedProps &= ~ENCRYPTED_MODIFIED; + } + + if ( m_nModifiedProps & ENCRYPTIONKEY_MODIFIED ) + { + if ( !isFolder() ) + xPropSet->setPropertyValue( + rtl::OUString::createFromAscii( "EncryptionKey" ), + uno::makeAny( m_aProps.aEncryptionKey ) ); + + m_nModifiedProps &= ~ENCRYPTIONKEY_MODIFIED; + } + + ////////////////////////////////////////////////////////////////// + // Store data stream... + ////////////////////////////////////////////////////////////////// + + if ( xStream.is() && !isFolder() ) + { + uno::Reference< io::XActiveDataSink > xSink( + xPropSet, uno::UNO_QUERY ); + + if ( !xSink.is() ) + { + OSL_ENSURE( sal_False, + "Content::storeData - " + "Got no XActiveDataSink interface!" ); + return sal_False; + } + + xSink->setInputStream( xStream ); + } + + return sal_True; + } + catch ( container::NoSuchElementException const & ) + { + // getByHierarchicalName + } + catch ( beans::UnknownPropertyException const & ) + { + // setPropertyValue + } + catch ( beans::PropertyVetoException const & ) + { + // setPropertyValue + } + catch ( lang::IllegalArgumentException const & ) + { + // setPropertyValue + } + catch ( lang::WrappedTargetException const & ) + { + // setPropertyValue + } + + OSL_ENSURE( sal_False, "Content::storeData - Error!" ); + return sal_False; +} + +//========================================================================= +sal_Bool Content::removeData() +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + uno::Reference< container::XHierarchicalNameAccess > xNA = getPackage(); + if ( !xNA.is() ) + return sal_False; + + PackageUri aParentUri( getParentURL() ); + if ( !xNA->hasByHierarchicalName( aParentUri.getPath() ) ) + return sal_False; + + try + { + uno::Any aEntry = xNA->getByHierarchicalName( aParentUri.getPath() ); + uno::Reference< container::XNameContainer > xContainer; + aEntry >>= xContainer; + + if ( !xContainer.is() ) + { + OSL_ENSURE( sal_False, + "Content::removeData - " + "Got no XNameContainer interface!" ); + return sal_False; + } + + xContainer->removeByName( m_aUri.getName() ); + return sal_True; + } + catch ( container::NoSuchElementException const & ) + { + // getByHierarchicalName, removeByName + } + catch ( lang::WrappedTargetException const & ) + { + // removeByName + } + + OSL_ENSURE( sal_False, "Content::removeData - Error!" ); + return sal_False; +} + +//========================================================================= +sal_Bool Content::flushData() +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + // Note: XChangesBatch is only implemented by the package itself, not + // by the single entries. Maybe this has to change... + + uno::Reference< container::XHierarchicalNameAccess > xNA = getPackage(); + if ( !xNA.is() ) + return sal_False; + + uno::Reference< util::XChangesBatch > xBatch( xNA, uno::UNO_QUERY ); + if ( !xBatch.is() ) + { + OSL_ENSURE( sal_False, + "Content::flushData - Got no XChangesBatch interface!" ); + return sal_False; + } + + try + { + xBatch->commitChanges(); + return sal_True; + } + catch ( lang::WrappedTargetException const & ) + { + } + + OSL_ENSURE( sal_False, "Content::flushData - Error!" ); + return sal_False; +} + +//========================================================================= +uno::Reference< io::XInputStream > Content::getInputStream() +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + uno::Reference< io::XInputStream > xStream; + uno::Reference< container::XHierarchicalNameAccess > xNA = getPackage(); + if ( !xNA.is() ) + return xStream; + + if ( !xNA->hasByHierarchicalName( m_aUri.getPath() ) ) + return xStream; + + try + { + uno::Any aEntry = xNA->getByHierarchicalName( m_aUri.getPath() ); + uno::Reference< io::XActiveDataSink > xSink; + aEntry >>= xSink; + + if ( !xSink.is() ) + { + OSL_ENSURE( sal_False, + "Content::getInputStream - " + "Got no XActiveDataSink interface!" ); + return xStream; + } + + xStream = xSink->getInputStream(); + + OSL_ENSURE( xStream.is(), + "Content::getInputStream - Got no stream!" ); + } + catch ( container::NoSuchElementException const & ) + { + // getByHierarchicalName + } + + return xStream; +} + +//========================================================================= +uno::Reference< container::XEnumeration > Content::getIterator() +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + uno::Reference< container::XEnumeration > xIter; + uno::Reference< container::XHierarchicalNameAccess > xNA = getPackage(); + if ( !xNA.is() ) + return xIter; + + if ( !xNA->hasByHierarchicalName( m_aUri.getPath() ) ) + return xIter; + + try + { + uno::Any aEntry = xNA->getByHierarchicalName( m_aUri.getPath() ); + uno::Reference< container::XEnumerationAccess > xIterFac; + aEntry >>= xIterFac; + + if ( !xIterFac.is() ) + { + OSL_ENSURE( sal_False, + "Content::getIterator - " + "Got no XEnumerationAccess interface!" ); + return xIter; + } + + xIter = xIterFac->createEnumeration(); + + OSL_ENSURE( xIter.is(), + "Content::getIterator - Got no iterator!" ); + } + catch ( container::NoSuchElementException const & ) + { + // getByHierarchicalName + } + + return xIter; +} diff --git a/ucb/source/ucp/package/pkgcontent.hxx b/ucb/source/ucp/package/pkgcontent.hxx new file mode 100644 index 000000000000..5dbc8a69c1de --- /dev/null +++ b/ucb/source/ucp/package/pkgcontent.hxx @@ -0,0 +1,335 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _PKGCONTENT_HXX +#define _PKGCONTENT_HXX + +#include <list> +#include <rtl/ref.hxx> + +#include <com/sun/star/ucb/InteractiveBadTransferURLException.hpp> +#include <com/sun/star/ucb/XContentCreator.hpp> +#include <ucbhelper/contenthelper.hxx> +#include "pkguri.hxx" + +namespace com { namespace sun { namespace star { + namespace beans + { + struct Property; + struct PropertyValue; + } + namespace container + { + class XHierarchicalNameAccess; + class XEnumeration; + } + namespace io + { + class XInputStream; + } + namespace sdbc + { + class XRow; + } + namespace ucb + { + struct OpenCommandArgument2; + struct TransferInfo; + } +} } } + +namespace package_ucp +{ + +//========================================================================= + +// UNO service name for the content. +#define PACKAGE_FOLDER_CONTENT_SERVICE_NAME \ + "com.sun.star.ucb.PackageFolderContent" +#define PACKAGE_STREAM_CONTENT_SERVICE_NAME \ + "com.sun.star.ucb.PackageStreamContent" + +//========================================================================= + +struct ContentProperties +{ + ::rtl::OUString aTitle; // Title + ::rtl::OUString aContentType; // ContentType + sal_Bool bIsDocument; // IsDocument + sal_Bool bIsFolder; // IsFolder + ::rtl::OUString aMediaType; // MediaType + com::sun::star::uno::Sequence < + sal_Int8 > aEncryptionKey; // EncryptionKey + sal_Int64 nSize; // Size + sal_Bool bCompressed; // Compressed + sal_Bool bEncrypted; // Encrypted + sal_Bool bHasEncryptedEntries; // HasEncryptedEntries + + ContentProperties() + : bIsDocument( sal_True ), bIsFolder( sal_False ), nSize( 0 ), + bCompressed( sal_True ), bEncrypted( sal_False ), + bHasEncryptedEntries( sal_False ) {} + + ContentProperties( const ::rtl::OUString& rContentType ); + + com::sun::star::uno::Sequence< com::sun::star::ucb::ContentInfo > + getCreatableContentsInfo( PackageUri const & rUri ) const; +}; + +//========================================================================= + +class ContentProvider; + +class Content : public ::ucbhelper::ContentImplHelper, + public com::sun::star::ucb::XContentCreator +{ + enum ContentState { TRANSIENT, // created via CreateNewContent, + // but did not process "insert" yet + PERSISTENT, // processed "insert" + DEAD // processed "delete" + }; + + PackageUri m_aUri; + ContentProperties m_aProps; + ContentState m_eState; + com::sun::star::uno::Reference< + com::sun::star::container::XHierarchicalNameAccess > m_xPackage; + ContentProvider* m_pProvider; + sal_uInt32 m_nModifiedProps; + +private: + Content( const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + ContentProvider* pProvider, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& Identifier, + const ::com::sun::star::uno::Reference< + com::sun::star::container::XHierarchicalNameAccess >& Package, + const PackageUri& rUri, + const ContentProperties& rProps ); + Content( const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + ContentProvider* pProvider, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& Identifier, + const com::sun::star::uno::Reference< + com::sun::star::container::XHierarchicalNameAccess >& Package, + const PackageUri& rUri, + const com::sun::star::ucb::ContentInfo& Info ); + + virtual com::sun::star::uno::Sequence< com::sun::star::beans::Property > + getProperties( const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv ); + virtual com::sun::star::uno::Sequence< com::sun::star::ucb::CommandInfo > + getCommands( const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv ); + virtual ::rtl::OUString getParentURL(); + + static ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRow > + getPropertyValues( const ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XMultiServiceFactory >& rSMgr, + const ::com::sun::star::uno::Sequence< + ::com::sun::star::beans::Property >& rProperties, + const ContentProperties& rData, + const rtl::Reference< + ::ucbhelper::ContentProviderImplHelper >& rProvider, + const ::rtl::OUString& rContentId ); + + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRow > + getPropertyValues( const ::com::sun::star::uno::Sequence< + ::com::sun::star::beans::Property >& rProperties ); + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > + setPropertyValues( const ::com::sun::star::uno::Sequence< + ::com::sun::star::beans::PropertyValue >& rValues, + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw( ::com::sun::star::uno::Exception ); + + com::sun::star::uno::Reference< + com::sun::star::container::XHierarchicalNameAccess > + getPackage( const PackageUri& rURI ); + com::sun::star::uno::Reference< + com::sun::star::container::XHierarchicalNameAccess > + getPackage(); + + static sal_Bool + loadData( ContentProvider* pProvider, + const PackageUri& rURI, + ContentProperties& rProps, + com::sun::star::uno::Reference< + com::sun::star::container::XHierarchicalNameAccess > & + rxPackage ); + static sal_Bool + hasData( ContentProvider* pProvider, + const PackageUri& rURI, + com::sun::star::uno::Reference< + com::sun::star::container::XHierarchicalNameAccess > & + rxPackage ); + + sal_Bool + hasData( const PackageUri& rURI ); + sal_Bool + renameData( const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& xOldId, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& xNewId ); + sal_Bool + storeData( const com::sun::star::uno::Reference< + com::sun::star::io::XInputStream >& xStream ); + sal_Bool + removeData(); + + sal_Bool + flushData(); + + typedef rtl::Reference< Content > ContentRef; + typedef std::list< ContentRef > ContentRefList; + void queryChildren( ContentRefList& rChildren ); + + sal_Bool + exchangeIdentity( const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XContentIdentifier >& xNewId ); + + ::com::sun::star::uno::Any + open( const ::com::sun::star::ucb::OpenCommandArgument2& rArg, + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw( ::com::sun::star::uno::Exception ); + + void insert( const ::com::sun::star::uno::Reference< + ::com::sun::star::io::XInputStream >& xStream, + sal_Int32 nNameClashResolve, + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw( ::com::sun::star::uno::Exception ); + + void destroy( sal_Bool bDeletePhysical, + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw( ::com::sun::star::uno::Exception ); + + void transfer( const ::com::sun::star::ucb::TransferInfo& rInfo, + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw( ::com::sun::star::uno::Exception ); + + ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > + getInputStream(); + + sal_Bool isFolder() const { return m_aProps.bIsFolder; } + +public: + // Create existing content. Fail, if not already exists. + static Content* create( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + ContentProvider* pProvider, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& Identifier ); + + // Create new content. Fail, if already exists. + static Content* create( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + ContentProvider* pProvider, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& Identifier, + const com::sun::star::ucb::ContentInfo& Info ); + + virtual ~Content(); + + // XInterface + XINTERFACE_DECL() + + // XTypeProvider + XTYPEPROVIDER_DECL() + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL + getImplementationName() + throw( ::com::sun::star::uno::RuntimeException ); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL + getSupportedServiceNames() + throw( ::com::sun::star::uno::RuntimeException ); + + // XContent + virtual rtl::OUString SAL_CALL + getContentType() + throw( com::sun::star::uno::RuntimeException ); + + // XCommandProcessor + virtual com::sun::star::uno::Any SAL_CALL + execute( const com::sun::star::ucb::Command& aCommand, + sal_Int32 CommandId, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment >& Environment ) + throw( com::sun::star::uno::Exception, + com::sun::star::ucb::CommandAbortedException, + com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + abort( sal_Int32 CommandId ) + throw( com::sun::star::uno::RuntimeException ); + + ////////////////////////////////////////////////////////////////////// + // Additional interfaces + ////////////////////////////////////////////////////////////////////// + + // XContentCreator + virtual com::sun::star::uno::Sequence< + com::sun::star::ucb::ContentInfo > SAL_CALL + queryCreatableContentsInfo() + throw( com::sun::star::uno::RuntimeException ); + virtual com::sun::star::uno::Reference< + com::sun::star::ucb::XContent > SAL_CALL + createNewContent( const com::sun::star::ucb::ContentInfo& Info ) + throw( com::sun::star::uno::RuntimeException ); + + ////////////////////////////////////////////////////////////////////// + // Non-interface methods. + ////////////////////////////////////////////////////////////////////// + + // Called from resultset data supplier. + static ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRow > + getPropertyValues( const ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XMultiServiceFactory >& rSMgr, + const ::com::sun::star::uno::Sequence< + ::com::sun::star::beans::Property >& rProperties, + ContentProvider* pProvider, + const ::rtl::OUString& rContentId ); + + // Called from resultset data supplier. + ::com::sun::star::uno::Reference< + ::com::sun::star::container::XEnumeration > + getIterator(); + + static ::rtl::OUString + getContentType( const ::rtl::OUString& aScheme, sal_Bool bFolder ); +}; + +} + +#endif diff --git a/ucb/source/ucp/package/pkgcontentcaps.cxx b/ucb/source/ucp/package/pkgcontentcaps.cxx new file mode 100644 index 000000000000..88807d900275 --- /dev/null +++ b/ucb/source/ucp/package/pkgcontentcaps.cxx @@ -0,0 +1,562 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + Props/Commands: + + rootfolder folder stream + --------------------------------------------- + ContentType r r r + IsDocument r r r + IsFolder r r r + MediaType (w) (w) w + Title r w w + Size - - r + CreatableContentsInfo r r r + Compressed - - w + Encrypted - - w + HasEncryptedEntries r - - + + getCommandInfo x x x + getPropertySetInfo x x x + getPropertyValues x x x + setPropertyValues x x x + insert - x x + delete - x x + open x x x + transfer x x - + flush x x - + createNewContent x x - + + *************************************************************************/ +#include <com/sun/star/beans/Property.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/ucb/CommandInfo.hpp> +#include <com/sun/star/ucb/OpenCommandArgument2.hpp> +#include <com/sun/star/ucb/TransferInfo.hpp> +#include <com/sun/star/uno/Sequence.hxx> +#include "pkgcontent.hxx" + +using namespace com::sun::star; +using namespace package_ucp; + +//========================================================================= +// +// Content implementation. +// +//========================================================================= + +#define MAKEPROPSEQUENCE( a ) \ + uno::Sequence< beans::Property >( a, sizeof( a ) / sizeof( a[ 0 ] ) ) + +#define MAKECMDSEQUENCE( a ) \ + uno::Sequence< ucb::CommandInfo >( a, sizeof( a ) / sizeof( a[ 0 ] ) ) + +//========================================================================= +// +// IMPORTENT: If any property data ( name / type / ... ) are changed, then +// Content::getPropertyValues(...) must be adapted too! +// +//========================================================================= + +// virtual +uno::Sequence< beans::Property > Content::getProperties( + const uno::Reference< ucb::XCommandEnvironment > & /*xEnv*/ ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + if ( isFolder() ) + { + if ( m_aUri.isRootFolder() ) + { + //================================================================= + // + // Root Folder: Supported properties + // + //================================================================= + + static const beans::Property aRootFolderPropertyInfoTable[] = + { + /////////////////////////////////////////////////////////////// + // Required properties + /////////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "ContentType" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "IsDocument" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + /////////////////////////////////////////////////////////////// + // Optional standard properties + /////////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "CreatableContentsInfo" ) ), + -1, + getCppuType( static_cast< + const uno::Sequence< ucb::ContentInfo > * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + /////////////////////////////////////////////////////////////// + // New properties + /////////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "HasEncryptedEntries" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ) + }; + return MAKEPROPSEQUENCE( aRootFolderPropertyInfoTable ); + } + else + { + //================================================================= + // + // Folder: Supported properties + // + //================================================================= + + static const beans::Property aFolderPropertyInfoTable[] = + { + /////////////////////////////////////////////////////////////// + // Required properties + /////////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "ContentType" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "IsDocument" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + ), + /////////////////////////////////////////////////////////////// + // Optional standard properties + /////////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "CreatableContentsInfo" ) ), + -1, + getCppuType( static_cast< + const uno::Sequence< ucb::ContentInfo > * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ) + /////////////////////////////////////////////////////////////// + // New properties + /////////////////////////////////////////////////////////////// + }; + return MAKEPROPSEQUENCE( aFolderPropertyInfoTable ); + } + } + else + { + //================================================================= + // + // Stream: Supported properties + // + //================================================================= + + static const beans::Property aStreamPropertyInfoTable[] = + { + /////////////////////////////////////////////////////////////// + // Required properties + /////////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ContentType" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsDocument" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + ), + /////////////////////////////////////////////////////////////// + // Optional standard properties + /////////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Size" ) ), + -1, + getCppuType( static_cast< const sal_Int64 * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "CreatableContentsInfo" ) ), + -1, + getCppuType( static_cast< + const uno::Sequence< ucb::ContentInfo > * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + /////////////////////////////////////////////////////////////// + // New properties + /////////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Compressed" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Encrypted" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + ) + }; + return MAKEPROPSEQUENCE( aStreamPropertyInfoTable ); + } +} + +//========================================================================= +// virtual +uno::Sequence< ucb::CommandInfo > Content::getCommands( + const uno::Reference< ucb::XCommandEnvironment > & /*xEnv*/ ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + if ( isFolder() ) + { + if ( m_aUri.isRootFolder() ) + { + //================================================================= + // + // Root Folder: Supported commands + // + //================================================================= + + static const ucb::CommandInfo aRootFolderCommandInfoTable[] = + { + /////////////////////////////////////////////////////////// + // Required commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getCommandInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertySetInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertyValues" ) ), + -1, + getCppuType( + static_cast< + uno::Sequence< beans::Property > * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ), + -1, + getCppuType( + static_cast< + uno::Sequence< beans::PropertyValue > * >( 0 ) ) + ), + /////////////////////////////////////////////////////////// + // Optional standard commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "open" ) ), + -1, + getCppuType( + static_cast< ucb::OpenCommandArgument2 * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "transfer" ) ), + -1, + getCppuType( + static_cast< ucb::TransferInfo * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "createNewContent" ) ), + -1, + getCppuType( static_cast< ucb::ContentInfo * >( 0 ) ) + ), + /////////////////////////////////////////////////////////// + // New commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "flush" ) ), + -1, + getCppuVoidType() + ) + }; + + return MAKECMDSEQUENCE( aRootFolderCommandInfoTable ); + } + else + { + //================================================================= + // + // Folder: Supported commands + // + //================================================================= + + static const ucb::CommandInfo aFolderCommandInfoTable[] = + { + /////////////////////////////////////////////////////////// + // Required commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getCommandInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertySetInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertyValues" ) ), + -1, + getCppuType( + static_cast< + uno::Sequence< beans::Property > * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ), + -1, + getCppuType( + static_cast< + uno::Sequence< beans::PropertyValue > * >( 0 ) ) + ), + /////////////////////////////////////////////////////////// + // Optional standard commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "delete" ) ), + -1, + getCppuBooleanType() + ), + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "insert" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "open" ) ), + -1, + getCppuType( + static_cast< ucb::OpenCommandArgument2 * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "transfer" ) ), + -1, + getCppuType( + static_cast< ucb::TransferInfo * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "createNewContent" ) ), + -1, + getCppuType( static_cast< ucb::ContentInfo * >( 0 ) ) + ), + /////////////////////////////////////////////////////////// + // New commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "flush" ) ), + -1, + getCppuVoidType() + ) + }; + + return MAKECMDSEQUENCE( aFolderCommandInfoTable ); + } + } + else + { + //================================================================= + // + // Stream: Supported commands + // + //================================================================= + + static const ucb::CommandInfo aStreamCommandInfoTable[] = + { + /////////////////////////////////////////////////////////////// + // Required commands + /////////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getCommandInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertySetInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertyValues" ) ), + -1, + getCppuType( + static_cast< uno::Sequence< beans::Property > * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ), + -1, + getCppuType( + static_cast< + uno::Sequence< beans::PropertyValue > * >( 0 ) ) + ), + /////////////////////////////////////////////////////////////// + // Optional standard commands + /////////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "delete" ) ), + -1, + getCppuBooleanType() + ), + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "insert" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "open" ) ), + -1, + getCppuType( + static_cast< ucb::OpenCommandArgument2 * >( 0 ) ) + ) + /////////////////////////////////////////////////////////////// + // New commands + /////////////////////////////////////////////////////////////// + }; + + return MAKECMDSEQUENCE( aStreamCommandInfoTable ); + } +} diff --git a/ucb/source/ucp/package/pkgdatasupplier.cxx b/ucb/source/ucp/package/pkgdatasupplier.cxx new file mode 100644 index 000000000000..133e16dc7ed8 --- /dev/null +++ b/ucb/source/ucp/package/pkgdatasupplier.cxx @@ -0,0 +1,498 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ + +#include <vector> +#include <osl/diagnose.h> +#include <com/sun/star/container/XEnumeration.hpp> +#include <com/sun/star/container/XNamed.hpp> +#include <ucbhelper/contentidentifier.hxx> +#include <ucbhelper/providerhelper.hxx> +#include "pkgdatasupplier.hxx" +#include "pkgcontent.hxx" +#include "pkgprovider.hxx" + +#include "../inc/urihelper.hxx" + +using namespace com::sun::star; +using namespace package_ucp; + +namespace package_ucp +{ + +//========================================================================= +// +// struct ResultListEntry. +// +//========================================================================= + +struct ResultListEntry +{ + rtl::OUString aURL; + uno::Reference< ucb::XContentIdentifier > xId; + uno::Reference< ucb::XContent > xContent; + uno::Reference< sdbc::XRow > xRow; + + ResultListEntry( const rtl::OUString& rURL ) : aURL( rURL ) {} +}; + +//========================================================================= +// +// ResultList. +// +//========================================================================= + +typedef std::vector< ResultListEntry* > ResultList; + +//========================================================================= +// +// struct DataSupplier_Impl. +// +//========================================================================= + +struct DataSupplier_Impl +{ + osl::Mutex m_aMutex; + ResultList m_aResults; + rtl::Reference< Content > m_xContent; + uno::Reference< lang::XMultiServiceFactory > m_xSMgr; + uno::Reference< container::XEnumeration > m_xFolderEnum; + sal_Int32 m_nOpenMode; + sal_Bool m_bCountFinal; + sal_Bool m_bThrowException; + + DataSupplier_Impl( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + const rtl::Reference< Content >& rContent, + sal_Int32 nOpenMode ) + : m_xContent( rContent ), m_xSMgr( rxSMgr ), + m_xFolderEnum( rContent->getIterator() ), m_nOpenMode( nOpenMode ), + m_bCountFinal( !m_xFolderEnum.is() ), m_bThrowException( m_bCountFinal ) + {} + ~DataSupplier_Impl(); +}; + +//========================================================================= +DataSupplier_Impl::~DataSupplier_Impl() +{ + ResultList::const_iterator it = m_aResults.begin(); + ResultList::const_iterator end = m_aResults.end(); + + while ( it != end ) + { + delete (*it); + it++; + } +} + +} + +//========================================================================= +//========================================================================= +// +// DataSupplier Implementation. +// +//========================================================================= +//========================================================================= + +DataSupplier::DataSupplier( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + const rtl::Reference< Content >& rContent, + sal_Int32 nOpenMode ) +: m_pImpl( new DataSupplier_Impl( rxSMgr, rContent, nOpenMode ) ) +{ +} + +//========================================================================= +// virtual +DataSupplier::~DataSupplier() +{ + delete m_pImpl; +} + +//========================================================================= +// virtual +rtl::OUString DataSupplier::queryContentIdentifierString( sal_uInt32 nIndex ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( nIndex < m_pImpl->m_aResults.size() ) + { + rtl::OUString aId = m_pImpl->m_aResults[ nIndex ]->aURL; + if ( aId.getLength() ) + { + // Already cached. + return aId; + } + } + + if ( getResult( nIndex ) ) + { + // Note: getResult fills m_pImpl->m_aResults[ nIndex ]->aURL. + return m_pImpl->m_aResults[ nIndex ]->aURL; + } + return rtl::OUString(); +} + +//========================================================================= +// virtual +uno::Reference< ucb::XContentIdentifier > +DataSupplier::queryContentIdentifier( sal_uInt32 nIndex ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( nIndex < m_pImpl->m_aResults.size() ) + { + uno::Reference< ucb::XContentIdentifier > xId + = m_pImpl->m_aResults[ nIndex ]->xId; + if ( xId.is() ) + { + // Already cached. + return xId; + } + } + + rtl::OUString aId = queryContentIdentifierString( nIndex ); + if ( aId.getLength() ) + { + uno::Reference< ucb::XContentIdentifier > xId + = new ::ucbhelper::ContentIdentifier( aId ); + m_pImpl->m_aResults[ nIndex ]->xId = xId; + return xId; + } + return uno::Reference< ucb::XContentIdentifier >(); +} + +//========================================================================= +// virtual +uno::Reference< ucb::XContent > DataSupplier::queryContent( + sal_uInt32 nIndex ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( nIndex < m_pImpl->m_aResults.size() ) + { + uno::Reference< ucb::XContent > xContent + = m_pImpl->m_aResults[ nIndex ]->xContent; + if ( xContent.is() ) + { + // Already cached. + return xContent; + } + } + + uno::Reference< ucb::XContentIdentifier > xId + = queryContentIdentifier( nIndex ); + if ( xId.is() ) + { + try + { + uno::Reference< ucb::XContent > xContent + = m_pImpl->m_xContent->getProvider()->queryContent( xId ); + m_pImpl->m_aResults[ nIndex ]->xContent = xContent; + return xContent; + + } + catch ( ucb::IllegalIdentifierException const & ) + { + } + } + return uno::Reference< ucb::XContent >(); +} + +//========================================================================= +// virtual +sal_Bool DataSupplier::getResult( sal_uInt32 nIndex ) +{ + osl::ClearableGuard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( m_pImpl->m_aResults.size() > nIndex ) + { + // Result already present. + return sal_True; + } + + // Result not (yet) present. + + if ( m_pImpl->m_bCountFinal ) + return sal_False; + + // Try to obtain result... + + sal_uInt32 nOldCount = m_pImpl->m_aResults.size(); + sal_Bool bFound = sal_False; + sal_uInt32 nPos = nOldCount; + + while ( m_pImpl->m_xFolderEnum->hasMoreElements() ) + { + try + { + uno::Reference< container::XNamed > xNamed; + m_pImpl->m_xFolderEnum->nextElement() >>= xNamed; + + if ( !xNamed.is() ) + { + OSL_ENSURE( sal_False, + "DataSupplier::getResult - Got no XNamed!" ); + break; + } + + rtl::OUString aName = xNamed->getName(); + + if ( !aName.getLength() ) + { + OSL_ENSURE( sal_False, + "DataSupplier::getResult - Empty name!" ); + break; + } + + // Assemble URL for child. + rtl::OUString aURL = assembleChildURL( aName ); + + m_pImpl->m_aResults.push_back( new ResultListEntry( aURL ) ); + + if ( nPos == nIndex ) + { + // Result obtained. + bFound = sal_True; + break; + } + + nPos++; + } + catch ( container::NoSuchElementException const & ) + { + m_pImpl->m_bThrowException = sal_True; + break; + } + catch ( lang::WrappedTargetException const & ) + { + m_pImpl->m_bThrowException = sal_True; + break; + } + } + + if ( !bFound ) + m_pImpl->m_bCountFinal = sal_True; + + rtl::Reference< ::ucbhelper::ResultSet > xResultSet = getResultSet().get(); + if ( xResultSet.is() ) + { + // Callbacks follow! + aGuard.clear(); + + if ( nOldCount < m_pImpl->m_aResults.size() ) + xResultSet->rowCountChanged( + nOldCount, m_pImpl->m_aResults.size() ); + + if ( m_pImpl->m_bCountFinal ) + xResultSet->rowCountFinal(); + } + + return bFound; +} + +//========================================================================= +// virtual +sal_uInt32 DataSupplier::totalCount() +{ + osl::ClearableGuard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( m_pImpl->m_bCountFinal ) + return m_pImpl->m_aResults.size(); + + sal_uInt32 nOldCount = m_pImpl->m_aResults.size(); + + while ( m_pImpl->m_xFolderEnum->hasMoreElements() ) + { + try + { + uno::Reference< container::XNamed > xNamed; + m_pImpl->m_xFolderEnum->nextElement() >>= xNamed; + + if ( !xNamed.is() ) + { + OSL_ENSURE( sal_False, + "DataSupplier::getResult - Got no XNamed!" ); + break; + } + + rtl::OUString aName = xNamed->getName(); + + if ( !aName.getLength() ) + { + OSL_ENSURE( sal_False, + "DataSupplier::getResult - Empty name!" ); + break; + } + + // Assemble URL for child. + rtl::OUString aURL = assembleChildURL( aName ); + + m_pImpl->m_aResults.push_back( new ResultListEntry( aURL ) ); + } + catch ( container::NoSuchElementException const & ) + { + m_pImpl->m_bThrowException = sal_True; + break; + } + catch ( lang::WrappedTargetException const & ) + { + m_pImpl->m_bThrowException = sal_True; + break; + } + } + + m_pImpl->m_bCountFinal = sal_True; + + rtl::Reference< ::ucbhelper::ResultSet > xResultSet = getResultSet().get(); + if ( xResultSet.is() ) + { + // Callbacks follow! + aGuard.clear(); + + if ( nOldCount < m_pImpl->m_aResults.size() ) + xResultSet->rowCountChanged( + nOldCount, m_pImpl->m_aResults.size() ); + + xResultSet->rowCountFinal(); + } + + return m_pImpl->m_aResults.size(); +} + +//========================================================================= +// virtual +sal_uInt32 DataSupplier::currentCount() +{ + return m_pImpl->m_aResults.size(); +} + +//========================================================================= +// virtual +sal_Bool DataSupplier::isCountFinal() +{ + return m_pImpl->m_bCountFinal; +} + +//========================================================================= +// virtual +uno::Reference< sdbc::XRow > DataSupplier::queryPropertyValues( + sal_uInt32 nIndex ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( nIndex < m_pImpl->m_aResults.size() ) + { + uno::Reference< sdbc::XRow > xRow = m_pImpl->m_aResults[ nIndex ]->xRow; + if ( xRow.is() ) + { + // Already cached. + return xRow; + } + } + + if ( getResult( nIndex ) ) + { + uno::Reference< sdbc::XRow > xRow = Content::getPropertyValues( + m_pImpl->m_xSMgr, + getResultSet()->getProperties(), + static_cast< ContentProvider * >( + m_pImpl->m_xContent->getProvider().get() ), + queryContentIdentifierString( nIndex ) ); + m_pImpl->m_aResults[ nIndex ]->xRow = xRow; + return xRow; + } + + return uno::Reference< sdbc::XRow >(); +} + +//========================================================================= +// virtual +void DataSupplier::releasePropertyValues( sal_uInt32 nIndex ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( nIndex < m_pImpl->m_aResults.size() ) + m_pImpl->m_aResults[ nIndex ]->xRow = uno::Reference< sdbc::XRow >(); +} + +//========================================================================= +// virtual +void DataSupplier::close() +{ +} + +//========================================================================= +// virtual +void DataSupplier::validate() + throw( ucb::ResultSetException ) +{ + if ( m_pImpl->m_bThrowException ) + throw ucb::ResultSetException(); +} + +//========================================================================= +::rtl::OUString DataSupplier::assembleChildURL( const ::rtl::OUString& aName ) +{ + rtl::OUString aURL; + rtl::OUString aContURL + = m_pImpl->m_xContent->getIdentifier()->getContentIdentifier(); + sal_Int32 nParam = aContURL.indexOf( '?' ); + if ( nParam >= 0 ) + { + aURL = aContURL.copy( 0, nParam ); + + sal_Int32 nPackageUrlEnd = aURL.lastIndexOf( '/' ); + if ( nPackageUrlEnd != aURL.getLength() - 1 ) + aURL += rtl::OUString::createFromAscii( "/" ); + + aURL += ::ucb_impl::urihelper::encodeSegment( aName ); + aURL += aContURL.copy( nParam ); + } + else + { + aURL = aContURL; + + sal_Int32 nPackageUrlEnd = aURL.lastIndexOf( '/' ); + if ( nPackageUrlEnd != aURL.getLength() - 1 ) + aURL += rtl::OUString::createFromAscii( "/" ); + + aURL += ::ucb_impl::urihelper::encodeSegment( aName ); + } + return aURL; +} + + diff --git a/ucb/source/ucp/package/pkgdatasupplier.hxx b/ucb/source/ucp/package/pkgdatasupplier.hxx new file mode 100644 index 000000000000..2342becad8eb --- /dev/null +++ b/ucb/source/ucp/package/pkgdatasupplier.hxx @@ -0,0 +1,77 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _PKGDATASUPPLIER_HXX +#define _PKGDATASUPPLIER_HXX + +#include <rtl/ref.hxx> +#include <ucbhelper/resultset.hxx> + +namespace package_ucp { + +struct DataSupplier_Impl; +class Content; + +class DataSupplier : public ::ucbhelper::ResultSetDataSupplier +{ + DataSupplier_Impl* m_pImpl; + +public: + DataSupplier( const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + const rtl::Reference< Content >& rContent, + sal_Int32 nOpenMode ); + virtual ~DataSupplier(); + + virtual rtl::OUString queryContentIdentifierString( sal_uInt32 nIndex ); + virtual com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier > + queryContentIdentifier( sal_uInt32 nIndex ); + virtual com::sun::star::uno::Reference< com::sun::star::ucb::XContent > + queryContent( sal_uInt32 nIndex ); + + virtual sal_Bool getResult( sal_uInt32 nIndex ); + + virtual sal_uInt32 totalCount(); + virtual sal_uInt32 currentCount(); + virtual sal_Bool isCountFinal(); + + virtual com::sun::star::uno::Reference< com::sun::star::sdbc::XRow > + queryPropertyValues( sal_uInt32 nIndex ); + virtual void releasePropertyValues( sal_uInt32 nIndex ); + + virtual void close(); + + virtual void validate() + throw( com::sun::star::ucb::ResultSetException ); + + ::rtl::OUString assembleChildURL( const ::rtl::OUString& aName ); +}; + +} + +#endif diff --git a/ucb/source/ucp/package/pkgprovider.cxx b/ucb/source/ucp/package/pkgprovider.cxx new file mode 100644 index 000000000000..92c35fe78bb9 --- /dev/null +++ b/ucb/source/ucp/package/pkgprovider.cxx @@ -0,0 +1,330 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ + +#include <hash_map> +#include <osl/diagnose.h> +#include <cppuhelper/weak.hxx> +#include <ucbhelper/contentidentifier.hxx> +#include <com/sun/star/container/XHierarchicalNameAccess.hpp> +#include "pkgprovider.hxx" +#include "pkgcontent.hxx" +#include "pkguri.hxx" + +using namespace com::sun::star; + +namespace package_ucp +{ + +//========================================================================= +// +// class Package. +// +//========================================================================= + +class Package : public cppu::OWeakObject, + public container::XHierarchicalNameAccess +{ + friend class ContentProvider; + + rtl::OUString m_aName; + uno::Reference< container::XHierarchicalNameAccess > m_xNA; + ContentProvider* m_pOwner; + +public: + Package( const rtl::OUString& rName, + const uno::Reference< container::XHierarchicalNameAccess > & xNA, + ContentProvider* pOwner ) + : m_aName( rName ), m_xNA( xNA ), m_pOwner( pOwner ) {} + virtual ~Package() { m_pOwner->removePackage( m_aName ); } + + // XInterface + virtual uno::Any SAL_CALL + queryInterface( const uno::Type& aType ) + throw( uno::RuntimeException ) + { return m_xNA->queryInterface( aType ); } + virtual void SAL_CALL + acquire() throw() + { OWeakObject::acquire(); } + virtual void SAL_CALL + release() throw() + { OWeakObject::release(); } + + // XHierarchicalNameAccess + virtual uno::Any SAL_CALL + getByHierarchicalName( const rtl::OUString& aName ) + throw( container::NoSuchElementException, uno::RuntimeException ) + { return m_xNA->getByHierarchicalName( aName ); } + virtual sal_Bool SAL_CALL + hasByHierarchicalName( const rtl::OUString& aName ) + throw( uno::RuntimeException ) + { return m_xNA->hasByHierarchicalName( aName ); } +}; + +//========================================================================= +// +// Packages. +// +//========================================================================= + +struct equalString +{ + bool operator()( + const rtl::OUString& rKey1, const rtl::OUString& rKey2 ) const + { + return !!( rKey1 == rKey2 ); + } +}; + +struct hashString +{ + size_t operator()( const rtl::OUString & rName ) const + { + return rName.hashCode(); + } +}; + +typedef std::hash_map +< + rtl::OUString, + Package*, + hashString, + equalString +> +PackageMap; + +class Packages : public PackageMap {}; + +} + +using namespace package_ucp; + +//========================================================================= +//========================================================================= +// +// ContentProvider Implementation. +// +//========================================================================= +//========================================================================= + +ContentProvider::ContentProvider( + const uno::Reference< lang::XMultiServiceFactory >& rSMgr ) +: ::ucbhelper::ContentProviderImplHelper( rSMgr ), + m_pPackages( 0 ) +{ +} + +//========================================================================= +// virtual +ContentProvider::~ContentProvider() +{ + delete m_pPackages; +} + +//========================================================================= +// +// XInterface methods. +// +//========================================================================= + +XINTERFACE_IMPL_3( ContentProvider, + lang::XTypeProvider, + lang::XServiceInfo, + ucb::XContentProvider ); + +//========================================================================= +// +// XTypeProvider methods. +// +//========================================================================= + +XTYPEPROVIDER_IMPL_3( ContentProvider, + lang::XTypeProvider, + lang::XServiceInfo, + ucb::XContentProvider ); + +//========================================================================= +// +// XServiceInfo methods. +// +//========================================================================= + +XSERVICEINFO_IMPL_1( ContentProvider, + rtl::OUString::createFromAscii( + "com.sun.star.comp.ucb.PackageContentProvider" ), + rtl::OUString::createFromAscii( + PACKAGE_CONTENT_PROVIDER_SERVICE_NAME ) ); + +//========================================================================= +// +// Service factory implementation. +// +//========================================================================= + +ONE_INSTANCE_SERVICE_FACTORY_IMPL( ContentProvider ); + +//========================================================================= +// +// XContentProvider methods. +// +//========================================================================= + +// virtual +uno::Reference< ucb::XContent > SAL_CALL ContentProvider::queryContent( + const uno::Reference< ucb::XContentIdentifier >& Identifier ) + throw( ucb::IllegalIdentifierException, uno::RuntimeException ) +{ + if ( !Identifier.is() ) + return uno::Reference< ucb::XContent >(); + + PackageUri aUri( Identifier->getContentIdentifier() ); + if ( !aUri.isValid() ) + throw ucb::IllegalIdentifierException(); + + // Create a new identifier for the mormalized URL returned by + // PackageUri::getUri(). + uno::Reference< ucb::XContentIdentifier > xId + = new ::ucbhelper::ContentIdentifier( m_xSMgr, aUri.getUri() ); + + osl::MutexGuard aGuard( m_aMutex ); + + // Check, if a content with given id already exists... + uno::Reference< ucb::XContent > xContent + = queryExistingContent( xId ).get(); + if ( xContent.is() ) + return xContent; + + // Create a new content. + + xContent = Content::create( m_xSMgr, this, Identifier ); // not xId!!! + registerNewContent( xContent ); + + if ( xContent.is() && !xContent->getIdentifier().is() ) + throw ucb::IllegalIdentifierException(); + + return xContent; +} + +//========================================================================= +// +// Other methods. +// +//========================================================================= + +uno::Reference< container::XHierarchicalNameAccess > +ContentProvider::createPackage( const rtl::OUString & rName, const rtl::OUString & rParam ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + if ( !rName.getLength() ) + { + OSL_ENSURE( sal_False, + "ContentProvider::createPackage - Invalid URL!" ); + return uno::Reference< container::XHierarchicalNameAccess >(); + } + + rtl::OUString rURL = rName + rParam; + + if ( m_pPackages ) + { + Packages::const_iterator it = m_pPackages->find( rURL ); + if ( it != m_pPackages->end() ) + { + // Already instanciated. Return package. + return (*it).second->m_xNA; + } + } + else + m_pPackages = new Packages; + + // Create new package... + try + { + uno::Sequence< uno::Any > aArguments( 1 ); + aArguments[ 0 ] <<= rURL; + + uno::Reference< uno::XInterface > xIfc + = m_xSMgr->createInstanceWithArguments( + rtl::OUString::createFromAscii( + "com.sun.star.packages.comp.ZipPackage" ), + aArguments ); + + if ( xIfc.is() ) + { + uno::Reference< + container::XHierarchicalNameAccess > xNameAccess( + xIfc, uno::UNO_QUERY ); + + OSL_ENSURE( xNameAccess.is(), + "ContentProvider::createPackage - " + "Got no hierarchical name access!" ); + + rtl::Reference< Package> xPackage + = new Package( rURL, xNameAccess, this ); + + (*m_pPackages)[ rURL ] = xPackage.get(); + + return xPackage.get(); + } + } + catch ( uno::RuntimeException const & ) + { + // createInstanceWithArguemts + } + catch ( uno::Exception const & ) + { + // createInstanceWithArguemts + } + + return uno::Reference< container::XHierarchicalNameAccess >(); +} + +//========================================================================= +sal_Bool ContentProvider::removePackage( const rtl::OUString & rName ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + if ( m_pPackages ) + { + Packages::iterator it = m_pPackages->find( rName ); + if ( it != m_pPackages->end() ) + { + m_pPackages->erase( it ); + return sal_True; + } + } + return sal_False; +} + diff --git a/ucb/source/ucp/package/pkgprovider.hxx b/ucb/source/ucp/package/pkgprovider.hxx new file mode 100644 index 000000000000..89843f192cc1 --- /dev/null +++ b/ucb/source/ucp/package/pkgprovider.hxx @@ -0,0 +1,105 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _PKGPROVIDER_HXX +#define _PKGPROVIDER_HXX + +#include <ucbhelper/providerhelper.hxx> +#include "pkguri.hxx" + +namespace com { namespace sun { namespace star { namespace container { + class XHierarchicalNameAccess; +} } } } + +namespace package_ucp { + +//========================================================================= + +// UNO service name for the provider. This name will be used by the UCB to +// create instances of the provider. +#define PACKAGE_CONTENT_PROVIDER_SERVICE_NAME \ + "com.sun.star.ucb.PackageContentProvider" +#define PACKAGE_CONTENT_PROVIDER_SERVICE_NAME_LENGTH 39 + +// UCB Content Type. +#define PACKAGE_FOLDER_CONTENT_TYPE \ + "application/" PACKAGE_URL_SCHEME "-folder" +#define PACKAGE_STREAM_CONTENT_TYPE \ + "application/" PACKAGE_URL_SCHEME "-stream" +#define PACKAGE_ZIP_FOLDER_CONTENT_TYPE \ + "application/" PACKAGE_ZIP_URL_SCHEME "-folder" +#define PACKAGE_ZIP_STREAM_CONTENT_TYPE \ + "application/" PACKAGE_ZIP_URL_SCHEME "-stream" + +//========================================================================= + +class Packages; + +class ContentProvider : public ::ucbhelper::ContentProviderImplHelper +{ + Packages* m_pPackages; + +public: + ContentProvider( const ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XMultiServiceFactory >& rSMgr ); + virtual ~ContentProvider(); + + // XInterface + XINTERFACE_DECL() + + // XTypeProvider + XTYPEPROVIDER_DECL() + + // XServiceInfo + XSERVICEINFO_DECL() + + // XContentProvider + virtual ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XContent > SAL_CALL + queryContent( const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XContentIdentifier >& Identifier ) + throw( ::com::sun::star::ucb::IllegalIdentifierException, + ::com::sun::star::uno::RuntimeException ); + + ////////////////////////////////////////////////////////////////////// + // Additional interfaces + ////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////// + // Non-interface methods. + ////////////////////////////////////////////////////////////////////// + + ::com::sun::star::uno::Reference< + ::com::sun::star::container::XHierarchicalNameAccess > + createPackage( const rtl::OUString & rName, const rtl::OUString & rParam ); + sal_Bool + removePackage( const rtl::OUString & rName ); +}; + +} + +#endif diff --git a/ucb/source/ucp/package/pkgresultset.cxx b/ucb/source/ucp/package/pkgresultset.cxx new file mode 100644 index 000000000000..076e7aa69132 --- /dev/null +++ b/ucb/source/ucp/package/pkgresultset.cxx @@ -0,0 +1,94 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + - This implementation is not a dynamic result set!!! It only implements + the necessary interfaces, but never recognizes/notifies changes!!! + + *************************************************************************/ +#include "pkgdatasupplier.hxx" +#include "pkgresultset.hxx" + +using namespace com::sun::star; + +using namespace package_ucp; + +//========================================================================= +//========================================================================= +// +// DynamicResultSet Implementation. +// +//========================================================================= +//========================================================================= + +DynamicResultSet::DynamicResultSet( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + const rtl::Reference< Content >& rxContent, + const ucb::OpenCommandArgument2& rCommand, + const uno::Reference< ucb::XCommandEnvironment >& rxEnv ) +: ResultSetImplHelper( rxSMgr, rCommand ), + m_xContent( rxContent ), + m_xEnv( rxEnv ) +{ +} + +//========================================================================= +// +// Non-interface methods. +// +//========================================================================= + +void DynamicResultSet::initStatic() +{ + m_xResultSet1 + = new ::ucbhelper::ResultSet( m_xSMgr, + m_aCommand.Properties, + new DataSupplier( m_xSMgr, + m_xContent, + m_aCommand.Mode ), + m_xEnv ); +} + +//========================================================================= +void DynamicResultSet::initDynamic() +{ + m_xResultSet1 + = new ::ucbhelper::ResultSet( m_xSMgr, + m_aCommand.Properties, + new DataSupplier( m_xSMgr, + m_xContent, + m_aCommand.Mode ), + m_xEnv ); + m_xResultSet2 = m_xResultSet1; +} + diff --git a/ucb/source/ucp/package/pkgresultset.hxx b/ucb/source/ucp/package/pkgresultset.hxx new file mode 100644 index 000000000000..43621f8adf90 --- /dev/null +++ b/ucb/source/ucp/package/pkgresultset.hxx @@ -0,0 +1,59 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _PKGRESULTSET_HXX +#define _PKGRESULTSET_HXX + +#include <rtl/ref.hxx> +#include <ucbhelper/resultsethelper.hxx> +#include "pkgcontent.hxx" + +namespace package_ucp { + +class DynamicResultSet : public ::ucbhelper::ResultSetImplHelper +{ + rtl::Reference< Content > m_xContent; + com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > m_xEnv; + +private: + virtual void initStatic(); + virtual void initDynamic(); + +public: + DynamicResultSet( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + const rtl::Reference< Content >& rxContent, + const com::sun::star::ucb::OpenCommandArgument2& rCommand, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment >& rxEnv ); +}; + +} + +#endif diff --git a/ucb/source/ucp/package/pkgservices.cxx b/ucb/source/ucp/package/pkgservices.cxx new file mode 100644 index 000000000000..ad4af686d2d6 --- /dev/null +++ b/ucb/source/ucp/package/pkgservices.cxx @@ -0,0 +1,74 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <com/sun/star/registry/XRegistryKey.hpp> +#include "pkgprovider.hxx" + +using namespace com::sun::star; + +//========================================================================= +extern "C" void SAL_CALL component_getImplementationEnvironment( + const sal_Char ** ppEnvTypeName, uno_Environment ** /*ppEnv*/ ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + +//========================================================================= +extern "C" void * SAL_CALL component_getFactory( + const sal_Char * pImplName, void * pServiceManager, void * /*pRegistryKey*/ ) +{ + void * pRet = 0; + + uno::Reference< lang::XMultiServiceFactory > xSMgr( + reinterpret_cast< lang::XMultiServiceFactory * >( pServiceManager ) ); + uno::Reference< lang::XSingleServiceFactory > xFactory; + + ////////////////////////////////////////////////////////////////////// + // Create factory, if implementation name matches. + ////////////////////////////////////////////////////////////////////// + + if ( ::package_ucp::ContentProvider::getImplementationName_Static(). + compareToAscii( pImplName ) == 0 ) + { + xFactory = ::package_ucp::ContentProvider::createServiceFactory( xSMgr ); + } + + ////////////////////////////////////////////////////////////////////// + + if ( xFactory.is() ) + { + xFactory->acquire(); + pRet = xFactory.get(); + } + + return pRet; +} + diff --git a/ucb/source/ucp/package/pkguri.cxx b/ucb/source/ucp/package/pkguri.cxx new file mode 100644 index 000000000000..8424ed906e92 --- /dev/null +++ b/ucb/source/ucp/package/pkguri.cxx @@ -0,0 +1,249 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ + +#include "rtl/ustrbuf.hxx" +#include "osl/diagnose.h" +#include "comphelper/storagehelper.hxx" + +#include "../inc/urihelper.hxx" + +#include "pkguri.hxx" + +using namespace package_ucp; +using namespace rtl; + +//========================================================================= +//========================================================================= +// +// PackageUri Implementation. +// +//========================================================================= +//========================================================================= + +static void normalize( OUString& rURL ) +{ + sal_Int32 nPos = 0; + do + { + nPos = rURL.indexOf( '%', nPos ); + if ( nPos != -1 ) + { + if ( nPos < ( rURL.getLength() - 2 ) ) + { + OUString aTmp = rURL.copy( nPos + 1, 2 ); + rURL = rURL.replaceAt( nPos + 1, 2, aTmp.toAsciiUpperCase() ); + nPos++; + } + } + } + while ( nPos != -1 ); +} + +//========================================================================= +void PackageUri::init() const +{ + // Already inited? + if ( m_aUri.getLength() && !m_aPath.getLength() ) + { + // Note: Maybe it's a re-init, setUri only resets m_aPath! + m_aPackage = m_aParentUri = m_aName = m_aParam = m_aScheme + = OUString(); + + // URI must match at least: <sheme>://<non_empty_url_to_file> + if ( ( m_aUri.getLength() < PACKAGE_URL_SCHEME_LENGTH + 4 ) ) + { + // error, but remember that we did a init(). + m_aPath = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/" ) ); + return; + } + + // Scheme must be followed by '://' + if ( ( m_aUri.getStr()[ PACKAGE_URL_SCHEME_LENGTH ] + != sal_Unicode( ':' ) ) + || + ( m_aUri.getStr()[ PACKAGE_URL_SCHEME_LENGTH + 1 ] + != sal_Unicode( '/' ) ) + || + ( m_aUri.getStr()[ PACKAGE_URL_SCHEME_LENGTH + 2 ] + != sal_Unicode( '/' ) ) ) + { + // error, but remember that we did a init(). + m_aPath = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/" ) ); + return; + } + + rtl::OUString aPureUri; + sal_Int32 nParam = m_aUri.indexOf( '?' ); + if( nParam >= 0 ) + { + m_aParam = m_aUri.copy( nParam ); + aPureUri = m_aUri.copy( 0, nParam ); + } + else + aPureUri = m_aUri; + + // Scheme is case insensitive. + m_aScheme = aPureUri.copy( + 0, PACKAGE_URL_SCHEME_LENGTH ).toAsciiLowerCase(); + + if ( m_aScheme.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( PACKAGE_URL_SCHEME ) ) + || m_aScheme.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( PACKAGE_ZIP_URL_SCHEME ) ) ) + { + if ( m_aScheme.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( PACKAGE_ZIP_URL_SCHEME ) ) ) + { + m_aParam += + ( m_aParam.getLength() + ? ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "&purezip" ) ) + : ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "?purezip" ) ) ); + } + + aPureUri = aPureUri.replaceAt( 0, + m_aScheme.getLength(), + m_aScheme ); + + sal_Int32 nStart = PACKAGE_URL_SCHEME_LENGTH + 3; + sal_Int32 nEnd = aPureUri.lastIndexOf( '/' ); + if ( nEnd == PACKAGE_URL_SCHEME_LENGTH + 3 ) + { + // Only <scheme>:/// - Empty authority + + // error, but remember that we did a init(). + m_aPath = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/" ) ); + return; + } + else if ( nEnd == ( aPureUri.getLength() - 1 ) ) + { + if ( aPureUri.getStr()[ aPureUri.getLength() - 2 ] + == sal_Unicode( '/' ) ) + { + // Only <scheme>://// or <scheme>://<something>// + + // error, but remember that we did a init(). + m_aPath = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/" ) ); + return; + } + + // Remove trailing slash. + aPureUri = aPureUri.copy( 0, nEnd ); + } + + + nEnd = aPureUri.indexOf( '/', nStart ); + if ( nEnd == -1 ) + { + // root folder. + + OUString aNormPackage = aPureUri.copy( nStart ); + normalize( aNormPackage ); + + aPureUri = aPureUri.replaceAt( + nStart, aPureUri.getLength() - nStart, aNormPackage ); + m_aPackage + = ::ucb_impl::urihelper::decodeSegment( aNormPackage ); + m_aPath = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/" ) ); + m_aUri = m_aUri.replaceAt( 0, + ( nParam >= 0 ) + ? nParam + : m_aUri.getLength(), aPureUri ); + + sal_Int32 nLastSlash = m_aPackage.lastIndexOf( '/' ); + if ( nLastSlash != -1 ) + m_aName = ::ucb_impl::urihelper::decodeSegment( + m_aPackage.copy( nLastSlash + 1 ) ); + else + m_aName + = ::ucb_impl::urihelper::decodeSegment( m_aPackage ); + } + else + { + m_aPath = aPureUri.copy( nEnd + 1 ); + + // Unexpected sequences of characters: + // - empty path segments + // - encoded slashes + // - parent folder segments ".." + // - current folder segments "." + if ( m_aPath.indexOf( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "//" ) ) ) != -1 + || m_aPath.indexOf( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "%2F" ) ) ) != -1 + || m_aPath.indexOf( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "%2f" ) ) ) != -1 + || ::comphelper::OStorageHelper::PathHasSegment( m_aPath, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".." ) ) ) + || ::comphelper::OStorageHelper::PathHasSegment( m_aPath, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "." ) ) ) ) + { + // error, but remember that we did a init(). + m_aPath = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/" ) ); + return; + } + + OUString aNormPackage = aPureUri.copy( nStart, nEnd - nStart ); + normalize( aNormPackage ); + + aPureUri = aPureUri.replaceAt( + nStart, nEnd - nStart, aNormPackage ); + aPureUri = aPureUri.replaceAt( + nEnd + 1, + aPureUri.getLength() - nEnd - 1, + ::ucb_impl::urihelper::encodeURI( m_aPath ) ); + + m_aPackage + = ::ucb_impl::urihelper::decodeSegment( aNormPackage ); + m_aPath = ::ucb_impl::urihelper::decodeSegment( m_aPath ); + m_aUri = m_aUri.replaceAt( 0, + ( nParam >= 0 ) + ? nParam + : m_aUri.getLength(), aPureUri ); + + sal_Int32 nLastSlash = aPureUri.lastIndexOf( '/' ); + if ( nLastSlash != -1 ) + { + m_aParentUri = aPureUri.copy( 0, nLastSlash ); + m_aName = ::ucb_impl::urihelper::decodeSegment( + aPureUri.copy( nLastSlash + 1 ) ); + } + } + + // success + m_bValid = true; + } + else + { + // error, but remember that we did a init(). + m_aPath = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/" ) ); + } + } +} diff --git a/ucb/source/ucp/package/pkguri.hxx b/ucb/source/ucp/package/pkguri.hxx new file mode 100644 index 000000000000..68513bcfa940 --- /dev/null +++ b/ucb/source/ucp/package/pkguri.hxx @@ -0,0 +1,101 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _PKGURI_HXX +#define _PKGURI_HXX + +#include <rtl/ustring.hxx> + +namespace package_ucp { + +//========================================================================= + +#define PACKAGE_URL_SCHEME "vnd.sun.star.pkg" +#define PACKAGE_ZIP_URL_SCHEME "vnd.sun.star.zip" +#define PACKAGE_URL_SCHEME_LENGTH 16 + +//========================================================================= + +class PackageUri +{ + mutable ::rtl::OUString m_aUri; + mutable ::rtl::OUString m_aParentUri; + mutable ::rtl::OUString m_aPackage; + mutable ::rtl::OUString m_aPath; + mutable ::rtl::OUString m_aName; + mutable ::rtl::OUString m_aParam; + mutable ::rtl::OUString m_aScheme; + mutable bool m_bValid; + +private: + void init() const; + +public: + PackageUri() : m_bValid( false ) {} + PackageUri( const ::rtl::OUString & rPackageUri ) + : m_aUri( rPackageUri ), m_bValid( false ) {} + + sal_Bool isValid() const + { init(); return m_bValid; } + + const ::rtl::OUString & getUri() const + { init(); return m_aUri; } + + void setUri( const ::rtl::OUString & rPackageUri ) + { m_aPath = ::rtl::OUString(); m_aUri = rPackageUri; m_bValid = false; } + + const ::rtl::OUString & getParentUri() const + { init(); return m_aParentUri; } + + const ::rtl::OUString & getPackage() const + { init(); return m_aPackage; } + + const ::rtl::OUString & getPath() const + { init(); return m_aPath; } + + const ::rtl::OUString & getName() const + { init(); return m_aName; } + + const ::rtl::OUString & getParam() const + { init(); return m_aParam; } + + const ::rtl::OUString & getScheme() const + { init(); return m_aScheme; } + + inline sal_Bool isRootFolder() const; +}; + +inline sal_Bool PackageUri::isRootFolder() const +{ + init(); + return ( ( m_aPath.getLength() == 1 ) && + ( m_aPath.getStr()[ 0 ] == sal_Unicode( '/' ) ) ); +} + +} + +#endif diff --git a/ucb/source/ucp/package/ucppkg.xml b/ucb/source/ucp/package/ucppkg.xml new file mode 100644 index 000000000000..6b71fca63486 --- /dev/null +++ b/ucb/source/ucp/package/ucppkg.xml @@ -0,0 +1,92 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE module-description PUBLIC "-//StarOffice//DTD ComponentDescription 1.0//EN" "module-description.dtd"> +<module-description xmlns:xlink="http://www.w3.org/1999/xlink"> + + <module-name> + ucppkg + </module-name> + + <component-description> + <author> + Kai Sommerfeld + </author> + <name> + com.sun.star.comp.ucb.PackageContentProvider + </name> + <description> + This component implements a Content Provider for the Universal + Content Broker. It provides access to the contents of package (zip + archive) files. + </description> + <loader-name> + com.sun.star.loader.SharedLibrary + </loader-name> + <language> + c++ + </language> + <status value="final"/> + <supported-service> + com.sun.star.ucb.PackageContentProvider + </supported-service> + + <service-dependency> + com.sun.star.packages.comp.ZipPackage + </service-dependency> + </component-description> + + <project-build-dependency> sal </project-build-dependency> + <project-build-dependency> cppu </project-build-dependency> + <project-build-dependency> cppuhelper </project-build-dependency> + <project-build-dependency> ucbhelper </project-build-dependency> + + <runtime-module-dependency> sal3 </runtime-module-dependency> + <runtime-module-dependency> cppu3 </runtime-module-dependency> + <runtime-module-dependency> cppuhelper3$(COM) </runtime-module-dependency> + <runtime-module-dependency> ucbhelper4$(COM) </runtime-module-dependency> + + <type> com.sun.star.beans.PropertyAttribute </type> + <type> com.sun.star.beans.XPropertiesChangeNotifier </type> + <type> com.sun.star.beans.XPropertyAccess </type> + <type> com.sun.star.beans.XPropertyContainer </type> + <type> com.sun.star.beans.XPropertySetInfoChangeNotifier </type> + <type> com.sun.star.container.XChild </type> + <type> com.sun.star.container.XEnumerationAccess </type> + <type> com.sun.star.container.XHierarchicalNameAccess </type> + <type> com.sun.star.container.XNamed </type> + <type> com.sun.star.container.XNameContainer </type> + <type> com.sun.star.io.XActiveDataSink </type> + <type> com.sun.star.io.XOutputStream </type> + <type> com.sun.star.lang.IllegalAccessException </type> + <type> com.sun.star.lang.XComponent </type> + <type> com.sun.star.lang.XMultiServiceFactory </type> + <type> com.sun.star.lang.XServiceInfo </type> + <type> com.sun.star.lang.XSingleServiceFactory </type> + <type> com.sun.star.lang.XTypeProvider </type> + <type> com.sun.star.registry.XRegistryKey </type> + <type> com.sun.star.sdbc.XCloseable </type> + <type> com.sun.star.sdbc.XColumnLocate </type> + <type> com.sun.star.sdbc.XResultSetMetaDataSupplier </type> + <type> com.sun.star.sdbc.XRow </type> + <type> com.sun.star.ucb.ContentInfoAttribute </type> + <type> com.sun.star.ucb.InsertCommandArgument </type> + <type> com.sun.star.ucb.InteractiveBadTransferURLException </type> + <type> com.sun.star.ucb.MissingInputStreamException </type> + <type> com.sun.star.ucb.NameClash </type> + <type> com.sun.star.ucb.NameClashException </type> + <type> com.sun.star.ucb.OpenCommandArgument2 </type> + <type> com.sun.star.ucb.OpenMode </type> + <type> com.sun.star.ucb.ResultSetException </type> + <type> com.sun.star.ucb.TransferInfo </type> + <type> com.sun.star.ucb.UnsupportedDataSinkException </type> + <type> com.sun.star.ucb.UnsupportedNameClashException </type> + <type> com.sun.star.ucb.UnsupportedOpenModeException </type> + <type> com.sun.star.ucb.XCommandInfo </type> + <type> com.sun.star.ucb.XCommandProcessor </type> + <type> com.sun.star.ucb.XContentAccess </type> + <type> com.sun.star.ucb.XContentCreator </type> + <type> com.sun.star.ucb.XContentProvider </type> + <type> com.sun.star.ucb.XDynamicResultSet </type> + <type> com.sun.star.ucb.XPersistentPropertySet </type> + <type> com.sun.star.uno.XWeak </type> + <type> com.sun.star.util.XChangesBatch </type> +</module-description> diff --git a/ucb/source/ucp/package/ucppkg1.component b/ucb/source/ucp/package/ucppkg1.component new file mode 100644 index 000000000000..a2e2418b5602 --- /dev/null +++ b/ucb/source/ucp/package/ucppkg1.component @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* This file is part of OpenOffice.org. +* +* OpenOffice.org is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License version 3 +* only, as published by the Free Software Foundation. +* +* OpenOffice.org is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Lesser General Public License version 3 for more details +* (a copy is included in the LICENSE file that accompanied this code). +* +* You should have received a copy of the GNU Lesser General Public License +* version 3 along with OpenOffice.org. If not, see +* <http://www.openoffice.org/license.html> +* for a copy of the LGPLv3 License. +* +**********************************************************************--> + +<component loader="com.sun.star.loader.SharedLibrary" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.ucb.PackageContentProvider"> + <service name="com.sun.star.ucb.PackageContentProvider"/> + </implementation> +</component> |