Bump version to 6.4.7.2.M8
[LibreOffice.git] / ucbhelper / source / client / content.cxx
blob9641a4e0a87a9bd29fa7d4edb129abb48c1dc177
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 <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;
74 namespace ucbhelper
77 class EmptyInputStream : public ::cppu::WeakImplHelper< XInputStream >
79 public:
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 )
92 data.realloc( 0 );
93 return 0;
96 sal_Int32 EmptyInputStream::readSomeBytes(
97 Sequence< sal_Int8 > & data, sal_Int32 )
99 data.realloc( 0 );
100 return 0;
103 void EmptyInputStream::skipBytes( sal_Int32 )
107 sal_Int32 EmptyInputStream::available()
109 return 0;
112 void EmptyInputStream::closeInput()
117 // class ContentEventListener_Impl.
120 class ContentEventListener_Impl : public cppu::OWeakObject,
121 public XContentEventListener
123 Content_Impl& m_rContent;
125 public:
126 explicit ContentEventListener_Impl( Content_Impl& rContent )
127 : m_rContent( rContent ) {}
129 // XInterface
130 virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type & rType ) override;
131 virtual void SAL_CALL acquire()
132 throw() override;
133 virtual void SAL_CALL release()
134 throw() override;
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;
159 private:
160 void reinit( const Reference< XContent >& xContent );
161 void disposing(const EventObject& Source);
163 public:
164 Content_Impl() {};
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 );
183 void inserted();
187 // Helpers.
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 );
196 if ( !xProv.is() )
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 );
214 if (!xId.is())
216 ensureContentProviderForURL( rBroker, rURL );
218 throw ContentCreationException(
219 "Unable to create Content Identifier!",
220 Reference< XInterface >(),
221 ContentCreationError_IDENTIFIER_CREATION_FAILED );
224 return xId;
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;
242 OUString msg;
245 xContent = rBroker->queryContent( xId );
247 catch ( IllegalIdentifierException const & e )
249 msg = e.Message;
250 // handled below.
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 );
263 return xContent;
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);
281 return xContent;
285 // Content Implementation.
288 Content::Content()
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);
328 // static
329 bool Content::create( const OUString& rURL,
330 const Reference< XCommandEnvironment >& rEnv,
331 const Reference< XComponentContext >& rCtx,
332 Content& rContent )
334 Reference< XUniversalContentBroker > pBroker(
335 UniversalContentBroker::create( rCtx ) );
337 Reference< XContentIdentifier > xId
338 = getContentIdentifierNoThrow(pBroker, rURL);
339 if ( !xId.is() )
340 return false;
342 Reference< XContent > xContent = getContentNoThrow(pBroker, xId);
343 if ( !xContent.is() )
344 return false;
346 rContent.m_xImpl
347 = new Content_Impl( rCtx, xContent, rEnv );
349 return true;
353 Content::~Content()
358 Content& Content::operator=( const Content& rOther )
360 m_xImpl = rOther.m_xImpl;
361 return *this;
364 Content& Content::operator=( Content&& rOther ) noexcept
366 m_xImpl = std::move(rOther.m_xImpl);
367 return *this;
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()
397 Command aCommand;
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;
405 aResult >>= xInfo;
406 return xInfo;
410 Reference< XPropertySetInfo > Content::getProperties()
412 Command aCommand;
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;
420 aResult >>= xInfo;
421 return 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,
435 const Any& rValue )
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 );
455 if ( xRow.is() )
457 Any* pValues = aValues.getArray();
459 for ( sal_Int32 n = 0; n < nCount; ++n )
460 pValues[ n ] = xRow->getObject( n + 1, Reference< XNameAccess >() );
463 return aValues;
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
482 // rProp.Type =
483 // rProp.Attributes = ;
486 Command aCommand;
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;
494 aResult >>= xRow;
495 return 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!",
509 get(),
510 -1 ) ),
511 m_xImpl->getEnvironment() );
512 // Unreachable
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 ];
529 // rProp.State = ;
532 Command aCommand;
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;
540 aResult >>= aErrors;
541 return aErrors;
545 Any Content::executeCommand( const OUString& rCommandName,
546 const Any& rCommandArgument )
548 Command aCommand;
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 )
573 ? OpenMode::FOLDERS
574 : ( eMode == INCLUDE_DOCUMENTS_ONLY )
575 ? OpenMode::DOCUMENTS : OpenMode::ALL;
576 aArg.Priority = 0; // unused
577 aArg.Sink.clear(); // unused
578 aArg.Properties = aProps;
580 Command aCommand;
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;
599 if ( xDynSet.is() )
600 aResult = xDynSet->getStaticResultSet();
602 OSL_ENSURE( aResult.is(), "Content::createCursor - no cursor!" );
604 if ( !aResult.is() )
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 >!" );
614 return aResult;
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!" );
627 return aResult;
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;
644 if( aDynSet.is() )
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,
654 rSortInfo,
655 rAnyCompareFactory );
658 OSL_ENSURE( aDynResult.is(), "Content::createSortedCursor - no sorted cursor!" );
660 if( aDynResult.is() )
661 aResult = aDynResult->getStaticResultSet();
662 else
663 aResult = aDynSet->getStaticResultSet();
666 OSL_ENSURE( aResult.is(), "Content::createSortedCursor - no cursor!" );
668 if ( !aResult.is() )
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 >!" );
678 return aResult;
682 Reference< XInputStream > Content::openStream()
684 if ( !isDocument() )
685 return Reference< XInputStream >();
687 Reference< XActiveDataSink > xSink = new ActiveDataSink;
689 OpenCommandArgument2 aArg;
690 aArg.Mode = OpenMode::DOCUMENT;
691 aArg.Priority = 0; // unused
692 aArg.Sink = xSink;
693 aArg.Properties = Sequence< Property >( 0 ); // unused
695 Command aCommand;
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()
708 if ( !isDocument() )
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
716 aArg.Sink = xSink;
717 aArg.Properties = Sequence< Property >( 0 ); // unused
719 Command aCommand;
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()
732 if ( !isDocument() )
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
743 Command aCommand;
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()
756 if ( !isDocument() )
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
767 Command aCommand;
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 )
780 if ( !isDocument() )
781 return false;
783 OpenCommandArgument2 aArg;
784 aArg.Mode = OpenMode::DOCUMENT;
785 aArg.Priority = 0; // unused
786 aArg.Sink = rSink;
787 aArg.Properties = Sequence< Property >( 0 ); // unused
789 Command aCommand;
790 aCommand.Name = "open";
791 aCommand.Handle = -1; // n/a
792 aCommand.Argument <<= aArg;
794 m_xImpl->executeCommand( aCommand );
796 return true;
800 bool Content::openStream( const Reference< XOutputStream >& rStream )
802 if ( !isDocument() )
803 return false;
805 OpenCommandArgument2 aArg;
806 aArg.Mode = OpenMode::DOCUMENT;
807 aArg.Priority = 0; // unused
808 aArg.Sink = rStream;
809 aArg.Properties = Sequence< Property >( 0 ); // unused
811 Command aCommand;
812 aCommand.Name = "open";
813 aCommand.Handle = -1; // n/a
814 aCommand.Argument <<= aArg;
816 m_xImpl->executeCommand( aCommand );
818 return true;
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;
829 Command aCommand;
830 aCommand.Name = "insert";
831 aCommand.Handle = -1; // n/a
832 aCommand.Argument <<= aArg;
834 m_xImpl->executeCommand( aCommand );
836 m_xImpl->inserted();
840 Sequence< ContentInfo > Content::queryCreatableContentsInfo()
842 // First, try it using "CreatableContentsInfo" property -> the "new" way.
843 Sequence< ContentInfo > aInfo;
844 if ( getPropertyValue(
845 "CreatableContentsInfo" )
846 >>= aInfo )
847 return aInfo;
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 );
852 if ( xCreator.is() )
853 aInfo = xCreator->queryCreatableContentsInfo();
855 return aInfo;
859 bool Content::insertNewContent( const OUString& rContentType,
860 const Sequence< OUString >&
861 rPropertyNames,
862 const Sequence< Any >& rPropertyValues,
863 Content& rNewContent )
865 return insertNewContent( rContentType,
866 rPropertyNames,
867 rPropertyValues,
868 new EmptyInputStream,
869 rNewContent );
873 bool Content::insertNewContent( const OUString& rContentType,
874 const Sequence< OUString >&
875 rPropertyNames,
876 const Sequence< Any >& rPropertyValues,
877 const Reference< XInputStream >& rData,
878 Content& rNewContent )
880 if ( rContentType.isEmpty() )
881 return false;
883 // First, try it using "createNewContent" command -> the "new" way.
884 ContentInfo aInfo;
885 aInfo.Type = rContentType;
886 aInfo.Attributes = 0;
888 Command aCommand;
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 & )
900 throw;
902 catch ( Exception const & )
906 if ( !xNew.is() )
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() )
913 return false;
915 xNew = xCreator->createNewContent( aInfo );
917 if ( !xNew.is() )
918 return false;
921 Content aNewContent(
922 xNew, m_xImpl->getEnvironment(), m_xImpl->getComponentContext() );
923 aNewContent.setPropertyValues( rPropertyNames, rPropertyValues );
924 aNewContent.executeCommand( "insert",
925 makeAny(
926 InsertCommandArgument(
927 rData.is() ? rData : new EmptyInputStream,
928 false /* ReplaceExisting */ ) ) );
929 aNewContent.m_xImpl->inserted();
931 rNewContent = aNewContent;
932 return true;
936 void Content::transferContent( const Content& rSourceContent,
937 InsertOperation eOperation,
938 const OUString & rTitle,
939 const sal_Int32 nNameClashAction,
940 const OUString & rMimeType,
941 bool bMajorVersion,
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;
958 break;
960 case InsertOperation::Move:
961 eTransOp = TransferCommandOperation_MOVE;
962 break;
964 case InsertOperation::Checkin:
965 eTransOp = TransferCommandOperation_COPY;
966 sCommand = "checkin";
967 bCheckIn = true;
968 break;
970 Command aCommand;
971 aCommand.Name = sCommand;
972 aCommand.Handle = -1; // n/a
974 if ( !bCheckIn )
976 GlobalTransferCommandArgument2 aTransferArg(
977 eTransOp,
978 rSourceContent.getURL(), // SourceURL
979 getURL(), // TargetFolderURL,
980 rTitle,
981 nNameClashAction,
982 rMimeType,
983 rDocumentId );
984 aCommand.Argument <<= aTransferArg;
986 else
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")
1003 >>= bFolder )
1004 return bFolder;
1006 ucbhelper::cancelCommandExecution(
1007 makeAny( UnknownPropertyException(
1008 "Unable to retrieve value of property 'IsFolder'!",
1009 get() ) ),
1010 m_xImpl->getEnvironment() );
1012 #if !(defined(_MSC_VER) && defined(ENABLE_LTO))
1013 // Unreachable - cancelCommandExecution always throws an exception.
1014 // But some compilers complain...
1015 return false;
1016 #endif
1020 SAL_WNOUNREACHABLE_CODE_PUSH
1022 bool Content::isDocument()
1024 bool bDoc = false;
1025 if ( getPropertyValue("IsDocument")
1026 >>= bDoc )
1027 return bDoc;
1029 ucbhelper::cancelCommandExecution(
1030 makeAny( UnknownPropertyException(
1031 "Unable to retrieve value of property 'IsDocument'!",
1032 get() ) ),
1033 m_xImpl->getEnvironment() );
1035 // Unreachable - cancelCommandExecution always throws an exception,
1036 // But some compilers complain...
1037 return false;
1040 SAL_WNOUNREACHABLE_CODE_POP
1042 void Content::lock()
1044 Command aCommand;
1045 aCommand.Name = "lock";
1046 aCommand.Handle = -1; // n/a
1048 m_xImpl->executeCommand( aCommand );
1052 void Content::unlock()
1055 Command aCommand;
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 )
1070 : m_xCtx( rCtx ),
1071 m_xContent( rContent ),
1072 m_xEnv( rEnv )
1074 assert(rCtx.is());
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.
1083 getURL();
1084 #endif
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.
1116 getURL();
1117 #endif
1119 else
1121 // We need m_xContent's URL in order to be able to create the
1122 // content object again if demanded ( --> Content_Impl::getContent() )
1123 getURL();
1125 m_xContent = nullptr;
1130 // virtual
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)
1153 return;
1155 xContent = m_xContent;
1157 m_aURL.clear();
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();
1184 if ( xId.is() )
1185 m_aURL = xId->getContentIdentifier();
1189 return m_aURL;
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!" );
1212 if ( xId.is() )
1216 m_xContent = pBroker->queryContent( xId );
1218 catch ( IllegalIdentifierException const & )
1222 if ( m_xContent.is() )
1223 m_xContent->addContentEventListener(
1224 m_xContentEventListener );
1229 return m_xContent;
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();
1250 if ( !xProc.is() )
1251 return Any();
1253 // Execute command
1254 return xProc->execute( rCommand, 0, m_xEnv );
1258 inline const Reference< XCommandEnvironment >&
1259 Content_Impl::getEnvironment() const
1261 return m_xEnv;
1265 inline void Content_Impl::setEnvironment(
1266 const Reference< XCommandEnvironment >& xNewEnv )
1268 osl::MutexGuard aGuard( m_aMutex );
1269 m_xEnv = xNewEnv;
1273 void Content_Impl::inserted()
1275 // URL might have changed during 'insert' => recalculate in next getURL()
1276 osl::MutexGuard aGuard( m_aMutex );
1277 m_aURL.clear();
1281 // ContentEventListener_Impl Implementation.
1284 // XInterface methods.
1286 void SAL_CALL ContentEventListener_Impl::acquire()
1287 throw()
1289 OWeakObject::acquire();
1292 void SAL_CALL ContentEventListener_Impl::release()
1293 throw()
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.
1310 // virtual
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 >() );
1319 break;
1321 case ContentAction::EXCHANGED:
1322 m_rContent.reinit( evt.Content );
1323 break;
1325 default:
1326 break;
1332 // XEventListenr methods.
1335 // virtual
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: */