LibreOffice Module ucb (master) 1
bc.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <rtl/uri.hxx>
21#include <rtl/ustrbuf.hxx>
22#include <rtl/ref.hxx>
23
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>
36#include <utility>
37#include "filglob.hxx"
38#include "filid.hxx"
39#include "filrow.hxx"
40#include "bc.hxx"
41#include "prov.hxx"
42#include "filerror.hxx"
43#include "filinsreq.hxx"
44
45using namespace fileaccess;
46using namespace com::sun::star;
47using namespace com::sun::star::uno;
48using namespace com::sun::star::ucb;
49
50#if OSL_DEBUG_LEVEL > 0
51#define THROW_WHERE SAL_WHERE
52#else
53#define THROW_WHERE ""
54#endif
55
57{
59 std::unordered_map<OUString, ContainerHelper> m_aMap;
60
61public:
62 void disposeAndClear(std::unique_lock<std::mutex>& rGuard, const lang::EventObject& rEvt)
63 {
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);
68 }
69 void addInterface(std::unique_lock<std::mutex>& rGuard, const OUString& rKey, const uno::Reference<beans::XPropertiesChangeListener>& rListener)
70 {
71 m_aMap[rKey].addInterface(rGuard, rListener);
72 }
73 void removeInterface(std::unique_lock<std::mutex>& rGuard, const OUString& rKey, const uno::Reference<beans::XPropertiesChangeListener>& rListener)
74 {
75 // search container with id rKey
76 auto iter = m_aMap.find(rKey);
77 // container found?
78 if (iter != m_aMap.end())
79 iter->second.removeInterface(rGuard, rListener);
80 }
81 std::vector< OUString > getContainedTypes(std::unique_lock<std::mutex>& rGuard) const
82 {
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;
91 }
93 {
94 auto iter = m_aMap.find(rKey);
95 if (iter != m_aMap.end())
96 return &iter->second;
97 return nullptr;
98 }
99};
100
101
102/****************************************************************************************/
103/* */
104/* BaseContent */
105/* */
106/****************************************************************************************/
107
108
109// Private Constructor for just inserted Contents
110
111BaseContent::BaseContent( TaskManager* pMyShell,
112 OUString parentName,
113 bool bFolder )
114 : m_pMyShell( pMyShell ),
115 m_aUncPath(std::move( parentName )),
116 m_bFolder( bFolder ),
117 m_nState( JustInserted )
118{
119 m_pMyShell->m_pProvider->acquire();
120 // No registering, since we have no name
121}
122
123
124// Constructor for full featured Contents
125
127 const Reference< XContentIdentifier >& xContentIdentifier,
128 OUString aUncPath )
129 : m_pMyShell( pMyShell ),
130 m_xContentIdentifier( xContentIdentifier ),
131 m_aUncPath(std::move( aUncPath )),
132 m_bFolder( false ),
133 m_nState( FullFeatured )
134{
135 m_pMyShell->m_pProvider->acquire();
138}
139
140
142{
143 if( ( m_nState & FullFeatured ) || ( m_nState & Deleted ) )
144 {
146 }
147 m_pMyShell->m_pProvider->release();
148}
149
150
151// XComponent
152
153
154void SAL_CALL
156{
157 std::unique_lock aGuard( m_aMutex );
158
159 m_aDisposeEventListeners.addInterface( aGuard, Listener );
160}
161
162
163void SAL_CALL
165{
166 std::unique_lock aGuard( m_aMutex );
167
168 m_aDisposeEventListeners.removeInterface( aGuard, Listener );
169}
170
171
172void SAL_CALL
174{
175 lang::EventObject aEvt;
176 aEvt.Source = static_cast< XContent* >( this );
177
178 std::unique_lock aGuard( m_aMutex );
179
180 std::unique_ptr<PropertyListeners> pPropertyListener = std::move(m_pPropertyListener);
181
184
185 if( pPropertyListener )
186 pPropertyListener->disposeAndClear( aGuard, aEvt );
187
189}
190
191// XServiceInfo
192OUString SAL_CALL
194{
195 return "com.sun.star.comp.ucb.FileContent";
196}
197
198sal_Bool SAL_CALL
199BaseContent::supportsService( const OUString& ServiceName )
200{
201 return cppu::supportsService( this, ServiceName );
202}
203
206{
207 Sequence<OUString> ret { "com.sun.star.ucb.FileContent" };
208 return ret;
209}
210
211// XCommandProcessor
212
213
214sal_Int32 SAL_CALL
216{
217 return m_pMyShell->getCommandId();
218}
219
220
221void SAL_CALL
222BaseContent::abort( sal_Int32 /*CommandId*/ )
223{
224}
225
226
227Any SAL_CALL
228BaseContent::execute( const Command& aCommand,
229 sal_Int32 CommandId,
230 const Reference< XCommandEnvironment >& Environment )
231{
232 if( ! CommandId )
233 // A Command with commandid zero cannot be aborted
234 CommandId = createCommandIdentifier();
235
236 m_pMyShell->startTask( CommandId,
237 Environment );
238
239 Any aAny;
240
241 if (aCommand.Name == "getPropertySetInfo") // No exceptions
242 {
243 aAny <<= getPropertySetInfo();
244 }
245 else if (aCommand.Name == "getCommandInfo") // no exceptions
246 {
247 aAny <<= getCommandInfo();
248 }
249 else if ( aCommand.Name == "setPropertyValues" )
250 {
251 Sequence< beans::PropertyValue > sPropertyValues;
252
253 if( ! ( aCommand.Argument >>= sPropertyValues ) )
254 m_pMyShell->installError( CommandId,
256 else
257 aAny <<= setPropertyValues( CommandId,sPropertyValues ); // calls endTask by itself
258 }
259 else if ( aCommand.Name == "getPropertyValues" )
260 {
261 Sequence< beans::Property > ListOfRequestedProperties;
262
263 if( ! ( aCommand.Argument >>= ListOfRequestedProperties ) )
264 m_pMyShell->installError( CommandId,
266 else
267 aAny <<= getPropertyValues( CommandId,
268 ListOfRequestedProperties );
269 }
270 else if ( aCommand.Name == "open" )
271 {
272 OpenCommandArgument2 aOpenArgument;
273 if( ! ( aCommand.Argument >>= aOpenArgument ) )
274 m_pMyShell->installError( CommandId,
276 else
277 {
278 Reference< XDynamicResultSet > result = open( CommandId,aOpenArgument );
279 if( result.is() )
280 aAny <<= result;
281 }
282 }
283 else if ( aCommand.Name == "delete" )
284 {
285 if( ! aCommand.Argument.has< bool >() )
286 m_pMyShell->installError( CommandId,
288 else
289 deleteContent( CommandId );
290 }
291 else if ( aCommand.Name == "transfer" )
292 {
293 TransferInfo aTransferInfo;
294 if( ! ( aCommand.Argument >>= aTransferInfo ) )
295 m_pMyShell->installError( CommandId,
297 else
298 transfer( CommandId, aTransferInfo );
299 }
300 else if ( aCommand.Name == "insert" )
301 {
302 InsertCommandArgument aInsertArgument;
303 if( ! ( aCommand.Argument >>= aInsertArgument ) )
304 m_pMyShell->installError( CommandId,
306 else
307 insert( CommandId,aInsertArgument );
308 }
309 else if ( aCommand.Name == "getCasePreservingURL" )
310 {
311 Reference< sdbc::XRow > xRow = getPropertyValues( CommandId, { { "CasePreservingURL", -1, cppu::UnoType<sal_Bool>::get(), 0 } });
312 OUString CasePreservingURL = xRow->getString(1);
313 if(!xRow->wasNull())
314 aAny <<= CasePreservingURL;
315 }
316 else if ( aCommand.Name == "createNewContent" )
317 {
318 ucb::ContentInfo aArg;
319 if ( !( aCommand.Argument >>= aArg ) )
320 m_pMyShell->installError( CommandId,
322 else
323 aAny <<= createNewContent( aArg );
324 }
325 else
326 m_pMyShell->installError( CommandId,
328
329
330 // This is the only function allowed to throw an exception
331 endTask( CommandId );
332
333 return aAny;
334}
335
336
337void SAL_CALL
339 const Sequence< OUString >& PropertyNames,
341{
342 if( ! Listener.is() )
343 return;
344
345 std::unique_lock aGuard( m_aMutex );
346
347 if( ! m_pPropertyListener )
349
350
351 if( !PropertyNames.hasElements() )
352 m_pPropertyListener->addInterface( aGuard, OUString(),Listener );
353 else
354 {
356 for( const auto& rName : PropertyNames )
357 if( xProp->hasPropertyByName( rName ) )
358 m_pPropertyListener->addInterface( aGuard, rName,Listener );
359 }
360}
361
362
363void SAL_CALL
366{
367 if( ! Listener.is() )
368 return;
369
370 std::unique_lock aGuard( m_aMutex );
371
372 if( ! m_pPropertyListener )
373 return;
374
375 for( const auto& rName : PropertyNames )
376 m_pPropertyListener->removeInterface( aGuard, rName,Listener );
377
378 m_pPropertyListener->removeInterface( aGuard, OUString(), Listener );
379}
380
381
382// XContent
383
384
387{
389}
390
391
392OUString SAL_CALL
394{
395 if( !( m_nState & Deleted ) )
396 {
397 if( m_nState & JustInserted )
398 {
399 if ( m_bFolder )
401 else
403 }
404 else
405 {
406 try
407 {
408 // Who am I ?
409 Reference< sdbc::XRow > xRow = getPropertyValues( -1, { { "IsDocument", -1, cppu::UnoType<sal_Bool>::get(), 0 } });
410 bool IsDocument = xRow->getBoolean( 1 );
411
412 if ( !xRow->wasNull() )
413 {
414 if ( IsDocument )
416 else
418 }
419 else
420 {
421 OSL_FAIL( "BaseContent::getContentType - Property value was null!" );
422 }
423 }
424 catch (const sdbc::SQLException&)
425 {
426 TOOLS_WARN_EXCEPTION("ucb.ucp.file", "");
427 }
428 }
429 }
430
431 return OUString();
432}
433
434
435void SAL_CALL
437 const Reference< XContentEventListener >& Listener )
438{
439 std::unique_lock aGuard( m_aMutex );
440
441 m_aContentEventListeners.addInterface( aGuard, Listener );
442}
443
444
445void SAL_CALL
447 const Reference< XContentEventListener >& Listener )
448{
449 std::unique_lock aGuard( m_aMutex );
450
451 m_aContentEventListeners.removeInterface( aGuard, Listener );
452}
453
454
455// XPropertyContainer
456
457
458void SAL_CALL
460 const OUString& Name,
461 sal_Int16 Attributes,
462 const Any& DefaultValue )
463{
464 if( ( m_nState & JustInserted ) || ( m_nState & Deleted ) || Name.isEmpty() )
465 {
466 throw lang::IllegalArgumentException( THROW_WHERE, uno::Reference< uno::XInterface >(), 0 );
467 }
468
469 m_pMyShell->associate( m_aUncPath,Name,DefaultValue,Attributes );
470}
471
472
473void SAL_CALL
474BaseContent::removeProperty( const OUString& Name )
475{
476
477 if( m_nState & Deleted )
478 throw beans::UnknownPropertyException( Name );
479
481}
482
483
484// XContentCreator
485
486
489{
491}
492
493
496{
497 // Check type.
498 if ( Info.Type.isEmpty() )
499 return Reference< XContent >();
500
501 bool bFolder = Info.Type == TaskManager::FolderContentType;
502 if ( !bFolder )
503 {
505 {
506 // Neither folder nor file to create!
507 return Reference< XContent >();
508 }
509 }
510
511 // Who am I ?
512 bool IsDocument = false;
513
514 try
515 {
516 Reference< sdbc::XRow > xRow = getPropertyValues( -1, { { "IsDocument", -1, cppu::UnoType<sal_Bool>::get(), 0 } });
517 IsDocument = xRow->getBoolean( 1 );
518
519 if ( xRow->wasNull() )
520 {
521 IsDocument = false;
522// OSL_FAIL( // "BaseContent::createNewContent - Property value was null!" );
523// return Reference< XContent >();
524 }
525 }
526 catch (const sdbc::SQLException&)
527 {
528 TOOLS_WARN_EXCEPTION("ucb.ucp.file", "");
529 return Reference< XContent >();
530 }
531
532 OUString dstUncPath;
533
534 if( IsDocument )
535 {
536 // KSO: Why is a document a XContentCreator? This is quite unusual.
537 dstUncPath = getParentName( m_aUncPath );
538 }
539 else
540 dstUncPath = m_aUncPath;
541
542 return new BaseContent( m_pMyShell, dstUncPath, bFolder );
543}
544
545
546// XPropertySetInfoChangeNotifier
547
548
549void SAL_CALL
552{
553 std::unique_lock aGuard( m_aMutex );
554
556}
557
558
559void SAL_CALL
562{
563 std::unique_lock aGuard( m_aMutex );
564
566}
567
568
569// XChild
570
571
574{
575 OUString ParentUnq = getParentName( m_aUncPath );
576 OUString ParentUrl;
577
578
579 bool err = fileaccess::TaskManager::getUrlFromUnq( ParentUnq, ParentUrl );
580 if( err )
581 return Reference< XInterface >( nullptr );
582
584
585 try
586 {
588 }
589 catch (const IllegalIdentifierException&)
590 {
592 }
593}
594
595
596void SAL_CALL
599{
600 throw lang::NoSupportException( THROW_WHERE );
601}
602
603
604// Private Methods
605
606
609{
610 if( m_nState & Deleted )
612
613 return m_pMyShell->info_c();
614}
615
616
619{
620 if( m_nState & Deleted )
622
623 return m_pMyShell->info_p( m_aUncPath );
624}
625
628 sal_Int32 nMyCommandIdentifier,
629 const Sequence< beans::Property >& PropertySet )
630{
631 sal_Int32 nProps = PropertySet.getLength();
632 if ( !nProps )
634
635 if( m_nState & Deleted )
636 {
637 Sequence< Any > aValues( nProps );
638 return Reference< sdbc::XRow >( new XRow_impl( m_pMyShell, aValues ) );
639 }
640
641 if( m_nState & JustInserted )
642 {
643 Sequence< Any > aValues( nProps );
644 Any* pValues = aValues.getArray();
645
646 const beans::Property* pProps = PropertySet.getConstArray();
647
648 for ( sal_Int32 n = 0; n < nProps; ++n )
649 {
650 const beans::Property& rProp = pProps[ n ];
651 Any& rValue = pValues[ n ];
652
653 if ( rProp.Name == "ContentType" )
654 {
655 rValue <<= (m_bFolder ? OUString(TaskManager::FolderContentType)
656 : OUString(TaskManager::FileContentType));
657 }
658 else if ( rProp.Name == "IsFolder" )
659 {
660 rValue <<= m_bFolder;
661 }
662 else if ( rProp.Name == "IsDocument" )
663 {
664 rValue <<= !m_bFolder;
665 }
666 }
667
669 new XRow_impl( m_pMyShell, aValues ) );
670 }
671
672 return m_pMyShell->getv( nMyCommandIdentifier,
674 PropertySet );
675}
676
677
680 sal_Int32 nMyCommandIdentifier,
682{
683 if( m_nState & Deleted )
684 { // To do
685 return Sequence< Any >( Values.getLength() );
686 }
687
688 static constexpr OUStringLiteral Title(u"Title");
689
690 // Special handling for files which have to be inserted
691 if( m_nState & JustInserted )
692 {
693 for( const auto& rValue : Values )
694 {
695 if( rValue.Name == Title )
696 {
697 OUString NewTitle;
698 if( rValue.Value >>= NewTitle )
699 {
701 {
702 // User wants to set another Title before "insert".
703 // m_aUncPath contains previous own URI.
704
705 sal_Int32 nLastSlash = m_aUncPath.lastIndexOf( '/' );
706 bool bTrailingSlash = false;
707 if ( nLastSlash == m_aUncPath.getLength() - 1 )
708 {
709 bTrailingSlash = true;
710 nLastSlash
711 = m_aUncPath.lastIndexOf( '/', nLastSlash );
712 }
713
714 OSL_ENSURE( nLastSlash != -1,
715 "BaseContent::setPropertyValues: "
716 "Invalid URL!" );
717
718 OUStringBuffer aBuf(
719 m_aUncPath.subView( 0, nLastSlash + 1 ) );
720
721 if ( !NewTitle.isEmpty() )
722 {
723 aBuf.append( NewTitle );
724 if ( bTrailingSlash )
725 aBuf.append( '/' );
726 }
727 else
728 {
729 m_nState &= ~NameForInsertionSet;
730 }
731
732 m_aUncPath = aBuf.makeStringAndClear();
733 }
734 else
735 {
736 if ( !NewTitle.isEmpty() )
737 {
738 // Initial Title before "insert".
739 // m_aUncPath contains parent's URI.
740
741 if( !m_aUncPath.endsWith( "/" ) )
742 m_aUncPath += "/";
743
744 m_aUncPath += rtl::Uri::encode( NewTitle,
745 rtl_UriCharClassPchar,
746 rtl_UriEncodeIgnoreEscapes,
747 RTL_TEXTENCODING_UTF8 );
749 }
750 }
751 }
752 }
753 }
754
755 return Sequence< Any >( Values.getLength() );
756 }
757 else
758 {
759 Sequence< Any > ret = m_pMyShell->setv( m_aUncPath, // Does not handle Title
760 Values );
761 auto retRange = asNonConstRange(ret);
762
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 )
765 {
766 if( Values[i].Name != Title )
767 continue; // handled by setv
768
769 OUString NewTitle;
770 if( !( Values[i].Value >>= NewTitle ) )
771 {
772 retRange[i] <<= beans::IllegalTypeException( THROW_WHERE );
773 break;
774 }
775 else if( NewTitle.isEmpty() )
776 {
777 retRange[i] <<= lang::IllegalArgumentException( THROW_WHERE, uno::Reference< uno::XInterface >(), 0 );
778 break;
779 }
780
781
782 OUString aDstName = getParentName( m_aUncPath );
783 if( !aDstName.endsWith("/") )
784 aDstName += "/";
785
786 aDstName += rtl::Uri::encode( NewTitle,
787 rtl_UriCharClassPchar,
788 rtl_UriEncodeIgnoreEscapes,
789 RTL_TEXTENCODING_UTF8 );
790
791 m_pMyShell->move( nMyCommandIdentifier, // move notifies the children also;
793 aDstName,
794 NameClash::KEEP );
795
796 try
797 {
798 endTask( nMyCommandIdentifier );
799 }
800 catch(const Exception& e)
801 {
802 retRange[i] <<= e;
803 }
804
805 // NameChanges come back through a ContentEvent
806 break; // only handling Title
807 } // end for
808
809 return ret;
810 }
811}
812
813
816 sal_Int32 nMyCommandIdentifier,
817 const OpenCommandArgument2& aCommandArgument )
818{
820
821 if( m_nState & Deleted )
822 {
823 m_pMyShell->installError( nMyCommandIdentifier,
825 }
826 else if( m_nState & JustInserted )
827 {
828 m_pMyShell->installError( nMyCommandIdentifier,
830 }
831 else
832 {
833 if( aCommandArgument.Mode == OpenMode::DOCUMENT ||
834 aCommandArgument.Mode == OpenMode::DOCUMENT_SHARE_DENY_NONE )
835
836 {
837 Reference< io::XOutputStream > outputStream( aCommandArgument.Sink,UNO_QUERY );
838 if( outputStream.is() )
839 {
840 m_pMyShell->page( nMyCommandIdentifier,
842 outputStream );
843 }
844
845 bool bLock = ( aCommandArgument.Mode != OpenMode::DOCUMENT_SHARE_DENY_NONE );
846
847 Reference< io::XActiveDataSink > activeDataSink( aCommandArgument.Sink,UNO_QUERY );
848 if( activeDataSink.is() )
849 {
850 activeDataSink->setInputStream( m_pMyShell->open( nMyCommandIdentifier,
852 bLock ) );
853 }
854
855 Reference< io::XActiveDataStreamer > activeDataStreamer( aCommandArgument.Sink,UNO_QUERY );
856 if( activeDataStreamer.is() )
857 {
858 activeDataStreamer->setStream( m_pMyShell->open_rw( nMyCommandIdentifier,
860 bLock ) );
861 }
862 }
863 else if ( aCommandArgument.Mode == OpenMode::ALL ||
864 aCommandArgument.Mode == OpenMode::FOLDERS ||
865 aCommandArgument.Mode == OpenMode::DOCUMENTS )
866 {
867 retValue = m_pMyShell->ls( nMyCommandIdentifier,
869 aCommandArgument.Mode,
870 aCommandArgument.Properties,
871 aCommandArgument.SortingInfo );
872 }
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);
880 else
881 m_pMyShell->installError( nMyCommandIdentifier,
883 aCommandArgument.Mode);
884 }
885
886 return retValue;
887}
888
889
890void
891BaseContent::deleteContent( sal_Int32 nMyCommandIdentifier )
892{
893 if( m_nState & Deleted )
894 return;
895
896 if( m_pMyShell->remove( nMyCommandIdentifier,m_aUncPath ) )
897 {
898 std::unique_lock aGuard( m_aMutex );
899 m_nState |= Deleted;
900 }
901}
902
903
904void
905BaseContent::transfer( sal_Int32 nMyCommandIdentifier,
906 const TransferInfo& aTransferInfo )
907{
908 if( m_nState & Deleted )
909 return;
910
911 if( !comphelper::isFileUrl(aTransferInfo.SourceURL) )
912 {
913 m_pMyShell->installError( nMyCommandIdentifier,
915 return;
916 }
917
918 OUString srcUnc;
919 if( fileaccess::TaskManager::getUnqFromUrl( aTransferInfo.SourceURL,srcUnc ) )
920 {
921 m_pMyShell->installError( nMyCommandIdentifier,
923 return;
924 }
925
926 OUString srcUncPath = srcUnc;
927
928 // Determine the new title !
929 OUString NewTitle;
930 if( !aTransferInfo.NewTitle.isEmpty() )
931 NewTitle = rtl::Uri::encode( aTransferInfo.NewTitle,
932 rtl_UriCharClassPchar,
933 rtl_UriEncodeIgnoreEscapes,
934 RTL_TEXTENCODING_UTF8 );
935 else
936 NewTitle = srcUncPath.copy( 1 + srcUncPath.lastIndexOf( '/' ) );
937
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,
945 return;
946 }
947
948 OUString dstUncPath;
949 if( IsDocument )
950 { // as sibling
951 sal_Int32 lastSlash = m_aUncPath.lastIndexOf( '/' );
952 dstUncPath = m_aUncPath.copy(0,lastSlash );
953 }
954 else
955 // as child
956 dstUncPath = m_aUncPath;
957
958 dstUncPath += "/" + NewTitle;
959
960 sal_Int32 NameClash = aTransferInfo.NameClash;
961
962 if( aTransferInfo.MoveData )
963 m_pMyShell->move( nMyCommandIdentifier,srcUncPath,dstUncPath,NameClash );
964 else
965 m_pMyShell->copy( nMyCommandIdentifier,srcUncPath,dstUncPath,NameClash );
966}
967
968
969void BaseContent::insert( sal_Int32 nMyCommandIdentifier,
970 const InsertCommandArgument& aInsertArgument )
971{
972 if( m_nState & FullFeatured )
973 {
974 m_pMyShell->write( nMyCommandIdentifier,
976 aInsertArgument.ReplaceExisting,
977 aInsertArgument.Data );
978 return;
979 }
980
981 if( ! ( m_nState & JustInserted ) )
982 {
983 m_pMyShell->installError( nMyCommandIdentifier,
985 return;
986 }
987
988 // Inserts the content, which has the flag m_bIsFresh
989
990 if( ! (m_nState & NameForInsertionSet) )
991 {
992 m_pMyShell->installError( nMyCommandIdentifier,
994 return;
995 }
996
997 // Inserting a document or a file?
998 bool bDocument = false;
999
1000 Reference< sdbc::XRow > xRow = getPropertyValues( -1, { { "IsDocument", -1, cppu::UnoType<sal_Bool>::get(), 0 } });
1001
1002 bool contentTypeSet = true; // is set to false, if contentType not set
1003 try
1004 {
1005 bDocument = xRow->getBoolean( 1 );
1006 if( xRow->wasNull() )
1007 contentTypeSet = false;
1008
1009 }
1010 catch (const sdbc::SQLException&)
1011 {
1012 TOOLS_WARN_EXCEPTION("ucb.ucp.file", "");
1013 contentTypeSet = false;
1014 }
1015
1016 if( ! contentTypeSet )
1017 {
1018 m_pMyShell->installError( nMyCommandIdentifier,
1020 return;
1021 }
1022
1023
1024 bool success = false;
1025 if( bDocument )
1026 success = m_pMyShell->mkfil( nMyCommandIdentifier,
1027 m_aUncPath,
1028 aInsertArgument.ReplaceExisting,
1029 aInsertArgument.Data );
1030 else
1031 {
1032 while( ! success )
1033 {
1034 success = m_pMyShell->mkdir( nMyCommandIdentifier,
1035 m_aUncPath,
1036 aInsertArgument.ReplaceExisting );
1037 if( success )
1038 break;
1039
1040 XInteractionRequestImpl aRequestImpl(
1041 rtl::Uri::decode(
1042 OUString(getTitle(m_aUncPath)),
1043 rtl_UriDecodeWithCharset,
1044 RTL_TEXTENCODING_UTF8),
1045 getXWeak(),
1046 m_pMyShell,nMyCommandIdentifier);
1047 uno::Reference<task::XInteractionRequest> const& xReq(aRequestImpl.getRequest());
1048
1049 m_pMyShell->handleTask( nMyCommandIdentifier, xReq );
1050 if (aRequestImpl.aborted() || aRequestImpl.newName().isEmpty())
1051 // means aborting
1052 break;
1053
1054 // determine new uncpath
1055 m_pMyShell->clearError( nMyCommandIdentifier );
1057 if( !m_aUncPath.endsWith( "/" ) )
1058 m_aUncPath += "/";
1059
1060 m_aUncPath += rtl::Uri::encode( aRequestImpl.newName(),
1061 rtl_UriCharClassPchar,
1062 rtl_UriEncodeIgnoreEscapes,
1063 RTL_TEXTENCODING_UTF8 );
1064 }
1065 }
1066
1067 if ( ! success )
1068 return;
1069
1071
1074
1075 std::unique_lock aGuard( m_aMutex );
1077}
1078
1079
1080void BaseContent::endTask( sal_Int32 CommandId )
1081{
1082 // This is the only function allowed to throw an exception
1083 m_pMyShell->endTask( CommandId,m_aUncPath,this );
1084}
1085
1086
1087std::optional<ContentEventNotifier>
1089{
1090 std::unique_lock aGuard( m_aMutex );
1091
1092 m_nState |= Deleted;
1093
1094 if( m_aContentEventListeners.getLength(aGuard) == 0 )
1095 return {};
1096
1098 this,
1101}
1102
1103
1104std::optional<ContentEventNotifier>
1105BaseContent::cEXC( const OUString& aNewName )
1106{
1107 std::unique_lock aGuard( m_aMutex );
1108
1110 m_aUncPath = aNewName;
1112
1113 if( m_aContentEventListeners.getLength(aGuard) == 0 )
1114 return {};
1116 this,
1118 xOldRef,
1120}
1121
1122
1123std::optional<ContentEventNotifier>
1125{
1126 std::unique_lock aGuard( m_aMutex );
1127 if( m_aContentEventListeners.getLength(aGuard) == 0 )
1128 return {};
1130 this,
1133}
1134
1135std::optional<PropertySetInfoChangeNotifier>
1137{
1138 std::unique_lock aGuard( m_aMutex );
1140 return {};
1142}
1143
1144
1145std::optional<PropertyChangeNotifier>
1147{
1148 std::unique_lock aGuard( m_aMutex );
1149
1151 return {};
1152
1153 const std::vector< OUString > seqNames = m_pPropertyListener->getContainedTypes(aGuard);
1154 if( seqNames.empty() )
1155 return {};
1156
1157 ListenerMap listener;
1158 for( const auto& rName : seqNames )
1159 {
1161 if (!pContainer)
1162 continue;
1163 listener[rName] = pContainer->getElements(aGuard);
1164 }
1165
1166 return PropertyChangeNotifier( this, std::move(listener) );
1167}
1168
1169
1170/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const PropertyValue * pValues
#define THROW_WHERE
Definition: bc.cxx:51
std::vector< css::uno::Reference< ListenerT > > getElements(std::unique_lock< std::mutex > &rGuard) const
sal_Int32 addInterface(std::unique_lock< std::mutex > &rGuard, const css::uno::Reference< ListenerT > &rxIFace)
void disposeAndClear(::std::unique_lock<::std::mutex > &rGuard, const css::lang::EventObject &rEvt)
sal_Int32 getLength(std::unique_lock< std::mutex > &rGuard) const
sal_Int32 removeInterface(std::unique_lock< std::mutex > &rGuard, const css::uno::Reference< ListenerT > &rxIFace)
css::uno::Type const & get()
std::unique_ptr< PropertyListeners > m_pPropertyListener
Definition: bc.hxx:210
void endTask(sal_Int32 CommandId)
Definition: bc.cxx:1080
OUString m_aUncPath
Definition: bc.hxx:197
css::uno::Reference< css::ucb::XDynamicResultSet > open(sal_Int32 nMyCommandIdentifier, const css::ucb::OpenCommandArgument2 &aCommandArgument)
Definition: bc.cxx:815
virtual void SAL_CALL removePropertySetInfoChangeListener(const css::uno::Reference< css::beans::XPropertySetInfoChangeListener > &Listener) override
Definition: bc.cxx:560
virtual css::uno::Any SAL_CALL execute(const css::ucb::Command &aCommand, sal_Int32 CommandId, const css::uno::Reference< css::ucb::XCommandEnvironment > &Environment) override
Definition: bc.cxx:228
void deleteContent(sal_Int32 nMyCommandIdentifier)
Definition: bc.cxx:891
virtual void SAL_CALL removeEventListener(const css::uno::Reference< css::lang::XEventListener > &aListener) override
Definition: bc.cxx:164
virtual css::uno::Reference< css::ucb::XContent > SAL_CALL createNewContent(const css::ucb::ContentInfo &Info) override
Definition: bc.cxx:495
std::mutex m_aMutex
Definition: bc.hxx:206
virtual void SAL_CALL addEventListener(const css::uno::Reference< css::lang::XEventListener > &xListener) override
Definition: bc.cxx:155
css::uno::Sequence< css::uno::Any > setPropertyValues(sal_Int32 nMyCommandIdentifier, const css::uno::Sequence< css::beans::PropertyValue > &Values)
Definition: bc.cxx:679
std::optional< PropertySetInfoChangeNotifier > cPSL() override
Definition: bc.cxx:1136
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
Definition: bc.cxx:205
comphelper::OInterfaceContainerHelper4< css::ucb::XContentEventListener > m_aContentEventListeners
Definition: bc.hxx:208
void insert(sal_Int32 nMyCommandIdentifier, const css::ucb::InsertCommandArgument &aInsertArgument)
Definition: bc.cxx:969
BaseContent(TaskManager *pMyShell, OUString parentName, bool bFolder)
Definition: bc.cxx:111
virtual css::uno::Reference< css::ucb::XContentIdentifier > SAL_CALL getIdentifier() override
Definition: bc.cxx:386
virtual void SAL_CALL removePropertiesChangeListener(const css::uno::Sequence< OUString > &PropertyNames, const css::uno::Reference< css::beans::XPropertiesChangeListener > &Listener) override
Definition: bc.cxx:364
comphelper::OInterfaceContainerHelper4< css::lang::XEventListener > m_aDisposeEventListeners
Definition: bc.hxx:207
virtual OUString SAL_CALL getImplementationName() override
Definition: bc.cxx:193
virtual void SAL_CALL addContentEventListener(const css::uno::Reference< css::ucb::XContentEventListener > &Listener) override
Definition: bc.cxx:436
virtual ~BaseContent() override
Definition: bc.cxx:141
virtual sal_Bool SAL_CALL supportsService(const OUString &ServiceName) override
Definition: bc.cxx:199
virtual sal_Int32 SAL_CALL createCommandIdentifier() override
Definition: bc.cxx:215
virtual void SAL_CALL abort(sal_Int32 CommandId) override
Definition: bc.cxx:222
std::optional< ContentEventNotifier > cCEL() override
Definition: bc.cxx:1124
std::optional< PropertyChangeNotifier > cPCL() override
Definition: bc.cxx:1146
css::uno::Reference< css::ucb::XCommandInfo > getCommandInfo()
Definition: bc.cxx:608
comphelper::OInterfaceContainerHelper4< css::beans::XPropertySetInfoChangeListener > m_aPropertySetInfoChangeListeners
Definition: bc.hxx:209
std::optional< ContentEventNotifier > cEXC(const OUString &aNewName) override
Definition: bc.cxx:1105
virtual void SAL_CALL addProperty(const OUString &Name, sal_Int16 Attributes, const css::uno::Any &DefaultValue) override
Definition: bc.cxx:459
std::optional< ContentEventNotifier > cDEL() override
Definition: bc.cxx:1088
virtual void SAL_CALL removeProperty(const OUString &Name) override
Definition: bc.cxx:474
friend class ContentEventNotifier
Definition: bc.hxx:252
virtual void SAL_CALL addPropertySetInfoChangeListener(const css::uno::Reference< css::beans::XPropertySetInfoChangeListener > &Listener) override
Definition: bc.cxx:550
virtual css::uno::Sequence< css::ucb::ContentInfo > SAL_CALL queryCreatableContentsInfo() override
Definition: bc.cxx:488
virtual void SAL_CALL setParent(const css::uno::Reference< css::uno::XInterface > &Parent) override
Definition: bc.cxx:597
sal_uInt16 m_nState
Definition: bc.hxx:204
virtual void SAL_CALL dispose() override
Definition: bc.cxx:173
void transfer(sal_Int32 nMyCommandIdentifier, const css::ucb::TransferInfo &aTransferInfo)
Definition: bc.cxx:905
css::uno::Reference< css::sdbc::XRow > getPropertyValues(sal_Int32 nMyCommandIdentifier, const css::uno::Sequence< css::beans::Property > &PropertySet)
Definition: bc.cxx:627
virtual void SAL_CALL removeContentEventListener(const css::uno::Reference< css::ucb::XContentEventListener > &Listener) override
Definition: bc.cxx:446
virtual OUString SAL_CALL getContentType() override
Definition: bc.cxx:393
TaskManager * m_pMyShell
Definition: bc.hxx:195
virtual void SAL_CALL addPropertiesChangeListener(const css::uno::Sequence< OUString > &PropertyNames, const css::uno::Reference< css::beans::XPropertiesChangeListener > &Listener) override
Definition: bc.cxx:338
virtual css::uno::Reference< css::uno::XInterface > SAL_CALL getParent() override
Definition: bc.cxx:573
css::uno::Reference< css::ucb::XContentIdentifier > m_xContentIdentifier
Definition: bc.hxx:196
css::uno::Reference< css::beans::XPropertySetInfo > getPropertySetInfo()
Definition: bc.cxx:618
virtual css::uno::Reference< css::ucb::XContent > SAL_CALL queryContent(const css::uno::Reference< css::ucb::XContentIdentifier > &Identifier) override
Definition: prov.cxx:112
void addInterface(std::unique_lock< std::mutex > &rGuard, const OUString &rKey, const uno::Reference< beans::XPropertiesChangeListener > &rListener)
Definition: bc.cxx:69
std::unordered_map< OUString, ContainerHelper > m_aMap
Definition: bc.cxx:59
void disposeAndClear(std::unique_lock< std::mutex > &rGuard, const lang::EventObject &rEvt)
Definition: bc.cxx:62
comphelper::OInterfaceContainerHelper4< beans::XPropertiesChangeListener > ContainerHelper
Definition: bc.cxx:58
void removeInterface(std::unique_lock< std::mutex > &rGuard, const OUString &rKey, const uno::Reference< beans::XPropertiesChangeListener > &rListener)
Definition: bc.cxx:73
std::vector< OUString > getContainedTypes(std::unique_lock< std::mutex > &rGuard) const
Definition: bc.cxx:81
comphelper::OInterfaceContainerHelper4< beans::XPropertiesChangeListener > * getContainer(std::unique_lock< std::mutex > &, const OUString &rKey)
Definition: bc.cxx:92
static css::uno::Sequence< css::ucb::ContentInfo > queryCreatableContentsInfo()
Definition: filtask.cxx:2912
bool mkdir(sal_Int32 CommandId, const OUString &aDirectoryName, bool OverWrite)
Creates new directory with given URL, recursively if necessary Return:: success of operation.
Definition: filtask.cxx:1675
void endTask(sal_Int32 CommandId, const OUString &aUnqPath, BaseContent *pContent)
Deinstalls the task and evaluates a possibly set error code.
Definition: filtask.cxx:382
css::uno::Sequence< css::uno::Any > setv(const OUString &aUnqPath, const css::uno::Sequence< css::beans::PropertyValue > &values)
Sets the values of the properties belonging to fileURL aUnqPath.
Definition: filtask.cxx:836
bool write(sal_Int32 CommandId, const OUString &aUnqPath, bool OverWrite, const css::uno::Reference< css::io::XInputStream > &aInputStream)
writes to the file with given URL.
Definition: filtask.cxx:1766
void registerNotifier(const OUString &aUnqPath, Notifier *pNotifier)
This two methods register and deregister a change listener for the content belonging to URL aUnqPath.
Definition: filtask.cxx:483
css::uno::Reference< css::ucb::XDynamicResultSet > ls(sal_Int32 CommandId, const OUString &aUnqPath, const sal_Int32 OpenMode, const css::uno::Sequence< css::beans::Property > &sProperty, const css::uno::Sequence< css::ucb::NumberedSortingInfo > &sSortingInfo)
This method returns the result set containing the children of the directory belonging to file URL aUn...
Definition: filtask.cxx:774
sal_Int32 getCommandId()
Definition: filtask.cxx:448
static constexpr OUStringLiteral FolderContentType
Definition: filtask.hxx:627
FileProvider * m_pProvider
Definition: filtask.hxx:477
void installError(sal_Int32 CommandId, sal_Int32 ErrorCode, sal_Int32 minorCode=TASKHANDLER_NO_ERROR)
The error code may be one of the error codes defined in filerror.hxx.
Definition: filtask.cxx:436
bool mkfil(sal_Int32 CommandId, const OUString &aFileName, bool OverWrite, const css::uno::Reference< css::io::XInputStream > &aInputStream)
Creates new file with given URL.
Definition: filtask.cxx:1735
void deregisterNotifier(const OUString &aUnqPath, Notifier *pNotifier)
Definition: filtask.cxx:502
void handleTask(sal_Int32 CommandId, const css::uno::Reference< css::task::XInteractionRequest > &request)
Handles an interactionrequest.
Definition: filtask.cxx:455
static bool getUnqFromUrl(const OUString &Url, OUString &Unq)
Definition: filtask.cxx:1960
static bool getUrlFromUnq(const OUString &Unq, OUString &Url)
Definition: filtask.cxx:1981
css::uno::Reference< css::beans::XPropertySetInfo > info_p(const OUString &aUnqPath)
Definition: filtask.cxx:819
css::uno::Reference< css::io::XStream > open_rw(sal_Int32 CommandId, const OUString &aUnqPath, bool bLock)
Given a file URL aUnqPath, this methods returns a XStream which can be used to read and write from/to...
Definition: filtask.cxx:743
void startTask(sal_Int32 CommandId, const css::uno::Reference< css::ucb::XCommandEnvironment > &xCommandEnv)
Definition: filtask.cxx:367
void clearError(sal_Int32)
Clears any error which are set on the commandid.
Definition: filtask.cxx:413
css::uno::Reference< css::io::XInputStream > open(sal_Int32 CommandId, const OUString &aUnqPath, bool bLock)
Given a file URL aUnqPath, this methods returns a XInputStream which reads from the open file.
Definition: filtask.cxx:711
void insertDefaultProperties(const OUString &aUnqPath)
Definition: filtask.cxx:1925
bool remove(sal_Int32 CommandId, const OUString &aUnqPath, FileUrlType eTypeToMove=FileUrlType::Unknown, bool MustExist=true)
Deletes the content belonging to fileURL aUnqPath( recursively in case of directory )
Definition: filtask.cxx:1513
void move(sal_Int32 CommandId, const OUString &srcUnqPath, const OUString &dstUnqPath, const sal_Int32 NameClash)
Moves the content belonging to fileURL srcUnqPath to fileURL dstUnqPath( files and directories )
Definition: filtask.cxx:1133
void copy(sal_Int32 CommandId, const OUString &srcUnqPath, const OUString &dstUnqPath, sal_Int32 NameClash)
Copies the content belonging to fileURL srcUnqPath to fileURL dstUnqPath ( files and directories )
Definition: filtask.cxx:1341
void deassociate(const OUString &UnqPath, const OUString &PropertyName)
Definition: filtask.cxx:568
css::uno::Reference< css::ucb::XCommandInfo > info_c()
Info methods.
Definition: filtask.cxx:805
void page(sal_Int32 CommandId, const OUString &aUnqPath, const css::uno::Reference< css::io::XOutputStream > &xOutputStream)
Given an xOutputStream, this method writes the content of the file belonging to URL aUnqPath into the...
Definition: filtask.cxx:622
css::uno::Reference< css::sdbc::XRow > getv(sal_Int32 CommandId, const OUString &aUnqPath, const css::uno::Sequence< css::beans::Property > &properties)
Reads the values of the properties belonging to fileURL aUnqPath; Returns an XRow object containing t...
static constexpr OUStringLiteral FileContentType
Definition: filtask.hxx:629
void associate(const OUString &UnqPath, const OUString &PropertyName, const css::uno::Any &DefaultValue, const sal_Int16 Attributes)
Used to associate and deassociate a new property with the content belonging to URL UnqPath.
Definition: filtask.cxx:529
css::uno::Reference< css::task::XInteractionRequest > const & getRequest() const
Definition: filinsreq.hxx:124
#define TOOLS_WARN_EXCEPTION(area, stream)
float u
#define TASKHANDLING_TRANSFER_INVALIDURL
Definition: filerror.hxx:81
#define TASKHANDLING_UNSUPPORTED_OPEN_MODE
Definition: filerror.hxx:35
#define TASKHANDLING_WRONG_OPEN_ARGUMENT
Definition: filerror.hxx:30
#define TASKHANDLING_WRONG_GETPROPERTYVALUES_ARGUMENT
Definition: filerror.hxx:29
#define TASKHANDLING_WRONG_SETPROPERTYVALUES_ARGUMENT
Definition: filerror.hxx:28
#define TASKHANDLING_WRONG_DELETE_ARGUMENT
Definition: filerror.hxx:31
#define TASKHANDLING_WRONG_TRANSFER_ARGUMENT
Definition: filerror.hxx:32
#define TASKHANDLING_NONAMESET_INSERT_COMMAND
Definition: filerror.hxx:51
#define TASKHANDLING_WRONG_INSERT_ARGUMENT
Definition: filerror.hxx:33
#define TASKHANDLING_DELETED_STATE_IN_OPEN_COMMAND
Definition: filerror.hxx:37
#define TASKHANDLER_UNSUPPORTED_COMMAND
Definition: filerror.hxx:27
#define TASKHANDLING_NOFRESHINSERT_IN_INSERT_COMMAND
Definition: filerror.hxx:50
#define TASKHANDLING_NOCONTENTTYPE_INSERT_COMMAND
Definition: filerror.hxx:52
#define TASKHANDLING_TRANSFER_INVALIDSCHEME
Definition: filerror.hxx:80
#define TASKHANDLING_INSERTED_STATE_IN_OPEN_COMMAND
Definition: filerror.hxx:38
#define TASKHANDLING_TRANSFER_DESTFILETYPE
Definition: filerror.hxx:82
#define TASKHANDLING_WRONG_CREATENEWCONTENT_ARGUMENT
Definition: filerror.hxx:34
constexpr OUStringLiteral IsDocument(u"IsDocument")
constexpr OUStringLiteral CasePreservingURL(u"CasePreservingURL")
sal_Int64 n
aBuf
err
@ Exception
COMPHELPER_DLLPUBLIC bool isFileUrl(std::u16string_view url)
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
Info
OUString getParentName(std::u16string_view aFileName)
Definition: filglob.cxx:194
std::unordered_map< OUString, std::vector< css::uno::Reference< css::beans::XPropertiesChangeListener > > > ListenerMap
Definition: filnot.hxx:81
std::u16string_view getTitle(std::u16string_view aPath)
Definition: filglob.cxx:187
Value
int i
Title
OUString aCommand
OUString Name
unsigned char sal_Bool
Any result