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 <osl/diagnose.h>
25 #include <osl/mutex.hxx>
26 #include <sal/log.hxx>
27 #include <salhelper/simplereferenceobject.hxx>
28 #include <cppuhelper/weak.hxx>
29 #include <cppuhelper/queryinterface.hxx>
31 #include <cppuhelper/implbase.hxx>
32 #include <com/sun/star/ucb/CheckinArgument.hpp>
33 #include <com/sun/star/ucb/ContentCreationError.hpp>
34 #include <com/sun/star/ucb/ContentCreationException.hpp>
35 #include <com/sun/star/ucb/IllegalIdentifierException.hpp>
36 #include <com/sun/star/ucb/XCommandInfo.hpp>
37 #include <com/sun/star/ucb/XCommandProcessor.hpp>
38 #include <com/sun/star/ucb/Command.hpp>
39 #include <com/sun/star/ucb/ContentAction.hpp>
40 #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
41 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
42 #include <com/sun/star/ucb/GlobalTransferCommandArgument2.hpp>
43 #include <com/sun/star/ucb/OpenMode.hpp>
44 #include <com/sun/star/ucb/XContentCreator.hpp>
45 #include <com/sun/star/ucb/XContentEventListener.hpp>
46 #include <com/sun/star/ucb/XDynamicResultSet.hpp>
47 #include <com/sun/star/ucb/SortedDynamicResultSetFactory.hpp>
48 #include <com/sun/star/ucb/UniversalContentBroker.hpp>
49 #include <com/sun/star/ucb/XUniversalContentBroker.hpp>
50 #include <com/sun/star/beans/XPropertySetInfo.hpp>
51 #include <com/sun/star/beans/Property.hpp>
52 #include <com/sun/star/beans/PropertyValue.hpp>
53 #include <com/sun/star/sdbc/XRow.hpp>
54 #include <com/sun/star/lang/IllegalArgumentException.hpp>
55 #include <com/sun/star/beans/UnknownPropertyException.hpp>
56 #include <ucbhelper/content.hxx>
57 #include <ucbhelper/activedatasink.hxx>
58 #include <ucbhelper/activedatastreamer.hxx>
59 #include <ucbhelper/cancelcommandexecution.hxx>
61 namespace com::sun::star::ucb
{ class XCommandEnvironment
; }
62 namespace com::sun::star::ucb
{ class XContentProvider
; }
63 namespace com::sun::star::sdbc
{ class XResultSet
; }
65 using namespace com::sun::star::container
;
66 using namespace com::sun::star::beans
;
67 using namespace com::sun::star::io
;
68 using namespace com::sun::star::lang
;
69 using namespace com::sun::star::sdbc
;
70 using namespace com::sun::star::task
;
71 using namespace com::sun::star::ucb
;
72 using namespace com::sun::star::uno
;
77 class EmptyInputStream
: public ::cppu::WeakImplHelper
< XInputStream
>
80 virtual sal_Int32 SAL_CALL
readBytes(
81 Sequence
< sal_Int8
> & data
, sal_Int32 nBytesToRead
) override
;
82 virtual sal_Int32 SAL_CALL
readSomeBytes(
83 Sequence
< sal_Int8
> & data
, sal_Int32 nMaxBytesToRead
) override
;
84 virtual void SAL_CALL
skipBytes( sal_Int32 nBytesToSkip
) override
;
85 virtual sal_Int32 SAL_CALL
available() override
;
86 virtual void SAL_CALL
closeInput() override
;
89 sal_Int32
EmptyInputStream::readBytes(
90 Sequence
< sal_Int8
> & data
, sal_Int32
)
96 sal_Int32
EmptyInputStream::readSomeBytes(
97 Sequence
< sal_Int8
> & data
, sal_Int32
)
103 void EmptyInputStream::skipBytes( sal_Int32
)
107 sal_Int32
EmptyInputStream::available()
112 void EmptyInputStream::closeInput()
117 // class ContentEventListener_Impl.
120 class ContentEventListener_Impl
: public cppu::OWeakObject
,
121 public XContentEventListener
123 Content_Impl
& m_rContent
;
126 explicit ContentEventListener_Impl( Content_Impl
& rContent
)
127 : m_rContent( rContent
) {}
130 virtual css::uno::Any SAL_CALL
queryInterface( const css::uno::Type
& rType
) override
;
131 virtual void SAL_CALL
acquire()
133 virtual void SAL_CALL
release()
136 // XContentEventListener
137 virtual void SAL_CALL
contentEvent( const ContentEvent
& evt
) override
;
139 // XEventListener ( base of XContentEventListener )
140 virtual void SAL_CALL
disposing( const EventObject
& Source
) override
;
144 // class Content_Impl.
147 class Content_Impl
: public salhelper::SimpleReferenceObject
149 friend class ContentEventListener_Impl
;
151 mutable OUString m_aURL
;
152 Reference
< XComponentContext
> m_xCtx
;
153 Reference
< XContent
> m_xContent
;
154 Reference
< XCommandProcessor
> m_xCommandProcessor
;
155 Reference
< XCommandEnvironment
> m_xEnv
;
156 Reference
< XContentEventListener
> m_xContentEventListener
;
157 mutable osl::Mutex m_aMutex
;
160 void reinit( const Reference
< XContent
>& xContent
);
161 void disposing(const EventObject
& Source
);
165 Content_Impl( const Reference
< XComponentContext
>& rCtx
,
166 const Reference
< XContent
>& rContent
,
167 const Reference
< XCommandEnvironment
>& rEnv
);
169 virtual ~Content_Impl() override
;
171 const OUString
& getURL() const;
172 Reference
< XContent
> getContent();
173 Reference
< XCommandProcessor
> getCommandProcessor();
174 Reference
< XComponentContext
> const & getComponentContext() const
175 { assert(m_xCtx
.is()); return m_xCtx
; }
177 Any
executeCommand( const Command
& rCommand
);
179 inline const Reference
< XCommandEnvironment
>& getEnvironment() const;
180 inline void setEnvironment(
181 const Reference
< XCommandEnvironment
>& xNewEnv
);
189 /// @throws ContentCreationException
190 /// @throws RuntimeException
191 static void ensureContentProviderForURL( const Reference
< XUniversalContentBroker
>& rBroker
,
192 const OUString
& rURL
)
194 Reference
< XContentProvider
> xProv
195 = rBroker
->queryContentProvider( rURL
);
198 throw ContentCreationException(
199 "No Content Provider available for URL: " + rURL
,
200 Reference
< XInterface
>(),
201 ContentCreationError_NO_CONTENT_PROVIDER
);
205 /// @throws ContentCreationException
206 /// @throws RuntimeException
207 static Reference
< XContentIdentifier
> getContentIdentifierThrow(
208 const Reference
< XUniversalContentBroker
> & rBroker
,
209 const OUString
& rURL
)
211 Reference
< XContentIdentifier
> xId
212 = rBroker
->createContentIdentifier( rURL
);
216 ensureContentProviderForURL( rBroker
, rURL
);
218 throw ContentCreationException(
219 "Unable to create Content Identifier!",
220 Reference
< XInterface
>(),
221 ContentCreationError_IDENTIFIER_CREATION_FAILED
);
227 /// @throws RuntimeException
228 static Reference
< XContentIdentifier
> getContentIdentifierNoThrow(
229 const Reference
< XUniversalContentBroker
> & rBroker
,
230 const OUString
& rURL
)
232 return rBroker
->createContentIdentifier(rURL
);
235 /// @throws ContentCreationException
236 /// @throws RuntimeException
237 static Reference
< XContent
> getContentThrow(
238 const Reference
< XUniversalContentBroker
> & rBroker
,
239 const Reference
< XContentIdentifier
> & xId
)
241 Reference
< XContent
> xContent
;
245 xContent
= rBroker
->queryContent( xId
);
247 catch ( IllegalIdentifierException
const & e
)
253 if ( !xContent
.is() )
255 ensureContentProviderForURL( rBroker
, xId
->getContentIdentifier() );
257 throw ContentCreationException(
258 "Unable to create Content for <" + xId
->getContentIdentifier() + ">: " + msg
,
259 Reference
< XInterface
>(),
260 ContentCreationError_CONTENT_CREATION_FAILED
);
266 /// @throws RuntimeException
267 static Reference
< XContent
> getContentNoThrow(
268 const Reference
< XUniversalContentBroker
> & rBroker
,
269 const Reference
< XContentIdentifier
> & xId
)
271 Reference
< XContent
> xContent
;
274 xContent
= rBroker
->queryContent( xId
);
276 catch ( IllegalIdentifierException
const & e
)
278 SAL_WARN("ucbhelper", "getContentNoThrow: " << e
);
285 // Content Implementation.
289 : m_xImpl( new Content_Impl
)
294 Content::Content( const OUString
& rURL
,
295 const Reference
< XCommandEnvironment
>& rEnv
,
296 const Reference
< XComponentContext
>& rCtx
)
298 Reference
< XUniversalContentBroker
> pBroker(
299 UniversalContentBroker::create( rCtx
) );
301 Reference
< XContentIdentifier
> xId
302 = getContentIdentifierThrow(pBroker
, rURL
);
304 Reference
< XContent
> xContent
= getContentThrow(pBroker
, xId
);
306 m_xImpl
= new Content_Impl( rCtx
, xContent
, rEnv
);
310 Content::Content( const Reference
< XContent
>& rContent
,
311 const Reference
< XCommandEnvironment
>& rEnv
,
312 const Reference
< XComponentContext
>& rCtx
)
314 m_xImpl
= new Content_Impl( rCtx
, rContent
, rEnv
);
318 Content::Content( const Content
& rOther
)
320 m_xImpl
= rOther
.m_xImpl
;
323 Content::Content( Content
&& rOther
) noexcept
325 m_xImpl
= std::move(rOther
.m_xImpl
);
329 bool Content::create( const OUString
& rURL
,
330 const Reference
< XCommandEnvironment
>& rEnv
,
331 const Reference
< XComponentContext
>& rCtx
,
334 Reference
< XUniversalContentBroker
> pBroker(
335 UniversalContentBroker::create( rCtx
) );
337 Reference
< XContentIdentifier
> xId
338 = getContentIdentifierNoThrow(pBroker
, rURL
);
342 Reference
< XContent
> xContent
= getContentNoThrow(pBroker
, xId
);
343 if ( !xContent
.is() )
347 = new Content_Impl( rCtx
, xContent
, rEnv
);
358 Content
& Content::operator=( const Content
& rOther
)
360 m_xImpl
= rOther
.m_xImpl
;
364 Content
& Content::operator=( Content
&& rOther
) noexcept
366 m_xImpl
= std::move(rOther
.m_xImpl
);
370 Reference
< XContent
> Content::get() const
372 return m_xImpl
->getContent();
376 const OUString
& Content::getURL() const
378 return m_xImpl
->getURL();
382 const Reference
< XCommandEnvironment
>& Content::getCommandEnvironment() const
384 return m_xImpl
->getEnvironment();
388 void Content::setCommandEnvironment(
389 const Reference
< XCommandEnvironment
>& xNewEnv
)
391 m_xImpl
->setEnvironment( xNewEnv
);
395 Reference
< XCommandInfo
> Content::getCommands()
398 aCommand
.Name
= "getCommandInfo";
399 aCommand
.Handle
= -1; // n/a
400 aCommand
.Argument
= Any();
402 Any aResult
= m_xImpl
->executeCommand( aCommand
);
404 Reference
< XCommandInfo
> xInfo
;
410 Reference
< XPropertySetInfo
> Content::getProperties()
413 aCommand
.Name
= "getPropertySetInfo";
414 aCommand
.Handle
= -1; // n/a
415 aCommand
.Argument
= Any();
417 Any aResult
= m_xImpl
->executeCommand( aCommand
);
419 Reference
< XPropertySetInfo
> xInfo
;
425 Any
Content::getPropertyValue( const OUString
& rPropertyName
)
427 Sequence
<OUString
> aNames
{ rPropertyName
};
429 Sequence
< Any
> aRet
= getPropertyValues( aNames
);
430 return aRet
.getConstArray()[ 0 ];
434 Any
Content::setPropertyValue( const OUString
& rName
,
437 Sequence
<OUString
> aNames
{ rName
};
439 Sequence
< Any
> aValues( 1 );
440 aValues
.getArray()[ 0 ] = rValue
;
442 Sequence
< Any
> aErrors
= setPropertyValues( aNames
, aValues
);
443 return aErrors
.getConstArray()[ 0 ];
447 Sequence
< Any
> Content::getPropertyValues(
448 const Sequence
< OUString
>& rPropertyNames
)
450 Reference
< XRow
> xRow
= getPropertyValuesInterface( rPropertyNames
);
452 sal_Int32 nCount
= rPropertyNames
.getLength();
453 Sequence
< Any
> aValues( nCount
);
457 Any
* pValues
= aValues
.getArray();
459 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
460 pValues
[ n
] = xRow
->getObject( n
+ 1, Reference
< XNameAccess
>() );
467 Reference
< XRow
> Content::getPropertyValuesInterface(
468 const Sequence
< OUString
>& rPropertyNames
)
470 sal_Int32 nCount
= rPropertyNames
.getLength();
471 Sequence
< Property
> aProps( nCount
);
472 Property
* pProps
= aProps
.getArray();
474 const OUString
* pNames
= rPropertyNames
.getConstArray();
476 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
478 Property
& rProp
= pProps
[ n
];
480 rProp
.Name
= pNames
[ n
];
481 rProp
.Handle
= -1; // n/a
483 // rProp.Attributes = ;
487 aCommand
.Name
= "getPropertyValues";
488 aCommand
.Handle
= -1; // n/a
489 aCommand
.Argument
<<= aProps
;
491 Any aResult
= m_xImpl
->executeCommand( aCommand
);
493 Reference
< XRow
> xRow
;
499 Sequence
< Any
> Content::setPropertyValues(
500 const Sequence
< OUString
>& rPropertyNames
,
501 const Sequence
< Any
>& rValues
)
503 if ( rPropertyNames
.getLength() != rValues
.getLength() )
505 ucbhelper::cancelCommandExecution(
506 makeAny( IllegalArgumentException(
507 "Length of property names sequence and value "
508 "sequence are unequal!",
511 m_xImpl
->getEnvironment() );
515 sal_Int32 nCount
= rValues
.getLength();
516 Sequence
< PropertyValue
> aProps( nCount
);
517 PropertyValue
* pProps
= aProps
.getArray();
519 const OUString
* pNames
= rPropertyNames
.getConstArray();
520 const Any
* pValues
= rValues
.getConstArray();
522 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
524 PropertyValue
& rProp
= pProps
[ n
];
526 rProp
.Name
= pNames
[ n
];
527 rProp
.Handle
= -1; // n/a
528 rProp
.Value
= pValues
[ n
];
533 aCommand
.Name
= "setPropertyValues";
534 aCommand
.Handle
= -1; // n/a
535 aCommand
.Argument
<<= aProps
;
537 Any aResult
= m_xImpl
->executeCommand( aCommand
);
539 Sequence
< Any
> aErrors
;
545 Any
Content::executeCommand( const OUString
& rCommandName
,
546 const Any
& rCommandArgument
)
549 aCommand
.Name
= rCommandName
;
550 aCommand
.Handle
= -1; // n/a
551 aCommand
.Argument
= rCommandArgument
;
553 return m_xImpl
->executeCommand( aCommand
);
557 Any
Content::createCursorAny( const Sequence
< OUString
>& rPropertyNames
,
558 ResultSetInclude eMode
)
560 sal_Int32 nCount
= rPropertyNames
.getLength();
561 Sequence
< Property
> aProps( nCount
);
562 Property
* pProps
= aProps
.getArray();
563 const OUString
* pNames
= rPropertyNames
.getConstArray();
564 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
566 Property
& rProp
= pProps
[ n
];
567 rProp
.Name
= pNames
[ n
];
568 rProp
.Handle
= -1; // n/a
571 OpenCommandArgument2 aArg
;
572 aArg
.Mode
= ( eMode
== INCLUDE_FOLDERS_ONLY
)
574 : ( eMode
== INCLUDE_DOCUMENTS_ONLY
)
575 ? OpenMode::DOCUMENTS
: OpenMode::ALL
;
576 aArg
.Priority
= 0; // unused
577 aArg
.Sink
.clear(); // unused
578 aArg
.Properties
= aProps
;
581 aCommand
.Name
= "open";
582 aCommand
.Handle
= -1; // n/a
583 aCommand
.Argument
<<= aArg
;
585 return m_xImpl
->executeCommand( aCommand
);
589 Reference
< XResultSet
> Content::createCursor(
590 const Sequence
< OUString
>& rPropertyNames
,
591 ResultSetInclude eMode
)
593 Any aCursorAny
= createCursorAny( rPropertyNames
, eMode
);
595 Reference
< XDynamicResultSet
> xDynSet
;
596 Reference
< XResultSet
> aResult
;
598 aCursorAny
>>= xDynSet
;
600 aResult
= xDynSet
->getStaticResultSet();
602 OSL_ENSURE( aResult
.is(), "Content::createCursor - no cursor!" );
606 // Former, the open command directly returned a XResultSet.
607 aCursorAny
>>= aResult
;
609 OSL_ENSURE( !aResult
.is(),
610 "Content::createCursor - open-Command must "
611 "return a Reference< XDynnamicResultSet >!" );
618 Reference
< XDynamicResultSet
> Content::createDynamicCursor(
619 const Sequence
< OUString
>& rPropertyNames
,
620 ResultSetInclude eMode
)
622 Reference
< XDynamicResultSet
> aResult
;
623 createCursorAny( rPropertyNames
, eMode
) >>= aResult
;
625 OSL_ENSURE( aResult
.is(), "Content::createDynamicCursor - no cursor!" );
631 Reference
< XResultSet
> Content::createSortedCursor(
632 const Sequence
< OUString
>& rPropertyNames
,
633 const Sequence
< NumberedSortingInfo
>& rSortInfo
,
634 const Reference
< XAnyCompareFactory
>& rAnyCompareFactory
,
635 ResultSetInclude eMode
)
637 Reference
< XResultSet
> aResult
;
638 Reference
< XDynamicResultSet
> aDynSet
;
640 Any aCursorAny
= createCursorAny( rPropertyNames
, eMode
);
642 aCursorAny
>>= aDynSet
;
646 Reference
< XDynamicResultSet
> aDynResult
;
648 if( m_xImpl
->getComponentContext().is() )
650 Reference
< XSortedDynamicResultSetFactory
> aSortFactory
=
651 SortedDynamicResultSetFactory::create( m_xImpl
->getComponentContext());
653 aDynResult
= aSortFactory
->createSortedDynamicResultSet( aDynSet
,
655 rAnyCompareFactory
);
658 OSL_ENSURE( aDynResult
.is(), "Content::createSortedCursor - no sorted cursor!" );
660 if( aDynResult
.is() )
661 aResult
= aDynResult
->getStaticResultSet();
663 aResult
= aDynSet
->getStaticResultSet();
666 OSL_ENSURE( aResult
.is(), "Content::createSortedCursor - no cursor!" );
670 // Former, the open command directly returned a XResultSet.
671 aCursorAny
>>= aResult
;
673 OSL_ENSURE( !aResult
.is(),
674 "Content::createCursor - open-Command must "
675 "return a Reference< XDynnamicResultSet >!" );
682 Reference
< XInputStream
> Content::openStream()
685 return Reference
< XInputStream
>();
687 Reference
< XActiveDataSink
> xSink
= new ActiveDataSink
;
689 OpenCommandArgument2 aArg
;
690 aArg
.Mode
= OpenMode::DOCUMENT
;
691 aArg
.Priority
= 0; // unused
693 aArg
.Properties
= Sequence
< Property
>( 0 ); // unused
696 aCommand
.Name
= "open";
697 aCommand
.Handle
= -1; // n/a
698 aCommand
.Argument
<<= aArg
;
700 m_xImpl
->executeCommand( aCommand
);
702 return xSink
->getInputStream();
706 Reference
< XInputStream
> Content::openStreamNoLock()
709 return Reference
< XInputStream
>();
711 Reference
< XActiveDataSink
> xSink
= new ActiveDataSink
;
713 OpenCommandArgument2 aArg
;
714 aArg
.Mode
= OpenMode::DOCUMENT_SHARE_DENY_NONE
;
715 aArg
.Priority
= 0; // unused
717 aArg
.Properties
= Sequence
< Property
>( 0 ); // unused
720 aCommand
.Name
= "open";
721 aCommand
.Handle
= -1; // n/a
722 aCommand
.Argument
<<= aArg
;
724 m_xImpl
->executeCommand( aCommand
);
726 return xSink
->getInputStream();
730 Reference
< XStream
> Content::openWriteableStream()
733 return Reference
< XStream
>();
735 Reference
< XActiveDataStreamer
> xStreamer
= new ActiveDataStreamer
;
737 OpenCommandArgument2 aArg
;
738 aArg
.Mode
= OpenMode::DOCUMENT
;
739 aArg
.Priority
= 0; // unused
740 aArg
.Sink
= xStreamer
;
741 aArg
.Properties
= Sequence
< Property
>( 0 ); // unused
744 aCommand
.Name
= "open";
745 aCommand
.Handle
= -1; // n/a
746 aCommand
.Argument
<<= aArg
;
748 m_xImpl
->executeCommand( aCommand
);
750 return xStreamer
->getStream();
754 Reference
< XStream
> Content::openWriteableStreamNoLock()
757 return Reference
< XStream
>();
759 Reference
< XActiveDataStreamer
> xStreamer
= new ActiveDataStreamer
;
761 OpenCommandArgument2 aArg
;
762 aArg
.Mode
= OpenMode::DOCUMENT_SHARE_DENY_NONE
;
763 aArg
.Priority
= 0; // unused
764 aArg
.Sink
= xStreamer
;
765 aArg
.Properties
= Sequence
< Property
>( 0 ); // unused
768 aCommand
.Name
= "open";
769 aCommand
.Handle
= -1; // n/a
770 aCommand
.Argument
<<= aArg
;
772 m_xImpl
->executeCommand( aCommand
);
774 return xStreamer
->getStream();
778 bool Content::openStream( const Reference
< XActiveDataSink
>& rSink
)
783 OpenCommandArgument2 aArg
;
784 aArg
.Mode
= OpenMode::DOCUMENT
;
785 aArg
.Priority
= 0; // unused
787 aArg
.Properties
= Sequence
< Property
>( 0 ); // unused
790 aCommand
.Name
= "open";
791 aCommand
.Handle
= -1; // n/a
792 aCommand
.Argument
<<= aArg
;
794 m_xImpl
->executeCommand( aCommand
);
800 bool Content::openStream( const Reference
< XOutputStream
>& rStream
)
805 OpenCommandArgument2 aArg
;
806 aArg
.Mode
= OpenMode::DOCUMENT
;
807 aArg
.Priority
= 0; // unused
809 aArg
.Properties
= Sequence
< Property
>( 0 ); // unused
812 aCommand
.Name
= "open";
813 aCommand
.Handle
= -1; // n/a
814 aCommand
.Argument
<<= aArg
;
816 m_xImpl
->executeCommand( aCommand
);
822 void Content::writeStream( const Reference
< XInputStream
>& rStream
,
823 bool bReplaceExisting
)
825 InsertCommandArgument aArg
;
826 aArg
.Data
= rStream
.is() ? rStream
: new EmptyInputStream
;
827 aArg
.ReplaceExisting
= bReplaceExisting
;
830 aCommand
.Name
= "insert";
831 aCommand
.Handle
= -1; // n/a
832 aCommand
.Argument
<<= aArg
;
834 m_xImpl
->executeCommand( aCommand
);
840 Sequence
< ContentInfo
> Content::queryCreatableContentsInfo()
842 // First, try it using "CreatableContentsInfo" property -> the "new" way.
843 Sequence
< ContentInfo
> aInfo
;
844 if ( getPropertyValue(
845 "CreatableContentsInfo" )
849 // Second, try it using XContentCreator interface -> the "old" way (not
850 // providing the chance to supply an XCommandEnvironment.
851 Reference
< XContentCreator
> xCreator( m_xImpl
->getContent(), UNO_QUERY
);
853 aInfo
= xCreator
->queryCreatableContentsInfo();
859 bool Content::insertNewContent( const OUString
& rContentType
,
860 const Sequence
< OUString
>&
862 const Sequence
< Any
>& rPropertyValues
,
863 Content
& rNewContent
)
865 return insertNewContent( rContentType
,
868 new EmptyInputStream
,
873 bool Content::insertNewContent( const OUString
& rContentType
,
874 const Sequence
< OUString
>&
876 const Sequence
< Any
>& rPropertyValues
,
877 const Reference
< XInputStream
>& rData
,
878 Content
& rNewContent
)
880 if ( rContentType
.isEmpty() )
883 // First, try it using "createNewContent" command -> the "new" way.
885 aInfo
.Type
= rContentType
;
886 aInfo
.Attributes
= 0;
889 aCommand
.Name
= "createNewContent";
890 aCommand
.Handle
= -1; // n/a
891 aCommand
.Argument
<<= aInfo
;
893 Reference
< XContent
> xNew
;
896 m_xImpl
->executeCommand( aCommand
) >>= xNew
;
898 catch ( RuntimeException
const & )
902 catch ( Exception
const & )
908 // Second, try it using XContentCreator interface -> the "old"
909 // way (not providing the chance to supply an XCommandEnvironment.
910 Reference
< XContentCreator
> xCreator( m_xImpl
->getContent(), UNO_QUERY
);
912 if ( !xCreator
.is() )
915 xNew
= xCreator
->createNewContent( aInfo
);
922 xNew
, m_xImpl
->getEnvironment(), m_xImpl
->getComponentContext() );
923 aNewContent
.setPropertyValues( rPropertyNames
, rPropertyValues
);
924 aNewContent
.executeCommand( "insert",
926 InsertCommandArgument(
927 rData
.is() ? rData
: new EmptyInputStream
,
928 false /* ReplaceExisting */ ) ) );
929 aNewContent
.m_xImpl
->inserted();
931 rNewContent
= aNewContent
;
936 void Content::transferContent( const Content
& rSourceContent
,
937 InsertOperation eOperation
,
938 const OUString
& rTitle
,
939 const sal_Int32 nNameClashAction
,
940 const OUString
& rMimeType
,
942 const OUString
& rVersionComment
,
943 OUString
* pResultURL
,
944 const OUString
& rDocumentId
) const
946 Reference
< XUniversalContentBroker
> pBroker(
947 UniversalContentBroker::create( m_xImpl
->getComponentContext() ) );
949 // Execute command "globalTransfer" at UCB.
951 TransferCommandOperation eTransOp
= TransferCommandOperation();
952 OUString
sCommand( "globalTransfer" );
953 bool bCheckIn
= false;
954 switch ( eOperation
)
956 case InsertOperation::Copy
:
957 eTransOp
= TransferCommandOperation_COPY
;
960 case InsertOperation::Move
:
961 eTransOp
= TransferCommandOperation_MOVE
;
964 case InsertOperation::Checkin
:
965 eTransOp
= TransferCommandOperation_COPY
;
966 sCommand
= "checkin";
971 aCommand
.Name
= sCommand
;
972 aCommand
.Handle
= -1; // n/a
976 GlobalTransferCommandArgument2
aTransferArg(
978 rSourceContent
.getURL(), // SourceURL
979 getURL(), // TargetFolderURL,
984 aCommand
.Argument
<<= aTransferArg
;
988 CheckinArgument
aCheckinArg( bMajorVersion
, rVersionComment
,
989 rSourceContent
.getURL(), getURL(), rTitle
, rMimeType
);
990 aCommand
.Argument
<<= aCheckinArg
;
993 Any aRet
= pBroker
->execute( aCommand
, 0, m_xImpl
->getEnvironment() );
994 if ( pResultURL
!= nullptr )
995 aRet
>>= *pResultURL
;
999 bool Content::isFolder()
1001 bool bFolder
= false;
1002 if ( getPropertyValue("IsFolder")
1006 ucbhelper::cancelCommandExecution(
1007 makeAny( UnknownPropertyException(
1008 "Unable to retrieve value of property 'IsFolder'!",
1010 m_xImpl
->getEnvironment() );
1012 #if !(defined(_MSC_VER) && defined(ENABLE_LTO))
1013 // Unreachable - cancelCommandExecution always throws an exception.
1014 // But some compilers complain...
1020 SAL_WNOUNREACHABLE_CODE_PUSH
1022 bool Content::isDocument()
1025 if ( getPropertyValue("IsDocument")
1029 ucbhelper::cancelCommandExecution(
1030 makeAny( UnknownPropertyException(
1031 "Unable to retrieve value of property 'IsDocument'!",
1033 m_xImpl
->getEnvironment() );
1035 // Unreachable - cancelCommandExecution always throws an exception,
1036 // But some compilers complain...
1040 SAL_WNOUNREACHABLE_CODE_POP
1042 void Content::lock()
1045 aCommand
.Name
= "lock";
1046 aCommand
.Handle
= -1; // n/a
1048 m_xImpl
->executeCommand( aCommand
);
1052 void Content::unlock()
1056 aCommand
.Name
= "unlock";
1057 aCommand
.Handle
= -1; // n/a
1059 m_xImpl
->executeCommand( aCommand
);
1064 // Content_Impl Implementation.
1067 Content_Impl::Content_Impl( const Reference
< XComponentContext
>& rCtx
,
1068 const Reference
< XContent
>& rContent
,
1069 const Reference
< XCommandEnvironment
>& rEnv
)
1071 m_xContent( rContent
),
1075 if ( m_xContent
.is() )
1077 m_xContentEventListener
= new ContentEventListener_Impl( *this );
1078 m_xContent
->addContentEventListener( m_xContentEventListener
);
1080 #if OSL_DEBUG_LEVEL > 0
1081 // Only done on demand in product version for performance reasons,
1082 // but a nice debug helper.
1089 void Content_Impl::reinit( const Reference
< XContent
>& xContent
)
1091 osl::MutexGuard
aGuard( m_aMutex
);
1093 m_xCommandProcessor
= nullptr;
1095 // #92581# - Don't reset m_aURL!!!
1097 if ( m_xContent
.is() )
1101 m_xContent
->removeContentEventListener( m_xContentEventListener
);
1103 catch ( RuntimeException
const & )
1108 if ( xContent
.is() )
1110 m_xContent
= xContent
;
1111 m_xContent
->addContentEventListener( m_xContentEventListener
);
1113 #if OSL_DEBUG_LEVEL > 0
1114 // Only done on demand in product version for performance reasons,
1115 // but a nice debug helper.
1121 // We need m_xContent's URL in order to be able to create the
1122 // content object again if demanded ( --> Content_Impl::getContent() )
1125 m_xContent
= nullptr;
1131 Content_Impl::~Content_Impl()
1133 if ( m_xContent
.is() )
1137 m_xContent
->removeContentEventListener( m_xContentEventListener
);
1139 catch ( RuntimeException
const & )
1146 void Content_Impl::disposing( const EventObject
& Source
)
1148 Reference
<XContent
> xContent
;
1151 osl::MutexGuard
aGuard( m_aMutex
);
1152 if(Source
.Source
!= m_xContent
)
1155 xContent
= m_xContent
;
1158 m_xCommandProcessor
= nullptr;
1159 m_xContent
= nullptr;
1162 if ( xContent
.is() )
1166 xContent
->removeContentEventListener( m_xContentEventListener
);
1168 catch ( RuntimeException
const & )
1175 const OUString
& Content_Impl::getURL() const
1177 if ( m_aURL
.isEmpty() && m_xContent
.is() )
1179 osl::MutexGuard
aGuard( m_aMutex
);
1181 if ( m_aURL
.isEmpty() && m_xContent
.is() )
1183 Reference
< XContentIdentifier
> xId
= m_xContent
->getIdentifier();
1185 m_aURL
= xId
->getContentIdentifier();
1193 Reference
< XContent
> Content_Impl::getContent()
1195 if ( !m_xContent
.is() && !m_aURL
.isEmpty() )
1197 osl::MutexGuard
aGuard( m_aMutex
);
1199 if ( !m_xContent
.is() && !m_aURL
.isEmpty() )
1201 Reference
< XUniversalContentBroker
> pBroker(
1202 UniversalContentBroker::create( getComponentContext() ) );
1204 OSL_ENSURE( pBroker
->queryContentProviders().hasElements(),
1205 "Content Broker not configured (no providers)!" );
1207 Reference
< XContentIdentifier
> xId
1208 = pBroker
->createContentIdentifier( m_aURL
);
1210 OSL_ENSURE( xId
.is(), "No Content Identifier!" );
1216 m_xContent
= pBroker
->queryContent( xId
);
1218 catch ( IllegalIdentifierException
const & )
1222 if ( m_xContent
.is() )
1223 m_xContent
->addContentEventListener(
1224 m_xContentEventListener
);
1233 Reference
< XCommandProcessor
> Content_Impl::getCommandProcessor()
1235 if ( !m_xCommandProcessor
.is() )
1237 osl::MutexGuard
aGuard( m_aMutex
);
1239 if ( !m_xCommandProcessor
.is() )
1240 m_xCommandProcessor
.set( getContent(), UNO_QUERY
);
1243 return m_xCommandProcessor
;
1247 Any
Content_Impl::executeCommand( const Command
& rCommand
)
1249 Reference
< XCommandProcessor
> xProc
= getCommandProcessor();
1254 return xProc
->execute( rCommand
, 0, m_xEnv
);
1258 inline const Reference
< XCommandEnvironment
>&
1259 Content_Impl::getEnvironment() const
1265 inline void Content_Impl::setEnvironment(
1266 const Reference
< XCommandEnvironment
>& xNewEnv
)
1268 osl::MutexGuard
aGuard( m_aMutex
);
1273 void Content_Impl::inserted()
1275 // URL might have changed during 'insert' => recalculate in next getURL()
1276 osl::MutexGuard
aGuard( m_aMutex
);
1281 // ContentEventListener_Impl Implementation.
1284 // XInterface methods.
1286 void SAL_CALL
ContentEventListener_Impl::acquire()
1289 OWeakObject::acquire();
1292 void SAL_CALL
ContentEventListener_Impl::release()
1295 OWeakObject::release();
1298 css::uno::Any SAL_CALL
ContentEventListener_Impl::queryInterface( const css::uno::Type
& rType
)
1300 css::uno::Any aRet
= cppu::queryInterface( rType
,
1301 static_cast< XContentEventListener
* >(this),
1302 static_cast< XEventListener
* >(this)
1304 return aRet
.hasValue() ? aRet
: OWeakObject::queryInterface( rType
);
1307 // XContentEventListener methods.
1311 void SAL_CALL
ContentEventListener_Impl::contentEvent( const ContentEvent
& evt
)
1313 if ( evt
.Source
== m_rContent
.m_xContent
)
1315 switch ( evt
.Action
)
1317 case ContentAction::DELETED
:
1318 m_rContent
.reinit( Reference
< XContent
>() );
1321 case ContentAction::EXCHANGED
:
1322 m_rContent
.reinit( evt
.Content
);
1332 // XEventListenr methods.
1336 void SAL_CALL
ContentEventListener_Impl::disposing( const EventObject
& Source
)
1338 m_rContent
.disposing(Source
);
1341 } /* namespace ucbhelper */
1343 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */