calc: on editing invalidation of view with different zoom is wrong
[LibreOffice.git] / ucbhelper / source / client / content.cxx
blob8feab846baee10da4bc28a85d30b26cfb06ab8a6
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
22 #include <cassert>
24 #include <o3tl/unreachable.hxx>
25 #include <osl/diagnose.h>
26 #include <mutex>
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;
75 namespace ucbhelper
78 namespace {
80 class EmptyInputStream : public ::cppu::WeakImplHelper< XInputStream >
82 public:
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 )
97 data.realloc( 0 );
98 return 0;
101 sal_Int32 EmptyInputStream::readSomeBytes(
102 Sequence< sal_Int8 > & data, sal_Int32 )
104 data.realloc( 0 );
105 return 0;
108 void EmptyInputStream::skipBytes( sal_Int32 )
112 sal_Int32 EmptyInputStream::available()
114 return 0;
117 void EmptyInputStream::closeInput()
123 namespace {
125 class ContentEventListener_Impl : public cppu::OWeakObject,
126 public XContentEventListener
128 Content_Impl& m_rContent;
130 public:
131 explicit ContentEventListener_Impl( Content_Impl& rContent )
132 : m_rContent( rContent ) {}
134 // XInterface
135 virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type & rType ) override;
136 virtual void SAL_CALL acquire()
137 noexcept override;
138 virtual void SAL_CALL release()
139 noexcept override;
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;
164 private:
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;
170 public:
171 Content_Impl() {};
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 );
190 void inserted();
194 // Helpers.
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 );
203 if ( !xProv.is() )
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 );
221 if (!xId.is())
223 ensureContentProviderForURL( rBroker, rURL );
225 throw ContentCreationException(
226 "Unable to create Content Identifier!",
227 Reference< XInterface >(),
228 ContentCreationError_IDENTIFIER_CREATION_FAILED );
231 return xId;
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;
249 OUString msg;
252 xContent = rBroker->queryContent( xId );
254 catch ( IllegalIdentifierException const & e )
256 msg = e.Message;
257 // handled below.
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 );
270 return xContent;
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);
288 return xContent;
292 // Content Implementation.
295 Content::Content()
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);
335 // static
336 bool Content::create( const OUString& rURL,
337 const Reference< XCommandEnvironment >& rEnv,
338 const Reference< XComponentContext >& rCtx,
339 Content& rContent )
341 Reference< XUniversalContentBroker > pBroker(
342 UniversalContentBroker::create( rCtx ) );
344 Reference< XContentIdentifier > xId
345 = getContentIdentifierNoThrow(pBroker, rURL);
346 if ( !xId.is() )
347 return false;
349 Reference< XContent > xContent = getContentNoThrow(pBroker, xId);
350 if ( !xContent.is() )
351 return false;
353 rContent.m_xImpl
354 = new Content_Impl( rCtx, xContent, rEnv );
356 return true;
360 Content::~Content()
365 Content& Content::operator=( const Content& rOther )
367 m_xImpl = rOther.m_xImpl;
368 return *this;
371 Content& Content::operator=( Content&& rOther ) noexcept
373 m_xImpl = std::move(rOther.m_xImpl);
374 return *this;
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()
404 Command aCommand;
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;
412 aResult >>= xInfo;
413 return xInfo;
417 Reference< XPropertySetInfo > Content::getProperties()
419 static constexpr OUStringLiteral sgetPropertySetInfo = u"getPropertySetInfo";
420 Command aCommand;
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;
428 aResult >>= xInfo;
429 return 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,
443 const Any& rValue )
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 );
463 if ( xRow.is() )
465 Any* pValues = aValues.getArray();
467 for ( sal_Int32 n = 0; n < nCount; ++n )
468 pValues[ n ] = xRow->getObject( n + 1, Reference< XNameAccess >() );
471 return aValues;
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
490 // rProp.Type =
491 // rProp.Attributes = ;
494 static constexpr OUStringLiteral sgetPropertyValues = u"getPropertyValues";
495 Command aCommand;
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;
503 aResult >>= xRow;
504 return 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!",
518 get(),
519 -1 ) ),
520 m_xImpl->getEnvironment() );
521 // Unreachable
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 ];
538 // rProp.State = ;
541 Command aCommand;
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;
549 aResult >>= aErrors;
550 return aErrors;
554 Any Content::executeCommand( const OUString& rCommandName,
555 const Any& rCommandArgument )
557 Command aCommand;
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 )
582 ? OpenMode::FOLDERS
583 : ( eMode == INCLUDE_DOCUMENTS_ONLY )
584 ? OpenMode::DOCUMENTS : OpenMode::ALL;
585 aArg.Priority = 0; // unused
586 aArg.Sink.clear(); // unused
587 aArg.Properties = aProps;
589 Command aCommand;
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;
608 if ( xDynSet.is() )
609 aResult = xDynSet->getStaticResultSet();
611 OSL_ENSURE( aResult.is(), "Content::createCursor - no cursor!" );
613 if ( !aResult.is() )
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 >!" );
623 return aResult;
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!" );
636 return aResult;
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;
653 if( aDynSet.is() )
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,
663 rSortInfo,
664 rAnyCompareFactory );
667 OSL_ENSURE( aDynResult.is(), "Content::createSortedCursor - no sorted cursor!" );
669 if( aDynResult.is() )
670 aResult = aDynResult->getStaticResultSet();
671 else
672 aResult = aDynSet->getStaticResultSet();
675 OSL_ENSURE( aResult.is(), "Content::createSortedCursor - no cursor!" );
677 if ( !aResult.is() )
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 >!" );
687 return aResult;
691 Reference< XInputStream > Content::openStream()
693 if ( !isDocument() )
694 return Reference< XInputStream >();
696 Reference< XActiveDataSink > xSink = new ActiveDataSink;
698 OpenCommandArgument2 aArg;
699 aArg.Mode = OpenMode::DOCUMENT;
700 aArg.Priority = 0; // unused
701 aArg.Sink = xSink;
702 aArg.Properties = Sequence< Property >( 0 ); // unused
704 Command aCommand;
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()
717 if ( !isDocument() )
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
725 aArg.Sink = xSink;
726 aArg.Properties = Sequence< Property >( 0 ); // unused
728 Command aCommand;
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()
741 if ( !isDocument() )
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
752 Command aCommand;
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()
765 if ( !isDocument() )
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
776 Command aCommand;
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 )
789 if ( !isDocument() )
790 return false;
792 OpenCommandArgument2 aArg;
793 aArg.Mode = OpenMode::DOCUMENT;
794 aArg.Priority = 0; // unused
795 aArg.Sink = rSink;
796 aArg.Properties = Sequence< Property >( 0 ); // unused
798 Command aCommand;
799 aCommand.Name = "open";
800 aCommand.Handle = -1; // n/a
801 aCommand.Argument <<= aArg;
803 m_xImpl->executeCommand( aCommand );
805 return true;
809 bool Content::openStream( const Reference< XOutputStream >& rStream )
811 if ( !isDocument() )
812 return false;
814 OpenCommandArgument2 aArg;
815 aArg.Mode = OpenMode::DOCUMENT;
816 aArg.Priority = 0; // unused
817 aArg.Sink = rStream;
818 aArg.Properties = Sequence< Property >( 0 ); // unused
820 Command aCommand;
821 aCommand.Name = "open";
822 aCommand.Handle = -1; // n/a
823 aCommand.Argument <<= aArg;
825 m_xImpl->executeCommand( aCommand );
827 return true;
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;
838 Command aCommand;
839 aCommand.Name = "insert";
840 aCommand.Handle = -1; // n/a
841 aCommand.Argument <<= aArg;
843 m_xImpl->executeCommand( aCommand );
845 m_xImpl->inserted();
849 Sequence< ContentInfo > Content::queryCreatableContentsInfo()
851 // First, try it using "CreatableContentsInfo" property -> the "new" way.
852 Sequence< ContentInfo > aInfo;
853 if ( getPropertyValue(
854 "CreatableContentsInfo" )
855 >>= aInfo )
856 return aInfo;
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 );
861 if ( xCreator.is() )
862 aInfo = xCreator->queryCreatableContentsInfo();
864 return aInfo;
868 bool Content::insertNewContent( const OUString& rContentType,
869 const Sequence< OUString >&
870 rPropertyNames,
871 const Sequence< Any >& rPropertyValues,
872 Content& rNewContent )
874 return insertNewContent( rContentType,
875 rPropertyNames,
876 rPropertyValues,
877 new EmptyInputStream,
878 rNewContent );
882 bool Content::insertNewContent( const OUString& rContentType,
883 const Sequence< OUString >&
884 rPropertyNames,
885 const Sequence< Any >& rPropertyValues,
886 const Reference< XInputStream >& rData,
887 Content& rNewContent )
889 if ( rContentType.isEmpty() )
890 return false;
892 // First, try it using "createNewContent" command -> the "new" way.
893 ContentInfo aInfo;
894 aInfo.Type = rContentType;
895 aInfo.Attributes = 0;
897 Command aCommand;
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 & )
909 throw;
911 catch ( Exception const & )
915 if ( !xNew.is() )
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() )
922 return false;
924 xNew = xCreator->createNewContent( aInfo );
926 if ( !xNew.is() )
927 return false;
930 Content aNewContent(
931 xNew, m_xImpl->getEnvironment(), m_xImpl->getComponentContext() );
932 aNewContent.setPropertyValues( rPropertyNames, rPropertyValues );
933 aNewContent.executeCommand( "insert",
934 Any(
935 InsertCommandArgument(
936 rData.is() ? rData : new EmptyInputStream,
937 false /* ReplaceExisting */ ) ) );
938 aNewContent.m_xImpl->inserted();
940 rNewContent = aNewContent;
941 return true;
945 void Content::transferContent( const Content& rSourceContent,
946 InsertOperation eOperation,
947 const OUString & rTitle,
948 const sal_Int32 nNameClashAction,
949 const OUString & rMimeType,
950 bool bMajorVersion,
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;
967 break;
969 case InsertOperation::Move:
970 eTransOp = TransferCommandOperation_MOVE;
971 break;
973 case InsertOperation::Checkin:
974 eTransOp = TransferCommandOperation_COPY;
975 sCommand = "checkin";
976 bCheckIn = true;
977 break;
979 Command aCommand;
980 aCommand.Name = sCommand;
981 aCommand.Handle = -1; // n/a
983 if ( !bCheckIn )
985 GlobalTransferCommandArgument2 aTransferArg(
986 eTransOp,
987 rSourceContent.getURL(), // SourceURL
988 getURL(), // TargetFolderURL,
989 rTitle,
990 nNameClashAction,
991 rMimeType,
992 rDocumentId );
993 aCommand.Argument <<= aTransferArg;
995 else
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")
1012 >>= bFolder )
1013 return bFolder;
1015 ucbhelper::cancelCommandExecution(
1016 Any( UnknownPropertyException(
1017 "Unable to retrieve value of property 'IsFolder'!",
1018 get() ) ),
1019 m_xImpl->getEnvironment() );
1021 O3TL_UNREACHABLE;
1025 bool Content::isDocument()
1027 bool bDoc = false;
1028 if ( getPropertyValue("IsDocument")
1029 >>= bDoc )
1030 return bDoc;
1032 ucbhelper::cancelCommandExecution(
1033 Any( UnknownPropertyException(
1034 "Unable to retrieve value of property 'IsDocument'!",
1035 get() ) ),
1036 m_xImpl->getEnvironment() );
1038 O3TL_UNREACHABLE;
1041 void Content::lock()
1043 Command aCommand;
1044 aCommand.Name = "lock";
1045 aCommand.Handle = -1; // n/a
1047 m_xImpl->executeCommand( aCommand );
1051 void Content::unlock()
1054 Command aCommand;
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 )
1069 : m_xCtx( rCtx ),
1070 m_xContent( rContent ),
1071 m_xEnv( rEnv )
1073 assert(rCtx.is());
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.
1082 getURL();
1083 #endif
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.
1115 getURL_NoLock();
1116 #endif
1118 else
1120 // We need m_xContent's URL in order to be able to create the
1121 // content object again if demanded ( --> Content_Impl::getContent() )
1122 getURL_NoLock();
1124 m_xContent = nullptr;
1129 // virtual
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)
1152 return;
1154 xContent = m_xContent;
1156 m_aURL.clear();
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();
1183 return m_aURL;
1186 const OUString& Content_Impl::getURL_NoLock() const
1188 if ( m_aURL.isEmpty() && m_xContent.is() )
1190 Reference< XContentIdentifier > xId = m_xContent->getIdentifier();
1191 if ( xId.is() )
1192 m_aURL = xId->getContentIdentifier();
1195 return m_aURL;
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();
1205 return m_xContent;
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!" );
1223 if ( xId.is() )
1227 m_xContent = pBroker->queryContent( xId );
1229 catch ( IllegalIdentifierException const & )
1233 if ( m_xContent.is() )
1234 m_xContent->addContentEventListener(
1235 m_xContentEventListener );
1239 return m_xContent;
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();
1260 if ( !xProc.is() )
1261 return Any();
1263 // Execute command
1264 return xProc->execute( rCommand, 0, m_xEnv );
1268 inline const Reference< XCommandEnvironment >&
1269 Content_Impl::getEnvironment() const
1271 return m_xEnv;
1275 inline void Content_Impl::setEnvironment(
1276 const Reference< XCommandEnvironment >& xNewEnv )
1278 std::unique_lock aGuard( m_aMutex );
1279 m_xEnv = xNewEnv;
1283 void Content_Impl::inserted()
1285 // URL might have changed during 'insert' => recalculate in next getURL()
1286 std::unique_lock aGuard( m_aMutex );
1287 m_aURL.clear();
1291 // ContentEventListener_Impl Implementation.
1294 // XInterface methods.
1296 void SAL_CALL ContentEventListener_Impl::acquire()
1297 noexcept
1299 OWeakObject::acquire();
1302 void SAL_CALL ContentEventListener_Impl::release()
1303 noexcept
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.
1320 // virtual
1321 void SAL_CALL ContentEventListener_Impl::contentEvent( const ContentEvent& evt )
1323 if ( evt.Source != m_rContent.m_xContent )
1324 return;
1326 switch ( evt.Action )
1328 case ContentAction::DELETED:
1329 m_rContent.reinit( Reference< XContent >() );
1330 break;
1332 case ContentAction::EXCHANGED:
1333 m_rContent.reinit( evt.Content );
1334 break;
1336 default:
1337 break;
1342 // XEventListenr methods.
1345 // virtual
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: */