blob: 48331a2fcb925b406adaa1f30592737a096f4acc [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the 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;
}