summaryrefslogtreecommitdiffstats
path: root/ucb/source/ucp/file/bc.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'ucb/source/ucp/file/bc.cxx')
-rw-r--r--ucb/source/ucp/file/bc.cxx1169
1 files changed, 1169 insertions, 0 deletions
diff --git a/ucb/source/ucp/file/bc.cxx b/ucb/source/ucp/file/bc.cxx
new file mode 100644
index 000000000..03590d3e0
--- /dev/null
+++ b/ucb/source/ucp/file/bc.cxx
@@ -0,0 +1,1169 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include <rtl/uri.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <rtl/ref.hxx>
+
+#include <tools/diagnose_ex.h>
+#include <com/sun/star/lang/NoSupportException.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <com/sun/star/ucb/IllegalIdentifierException.hpp>
+#include <com/sun/star/ucb/OpenMode.hpp>
+#include <com/sun/star/beans/IllegalTypeException.hpp>
+#include <com/sun/star/io/XActiveDataStreamer.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+#include <com/sun/star/io/XActiveDataSink.hpp>
+#include <com/sun/star/ucb/NameClash.hpp>
+#include <comphelper/fileurl.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include "filglob.hxx"
+#include "filid.hxx"
+#include "filrow.hxx"
+#include "bc.hxx"
+#include "prov.hxx"
+#include "filerror.hxx"
+#include "filinsreq.hxx"
+
+using namespace fileaccess;
+using namespace com::sun::star;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::ucb;
+
+#if OSL_DEBUG_LEVEL > 0
+#define THROW_WHERE SAL_WHERE
+#else
+#define THROW_WHERE ""
+#endif
+
+class fileaccess::PropertyListeners
+{
+ typedef comphelper::OInterfaceContainerHelper4<beans::XPropertiesChangeListener> ContainerHelper;
+ std::unordered_map<OUString, ContainerHelper> m_aMap;
+
+public:
+ void disposeAndClear(std::unique_lock<std::mutex>& rGuard, const lang::EventObject& rEvt)
+ {
+ // create a copy, because do not fire event in a guarded section
+ std::unordered_map<OUString, ContainerHelper> tempMap = std::move(m_aMap);
+ for (auto& rPair : tempMap)
+ rPair.second.disposeAndClear(rGuard, rEvt);
+ }
+ void addInterface(std::unique_lock<std::mutex>& rGuard, const OUString& rKey, const uno::Reference<beans::XPropertiesChangeListener>& rListener)
+ {
+ m_aMap[rKey].addInterface(rGuard, rListener);
+ }
+ void removeInterface(std::unique_lock<std::mutex>& rGuard, const OUString& rKey, const uno::Reference<beans::XPropertiesChangeListener>& rListener)
+ {
+ // search container with id rKey
+ auto iter = m_aMap.find(rKey);
+ // container found?
+ if (iter != m_aMap.end())
+ iter->second.removeInterface(rGuard, rListener);
+ }
+ std::vector< OUString > getContainedTypes(std::unique_lock<std::mutex>& rGuard) const
+ {
+ std::vector<OUString> aInterfaceTypes;
+ aInterfaceTypes.reserve(m_aMap.size());
+ for (const auto& rPair : m_aMap)
+ // are interfaces added to this container?
+ if (rPair.second.getLength(rGuard))
+ // yes, put the type in the array
+ aInterfaceTypes.push_back(rPair.first);
+ return aInterfaceTypes;
+ }
+ comphelper::OInterfaceContainerHelper4<beans::XPropertiesChangeListener>* getContainer(std::unique_lock<std::mutex>& , const OUString& rKey)
+ {
+ auto iter = m_aMap.find(rKey);
+ if (iter != m_aMap.end())
+ return &iter->second;
+ return nullptr;
+ }
+};
+
+
+/****************************************************************************************/
+/* */
+/* BaseContent */
+/* */
+/****************************************************************************************/
+
+
+// Private Constructor for just inserted Contents
+
+BaseContent::BaseContent( TaskManager* pMyShell,
+ const OUString& parentName,
+ bool bFolder )
+ : m_pMyShell( pMyShell ),
+ m_aUncPath( parentName ),
+ m_bFolder( bFolder ),
+ m_nState( JustInserted )
+{
+ m_pMyShell->m_pProvider->acquire();
+ // No registering, since we have no name
+}
+
+
+// Constructor for full featured Contents
+
+BaseContent::BaseContent( TaskManager* pMyShell,
+ const Reference< XContentIdentifier >& xContentIdentifier,
+ const OUString& aUncPath )
+ : m_pMyShell( pMyShell ),
+ m_xContentIdentifier( xContentIdentifier ),
+ m_aUncPath( aUncPath ),
+ m_bFolder( false ),
+ m_nState( FullFeatured )
+{
+ m_pMyShell->m_pProvider->acquire();
+ m_pMyShell->registerNotifier( m_aUncPath,this );
+ m_pMyShell->insertDefaultProperties( m_aUncPath );
+}
+
+
+BaseContent::~BaseContent( )
+{
+ if( ( m_nState & FullFeatured ) || ( m_nState & Deleted ) )
+ {
+ m_pMyShell->deregisterNotifier( m_aUncPath,this );
+ }
+ m_pMyShell->m_pProvider->release();
+}
+
+
+// XComponent
+
+
+void SAL_CALL
+BaseContent::addEventListener( const Reference< lang::XEventListener >& Listener )
+{
+ std::unique_lock aGuard( m_aMutex );
+
+ m_aDisposeEventListeners.addInterface( aGuard, Listener );
+}
+
+
+void SAL_CALL
+BaseContent::removeEventListener( const Reference< lang::XEventListener >& Listener )
+{
+ std::unique_lock aGuard( m_aMutex );
+
+ m_aDisposeEventListeners.removeInterface( aGuard, Listener );
+}
+
+
+void SAL_CALL
+BaseContent::dispose()
+{
+ lang::EventObject aEvt;
+ aEvt.Source = static_cast< XContent* >( this );
+
+ std::unique_lock aGuard( m_aMutex );
+
+ std::unique_ptr<PropertyListeners> pPropertyListener = std::move(m_pPropertyListener);
+
+ m_aDisposeEventListeners.disposeAndClear( aGuard, aEvt );
+ m_aContentEventListeners.disposeAndClear( aGuard, aEvt );
+
+ if( pPropertyListener )
+ pPropertyListener->disposeAndClear( aGuard, aEvt );
+
+ m_aPropertySetInfoChangeListeners.disposeAndClear( aGuard, aEvt );
+}
+
+// XServiceInfo
+OUString SAL_CALL
+BaseContent::getImplementationName()
+{
+ return "com.sun.star.comp.ucb.FileContent";
+}
+
+sal_Bool SAL_CALL
+BaseContent::supportsService( const OUString& ServiceName )
+{
+ return cppu::supportsService( this, ServiceName );
+}
+
+Sequence< OUString > SAL_CALL
+BaseContent::getSupportedServiceNames()
+{
+ Sequence<OUString> ret { "com.sun.star.ucb.FileContent" };
+ return ret;
+}
+
+// XCommandProcessor
+
+
+sal_Int32 SAL_CALL
+BaseContent::createCommandIdentifier()
+{
+ return m_pMyShell->getCommandId();
+}
+
+
+void SAL_CALL
+BaseContent::abort( sal_Int32 /*CommandId*/ )
+{
+}
+
+
+Any SAL_CALL
+BaseContent::execute( const Command& aCommand,
+ sal_Int32 CommandId,
+ const Reference< XCommandEnvironment >& Environment )
+{
+ if( ! CommandId )
+ // A Command with commandid zero cannot be aborted
+ CommandId = createCommandIdentifier();
+
+ m_pMyShell->startTask( CommandId,
+ Environment );
+
+ Any aAny;
+
+ if (aCommand.Name == "getPropertySetInfo") // No exceptions
+ {
+ aAny <<= getPropertySetInfo();
+ }
+ else if (aCommand.Name == "getCommandInfo") // no exceptions
+ {
+ aAny <<= getCommandInfo();
+ }
+ else if ( aCommand.Name == "setPropertyValues" )
+ {
+ Sequence< beans::PropertyValue > sPropertyValues;
+
+ if( ! ( aCommand.Argument >>= sPropertyValues ) )
+ m_pMyShell->installError( CommandId,
+ TASKHANDLING_WRONG_SETPROPERTYVALUES_ARGUMENT );
+ else
+ aAny <<= setPropertyValues( CommandId,sPropertyValues ); // calls endTask by itself
+ }
+ else if ( aCommand.Name == "getPropertyValues" )
+ {
+ Sequence< beans::Property > ListOfRequestedProperties;
+
+ if( ! ( aCommand.Argument >>= ListOfRequestedProperties ) )
+ m_pMyShell->installError( CommandId,
+ TASKHANDLING_WRONG_GETPROPERTYVALUES_ARGUMENT );
+ else
+ aAny <<= getPropertyValues( CommandId,
+ ListOfRequestedProperties );
+ }
+ else if ( aCommand.Name == "open" )
+ {
+ OpenCommandArgument2 aOpenArgument;
+ if( ! ( aCommand.Argument >>= aOpenArgument ) )
+ m_pMyShell->installError( CommandId,
+ TASKHANDLING_WRONG_OPEN_ARGUMENT );
+ else
+ {
+ Reference< XDynamicResultSet > result = open( CommandId,aOpenArgument );
+ if( result.is() )
+ aAny <<= result;
+ }
+ }
+ else if ( aCommand.Name == "delete" )
+ {
+ if( ! aCommand.Argument.has< bool >() )
+ m_pMyShell->installError( CommandId,
+ TASKHANDLING_WRONG_DELETE_ARGUMENT );
+ else
+ deleteContent( CommandId );
+ }
+ else if ( aCommand.Name == "transfer" )
+ {
+ TransferInfo aTransferInfo;
+ if( ! ( aCommand.Argument >>= aTransferInfo ) )
+ m_pMyShell->installError( CommandId,
+ TASKHANDLING_WRONG_TRANSFER_ARGUMENT );
+ else
+ transfer( CommandId, aTransferInfo );
+ }
+ else if ( aCommand.Name == "insert" )
+ {
+ InsertCommandArgument aInsertArgument;
+ if( ! ( aCommand.Argument >>= aInsertArgument ) )
+ m_pMyShell->installError( CommandId,
+ TASKHANDLING_WRONG_INSERT_ARGUMENT );
+ else
+ insert( CommandId,aInsertArgument );
+ }
+ else if ( aCommand.Name == "getCasePreservingURL" )
+ {
+ Reference< sdbc::XRow > xRow = getPropertyValues( CommandId, { { "CasePreservingURL", -1, cppu::UnoType<sal_Bool>::get(), 0 } });
+ OUString CasePreservingURL = xRow->getString(1);
+ if(!xRow->wasNull())
+ aAny <<= CasePreservingURL;
+ }
+ else if ( aCommand.Name == "createNewContent" )
+ {
+ ucb::ContentInfo aArg;
+ if ( !( aCommand.Argument >>= aArg ) )
+ m_pMyShell->installError( CommandId,
+ TASKHANDLING_WRONG_CREATENEWCONTENT_ARGUMENT );
+ else
+ aAny <<= createNewContent( aArg );
+ }
+ else
+ m_pMyShell->installError( CommandId,
+ TASKHANDLER_UNSUPPORTED_COMMAND );
+
+
+ // This is the only function allowed to throw an exception
+ endTask( CommandId );
+
+ return aAny;
+}
+
+
+void SAL_CALL
+BaseContent::addPropertiesChangeListener(
+ const Sequence< OUString >& PropertyNames,
+ const Reference< beans::XPropertiesChangeListener >& Listener )
+{
+ if( ! Listener.is() )
+ return;
+
+ std::unique_lock aGuard( m_aMutex );
+
+ if( ! m_pPropertyListener )
+ m_pPropertyListener.reset( new PropertyListeners );
+
+
+ if( !PropertyNames.hasElements() )
+ m_pPropertyListener->addInterface( aGuard, OUString(),Listener );
+ else
+ {
+ Reference< beans::XPropertySetInfo > xProp = m_pMyShell->info_p( m_aUncPath );
+ for( const auto& rName : PropertyNames )
+ if( xProp->hasPropertyByName( rName ) )
+ m_pPropertyListener->addInterface( aGuard, rName,Listener );
+ }
+}
+
+
+void SAL_CALL
+BaseContent::removePropertiesChangeListener( const Sequence< OUString >& PropertyNames,
+ const Reference< beans::XPropertiesChangeListener >& Listener )
+{
+ if( ! Listener.is() )
+ return;
+
+ std::unique_lock aGuard( m_aMutex );
+
+ if( ! m_pPropertyListener )
+ return;
+
+ for( const auto& rName : PropertyNames )
+ m_pPropertyListener->removeInterface( aGuard, rName,Listener );
+
+ m_pPropertyListener->removeInterface( aGuard, OUString(), Listener );
+}
+
+
+// XContent
+
+
+Reference< ucb::XContentIdentifier > SAL_CALL
+BaseContent::getIdentifier()
+{
+ return m_xContentIdentifier;
+}
+
+
+OUString SAL_CALL
+BaseContent::getContentType()
+{
+ if( !( m_nState & Deleted ) )
+ {
+ if( m_nState & JustInserted )
+ {
+ if ( m_bFolder )
+ return TaskManager::FolderContentType;
+ else
+ return TaskManager::FileContentType;
+ }
+ else
+ {
+ try
+ {
+ // Who am I ?
+ Reference< sdbc::XRow > xRow = getPropertyValues( -1, { { "IsDocument", -1, cppu::UnoType<sal_Bool>::get(), 0 } });
+ bool IsDocument = xRow->getBoolean( 1 );
+
+ if ( !xRow->wasNull() )
+ {
+ if ( IsDocument )
+ return TaskManager::FileContentType;
+ else
+ return TaskManager::FolderContentType;
+ }
+ else
+ {
+ OSL_FAIL( "BaseContent::getContentType - Property value was null!" );
+ }
+ }
+ catch (const sdbc::SQLException&)
+ {
+ TOOLS_WARN_EXCEPTION("ucb.ucp.file", "");
+ }
+ }
+ }
+
+ return OUString();
+}
+
+
+void SAL_CALL
+BaseContent::addContentEventListener(
+ const Reference< XContentEventListener >& Listener )
+{
+ std::unique_lock aGuard( m_aMutex );
+
+ m_aContentEventListeners.addInterface( aGuard, Listener );
+}
+
+
+void SAL_CALL
+BaseContent::removeContentEventListener(
+ const Reference< XContentEventListener >& Listener )
+{
+ std::unique_lock aGuard( m_aMutex );
+
+ m_aContentEventListeners.removeInterface( aGuard, Listener );
+}
+
+
+// XPropertyContainer
+
+
+void SAL_CALL
+BaseContent::addProperty(
+ const OUString& Name,
+ sal_Int16 Attributes,
+ const Any& DefaultValue )
+{
+ if( ( m_nState & JustInserted ) || ( m_nState & Deleted ) || Name.isEmpty() )
+ {
+ throw lang::IllegalArgumentException( THROW_WHERE, uno::Reference< uno::XInterface >(), 0 );
+ }
+
+ m_pMyShell->associate( m_aUncPath,Name,DefaultValue,Attributes );
+}
+
+
+void SAL_CALL
+BaseContent::removeProperty( const OUString& Name )
+{
+
+ if( m_nState & Deleted )
+ throw beans::UnknownPropertyException( Name );
+
+ m_pMyShell->deassociate( m_aUncPath, Name );
+}
+
+
+// XContentCreator
+
+
+Sequence< ContentInfo > SAL_CALL
+BaseContent::queryCreatableContentsInfo()
+{
+ return TaskManager::queryCreatableContentsInfo();
+}
+
+
+Reference< XContent > SAL_CALL
+BaseContent::createNewContent( const ContentInfo& Info )
+{
+ // Check type.
+ if ( Info.Type.isEmpty() )
+ return Reference< XContent >();
+
+ bool bFolder = Info.Type == TaskManager::FolderContentType;
+ if ( !bFolder )
+ {
+ if ( Info.Type != TaskManager::FileContentType )
+ {
+ // Neither folder nor file to create!
+ return Reference< XContent >();
+ }
+ }
+
+ // Who am I ?
+ bool IsDocument = false;
+
+ try
+ {
+ Reference< sdbc::XRow > xRow = getPropertyValues( -1, { { "IsDocument", -1, cppu::UnoType<sal_Bool>::get(), 0 } });
+ IsDocument = xRow->getBoolean( 1 );
+
+ if ( xRow->wasNull() )
+ {
+ IsDocument = false;
+// OSL_FAIL( // "BaseContent::createNewContent - Property value was null!" );
+// return Reference< XContent >();
+ }
+ }
+ catch (const sdbc::SQLException&)
+ {
+ TOOLS_WARN_EXCEPTION("ucb.ucp.file", "");
+ return Reference< XContent >();
+ }
+
+ OUString dstUncPath;
+
+ if( IsDocument )
+ {
+ // KSO: Why is a document a XContentCreator? This is quite unusual.
+ dstUncPath = getParentName( m_aUncPath );
+ }
+ else
+ dstUncPath = m_aUncPath;
+
+ return new BaseContent( m_pMyShell, dstUncPath, bFolder );
+}
+
+
+// XPropertySetInfoChangeNotifier
+
+
+void SAL_CALL
+BaseContent::addPropertySetInfoChangeListener(
+ const Reference< beans::XPropertySetInfoChangeListener >& Listener )
+{
+ std::unique_lock aGuard( m_aMutex );
+
+ m_aPropertySetInfoChangeListeners.addInterface( aGuard, Listener );
+}
+
+
+void SAL_CALL
+BaseContent::removePropertySetInfoChangeListener(
+ const Reference< beans::XPropertySetInfoChangeListener >& Listener )
+{
+ std::unique_lock aGuard( m_aMutex );
+
+ m_aPropertySetInfoChangeListeners.removeInterface( aGuard, Listener );
+}
+
+
+// XChild
+
+
+Reference< XInterface > SAL_CALL
+BaseContent::getParent()
+{
+ OUString ParentUnq = getParentName( m_aUncPath );
+ OUString ParentUrl;
+
+
+ bool err = fileaccess::TaskManager::getUrlFromUnq( ParentUnq, ParentUrl );
+ if( err )
+ return Reference< XInterface >( nullptr );
+
+ rtl::Reference<FileContentIdentifier> Identifier = new FileContentIdentifier( ParentUnq );
+
+ try
+ {
+ return Reference<XInterface>( m_pMyShell->m_pProvider->queryContent( Identifier ), UNO_QUERY );
+ }
+ catch (const IllegalIdentifierException&)
+ {
+ return Reference< XInterface >();
+ }
+}
+
+
+void SAL_CALL
+BaseContent::setParent(
+ const Reference< XInterface >& )
+{
+ throw lang::NoSupportException( THROW_WHERE );
+}
+
+
+// Private Methods
+
+
+Reference< XCommandInfo >
+BaseContent::getCommandInfo()
+{
+ if( m_nState & Deleted )
+ return Reference< XCommandInfo >();
+
+ return m_pMyShell->info_c();
+}
+
+
+Reference< beans::XPropertySetInfo >
+BaseContent::getPropertySetInfo()
+{
+ if( m_nState & Deleted )
+ return Reference< beans::XPropertySetInfo >();
+
+ return m_pMyShell->info_p( m_aUncPath );
+}
+
+Reference< sdbc::XRow >
+BaseContent::getPropertyValues(
+ sal_Int32 nMyCommandIdentifier,
+ const Sequence< beans::Property >& PropertySet )
+{
+ sal_Int32 nProps = PropertySet.getLength();
+ if ( !nProps )
+ return Reference< sdbc::XRow >();
+
+ if( m_nState & Deleted )
+ {
+ Sequence< Any > aValues( nProps );
+ return Reference< sdbc::XRow >( new XRow_impl( m_pMyShell, aValues ) );
+ }
+
+ if( m_nState & JustInserted )
+ {
+ Sequence< Any > aValues( nProps );
+ Any* pValues = aValues.getArray();
+
+ const beans::Property* pProps = PropertySet.getConstArray();
+
+ for ( sal_Int32 n = 0; n < nProps; ++n )
+ {
+ const beans::Property& rProp = pProps[ n ];
+ Any& rValue = pValues[ n ];
+
+ if ( rProp.Name == "ContentType" )
+ {
+ rValue <<= (m_bFolder ? OUString(TaskManager::FolderContentType)
+ : OUString(TaskManager::FileContentType));
+ }
+ else if ( rProp.Name == "IsFolder" )
+ {
+ rValue <<= m_bFolder;
+ }
+ else if ( rProp.Name == "IsDocument" )
+ {
+ rValue <<= !m_bFolder;
+ }
+ }
+
+ return Reference< sdbc::XRow >(
+ new XRow_impl( m_pMyShell, aValues ) );
+ }
+
+ return m_pMyShell->getv( nMyCommandIdentifier,
+ m_aUncPath,
+ PropertySet );
+}
+
+
+Sequence< Any >
+BaseContent::setPropertyValues(
+ sal_Int32 nMyCommandIdentifier,
+ const Sequence< beans::PropertyValue >& Values )
+{
+ if( m_nState & Deleted )
+ { // To do
+ return Sequence< Any >( Values.getLength() );
+ }
+
+ static const OUStringLiteral Title(u"Title");
+
+ // Special handling for files which have to be inserted
+ if( m_nState & JustInserted )
+ {
+ for( const auto& rValue : Values )
+ {
+ if( rValue.Name == Title )
+ {
+ OUString NewTitle;
+ if( rValue.Value >>= NewTitle )
+ {
+ if ( m_nState & NameForInsertionSet )
+ {
+ // User wants to set another Title before "insert".
+ // m_aUncPath contains previous own URI.
+
+ sal_Int32 nLastSlash = m_aUncPath.lastIndexOf( '/' );
+ bool bTrailingSlash = false;
+ if ( nLastSlash == m_aUncPath.getLength() - 1 )
+ {
+ bTrailingSlash = true;
+ nLastSlash
+ = m_aUncPath.lastIndexOf( '/', nLastSlash );
+ }
+
+ OSL_ENSURE( nLastSlash != -1,
+ "BaseContent::setPropertyValues: "
+ "Invalid URL!" );
+
+ OUStringBuffer aBuf(
+ m_aUncPath.subView( 0, nLastSlash + 1 ) );
+
+ if ( !NewTitle.isEmpty() )
+ {
+ aBuf.append( NewTitle );
+ if ( bTrailingSlash )
+ aBuf.append( '/' );
+ }
+ else
+ {
+ m_nState &= ~NameForInsertionSet;
+ }
+
+ m_aUncPath = aBuf.makeStringAndClear();
+ }
+ else
+ {
+ if ( !NewTitle.isEmpty() )
+ {
+ // Initial Title before "insert".
+ // m_aUncPath contains parent's URI.
+
+ if( !m_aUncPath.endsWith( "/" ) )
+ m_aUncPath += "/";
+
+ m_aUncPath += rtl::Uri::encode( NewTitle,
+ rtl_UriCharClassPchar,
+ rtl_UriEncodeIgnoreEscapes,
+ RTL_TEXTENCODING_UTF8 );
+ m_nState |= NameForInsertionSet;
+ }
+ }
+ }
+ }
+ }
+
+ return Sequence< Any >( Values.getLength() );
+ }
+ else
+ {
+ Sequence< Any > ret = m_pMyShell->setv( m_aUncPath, // Does not handle Title
+ Values );
+ auto retRange = asNonConstRange(ret);
+
+ // Special handling Title: Setting Title is equivalent to a renaming of the underlying file
+ for( sal_Int32 i = 0; i < Values.getLength(); ++i )
+ {
+ if( Values[i].Name != Title )
+ continue; // handled by setv
+
+ OUString NewTitle;
+ if( !( Values[i].Value >>= NewTitle ) )
+ {
+ retRange[i] <<= beans::IllegalTypeException( THROW_WHERE );
+ break;
+ }
+ else if( NewTitle.isEmpty() )
+ {
+ retRange[i] <<= lang::IllegalArgumentException( THROW_WHERE, uno::Reference< uno::XInterface >(), 0 );
+ break;
+ }
+
+
+ OUString aDstName = getParentName( m_aUncPath );
+ if( !aDstName.endsWith("/") )
+ aDstName += "/";
+
+ aDstName += rtl::Uri::encode( NewTitle,
+ rtl_UriCharClassPchar,
+ rtl_UriEncodeIgnoreEscapes,
+ RTL_TEXTENCODING_UTF8 );
+
+ m_pMyShell->move( nMyCommandIdentifier, // move notifies the children also;
+ m_aUncPath,
+ aDstName,
+ NameClash::KEEP );
+
+ try
+ {
+ endTask( nMyCommandIdentifier );
+ }
+ catch(const Exception& e)
+ {
+ retRange[i] <<= e;
+ }
+
+ // NameChanges come back through a ContentEvent
+ break; // only handling Title
+ } // end for
+
+ return ret;
+ }
+}
+
+
+Reference< XDynamicResultSet >
+BaseContent::open(
+ sal_Int32 nMyCommandIdentifier,
+ const OpenCommandArgument2& aCommandArgument )
+{
+ Reference< XDynamicResultSet > retValue;
+
+ if( m_nState & Deleted )
+ {
+ m_pMyShell->installError( nMyCommandIdentifier,
+ TASKHANDLING_DELETED_STATE_IN_OPEN_COMMAND );
+ }
+ else if( m_nState & JustInserted )
+ {
+ m_pMyShell->installError( nMyCommandIdentifier,
+ TASKHANDLING_INSERTED_STATE_IN_OPEN_COMMAND );
+ }
+ else
+ {
+ if( aCommandArgument.Mode == OpenMode::DOCUMENT ||
+ aCommandArgument.Mode == OpenMode::DOCUMENT_SHARE_DENY_NONE )
+
+ {
+ Reference< io::XOutputStream > outputStream( aCommandArgument.Sink,UNO_QUERY );
+ if( outputStream.is() )
+ {
+ m_pMyShell->page( nMyCommandIdentifier,
+ m_aUncPath,
+ outputStream );
+ }
+
+ bool bLock = ( aCommandArgument.Mode != OpenMode::DOCUMENT_SHARE_DENY_NONE );
+
+ Reference< io::XActiveDataSink > activeDataSink( aCommandArgument.Sink,UNO_QUERY );
+ if( activeDataSink.is() )
+ {
+ activeDataSink->setInputStream( m_pMyShell->open( nMyCommandIdentifier,
+ m_aUncPath,
+ bLock ) );
+ }
+
+ Reference< io::XActiveDataStreamer > activeDataStreamer( aCommandArgument.Sink,UNO_QUERY );
+ if( activeDataStreamer.is() )
+ {
+ activeDataStreamer->setStream( m_pMyShell->open_rw( nMyCommandIdentifier,
+ m_aUncPath,
+ bLock ) );
+ }
+ }
+ else if ( aCommandArgument.Mode == OpenMode::ALL ||
+ aCommandArgument.Mode == OpenMode::FOLDERS ||
+ aCommandArgument.Mode == OpenMode::DOCUMENTS )
+ {
+ retValue = m_pMyShell->ls( nMyCommandIdentifier,
+ m_aUncPath,
+ aCommandArgument.Mode,
+ aCommandArgument.Properties,
+ aCommandArgument.SortingInfo );
+ }
+// else if( aCommandArgument.Mode ==
+// OpenMode::DOCUMENT_SHARE_DENY_NONE ||
+// aCommandArgument.Mode ==
+// OpenMode::DOCUMENT_SHARE_DENY_WRITE )
+// m_pMyShell->installError( nMyCommandIdentifier,
+// TASKHANDLING_UNSUPPORTED_OPEN_MODE,
+// aCommandArgument.Mode);
+ else
+ m_pMyShell->installError( nMyCommandIdentifier,
+ TASKHANDLING_UNSUPPORTED_OPEN_MODE,
+ aCommandArgument.Mode);
+ }
+
+ return retValue;
+}
+
+
+void
+BaseContent::deleteContent( sal_Int32 nMyCommandIdentifier )
+{
+ if( m_nState & Deleted )
+ return;
+
+ if( m_pMyShell->remove( nMyCommandIdentifier,m_aUncPath ) )
+ {
+ std::unique_lock aGuard( m_aMutex );
+ m_nState |= Deleted;
+ }
+}
+
+
+void
+BaseContent::transfer( sal_Int32 nMyCommandIdentifier,
+ const TransferInfo& aTransferInfo )
+{
+ if( m_nState & Deleted )
+ return;
+
+ if( !comphelper::isFileUrl(aTransferInfo.SourceURL) )
+ {
+ m_pMyShell->installError( nMyCommandIdentifier,
+ TASKHANDLING_TRANSFER_INVALIDSCHEME );
+ return;
+ }
+
+ OUString srcUnc;
+ if( fileaccess::TaskManager::getUnqFromUrl( aTransferInfo.SourceURL,srcUnc ) )
+ {
+ m_pMyShell->installError( nMyCommandIdentifier,
+ TASKHANDLING_TRANSFER_INVALIDURL );
+ return;
+ }
+
+ OUString srcUncPath = srcUnc;
+
+ // Determine the new title !
+ OUString NewTitle;
+ if( !aTransferInfo.NewTitle.isEmpty() )
+ NewTitle = rtl::Uri::encode( aTransferInfo.NewTitle,
+ rtl_UriCharClassPchar,
+ rtl_UriEncodeIgnoreEscapes,
+ RTL_TEXTENCODING_UTF8 );
+ else
+ NewTitle = srcUncPath.copy( 1 + srcUncPath.lastIndexOf( '/' ) );
+
+ // Is destination a document or a folder ?
+ Reference< sdbc::XRow > xRow = getPropertyValues( nMyCommandIdentifier,{ { "IsDocument", -1, cppu::UnoType<sal_Bool>::get(), 0 } } );
+ bool IsDocument = xRow->getBoolean( 1 );
+ if( xRow->wasNull() )
+ { // Destination file type could not be determined
+ m_pMyShell->installError( nMyCommandIdentifier,
+ TASKHANDLING_TRANSFER_DESTFILETYPE );
+ return;
+ }
+
+ OUString dstUncPath;
+ if( IsDocument )
+ { // as sibling
+ sal_Int32 lastSlash = m_aUncPath.lastIndexOf( '/' );
+ dstUncPath = m_aUncPath.copy(0,lastSlash );
+ }
+ else
+ // as child
+ dstUncPath = m_aUncPath;
+
+ dstUncPath += "/" + NewTitle;
+
+ sal_Int32 NameClash = aTransferInfo.NameClash;
+
+ if( aTransferInfo.MoveData )
+ m_pMyShell->move( nMyCommandIdentifier,srcUncPath,dstUncPath,NameClash );
+ else
+ m_pMyShell->copy( nMyCommandIdentifier,srcUncPath,dstUncPath,NameClash );
+}
+
+
+void BaseContent::insert( sal_Int32 nMyCommandIdentifier,
+ const InsertCommandArgument& aInsertArgument )
+{
+ if( m_nState & FullFeatured )
+ {
+ m_pMyShell->write( nMyCommandIdentifier,
+ m_aUncPath,
+ aInsertArgument.ReplaceExisting,
+ aInsertArgument.Data );
+ return;
+ }
+
+ if( ! ( m_nState & JustInserted ) )
+ {
+ m_pMyShell->installError( nMyCommandIdentifier,
+ TASKHANDLING_NOFRESHINSERT_IN_INSERT_COMMAND );
+ return;
+ }
+
+ // Inserts the content, which has the flag m_bIsFresh
+
+ if( ! (m_nState & NameForInsertionSet) )
+ {
+ m_pMyShell->installError( nMyCommandIdentifier,
+ TASKHANDLING_NONAMESET_INSERT_COMMAND );
+ return;
+ }
+
+ // Inserting a document or a file?
+ bool bDocument = false;
+
+ Reference< sdbc::XRow > xRow = getPropertyValues( -1, { { "IsDocument", -1, cppu::UnoType<sal_Bool>::get(), 0 } });
+
+ bool contentTypeSet = true; // is set to false, if contentType not set
+ try
+ {
+ bDocument = xRow->getBoolean( 1 );
+ if( xRow->wasNull() )
+ contentTypeSet = false;
+
+ }
+ catch (const sdbc::SQLException&)
+ {
+ TOOLS_WARN_EXCEPTION("ucb.ucp.file", "");
+ contentTypeSet = false;
+ }
+
+ if( ! contentTypeSet )
+ {
+ m_pMyShell->installError( nMyCommandIdentifier,
+ TASKHANDLING_NOCONTENTTYPE_INSERT_COMMAND );
+ return;
+ }
+
+
+ bool success = false;
+ if( bDocument )
+ success = m_pMyShell->mkfil( nMyCommandIdentifier,
+ m_aUncPath,
+ aInsertArgument.ReplaceExisting,
+ aInsertArgument.Data );
+ else
+ {
+ while( ! success )
+ {
+ success = m_pMyShell->mkdir( nMyCommandIdentifier,
+ m_aUncPath,
+ aInsertArgument.ReplaceExisting );
+ if( success )
+ break;
+
+ XInteractionRequestImpl aRequestImpl(
+ rtl::Uri::decode(
+ OUString(getTitle(m_aUncPath)),
+ rtl_UriDecodeWithCharset,
+ RTL_TEXTENCODING_UTF8),
+ static_cast<cppu::OWeakObject*>(this),
+ m_pMyShell,nMyCommandIdentifier);
+ uno::Reference<task::XInteractionRequest> const& xReq(aRequestImpl.getRequest());
+
+ m_pMyShell->handleTask( nMyCommandIdentifier, xReq );
+ if (aRequestImpl.aborted() || aRequestImpl.newName().isEmpty())
+ // means aborting
+ break;
+
+ // determine new uncpath
+ m_pMyShell->clearError( nMyCommandIdentifier );
+ m_aUncPath = getParentName( m_aUncPath );
+ if( !m_aUncPath.endsWith( "/" ) )
+ m_aUncPath += "/";
+
+ m_aUncPath += rtl::Uri::encode( aRequestImpl.newName(),
+ rtl_UriCharClassPchar,
+ rtl_UriEncodeIgnoreEscapes,
+ RTL_TEXTENCODING_UTF8 );
+ }
+ }
+
+ if ( ! success )
+ return;
+
+ m_xContentIdentifier.set( new FileContentIdentifier( m_aUncPath ) );
+
+ m_pMyShell->registerNotifier( m_aUncPath,this );
+ m_pMyShell->insertDefaultProperties( m_aUncPath );
+
+ std::unique_lock aGuard( m_aMutex );
+ m_nState = FullFeatured;
+}
+
+
+void BaseContent::endTask( sal_Int32 CommandId )
+{
+ // This is the only function allowed to throw an exception
+ m_pMyShell->endTask( CommandId,m_aUncPath,this );
+}
+
+
+std::optional<ContentEventNotifier>
+BaseContent::cDEL()
+{
+ std::unique_lock aGuard( m_aMutex );
+
+ m_nState |= Deleted;
+
+ if( m_aContentEventListeners.getLength(aGuard) == 0 )
+ return {};
+
+ return ContentEventNotifier( m_pMyShell,
+ this,
+ m_xContentIdentifier,
+ m_aContentEventListeners.getElements(aGuard) );
+}
+
+
+std::optional<ContentEventNotifier>
+BaseContent::cEXC( const OUString& aNewName )
+{
+ std::unique_lock aGuard( m_aMutex );
+
+ Reference< XContentIdentifier > xOldRef = m_xContentIdentifier;
+ m_aUncPath = aNewName;
+ m_xContentIdentifier = new FileContentIdentifier( aNewName );
+
+ if( m_aContentEventListeners.getLength(aGuard) == 0 )
+ return {};
+ return ContentEventNotifier( m_pMyShell,
+ this,
+ m_xContentIdentifier,
+ xOldRef,
+ m_aContentEventListeners.getElements(aGuard) );
+}
+
+
+std::optional<ContentEventNotifier>
+BaseContent::cCEL()
+{
+ std::unique_lock aGuard( m_aMutex );
+ if( m_aContentEventListeners.getLength(aGuard) == 0 )
+ return {};
+ return ContentEventNotifier( m_pMyShell,
+ this,
+ m_xContentIdentifier,
+ m_aContentEventListeners.getElements(aGuard) );
+}
+
+std::optional<PropertySetInfoChangeNotifier>
+BaseContent::cPSL()
+{
+ std::unique_lock aGuard( m_aMutex );
+ if( m_aPropertySetInfoChangeListeners.getLength(aGuard) == 0 )
+ return {};
+ return PropertySetInfoChangeNotifier( this, m_aPropertySetInfoChangeListeners.getElements(aGuard) );
+}
+
+
+std::optional<PropertyChangeNotifier>
+BaseContent::cPCL()
+{
+ std::unique_lock aGuard( m_aMutex );
+
+ if (!m_pPropertyListener)
+ return {};
+
+ const std::vector< OUString > seqNames = m_pPropertyListener->getContainedTypes(aGuard);
+ if( seqNames.empty() )
+ return {};
+
+ ListenerMap listener;
+ for( const auto& rName : seqNames )
+ {
+ comphelper::OInterfaceContainerHelper4<beans::XPropertiesChangeListener>* pContainer = m_pPropertyListener->getContainer(aGuard, rName);
+ if (!pContainer)
+ continue;
+ listener[rName] = pContainer->getElements(aGuard);
+ }
+
+ return PropertyChangeNotifier( this, std::move(listener) );
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */