1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <rtl/uri.hxx>
21 #include <rtl/ustrbuf.hxx>
22 #include <rtl/ref.hxx>
24 #include <comphelper/diagnose_ex.hxx>
25 #include <com/sun/star/lang/NoSupportException.hpp>
26 #include <com/sun/star/sdbc/SQLException.hpp>
27 #include <com/sun/star/ucb/IllegalIdentifierException.hpp>
28 #include <com/sun/star/ucb/OpenMode.hpp>
29 #include <com/sun/star/beans/IllegalTypeException.hpp>
30 #include <com/sun/star/io/XActiveDataStreamer.hpp>
31 #include <com/sun/star/io/XOutputStream.hpp>
32 #include <com/sun/star/io/XActiveDataSink.hpp>
33 #include <com/sun/star/ucb/NameClash.hpp>
34 #include <comphelper/fileurl.hxx>
35 #include <cppuhelper/supportsservice.hxx>
37 #include "filglob.hxx"
42 #include "filerror.hxx"
43 #include "filinsreq.hxx"
45 using namespace fileaccess
;
46 using namespace com::sun::star
;
47 using namespace com::sun::star::uno
;
48 using namespace com::sun::star::ucb
;
50 #if OSL_DEBUG_LEVEL > 0
51 #define THROW_WHERE SAL_WHERE
53 #define THROW_WHERE ""
56 class fileaccess::PropertyListeners
58 typedef comphelper::OInterfaceContainerHelper4
<beans::XPropertiesChangeListener
> ContainerHelper
;
59 std::unordered_map
<OUString
, ContainerHelper
> m_aMap
;
62 void disposeAndClear(std::unique_lock
<std::mutex
>& rGuard
, const lang::EventObject
& rEvt
)
64 // create a copy, because do not fire event in a guarded section
65 std::unordered_map
<OUString
, ContainerHelper
> tempMap
= std::move(m_aMap
);
66 for (auto& rPair
: tempMap
)
67 rPair
.second
.disposeAndClear(rGuard
, rEvt
);
69 void addInterface(std::unique_lock
<std::mutex
>& rGuard
, const OUString
& rKey
, const uno::Reference
<beans::XPropertiesChangeListener
>& rListener
)
71 m_aMap
[rKey
].addInterface(rGuard
, rListener
);
73 void removeInterface(std::unique_lock
<std::mutex
>& rGuard
, const OUString
& rKey
, const uno::Reference
<beans::XPropertiesChangeListener
>& rListener
)
75 // search container with id rKey
76 auto iter
= m_aMap
.find(rKey
);
78 if (iter
!= m_aMap
.end())
79 iter
->second
.removeInterface(rGuard
, rListener
);
81 std::vector
< OUString
> getContainedTypes(std::unique_lock
<std::mutex
>& rGuard
) const
83 std::vector
<OUString
> aInterfaceTypes
;
84 aInterfaceTypes
.reserve(m_aMap
.size());
85 for (const auto& rPair
: m_aMap
)
86 // are interfaces added to this container?
87 if (rPair
.second
.getLength(rGuard
))
88 // yes, put the type in the array
89 aInterfaceTypes
.push_back(rPair
.first
);
90 return aInterfaceTypes
;
92 comphelper::OInterfaceContainerHelper4
<beans::XPropertiesChangeListener
>* getContainer(std::unique_lock
<std::mutex
>& , const OUString
& rKey
)
94 auto iter
= m_aMap
.find(rKey
);
95 if (iter
!= m_aMap
.end())
102 /****************************************************************************************/
106 /****************************************************************************************/
109 // Private Constructor for just inserted Contents
111 BaseContent::BaseContent( TaskManager
* pMyShell
,
114 : m_pMyShell( pMyShell
),
115 m_aUncPath(std::move( parentName
)),
116 m_bFolder( bFolder
),
117 m_nState( JustInserted
)
119 m_pMyShell
->m_pProvider
->acquire();
120 // No registering, since we have no name
124 // Constructor for full featured Contents
126 BaseContent::BaseContent( TaskManager
* pMyShell
,
127 const Reference
< XContentIdentifier
>& xContentIdentifier
,
129 : m_pMyShell( pMyShell
),
130 m_xContentIdentifier( xContentIdentifier
),
131 m_aUncPath(std::move( aUncPath
)),
133 m_nState( FullFeatured
)
135 m_pMyShell
->m_pProvider
->acquire();
136 m_pMyShell
->registerNotifier( m_aUncPath
,this );
137 m_pMyShell
->insertDefaultProperties( m_aUncPath
);
141 BaseContent::~BaseContent( )
143 if( ( m_nState
& FullFeatured
) || ( m_nState
& Deleted
) )
145 m_pMyShell
->deregisterNotifier( m_aUncPath
,this );
147 m_pMyShell
->m_pProvider
->release();
155 BaseContent::addEventListener( const Reference
< lang::XEventListener
>& Listener
)
157 std::unique_lock
aGuard( m_aMutex
);
159 m_aDisposeEventListeners
.addInterface( aGuard
, Listener
);
164 BaseContent::removeEventListener( const Reference
< lang::XEventListener
>& Listener
)
166 std::unique_lock
aGuard( m_aMutex
);
168 m_aDisposeEventListeners
.removeInterface( aGuard
, Listener
);
173 BaseContent::dispose()
175 lang::EventObject aEvt
;
176 aEvt
.Source
= static_cast< XContent
* >( this );
178 std::unique_lock
aGuard( m_aMutex
);
180 std::unique_ptr
<PropertyListeners
> pPropertyListener
= std::move(m_pPropertyListener
);
182 m_aDisposeEventListeners
.disposeAndClear( aGuard
, aEvt
);
183 m_aContentEventListeners
.disposeAndClear( aGuard
, aEvt
);
185 if( pPropertyListener
)
186 pPropertyListener
->disposeAndClear( aGuard
, aEvt
);
188 m_aPropertySetInfoChangeListeners
.disposeAndClear( aGuard
, aEvt
);
193 BaseContent::getImplementationName()
195 return "com.sun.star.comp.ucb.FileContent";
199 BaseContent::supportsService( const OUString
& ServiceName
)
201 return cppu::supportsService( this, ServiceName
);
204 Sequence
< OUString
> SAL_CALL
205 BaseContent::getSupportedServiceNames()
207 Sequence
<OUString
> ret
{ "com.sun.star.ucb.FileContent" };
215 BaseContent::createCommandIdentifier()
217 return m_pMyShell
->getCommandId();
222 BaseContent::abort( sal_Int32
/*CommandId*/ )
228 BaseContent::execute( const Command
& aCommand
,
230 const Reference
< XCommandEnvironment
>& Environment
)
233 // A Command with commandid zero cannot be aborted
234 CommandId
= createCommandIdentifier();
236 m_pMyShell
->startTask( CommandId
,
241 if (aCommand
.Name
== "getPropertySetInfo") // No exceptions
243 aAny
<<= getPropertySetInfo();
245 else if (aCommand
.Name
== "getCommandInfo") // no exceptions
247 aAny
<<= getCommandInfo();
249 else if ( aCommand
.Name
== "setPropertyValues" )
251 Sequence
< beans::PropertyValue
> sPropertyValues
;
253 if( ! ( aCommand
.Argument
>>= sPropertyValues
) )
254 m_pMyShell
->installError( CommandId
,
255 TASKHANDLING_WRONG_SETPROPERTYVALUES_ARGUMENT
);
257 aAny
<<= setPropertyValues( CommandId
,sPropertyValues
); // calls endTask by itself
259 else if ( aCommand
.Name
== "getPropertyValues" )
261 Sequence
< beans::Property
> ListOfRequestedProperties
;
263 if( ! ( aCommand
.Argument
>>= ListOfRequestedProperties
) )
264 m_pMyShell
->installError( CommandId
,
265 TASKHANDLING_WRONG_GETPROPERTYVALUES_ARGUMENT
);
267 aAny
<<= getPropertyValues( CommandId
,
268 ListOfRequestedProperties
);
270 else if ( aCommand
.Name
== "open" )
272 OpenCommandArgument2 aOpenArgument
;
273 if( ! ( aCommand
.Argument
>>= aOpenArgument
) )
274 m_pMyShell
->installError( CommandId
,
275 TASKHANDLING_WRONG_OPEN_ARGUMENT
);
278 Reference
< XDynamicResultSet
> result
= open( CommandId
,aOpenArgument
);
283 else if ( aCommand
.Name
== "delete" )
285 if( ! aCommand
.Argument
.has
< bool >() )
286 m_pMyShell
->installError( CommandId
,
287 TASKHANDLING_WRONG_DELETE_ARGUMENT
);
289 deleteContent( CommandId
);
291 else if ( aCommand
.Name
== "transfer" )
293 TransferInfo aTransferInfo
;
294 if( ! ( aCommand
.Argument
>>= aTransferInfo
) )
295 m_pMyShell
->installError( CommandId
,
296 TASKHANDLING_WRONG_TRANSFER_ARGUMENT
);
298 transfer( CommandId
, aTransferInfo
);
300 else if ( aCommand
.Name
== "insert" )
302 InsertCommandArgument aInsertArgument
;
303 if( ! ( aCommand
.Argument
>>= aInsertArgument
) )
304 m_pMyShell
->installError( CommandId
,
305 TASKHANDLING_WRONG_INSERT_ARGUMENT
);
307 insert( CommandId
,aInsertArgument
);
309 else if ( aCommand
.Name
== "getCasePreservingURL" )
311 Reference
< sdbc::XRow
> xRow
= getPropertyValues( CommandId
, { { "CasePreservingURL", -1, cppu::UnoType
<sal_Bool
>::get(), 0 } });
312 OUString CasePreservingURL
= xRow
->getString(1);
314 aAny
<<= CasePreservingURL
;
316 else if ( aCommand
.Name
== "createNewContent" )
318 ucb::ContentInfo aArg
;
319 if ( !( aCommand
.Argument
>>= aArg
) )
320 m_pMyShell
->installError( CommandId
,
321 TASKHANDLING_WRONG_CREATENEWCONTENT_ARGUMENT
);
323 aAny
<<= createNewContent( aArg
);
326 m_pMyShell
->installError( CommandId
,
327 TASKHANDLER_UNSUPPORTED_COMMAND
);
330 // This is the only function allowed to throw an exception
331 endTask( CommandId
);
338 BaseContent::addPropertiesChangeListener(
339 const Sequence
< OUString
>& PropertyNames
,
340 const Reference
< beans::XPropertiesChangeListener
>& Listener
)
342 if( ! Listener
.is() )
345 std::unique_lock
aGuard( m_aMutex
);
347 if( ! m_pPropertyListener
)
348 m_pPropertyListener
.reset( new PropertyListeners
);
351 if( !PropertyNames
.hasElements() )
352 m_pPropertyListener
->addInterface( aGuard
, OUString(),Listener
);
355 Reference
< beans::XPropertySetInfo
> xProp
= m_pMyShell
->info_p( m_aUncPath
);
356 for( const auto& rName
: PropertyNames
)
357 if( xProp
->hasPropertyByName( rName
) )
358 m_pPropertyListener
->addInterface( aGuard
, rName
,Listener
);
364 BaseContent::removePropertiesChangeListener( const Sequence
< OUString
>& PropertyNames
,
365 const Reference
< beans::XPropertiesChangeListener
>& Listener
)
367 if( ! Listener
.is() )
370 std::unique_lock
aGuard( m_aMutex
);
372 if( ! m_pPropertyListener
)
375 for( const auto& rName
: PropertyNames
)
376 m_pPropertyListener
->removeInterface( aGuard
, rName
,Listener
);
378 m_pPropertyListener
->removeInterface( aGuard
, OUString(), Listener
);
385 Reference
< ucb::XContentIdentifier
> SAL_CALL
386 BaseContent::getIdentifier()
388 return m_xContentIdentifier
;
393 BaseContent::getContentType()
395 if( !( m_nState
& Deleted
) )
397 if( m_nState
& JustInserted
)
400 return TaskManager::FolderContentType
;
402 return TaskManager::FileContentType
;
409 Reference
< sdbc::XRow
> xRow
= getPropertyValues( -1, { { "IsDocument", -1, cppu::UnoType
<sal_Bool
>::get(), 0 } });
410 bool IsDocument
= xRow
->getBoolean( 1 );
412 if ( !xRow
->wasNull() )
415 return TaskManager::FileContentType
;
417 return TaskManager::FolderContentType
;
421 OSL_FAIL( "BaseContent::getContentType - Property value was null!" );
424 catch (const sdbc::SQLException
&)
426 TOOLS_WARN_EXCEPTION("ucb.ucp.file", "");
436 BaseContent::addContentEventListener(
437 const Reference
< XContentEventListener
>& Listener
)
439 std::unique_lock
aGuard( m_aMutex
);
441 m_aContentEventListeners
.addInterface( aGuard
, Listener
);
446 BaseContent::removeContentEventListener(
447 const Reference
< XContentEventListener
>& Listener
)
449 std::unique_lock
aGuard( m_aMutex
);
451 m_aContentEventListeners
.removeInterface( aGuard
, Listener
);
455 // XPropertyContainer
459 BaseContent::addProperty(
460 const OUString
& Name
,
461 sal_Int16 Attributes
,
462 const Any
& DefaultValue
)
464 if( ( m_nState
& JustInserted
) || ( m_nState
& Deleted
) || Name
.isEmpty() )
466 throw lang::IllegalArgumentException( THROW_WHERE
, uno::Reference
< uno::XInterface
>(), 0 );
469 m_pMyShell
->associate( m_aUncPath
,Name
,DefaultValue
,Attributes
);
474 BaseContent::removeProperty( const OUString
& Name
)
477 if( m_nState
& Deleted
)
478 throw beans::UnknownPropertyException( Name
);
480 m_pMyShell
->deassociate( m_aUncPath
, Name
);
487 Sequence
< ContentInfo
> SAL_CALL
488 BaseContent::queryCreatableContentsInfo()
490 return TaskManager::queryCreatableContentsInfo();
494 Reference
< XContent
> SAL_CALL
495 BaseContent::createNewContent( const ContentInfo
& Info
)
498 if ( Info
.Type
.isEmpty() )
499 return Reference
< XContent
>();
501 bool bFolder
= Info
.Type
== TaskManager::FolderContentType
;
504 if ( Info
.Type
!= TaskManager::FileContentType
)
506 // Neither folder nor file to create!
507 return Reference
< XContent
>();
512 bool IsDocument
= false;
516 Reference
< sdbc::XRow
> xRow
= getPropertyValues( -1, { { "IsDocument", -1, cppu::UnoType
<sal_Bool
>::get(), 0 } });
517 IsDocument
= xRow
->getBoolean( 1 );
519 if ( xRow
->wasNull() )
522 // OSL_FAIL( // "BaseContent::createNewContent - Property value was null!" );
523 // return Reference< XContent >();
526 catch (const sdbc::SQLException
&)
528 TOOLS_WARN_EXCEPTION("ucb.ucp.file", "");
529 return Reference
< XContent
>();
536 // KSO: Why is a document a XContentCreator? This is quite unusual.
537 dstUncPath
= getParentName( m_aUncPath
);
540 dstUncPath
= m_aUncPath
;
542 return new BaseContent( m_pMyShell
, dstUncPath
, bFolder
);
546 // XPropertySetInfoChangeNotifier
550 BaseContent::addPropertySetInfoChangeListener(
551 const Reference
< beans::XPropertySetInfoChangeListener
>& Listener
)
553 std::unique_lock
aGuard( m_aMutex
);
555 m_aPropertySetInfoChangeListeners
.addInterface( aGuard
, Listener
);
560 BaseContent::removePropertySetInfoChangeListener(
561 const Reference
< beans::XPropertySetInfoChangeListener
>& Listener
)
563 std::unique_lock
aGuard( m_aMutex
);
565 m_aPropertySetInfoChangeListeners
.removeInterface( aGuard
, Listener
);
572 Reference
< XInterface
> SAL_CALL
573 BaseContent::getParent()
575 OUString ParentUnq
= getParentName( m_aUncPath
);
579 bool err
= fileaccess::TaskManager::getUrlFromUnq( ParentUnq
, ParentUrl
);
581 return Reference
< XInterface
>( nullptr );
583 rtl::Reference
<FileContentIdentifier
> Identifier
= new FileContentIdentifier( ParentUnq
);
587 return Reference
<XInterface
>( m_pMyShell
->m_pProvider
->queryContent( Identifier
), UNO_QUERY
);
589 catch (const IllegalIdentifierException
&)
591 return Reference
< XInterface
>();
597 BaseContent::setParent(
598 const Reference
< XInterface
>& )
600 throw lang::NoSupportException( THROW_WHERE
);
607 Reference
< XCommandInfo
>
608 BaseContent::getCommandInfo()
610 if( m_nState
& Deleted
)
611 return Reference
< XCommandInfo
>();
613 return m_pMyShell
->info_c();
617 Reference
< beans::XPropertySetInfo
>
618 BaseContent::getPropertySetInfo()
620 if( m_nState
& Deleted
)
621 return Reference
< beans::XPropertySetInfo
>();
623 return m_pMyShell
->info_p( m_aUncPath
);
626 Reference
< sdbc::XRow
>
627 BaseContent::getPropertyValues(
628 sal_Int32 nMyCommandIdentifier
,
629 const Sequence
< beans::Property
>& PropertySet
)
631 sal_Int32 nProps
= PropertySet
.getLength();
633 return Reference
< sdbc::XRow
>();
635 if( m_nState
& Deleted
)
637 Sequence
< Any
> aValues( nProps
);
638 return Reference
< sdbc::XRow
>( new XRow_impl( m_pMyShell
, aValues
) );
641 if( m_nState
& JustInserted
)
643 Sequence
< Any
> aValues( nProps
);
644 Any
* pValues
= aValues
.getArray();
646 const beans::Property
* pProps
= PropertySet
.getConstArray();
648 for ( sal_Int32 n
= 0; n
< nProps
; ++n
)
650 const beans::Property
& rProp
= pProps
[ n
];
651 Any
& rValue
= pValues
[ n
];
653 if ( rProp
.Name
== "ContentType" )
655 rValue
<<= (m_bFolder
? OUString(TaskManager::FolderContentType
)
656 : OUString(TaskManager::FileContentType
));
658 else if ( rProp
.Name
== "IsFolder" )
660 rValue
<<= m_bFolder
;
662 else if ( rProp
.Name
== "IsDocument" )
664 rValue
<<= !m_bFolder
;
668 return Reference
< sdbc::XRow
>(
669 new XRow_impl( m_pMyShell
, aValues
) );
672 return m_pMyShell
->getv( nMyCommandIdentifier
,
679 BaseContent::setPropertyValues(
680 sal_Int32 nMyCommandIdentifier
,
681 const Sequence
< beans::PropertyValue
>& Values
)
683 if( m_nState
& Deleted
)
685 return Sequence
< Any
>( Values
.getLength() );
688 static const OUStringLiteral
Title(u
"Title");
690 // Special handling for files which have to be inserted
691 if( m_nState
& JustInserted
)
693 for( const auto& rValue
: Values
)
695 if( rValue
.Name
== Title
)
698 if( rValue
.Value
>>= NewTitle
)
700 if ( m_nState
& NameForInsertionSet
)
702 // User wants to set another Title before "insert".
703 // m_aUncPath contains previous own URI.
705 sal_Int32 nLastSlash
= m_aUncPath
.lastIndexOf( '/' );
706 bool bTrailingSlash
= false;
707 if ( nLastSlash
== m_aUncPath
.getLength() - 1 )
709 bTrailingSlash
= true;
711 = m_aUncPath
.lastIndexOf( '/', nLastSlash
);
714 OSL_ENSURE( nLastSlash
!= -1,
715 "BaseContent::setPropertyValues: "
719 m_aUncPath
.subView( 0, nLastSlash
+ 1 ) );
721 if ( !NewTitle
.isEmpty() )
723 aBuf
.append( NewTitle
);
724 if ( bTrailingSlash
)
729 m_nState
&= ~NameForInsertionSet
;
732 m_aUncPath
= aBuf
.makeStringAndClear();
736 if ( !NewTitle
.isEmpty() )
738 // Initial Title before "insert".
739 // m_aUncPath contains parent's URI.
741 if( !m_aUncPath
.endsWith( "/" ) )
744 m_aUncPath
+= rtl::Uri::encode( NewTitle
,
745 rtl_UriCharClassPchar
,
746 rtl_UriEncodeIgnoreEscapes
,
747 RTL_TEXTENCODING_UTF8
);
748 m_nState
|= NameForInsertionSet
;
755 return Sequence
< Any
>( Values
.getLength() );
759 Sequence
< Any
> ret
= m_pMyShell
->setv( m_aUncPath
, // Does not handle Title
761 auto retRange
= asNonConstRange(ret
);
763 // Special handling Title: Setting Title is equivalent to a renaming of the underlying file
764 for( sal_Int32 i
= 0; i
< Values
.getLength(); ++i
)
766 if( Values
[i
].Name
!= Title
)
767 continue; // handled by setv
770 if( !( Values
[i
].Value
>>= NewTitle
) )
772 retRange
[i
] <<= beans::IllegalTypeException( THROW_WHERE
);
775 else if( NewTitle
.isEmpty() )
777 retRange
[i
] <<= lang::IllegalArgumentException( THROW_WHERE
, uno::Reference
< uno::XInterface
>(), 0 );
782 OUString aDstName
= getParentName( m_aUncPath
);
783 if( !aDstName
.endsWith("/") )
786 aDstName
+= rtl::Uri::encode( NewTitle
,
787 rtl_UriCharClassPchar
,
788 rtl_UriEncodeIgnoreEscapes
,
789 RTL_TEXTENCODING_UTF8
);
791 m_pMyShell
->move( nMyCommandIdentifier
, // move notifies the children also;
798 endTask( nMyCommandIdentifier
);
800 catch(const Exception
& e
)
805 // NameChanges come back through a ContentEvent
806 break; // only handling Title
814 Reference
< XDynamicResultSet
>
816 sal_Int32 nMyCommandIdentifier
,
817 const OpenCommandArgument2
& aCommandArgument
)
819 Reference
< XDynamicResultSet
> retValue
;
821 if( m_nState
& Deleted
)
823 m_pMyShell
->installError( nMyCommandIdentifier
,
824 TASKHANDLING_DELETED_STATE_IN_OPEN_COMMAND
);
826 else if( m_nState
& JustInserted
)
828 m_pMyShell
->installError( nMyCommandIdentifier
,
829 TASKHANDLING_INSERTED_STATE_IN_OPEN_COMMAND
);
833 if( aCommandArgument
.Mode
== OpenMode::DOCUMENT
||
834 aCommandArgument
.Mode
== OpenMode::DOCUMENT_SHARE_DENY_NONE
)
837 Reference
< io::XOutputStream
> outputStream( aCommandArgument
.Sink
,UNO_QUERY
);
838 if( outputStream
.is() )
840 m_pMyShell
->page( nMyCommandIdentifier
,
845 bool bLock
= ( aCommandArgument
.Mode
!= OpenMode::DOCUMENT_SHARE_DENY_NONE
);
847 Reference
< io::XActiveDataSink
> activeDataSink( aCommandArgument
.Sink
,UNO_QUERY
);
848 if( activeDataSink
.is() )
850 activeDataSink
->setInputStream( m_pMyShell
->open( nMyCommandIdentifier
,
855 Reference
< io::XActiveDataStreamer
> activeDataStreamer( aCommandArgument
.Sink
,UNO_QUERY
);
856 if( activeDataStreamer
.is() )
858 activeDataStreamer
->setStream( m_pMyShell
->open_rw( nMyCommandIdentifier
,
863 else if ( aCommandArgument
.Mode
== OpenMode::ALL
||
864 aCommandArgument
.Mode
== OpenMode::FOLDERS
||
865 aCommandArgument
.Mode
== OpenMode::DOCUMENTS
)
867 retValue
= m_pMyShell
->ls( nMyCommandIdentifier
,
869 aCommandArgument
.Mode
,
870 aCommandArgument
.Properties
,
871 aCommandArgument
.SortingInfo
);
873 // else if( aCommandArgument.Mode ==
874 // OpenMode::DOCUMENT_SHARE_DENY_NONE ||
875 // aCommandArgument.Mode ==
876 // OpenMode::DOCUMENT_SHARE_DENY_WRITE )
877 // m_pMyShell->installError( nMyCommandIdentifier,
878 // TASKHANDLING_UNSUPPORTED_OPEN_MODE,
879 // aCommandArgument.Mode);
881 m_pMyShell
->installError( nMyCommandIdentifier
,
882 TASKHANDLING_UNSUPPORTED_OPEN_MODE
,
883 aCommandArgument
.Mode
);
891 BaseContent::deleteContent( sal_Int32 nMyCommandIdentifier
)
893 if( m_nState
& Deleted
)
896 if( m_pMyShell
->remove( nMyCommandIdentifier
,m_aUncPath
) )
898 std::unique_lock
aGuard( m_aMutex
);
905 BaseContent::transfer( sal_Int32 nMyCommandIdentifier
,
906 const TransferInfo
& aTransferInfo
)
908 if( m_nState
& Deleted
)
911 if( !comphelper::isFileUrl(aTransferInfo
.SourceURL
) )
913 m_pMyShell
->installError( nMyCommandIdentifier
,
914 TASKHANDLING_TRANSFER_INVALIDSCHEME
);
919 if( fileaccess::TaskManager::getUnqFromUrl( aTransferInfo
.SourceURL
,srcUnc
) )
921 m_pMyShell
->installError( nMyCommandIdentifier
,
922 TASKHANDLING_TRANSFER_INVALIDURL
);
926 OUString srcUncPath
= srcUnc
;
928 // Determine the new title !
930 if( !aTransferInfo
.NewTitle
.isEmpty() )
931 NewTitle
= rtl::Uri::encode( aTransferInfo
.NewTitle
,
932 rtl_UriCharClassPchar
,
933 rtl_UriEncodeIgnoreEscapes
,
934 RTL_TEXTENCODING_UTF8
);
936 NewTitle
= srcUncPath
.copy( 1 + srcUncPath
.lastIndexOf( '/' ) );
938 // Is destination a document or a folder ?
939 Reference
< sdbc::XRow
> xRow
= getPropertyValues( nMyCommandIdentifier
,{ { "IsDocument", -1, cppu::UnoType
<sal_Bool
>::get(), 0 } } );
940 bool IsDocument
= xRow
->getBoolean( 1 );
941 if( xRow
->wasNull() )
942 { // Destination file type could not be determined
943 m_pMyShell
->installError( nMyCommandIdentifier
,
944 TASKHANDLING_TRANSFER_DESTFILETYPE
);
951 sal_Int32 lastSlash
= m_aUncPath
.lastIndexOf( '/' );
952 dstUncPath
= m_aUncPath
.copy(0,lastSlash
);
956 dstUncPath
= m_aUncPath
;
958 dstUncPath
+= "/" + NewTitle
;
960 sal_Int32 NameClash
= aTransferInfo
.NameClash
;
962 if( aTransferInfo
.MoveData
)
963 m_pMyShell
->move( nMyCommandIdentifier
,srcUncPath
,dstUncPath
,NameClash
);
965 m_pMyShell
->copy( nMyCommandIdentifier
,srcUncPath
,dstUncPath
,NameClash
);
969 void BaseContent::insert( sal_Int32 nMyCommandIdentifier
,
970 const InsertCommandArgument
& aInsertArgument
)
972 if( m_nState
& FullFeatured
)
974 m_pMyShell
->write( nMyCommandIdentifier
,
976 aInsertArgument
.ReplaceExisting
,
977 aInsertArgument
.Data
);
981 if( ! ( m_nState
& JustInserted
) )
983 m_pMyShell
->installError( nMyCommandIdentifier
,
984 TASKHANDLING_NOFRESHINSERT_IN_INSERT_COMMAND
);
988 // Inserts the content, which has the flag m_bIsFresh
990 if( ! (m_nState
& NameForInsertionSet
) )
992 m_pMyShell
->installError( nMyCommandIdentifier
,
993 TASKHANDLING_NONAMESET_INSERT_COMMAND
);
997 // Inserting a document or a file?
998 bool bDocument
= false;
1000 Reference
< sdbc::XRow
> xRow
= getPropertyValues( -1, { { "IsDocument", -1, cppu::UnoType
<sal_Bool
>::get(), 0 } });
1002 bool contentTypeSet
= true; // is set to false, if contentType not set
1005 bDocument
= xRow
->getBoolean( 1 );
1006 if( xRow
->wasNull() )
1007 contentTypeSet
= false;
1010 catch (const sdbc::SQLException
&)
1012 TOOLS_WARN_EXCEPTION("ucb.ucp.file", "");
1013 contentTypeSet
= false;
1016 if( ! contentTypeSet
)
1018 m_pMyShell
->installError( nMyCommandIdentifier
,
1019 TASKHANDLING_NOCONTENTTYPE_INSERT_COMMAND
);
1024 bool success
= false;
1026 success
= m_pMyShell
->mkfil( nMyCommandIdentifier
,
1028 aInsertArgument
.ReplaceExisting
,
1029 aInsertArgument
.Data
);
1034 success
= m_pMyShell
->mkdir( nMyCommandIdentifier
,
1036 aInsertArgument
.ReplaceExisting
);
1040 XInteractionRequestImpl
aRequestImpl(
1042 OUString(getTitle(m_aUncPath
)),
1043 rtl_UriDecodeWithCharset
,
1044 RTL_TEXTENCODING_UTF8
),
1045 static_cast<cppu::OWeakObject
*>(this),
1046 m_pMyShell
,nMyCommandIdentifier
);
1047 uno::Reference
<task::XInteractionRequest
> const& xReq(aRequestImpl
.getRequest());
1049 m_pMyShell
->handleTask( nMyCommandIdentifier
, xReq
);
1050 if (aRequestImpl
.aborted() || aRequestImpl
.newName().isEmpty())
1054 // determine new uncpath
1055 m_pMyShell
->clearError( nMyCommandIdentifier
);
1056 m_aUncPath
= getParentName( m_aUncPath
);
1057 if( !m_aUncPath
.endsWith( "/" ) )
1060 m_aUncPath
+= rtl::Uri::encode( aRequestImpl
.newName(),
1061 rtl_UriCharClassPchar
,
1062 rtl_UriEncodeIgnoreEscapes
,
1063 RTL_TEXTENCODING_UTF8
);
1070 m_xContentIdentifier
.set( new FileContentIdentifier( m_aUncPath
) );
1072 m_pMyShell
->registerNotifier( m_aUncPath
,this );
1073 m_pMyShell
->insertDefaultProperties( m_aUncPath
);
1075 std::unique_lock
aGuard( m_aMutex
);
1076 m_nState
= FullFeatured
;
1080 void BaseContent::endTask( sal_Int32 CommandId
)
1082 // This is the only function allowed to throw an exception
1083 m_pMyShell
->endTask( CommandId
,m_aUncPath
,this );
1087 std::optional
<ContentEventNotifier
>
1090 std::unique_lock
aGuard( m_aMutex
);
1092 m_nState
|= Deleted
;
1094 if( m_aContentEventListeners
.getLength(aGuard
) == 0 )
1097 return ContentEventNotifier( m_pMyShell
,
1099 m_xContentIdentifier
,
1100 m_aContentEventListeners
.getElements(aGuard
) );
1104 std::optional
<ContentEventNotifier
>
1105 BaseContent::cEXC( const OUString
& aNewName
)
1107 std::unique_lock
aGuard( m_aMutex
);
1109 Reference
< XContentIdentifier
> xOldRef
= m_xContentIdentifier
;
1110 m_aUncPath
= aNewName
;
1111 m_xContentIdentifier
= new FileContentIdentifier( aNewName
);
1113 if( m_aContentEventListeners
.getLength(aGuard
) == 0 )
1115 return ContentEventNotifier( m_pMyShell
,
1117 m_xContentIdentifier
,
1119 m_aContentEventListeners
.getElements(aGuard
) );
1123 std::optional
<ContentEventNotifier
>
1126 std::unique_lock
aGuard( m_aMutex
);
1127 if( m_aContentEventListeners
.getLength(aGuard
) == 0 )
1129 return ContentEventNotifier( m_pMyShell
,
1131 m_xContentIdentifier
,
1132 m_aContentEventListeners
.getElements(aGuard
) );
1135 std::optional
<PropertySetInfoChangeNotifier
>
1138 std::unique_lock
aGuard( m_aMutex
);
1139 if( m_aPropertySetInfoChangeListeners
.getLength(aGuard
) == 0 )
1141 return PropertySetInfoChangeNotifier( this, m_aPropertySetInfoChangeListeners
.getElements(aGuard
) );
1145 std::optional
<PropertyChangeNotifier
>
1148 std::unique_lock
aGuard( m_aMutex
);
1150 if (!m_pPropertyListener
)
1153 const std::vector
< OUString
> seqNames
= m_pPropertyListener
->getContainedTypes(aGuard
);
1154 if( seqNames
.empty() )
1157 ListenerMap listener
;
1158 for( const auto& rName
: seqNames
)
1160 comphelper::OInterfaceContainerHelper4
<beans::XPropertiesChangeListener
>* pContainer
= m_pPropertyListener
->getContainer(aGuard
, rName
);
1163 listener
[rName
] = pContainer
->getElements(aGuard
);
1166 return PropertyChangeNotifier( this, std::move(listener
) );
1170 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */