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 <sal/config.h>
24 #include <o3tl/unreachable.hxx>
25 #include <osl/diagnose.h>
27 #include <sal/log.hxx>
28 #include <salhelper/simplereferenceobject.hxx>
29 #include <cppuhelper/weak.hxx>
30 #include <cppuhelper/queryinterface.hxx>
32 #include <cppuhelper/implbase.hxx>
33 #include <com/sun/star/ucb/CheckinArgument.hpp>
34 #include <com/sun/star/ucb/ContentCreationError.hpp>
35 #include <com/sun/star/ucb/ContentCreationException.hpp>
36 #include <com/sun/star/ucb/IllegalIdentifierException.hpp>
37 #include <com/sun/star/ucb/XCommandInfo.hpp>
38 #include <com/sun/star/ucb/XCommandProcessor.hpp>
39 #include <com/sun/star/ucb/Command.hpp>
40 #include <com/sun/star/ucb/ContentAction.hpp>
41 #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
42 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
43 #include <com/sun/star/ucb/GlobalTransferCommandArgument2.hpp>
44 #include <com/sun/star/ucb/OpenMode.hpp>
45 #include <com/sun/star/ucb/XContentCreator.hpp>
46 #include <com/sun/star/ucb/XContentEventListener.hpp>
47 #include <com/sun/star/ucb/XDynamicResultSet.hpp>
48 #include <com/sun/star/ucb/SortedDynamicResultSetFactory.hpp>
49 #include <com/sun/star/ucb/UniversalContentBroker.hpp>
50 #include <com/sun/star/ucb/XUniversalContentBroker.hpp>
51 #include <com/sun/star/beans/XPropertySetInfo.hpp>
52 #include <com/sun/star/beans/Property.hpp>
53 #include <com/sun/star/beans/PropertyValue.hpp>
54 #include <com/sun/star/sdbc/XRow.hpp>
55 #include <com/sun/star/lang/IllegalArgumentException.hpp>
56 #include <com/sun/star/beans/UnknownPropertyException.hpp>
57 #include <ucbhelper/content.hxx>
58 #include <ucbhelper/activedatasink.hxx>
59 #include "activedatastreamer.hxx"
60 #include <ucbhelper/cancelcommandexecution.hxx>
62 namespace com::sun::star::ucb
{ class XCommandEnvironment
; }
63 namespace com::sun::star::ucb
{ class XContentProvider
; }
64 namespace com::sun::star::sdbc
{ class XResultSet
; }
66 using namespace com::sun::star::container
;
67 using namespace com::sun::star::beans
;
68 using namespace com::sun::star::io
;
69 using namespace com::sun::star::lang
;
70 using namespace com::sun::star::sdbc
;
71 using namespace com::sun::star::task
;
72 using namespace com::sun::star::ucb
;
73 using namespace com::sun::star::uno
;
80 class EmptyInputStream
: public ::cppu::WeakImplHelper
< XInputStream
>
83 virtual sal_Int32 SAL_CALL
readBytes(
84 Sequence
< sal_Int8
> & data
, sal_Int32 nBytesToRead
) override
;
85 virtual sal_Int32 SAL_CALL
readSomeBytes(
86 Sequence
< sal_Int8
> & data
, sal_Int32 nMaxBytesToRead
) override
;
87 virtual void SAL_CALL
skipBytes( sal_Int32 nBytesToSkip
) override
;
88 virtual sal_Int32 SAL_CALL
available() override
;
89 virtual void SAL_CALL
closeInput() override
;
94 sal_Int32
EmptyInputStream::readBytes(
95 Sequence
< sal_Int8
> & data
, sal_Int32
)
101 sal_Int32
EmptyInputStream::readSomeBytes(
102 Sequence
< sal_Int8
> & data
, sal_Int32
)
108 void EmptyInputStream::skipBytes( sal_Int32
)
112 sal_Int32
EmptyInputStream::available()
117 void EmptyInputStream::closeInput()
125 class ContentEventListener_Impl
: public cppu::OWeakObject
,
126 public XContentEventListener
128 Content_Impl
& m_rContent
;
131 explicit ContentEventListener_Impl( Content_Impl
& rContent
)
132 : m_rContent( rContent
) {}
135 virtual css::uno::Any SAL_CALL
queryInterface( const css::uno::Type
& rType
) override
;
136 virtual void SAL_CALL
acquire()
138 virtual void SAL_CALL
release()
141 // XContentEventListener
142 virtual void SAL_CALL
contentEvent( const ContentEvent
& evt
) override
;
144 // XEventListener ( base of XContentEventListener )
145 virtual void SAL_CALL
disposing( const EventObject
& Source
) override
;
152 class Content_Impl
: public salhelper::SimpleReferenceObject
154 friend ContentEventListener_Impl
;
156 mutable OUString m_aURL
;
157 Reference
< XComponentContext
> m_xCtx
;
158 Reference
< XContent
> m_xContent
;
159 Reference
< XCommandProcessor
> m_xCommandProcessor
;
160 Reference
< XCommandEnvironment
> m_xEnv
;
161 Reference
< XContentEventListener
> m_xContentEventListener
;
162 mutable std::mutex m_aMutex
;
165 void reinit( const Reference
< XContent
>& xContent
);
166 void disposing(const EventObject
& Source
);
167 const Reference
< XContent
> & getContent_NoLock();
168 const OUString
& getURL_NoLock() const;
172 Content_Impl( const Reference
< XComponentContext
>& rCtx
,
173 const Reference
< XContent
>& rContent
,
174 const Reference
< XCommandEnvironment
>& rEnv
);
176 virtual ~Content_Impl() override
;
178 const OUString
& getURL() const;
179 Reference
< XContent
> getContent();
180 Reference
< XCommandProcessor
> getCommandProcessor();
181 Reference
< XComponentContext
> const & getComponentContext() const
182 { assert(m_xCtx
.is()); return m_xCtx
; }
184 Any
executeCommand( const Command
& rCommand
);
186 inline const Reference
< XCommandEnvironment
>& getEnvironment() const;
187 inline void setEnvironment(
188 const Reference
< XCommandEnvironment
>& xNewEnv
);
196 /// @throws ContentCreationException
197 /// @throws RuntimeException
198 static void ensureContentProviderForURL( const Reference
< XUniversalContentBroker
>& rBroker
,
199 const OUString
& rURL
)
201 Reference
< XContentProvider
> xProv
202 = rBroker
->queryContentProvider( rURL
);
205 throw ContentCreationException(
206 "No Content Provider available for URL: " + rURL
,
207 Reference
< XInterface
>(),
208 ContentCreationError_NO_CONTENT_PROVIDER
);
212 /// @throws ContentCreationException
213 /// @throws RuntimeException
214 static Reference
< XContentIdentifier
> getContentIdentifierThrow(
215 const Reference
< XUniversalContentBroker
> & rBroker
,
216 const OUString
& rURL
)
218 Reference
< XContentIdentifier
> xId
219 = rBroker
->createContentIdentifier( rURL
);
223 ensureContentProviderForURL( rBroker
, rURL
);
225 throw ContentCreationException(
226 "Unable to create Content Identifier!",
227 Reference
< XInterface
>(),
228 ContentCreationError_IDENTIFIER_CREATION_FAILED
);
234 /// @throws RuntimeException
235 static Reference
< XContentIdentifier
> getContentIdentifierNoThrow(
236 const Reference
< XUniversalContentBroker
> & rBroker
,
237 const OUString
& rURL
)
239 return rBroker
->createContentIdentifier(rURL
);
242 /// @throws ContentCreationException
243 /// @throws RuntimeException
244 static Reference
< XContent
> getContentThrow(
245 const Reference
< XUniversalContentBroker
> & rBroker
,
246 const Reference
< XContentIdentifier
> & xId
)
248 Reference
< XContent
> xContent
;
252 xContent
= rBroker
->queryContent( xId
);
254 catch ( IllegalIdentifierException
const & e
)
260 if ( !xContent
.is() )
262 ensureContentProviderForURL( rBroker
, xId
->getContentIdentifier() );
264 throw ContentCreationException(
265 "Unable to create Content for <" + xId
->getContentIdentifier() + ">: " + msg
,
266 Reference
< XInterface
>(),
267 ContentCreationError_CONTENT_CREATION_FAILED
);
273 /// @throws RuntimeException
274 static Reference
< XContent
> getContentNoThrow(
275 const Reference
< XUniversalContentBroker
> & rBroker
,
276 const Reference
< XContentIdentifier
> & xId
)
278 Reference
< XContent
> xContent
;
281 xContent
= rBroker
->queryContent( xId
);
283 catch ( IllegalIdentifierException
const & e
)
285 SAL_WARN("ucbhelper", "getContentNoThrow: " << e
);
292 // Content Implementation.
296 : m_xImpl( new Content_Impl
)
301 Content::Content( const OUString
& rURL
,
302 const Reference
< XCommandEnvironment
>& rEnv
,
303 const Reference
< XComponentContext
>& rCtx
)
305 Reference
< XUniversalContentBroker
> pBroker(
306 UniversalContentBroker::create( rCtx
) );
308 Reference
< XContentIdentifier
> xId
309 = getContentIdentifierThrow(pBroker
, rURL
);
311 Reference
< XContent
> xContent
= getContentThrow(pBroker
, xId
);
313 m_xImpl
= new Content_Impl( rCtx
, xContent
, rEnv
);
317 Content::Content( const Reference
< XContent
>& rContent
,
318 const Reference
< XCommandEnvironment
>& rEnv
,
319 const Reference
< XComponentContext
>& rCtx
)
321 m_xImpl
= new Content_Impl( rCtx
, rContent
, rEnv
);
325 Content::Content( const Content
& rOther
)
327 m_xImpl
= rOther
.m_xImpl
;
330 Content::Content( Content
&& rOther
) noexcept
332 m_xImpl
= std::move(rOther
.m_xImpl
);
336 bool Content::create( const OUString
& rURL
,
337 const Reference
< XCommandEnvironment
>& rEnv
,
338 const Reference
< XComponentContext
>& rCtx
,
341 Reference
< XUniversalContentBroker
> pBroker(
342 UniversalContentBroker::create( rCtx
) );
344 Reference
< XContentIdentifier
> xId
345 = getContentIdentifierNoThrow(pBroker
, rURL
);
349 Reference
< XContent
> xContent
= getContentNoThrow(pBroker
, xId
);
350 if ( !xContent
.is() )
354 = new Content_Impl( rCtx
, xContent
, rEnv
);
365 Content
& Content::operator=( const Content
& rOther
)
367 m_xImpl
= rOther
.m_xImpl
;
371 Content
& Content::operator=( Content
&& rOther
) noexcept
373 m_xImpl
= std::move(rOther
.m_xImpl
);
377 Reference
< XContent
> Content::get() const
379 return m_xImpl
->getContent();
383 const OUString
& Content::getURL() const
385 return m_xImpl
->getURL();
389 const Reference
< XCommandEnvironment
>& Content::getCommandEnvironment() const
391 return m_xImpl
->getEnvironment();
395 void Content::setCommandEnvironment(
396 const Reference
< XCommandEnvironment
>& xNewEnv
)
398 m_xImpl
->setEnvironment( xNewEnv
);
402 Reference
< XCommandInfo
> Content::getCommands()
405 aCommand
.Name
= "getCommandInfo";
406 aCommand
.Handle
= -1; // n/a
407 aCommand
.Argument
= Any();
409 Any aResult
= m_xImpl
->executeCommand( aCommand
);
411 Reference
< XCommandInfo
> xInfo
;
417 Reference
< XPropertySetInfo
> Content::getProperties()
419 static constexpr OUStringLiteral sgetPropertySetInfo
= u
"getPropertySetInfo";
421 aCommand
.Name
= sgetPropertySetInfo
;
422 aCommand
.Handle
= -1; // n/a
423 aCommand
.Argument
= Any();
425 Any aResult
= m_xImpl
->executeCommand( aCommand
);
427 Reference
< XPropertySetInfo
> xInfo
;
433 Any
Content::getPropertyValue( const OUString
& rPropertyName
)
435 Sequence
<OUString
> aNames
{ rPropertyName
};
437 Sequence
< Any
> aRet
= getPropertyValues( aNames
);
438 return aRet
.getConstArray()[ 0 ];
442 Any
Content::setPropertyValue( const OUString
& rName
,
445 Sequence
<OUString
> aNames
{ rName
};
447 Sequence
< Any
> aValues( 1 );
448 aValues
.getArray()[ 0 ] = rValue
;
450 Sequence
< Any
> aErrors
= setPropertyValues( aNames
, aValues
);
451 return aErrors
.getConstArray()[ 0 ];
455 Sequence
< Any
> Content::getPropertyValues(
456 const Sequence
< OUString
>& rPropertyNames
)
458 Reference
< XRow
> xRow
= getPropertyValuesInterface( rPropertyNames
);
460 sal_Int32 nCount
= rPropertyNames
.getLength();
461 Sequence
< Any
> aValues( nCount
);
465 Any
* pValues
= aValues
.getArray();
467 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
468 pValues
[ n
] = xRow
->getObject( n
+ 1, Reference
< XNameAccess
>() );
475 Reference
< XRow
> Content::getPropertyValuesInterface(
476 const Sequence
< OUString
>& rPropertyNames
)
478 sal_Int32 nCount
= rPropertyNames
.getLength();
479 Sequence
< Property
> aProps( nCount
);
480 Property
* pProps
= aProps
.getArray();
482 const OUString
* pNames
= rPropertyNames
.getConstArray();
484 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
486 Property
& rProp
= pProps
[ n
];
488 rProp
.Name
= pNames
[ n
];
489 rProp
.Handle
= -1; // n/a
491 // rProp.Attributes = ;
494 static constexpr OUStringLiteral sgetPropertyValues
= u
"getPropertyValues";
496 aCommand
.Name
= sgetPropertyValues
;
497 aCommand
.Handle
= -1; // n/a
498 aCommand
.Argument
<<= aProps
;
500 Any aResult
= m_xImpl
->executeCommand( aCommand
);
502 Reference
< XRow
> xRow
;
508 Sequence
< Any
> Content::setPropertyValues(
509 const Sequence
< OUString
>& rPropertyNames
,
510 const Sequence
< Any
>& rValues
)
512 if ( rPropertyNames
.getLength() != rValues
.getLength() )
514 ucbhelper::cancelCommandExecution(
515 Any( IllegalArgumentException(
516 "Length of property names sequence and value "
517 "sequence are unequal!",
520 m_xImpl
->getEnvironment() );
524 sal_Int32 nCount
= rValues
.getLength();
525 Sequence
< PropertyValue
> aProps( nCount
);
526 PropertyValue
* pProps
= aProps
.getArray();
528 const OUString
* pNames
= rPropertyNames
.getConstArray();
529 const Any
* pValues
= rValues
.getConstArray();
531 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
533 PropertyValue
& rProp
= pProps
[ n
];
535 rProp
.Name
= pNames
[ n
];
536 rProp
.Handle
= -1; // n/a
537 rProp
.Value
= pValues
[ n
];
542 aCommand
.Name
= "setPropertyValues";
543 aCommand
.Handle
= -1; // n/a
544 aCommand
.Argument
<<= aProps
;
546 Any aResult
= m_xImpl
->executeCommand( aCommand
);
548 Sequence
< Any
> aErrors
;
554 Any
Content::executeCommand( const OUString
& rCommandName
,
555 const Any
& rCommandArgument
)
558 aCommand
.Name
= rCommandName
;
559 aCommand
.Handle
= -1; // n/a
560 aCommand
.Argument
= rCommandArgument
;
562 return m_xImpl
->executeCommand( aCommand
);
566 Any
Content::createCursorAny( const Sequence
< OUString
>& rPropertyNames
,
567 ResultSetInclude eMode
)
569 sal_Int32 nCount
= rPropertyNames
.getLength();
570 Sequence
< Property
> aProps( nCount
);
571 Property
* pProps
= aProps
.getArray();
572 const OUString
* pNames
= rPropertyNames
.getConstArray();
573 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
575 Property
& rProp
= pProps
[ n
];
576 rProp
.Name
= pNames
[ n
];
577 rProp
.Handle
= -1; // n/a
580 OpenCommandArgument2 aArg
;
581 aArg
.Mode
= ( eMode
== INCLUDE_FOLDERS_ONLY
)
583 : ( eMode
== INCLUDE_DOCUMENTS_ONLY
)
584 ? OpenMode::DOCUMENTS
: OpenMode::ALL
;
585 aArg
.Priority
= 0; // unused
586 aArg
.Sink
.clear(); // unused
587 aArg
.Properties
= aProps
;
590 aCommand
.Name
= "open";
591 aCommand
.Handle
= -1; // n/a
592 aCommand
.Argument
<<= aArg
;
594 return m_xImpl
->executeCommand( aCommand
);
598 Reference
< XResultSet
> Content::createCursor(
599 const Sequence
< OUString
>& rPropertyNames
,
600 ResultSetInclude eMode
)
602 Any aCursorAny
= createCursorAny( rPropertyNames
, eMode
);
604 Reference
< XDynamicResultSet
> xDynSet
;
605 Reference
< XResultSet
> aResult
;
607 aCursorAny
>>= xDynSet
;
609 aResult
= xDynSet
->getStaticResultSet();
611 OSL_ENSURE( aResult
.is(), "Content::createCursor - no cursor!" );
615 // Former, the open command directly returned a XResultSet.
616 aCursorAny
>>= aResult
;
618 OSL_ENSURE( !aResult
.is(),
619 "Content::createCursor - open-Command must "
620 "return a Reference< XDynnamicResultSet >!" );
627 Reference
< XDynamicResultSet
> Content::createDynamicCursor(
628 const Sequence
< OUString
>& rPropertyNames
,
629 ResultSetInclude eMode
)
631 Reference
< XDynamicResultSet
> aResult
;
632 createCursorAny( rPropertyNames
, eMode
) >>= aResult
;
634 OSL_ENSURE( aResult
.is(), "Content::createDynamicCursor - no cursor!" );
640 Reference
< XResultSet
> Content::createSortedCursor(
641 const Sequence
< OUString
>& rPropertyNames
,
642 const Sequence
< NumberedSortingInfo
>& rSortInfo
,
643 const Reference
< XAnyCompareFactory
>& rAnyCompareFactory
,
644 ResultSetInclude eMode
)
646 Reference
< XResultSet
> aResult
;
647 Reference
< XDynamicResultSet
> aDynSet
;
649 Any aCursorAny
= createCursorAny( rPropertyNames
, eMode
);
651 aCursorAny
>>= aDynSet
;
655 Reference
< XDynamicResultSet
> aDynResult
;
657 if( m_xImpl
->getComponentContext().is() )
659 Reference
< XSortedDynamicResultSetFactory
> aSortFactory
=
660 SortedDynamicResultSetFactory::create( m_xImpl
->getComponentContext());
662 aDynResult
= aSortFactory
->createSortedDynamicResultSet( aDynSet
,
664 rAnyCompareFactory
);
667 OSL_ENSURE( aDynResult
.is(), "Content::createSortedCursor - no sorted cursor!" );
669 if( aDynResult
.is() )
670 aResult
= aDynResult
->getStaticResultSet();
672 aResult
= aDynSet
->getStaticResultSet();
675 OSL_ENSURE( aResult
.is(), "Content::createSortedCursor - no cursor!" );
679 // Former, the open command directly returned a XResultSet.
680 aCursorAny
>>= aResult
;
682 OSL_ENSURE( !aResult
.is(),
683 "Content::createCursor - open-Command must "
684 "return a Reference< XDynnamicResultSet >!" );
691 Reference
< XInputStream
> Content::openStream()
694 return Reference
< XInputStream
>();
696 Reference
< XActiveDataSink
> xSink
= new ActiveDataSink
;
698 OpenCommandArgument2 aArg
;
699 aArg
.Mode
= OpenMode::DOCUMENT
;
700 aArg
.Priority
= 0; // unused
702 aArg
.Properties
= Sequence
< Property
>( 0 ); // unused
705 aCommand
.Name
= "open";
706 aCommand
.Handle
= -1; // n/a
707 aCommand
.Argument
<<= aArg
;
709 m_xImpl
->executeCommand( aCommand
);
711 return xSink
->getInputStream();
715 Reference
< XInputStream
> Content::openStreamNoLock()
718 return Reference
< XInputStream
>();
720 Reference
< XActiveDataSink
> xSink
= new ActiveDataSink
;
722 OpenCommandArgument2 aArg
;
723 aArg
.Mode
= OpenMode::DOCUMENT_SHARE_DENY_NONE
;
724 aArg
.Priority
= 0; // unused
726 aArg
.Properties
= Sequence
< Property
>( 0 ); // unused
729 aCommand
.Name
= "open";
730 aCommand
.Handle
= -1; // n/a
731 aCommand
.Argument
<<= aArg
;
733 m_xImpl
->executeCommand( aCommand
);
735 return xSink
->getInputStream();
739 Reference
< XStream
> Content::openWriteableStream()
742 return Reference
< XStream
>();
744 Reference
< XActiveDataStreamer
> xStreamer
= new ActiveDataStreamer
;
746 OpenCommandArgument2 aArg
;
747 aArg
.Mode
= OpenMode::DOCUMENT
;
748 aArg
.Priority
= 0; // unused
749 aArg
.Sink
= xStreamer
;
750 aArg
.Properties
= Sequence
< Property
>( 0 ); // unused
753 aCommand
.Name
= "open";
754 aCommand
.Handle
= -1; // n/a
755 aCommand
.Argument
<<= aArg
;
757 m_xImpl
->executeCommand( aCommand
);
759 return xStreamer
->getStream();
763 Reference
< XStream
> Content::openWriteableStreamNoLock()
766 return Reference
< XStream
>();
768 Reference
< XActiveDataStreamer
> xStreamer
= new ActiveDataStreamer
;
770 OpenCommandArgument2 aArg
;
771 aArg
.Mode
= OpenMode::DOCUMENT_SHARE_DENY_NONE
;
772 aArg
.Priority
= 0; // unused
773 aArg
.Sink
= xStreamer
;
774 aArg
.Properties
= Sequence
< Property
>( 0 ); // unused
777 aCommand
.Name
= "open";
778 aCommand
.Handle
= -1; // n/a
779 aCommand
.Argument
<<= aArg
;
781 m_xImpl
->executeCommand( aCommand
);
783 return xStreamer
->getStream();
787 bool Content::openStream( const Reference
< XActiveDataSink
>& rSink
)
792 OpenCommandArgument2 aArg
;
793 aArg
.Mode
= OpenMode::DOCUMENT
;
794 aArg
.Priority
= 0; // unused
796 aArg
.Properties
= Sequence
< Property
>( 0 ); // unused
799 aCommand
.Name
= "open";
800 aCommand
.Handle
= -1; // n/a
801 aCommand
.Argument
<<= aArg
;
803 m_xImpl
->executeCommand( aCommand
);
809 bool Content::openStream( const Reference
< XOutputStream
>& rStream
)
814 OpenCommandArgument2 aArg
;
815 aArg
.Mode
= OpenMode::DOCUMENT
;
816 aArg
.Priority
= 0; // unused
818 aArg
.Properties
= Sequence
< Property
>( 0 ); // unused
821 aCommand
.Name
= "open";
822 aCommand
.Handle
= -1; // n/a
823 aCommand
.Argument
<<= aArg
;
825 m_xImpl
->executeCommand( aCommand
);
831 void Content::writeStream( const Reference
< XInputStream
>& rStream
,
832 bool bReplaceExisting
)
834 InsertCommandArgument aArg
;
835 aArg
.Data
= rStream
.is() ? rStream
: new EmptyInputStream
;
836 aArg
.ReplaceExisting
= bReplaceExisting
;
839 aCommand
.Name
= "insert";
840 aCommand
.Handle
= -1; // n/a
841 aCommand
.Argument
<<= aArg
;
843 m_xImpl
->executeCommand( aCommand
);
849 Sequence
< ContentInfo
> Content::queryCreatableContentsInfo()
851 // First, try it using "CreatableContentsInfo" property -> the "new" way.
852 Sequence
< ContentInfo
> aInfo
;
853 if ( getPropertyValue(
854 "CreatableContentsInfo" )
858 // Second, try it using XContentCreator interface -> the "old" way (not
859 // providing the chance to supply an XCommandEnvironment.
860 Reference
< XContentCreator
> xCreator( m_xImpl
->getContent(), UNO_QUERY
);
862 aInfo
= xCreator
->queryCreatableContentsInfo();
868 bool Content::insertNewContent( const OUString
& rContentType
,
869 const Sequence
< OUString
>&
871 const Sequence
< Any
>& rPropertyValues
,
872 Content
& rNewContent
)
874 return insertNewContent( rContentType
,
877 new EmptyInputStream
,
882 bool Content::insertNewContent( const OUString
& rContentType
,
883 const Sequence
< OUString
>&
885 const Sequence
< Any
>& rPropertyValues
,
886 const Reference
< XInputStream
>& rData
,
887 Content
& rNewContent
)
889 if ( rContentType
.isEmpty() )
892 // First, try it using "createNewContent" command -> the "new" way.
894 aInfo
.Type
= rContentType
;
895 aInfo
.Attributes
= 0;
898 aCommand
.Name
= "createNewContent";
899 aCommand
.Handle
= -1; // n/a
900 aCommand
.Argument
<<= aInfo
;
902 Reference
< XContent
> xNew
;
905 m_xImpl
->executeCommand( aCommand
) >>= xNew
;
907 catch ( RuntimeException
const & )
911 catch ( Exception
const & )
917 // Second, try it using XContentCreator interface -> the "old"
918 // way (not providing the chance to supply an XCommandEnvironment.
919 Reference
< XContentCreator
> xCreator( m_xImpl
->getContent(), UNO_QUERY
);
921 if ( !xCreator
.is() )
924 xNew
= xCreator
->createNewContent( aInfo
);
931 xNew
, m_xImpl
->getEnvironment(), m_xImpl
->getComponentContext() );
932 aNewContent
.setPropertyValues( rPropertyNames
, rPropertyValues
);
933 aNewContent
.executeCommand( "insert",
935 InsertCommandArgument(
936 rData
.is() ? rData
: new EmptyInputStream
,
937 false /* ReplaceExisting */ ) ) );
938 aNewContent
.m_xImpl
->inserted();
940 rNewContent
= aNewContent
;
945 void Content::transferContent( const Content
& rSourceContent
,
946 InsertOperation eOperation
,
947 const OUString
& rTitle
,
948 const sal_Int32 nNameClashAction
,
949 const OUString
& rMimeType
,
951 const OUString
& rVersionComment
,
952 OUString
* pResultURL
,
953 const OUString
& rDocumentId
) const
955 Reference
< XUniversalContentBroker
> pBroker(
956 UniversalContentBroker::create( m_xImpl
->getComponentContext() ) );
958 // Execute command "globalTransfer" at UCB.
960 TransferCommandOperation eTransOp
= TransferCommandOperation();
961 OUString
sCommand( "globalTransfer" );
962 bool bCheckIn
= false;
963 switch ( eOperation
)
965 case InsertOperation::Copy
:
966 eTransOp
= TransferCommandOperation_COPY
;
969 case InsertOperation::Move
:
970 eTransOp
= TransferCommandOperation_MOVE
;
973 case InsertOperation::Checkin
:
974 eTransOp
= TransferCommandOperation_COPY
;
975 sCommand
= "checkin";
980 aCommand
.Name
= sCommand
;
981 aCommand
.Handle
= -1; // n/a
985 GlobalTransferCommandArgument2
aTransferArg(
987 rSourceContent
.getURL(), // SourceURL
988 getURL(), // TargetFolderURL,
993 aCommand
.Argument
<<= aTransferArg
;
997 CheckinArgument
aCheckinArg( bMajorVersion
, rVersionComment
,
998 rSourceContent
.getURL(), getURL(), rTitle
, rMimeType
);
999 aCommand
.Argument
<<= aCheckinArg
;
1002 Any aRet
= pBroker
->execute( aCommand
, 0, m_xImpl
->getEnvironment() );
1003 if ( pResultURL
!= nullptr )
1004 aRet
>>= *pResultURL
;
1008 bool Content::isFolder()
1010 bool bFolder
= false;
1011 if ( getPropertyValue("IsFolder")
1015 ucbhelper::cancelCommandExecution(
1016 Any( UnknownPropertyException(
1017 "Unable to retrieve value of property 'IsFolder'!",
1019 m_xImpl
->getEnvironment() );
1025 bool Content::isDocument()
1028 if ( getPropertyValue("IsDocument")
1032 ucbhelper::cancelCommandExecution(
1033 Any( UnknownPropertyException(
1034 "Unable to retrieve value of property 'IsDocument'!",
1036 m_xImpl
->getEnvironment() );
1041 void Content::lock()
1044 aCommand
.Name
= "lock";
1045 aCommand
.Handle
= -1; // n/a
1047 m_xImpl
->executeCommand( aCommand
);
1051 void Content::unlock()
1055 aCommand
.Name
= "unlock";
1056 aCommand
.Handle
= -1; // n/a
1058 m_xImpl
->executeCommand( aCommand
);
1063 // Content_Impl Implementation.
1066 Content_Impl::Content_Impl( const Reference
< XComponentContext
>& rCtx
,
1067 const Reference
< XContent
>& rContent
,
1068 const Reference
< XCommandEnvironment
>& rEnv
)
1070 m_xContent( rContent
),
1074 if ( m_xContent
.is() )
1076 m_xContentEventListener
= new ContentEventListener_Impl( *this );
1077 m_xContent
->addContentEventListener( m_xContentEventListener
);
1079 #if OSL_DEBUG_LEVEL > 0
1080 // Only done on demand in product version for performance reasons,
1081 // but a nice debug helper.
1088 void Content_Impl::reinit( const Reference
< XContent
>& xContent
)
1090 std::unique_lock
aGuard( m_aMutex
);
1092 m_xCommandProcessor
= nullptr;
1094 // #92581# - Don't reset m_aURL!!!
1096 if ( m_xContent
.is() )
1100 m_xContent
->removeContentEventListener( m_xContentEventListener
);
1102 catch ( RuntimeException
const & )
1107 if ( xContent
.is() )
1109 m_xContent
= xContent
;
1110 m_xContent
->addContentEventListener( m_xContentEventListener
);
1112 #if OSL_DEBUG_LEVEL > 0
1113 // Only done on demand in product version for performance reasons,
1114 // but a nice debug helper.
1120 // We need m_xContent's URL in order to be able to create the
1121 // content object again if demanded ( --> Content_Impl::getContent() )
1124 m_xContent
= nullptr;
1130 Content_Impl::~Content_Impl()
1132 if ( m_xContent
.is() )
1136 m_xContent
->removeContentEventListener( m_xContentEventListener
);
1138 catch ( RuntimeException
const & )
1145 void Content_Impl::disposing( const EventObject
& Source
)
1147 Reference
<XContent
> xContent
;
1150 std::unique_lock
aGuard( m_aMutex
);
1151 if(Source
.Source
!= m_xContent
)
1154 xContent
= m_xContent
;
1157 m_xCommandProcessor
= nullptr;
1158 m_xContent
= nullptr;
1161 if ( xContent
.is() )
1165 xContent
->removeContentEventListener( m_xContentEventListener
);
1167 catch ( RuntimeException
const & )
1174 const OUString
& Content_Impl::getURL() const
1176 if ( m_aURL
.isEmpty() && m_xContent
.is() )
1178 std::unique_lock
aGuard( m_aMutex
);
1180 return getURL_NoLock();
1186 const OUString
& Content_Impl::getURL_NoLock() const
1188 if ( m_aURL
.isEmpty() && m_xContent
.is() )
1190 Reference
< XContentIdentifier
> xId
= m_xContent
->getIdentifier();
1192 m_aURL
= xId
->getContentIdentifier();
1198 Reference
< XContent
> Content_Impl::getContent()
1200 if ( !m_xContent
.is() && !m_aURL
.isEmpty() )
1202 std::unique_lock
aGuard( m_aMutex
);
1203 return getContent_NoLock();
1208 const Reference
< XContent
> & Content_Impl::getContent_NoLock()
1210 if ( !m_xContent
.is() && !m_aURL
.isEmpty() )
1212 Reference
< XUniversalContentBroker
> pBroker(
1213 UniversalContentBroker::create( getComponentContext() ) );
1215 OSL_ENSURE( pBroker
->queryContentProviders().hasElements(),
1216 "Content Broker not configured (no providers)!" );
1218 Reference
< XContentIdentifier
> xId
1219 = pBroker
->createContentIdentifier( m_aURL
);
1221 OSL_ENSURE( xId
.is(), "No Content Identifier!" );
1227 m_xContent
= pBroker
->queryContent( xId
);
1229 catch ( IllegalIdentifierException
const & )
1233 if ( m_xContent
.is() )
1234 m_xContent
->addContentEventListener(
1235 m_xContentEventListener
);
1243 Reference
< XCommandProcessor
> Content_Impl::getCommandProcessor()
1245 if ( !m_xCommandProcessor
.is() )
1247 std::unique_lock
aGuard( m_aMutex
);
1249 if ( !m_xCommandProcessor
.is() )
1250 m_xCommandProcessor
.set( getContent_NoLock(), UNO_QUERY
);
1253 return m_xCommandProcessor
;
1257 Any
Content_Impl::executeCommand( const Command
& rCommand
)
1259 Reference
< XCommandProcessor
> xProc
= getCommandProcessor();
1264 return xProc
->execute( rCommand
, 0, m_xEnv
);
1268 inline const Reference
< XCommandEnvironment
>&
1269 Content_Impl::getEnvironment() const
1275 inline void Content_Impl::setEnvironment(
1276 const Reference
< XCommandEnvironment
>& xNewEnv
)
1278 std::unique_lock
aGuard( m_aMutex
);
1283 void Content_Impl::inserted()
1285 // URL might have changed during 'insert' => recalculate in next getURL()
1286 std::unique_lock
aGuard( m_aMutex
);
1291 // ContentEventListener_Impl Implementation.
1294 // XInterface methods.
1296 void SAL_CALL
ContentEventListener_Impl::acquire()
1299 OWeakObject::acquire();
1302 void SAL_CALL
ContentEventListener_Impl::release()
1305 OWeakObject::release();
1308 css::uno::Any SAL_CALL
ContentEventListener_Impl::queryInterface( const css::uno::Type
& rType
)
1310 css::uno::Any aRet
= cppu::queryInterface( rType
,
1311 static_cast< XContentEventListener
* >(this),
1312 static_cast< XEventListener
* >(this)
1314 return aRet
.hasValue() ? aRet
: OWeakObject::queryInterface( rType
);
1317 // XContentEventListener methods.
1321 void SAL_CALL
ContentEventListener_Impl::contentEvent( const ContentEvent
& evt
)
1323 if ( evt
.Source
!= m_rContent
.m_xContent
)
1326 switch ( evt
.Action
)
1328 case ContentAction::DELETED
:
1329 m_rContent
.reinit( Reference
< XContent
>() );
1332 case ContentAction::EXCHANGED
:
1333 m_rContent
.reinit( evt
.Content
);
1342 // XEventListenr methods.
1346 void SAL_CALL
ContentEventListener_Impl::disposing( const EventObject
& Source
)
1348 m_rContent
.disposing(Source
);
1351 } /* namespace ucbhelper */
1353 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */