build fix
[LibreOffice.git] / ucbhelper / source / client / content.cxx
blobbcc44b686970bbfd0407b8fe51888c3816382d53
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>
30 #include <cppuhelper/implbase.hxx>
31 #include <com/sun/star/ucb/CheckinArgument.hpp>
32 #include <com/sun/star/ucb/ContentCreationError.hpp>
33 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
34 #include <com/sun/star/ucb/XCommandInfo.hpp>
35 #include <com/sun/star/ucb/XCommandProcessor.hpp>
36 #include <com/sun/star/ucb/Command.hpp>
37 #include <com/sun/star/ucb/CommandInfo.hpp>
38 #include <com/sun/star/ucb/ContentAction.hpp>
39 #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
40 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
41 #include <com/sun/star/ucb/GlobalTransferCommandArgument2.hpp>
42 #include <com/sun/star/ucb/NameClash.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/XContentIdentifierFactory.hpp>
47 #include <com/sun/star/ucb/XContentProvider.hpp>
48 #include <com/sun/star/ucb/XContentProviderManager.hpp>
49 #include <com/sun/star/ucb/XDynamicResultSet.hpp>
50 #include <com/sun/star/ucb/SortedDynamicResultSetFactory.hpp>
51 #include <com/sun/star/ucb/UniversalContentBroker.hpp>
52 #include <com/sun/star/ucb/XUniversalContentBroker.hpp>
53 #include <com/sun/star/beans/XPropertySetInfo.hpp>
54 #include <com/sun/star/beans/Property.hpp>
55 #include <com/sun/star/beans/PropertyValue.hpp>
56 #include <com/sun/star/sdbc/XResultSet.hpp>
57 #include <com/sun/star/sdbc/XRow.hpp>
58 #include <com/sun/star/lang/IllegalArgumentException.hpp>
59 #include <com/sun/star/beans/UnknownPropertyException.hpp>
60 #include <ucbhelper/macros.hxx>
61 #include <ucbhelper/content.hxx>
62 #include <ucbhelper/activedatasink.hxx>
63 #include <ucbhelper/activedatastreamer.hxx>
64 #include <ucbhelper/interactionrequest.hxx>
65 #include <ucbhelper/cancelcommandexecution.hxx>
67 using namespace com::sun::star::container;
68 using namespace com::sun::star::beans;
69 using namespace com::sun::star::io;
70 using namespace com::sun::star::lang;
71 using namespace com::sun::star::sdbc;
72 using namespace com::sun::star::task;
73 using namespace com::sun::star::ucb;
74 using namespace com::sun::star::uno;
76 namespace ucbhelper
79 class EmptyInputStream : public ::cppu::WeakImplHelper< XInputStream >
81 public:
82 virtual sal_Int32 SAL_CALL readBytes(
83 Sequence< sal_Int8 > & data, sal_Int32 nBytesToRead )
84 throw (IOException, RuntimeException, std::exception) override;
85 virtual sal_Int32 SAL_CALL readSomeBytes(
86 Sequence< sal_Int8 > & data, sal_Int32 nMaxBytesToRead )
87 throw (IOException, RuntimeException, std::exception) override;
88 virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip )
89 throw (IOException, RuntimeException, std::exception) override;
90 virtual sal_Int32 SAL_CALL available()
91 throw (IOException, RuntimeException, std::exception) override;
92 virtual void SAL_CALL closeInput()
93 throw (IOException, RuntimeException, std::exception) override;
96 sal_Int32 EmptyInputStream::readBytes(
97 Sequence< sal_Int8 > & data, sal_Int32 )
98 throw (IOException, RuntimeException, std::exception)
100 data.realloc( 0 );
101 return 0;
104 sal_Int32 EmptyInputStream::readSomeBytes(
105 Sequence< sal_Int8 > & data, sal_Int32 )
106 throw (IOException, RuntimeException, std::exception)
108 data.realloc( 0 );
109 return 0;
112 void EmptyInputStream::skipBytes( sal_Int32 )
113 throw (IOException, RuntimeException, std::exception)
117 sal_Int32 EmptyInputStream::available()
118 throw (IOException, RuntimeException, std::exception)
120 return 0;
123 void EmptyInputStream::closeInput()
124 throw (IOException, RuntimeException, std::exception)
129 // class ContentEventListener_Impl.
132 class ContentEventListener_Impl : public cppu::OWeakObject,
133 public XContentEventListener
135 Content_Impl& m_rContent;
137 public:
138 explicit ContentEventListener_Impl( Content_Impl& rContent )
139 : m_rContent( rContent ) {}
141 // XInterface
142 virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type & rType )
143 throw( css::uno::RuntimeException, std::exception ) override;
144 virtual void SAL_CALL acquire()
145 throw() override;
146 virtual void SAL_CALL release()
147 throw() override;
149 // XContentEventListener
150 virtual void SAL_CALL contentEvent( const ContentEvent& evt )
151 throw( RuntimeException, std::exception ) override;
153 // XEventListener ( base of XContentEventListener )
154 virtual void SAL_CALL disposing( const EventObject& Source )
155 throw( RuntimeException, std::exception ) override;
159 // class Content_Impl.
162 class Content_Impl : public salhelper::SimpleReferenceObject
164 friend class ContentEventListener_Impl;
166 mutable OUString m_aURL;
167 Reference< XComponentContext > m_xCtx;
168 Reference< XContent > m_xContent;
169 Reference< XCommandProcessor > m_xCommandProcessor;
170 Reference< XCommandEnvironment > m_xEnv;
171 Reference< XContentEventListener > m_xContentEventListener;
172 mutable osl::Mutex m_aMutex;
174 private:
175 void reinit( const Reference< XContent >& xContent );
176 void disposing(const EventObject& Source);
178 public:
179 Content_Impl() {};
180 Content_Impl( const Reference< XComponentContext >& rCtx,
181 const Reference< XContent >& rContent,
182 const Reference< XCommandEnvironment >& rEnv );
184 virtual ~Content_Impl() override;
186 const OUString& getURL() const;
187 Reference< XContent > getContent();
188 Reference< XCommandProcessor > getCommandProcessor();
189 Reference< XComponentContext > const & getComponentContext()
190 { assert(m_xCtx.is()); return m_xCtx; }
192 Any executeCommand( const Command& rCommand );
194 inline const Reference< XCommandEnvironment >& getEnvironment() const;
195 inline void setEnvironment(
196 const Reference< XCommandEnvironment >& xNewEnv );
198 void inserted();
202 // Helpers.
205 static void ensureContentProviderForURL( const Reference< XUniversalContentBroker >& rBroker,
206 const OUString & rURL )
207 throw ( ContentCreationException, RuntimeException )
209 Reference< XContentProvider > xProv
210 = rBroker->queryContentProvider( rURL );
211 if ( !xProv.is() )
213 throw ContentCreationException(
214 "No Content Provider available for URL: " + rURL,
215 Reference< XInterface >(),
216 ContentCreationError_NO_CONTENT_PROVIDER );
221 static Reference< XContentIdentifier > getContentIdentifierThrow(
222 const Reference< XUniversalContentBroker > & rBroker,
223 const OUString & rURL)
224 throw (ContentCreationException, RuntimeException)
226 Reference< XContentIdentifier > xId
227 = rBroker->createContentIdentifier( rURL );
229 if (!xId.is())
231 ensureContentProviderForURL( rBroker, rURL );
233 throw ContentCreationException(
234 "Unable to create Content Identifier!",
235 Reference< XInterface >(),
236 ContentCreationError_IDENTIFIER_CREATION_FAILED );
239 return xId;
242 static Reference< XContentIdentifier > getContentIdentifierNoThrow(
243 const Reference< XUniversalContentBroker > & rBroker,
244 const OUString & rURL)
245 throw (RuntimeException)
247 return rBroker->createContentIdentifier(rURL);
250 static Reference< XContent > getContentThrow(
251 const Reference< XUniversalContentBroker > & rBroker,
252 const Reference< XContentIdentifier > & xId)
253 throw ( ContentCreationException, RuntimeException )
255 Reference< XContent > xContent;
256 OUString msg;
259 xContent = rBroker->queryContent( xId );
261 catch ( IllegalIdentifierException const & e )
263 msg = e.Message;
264 // handled below.
267 if ( !xContent.is() )
269 ensureContentProviderForURL( rBroker, xId->getContentIdentifier() );
271 throw ContentCreationException(
272 "Unable to create Content for <" + xId->getContentIdentifier() + ">: " + msg,
273 Reference< XInterface >(),
274 ContentCreationError_CONTENT_CREATION_FAILED );
277 return xContent;
281 static Reference< XContent > getContentNoThrow(
282 const Reference< XUniversalContentBroker > & rBroker,
283 const Reference< XContentIdentifier > & xId)
284 throw ( RuntimeException )
286 Reference< XContent > xContent;
289 xContent = rBroker->queryContent( xId );
291 catch ( IllegalIdentifierException const & e )
293 SAL_WARN("ucbhelper", "getContentNoThrow: exception: " << e.Message);
296 return xContent;
300 // Content Implementation.
303 Content::Content()
304 : m_xImpl( new Content_Impl )
309 Content::Content( const OUString& rURL,
310 const Reference< XCommandEnvironment >& rEnv,
311 const Reference< XComponentContext >& rCtx )
312 throw ( ContentCreationException, RuntimeException )
314 Reference< XUniversalContentBroker > pBroker(
315 UniversalContentBroker::create( rCtx ) );
317 Reference< XContentIdentifier > xId
318 = getContentIdentifierThrow(pBroker, rURL);
320 Reference< XContent > xContent = getContentThrow(pBroker, xId);
322 m_xImpl = new Content_Impl( rCtx, xContent, rEnv );
326 Content::Content( const Reference< XContent >& rContent,
327 const Reference< XCommandEnvironment >& rEnv,
328 const Reference< XComponentContext >& rCtx )
329 throw ( ContentCreationException, RuntimeException )
331 m_xImpl = new Content_Impl( rCtx, rContent, rEnv );
335 Content::Content( const Content& rOther )
337 m_xImpl = rOther.m_xImpl;
340 Content::Content( Content&& rOther )
342 m_xImpl = std::move(rOther.m_xImpl);
345 // static
346 bool Content::create( const OUString& rURL,
347 const Reference< XCommandEnvironment >& rEnv,
348 const Reference< XComponentContext >& rCtx,
349 Content& rContent )
351 Reference< XUniversalContentBroker > pBroker(
352 UniversalContentBroker::create( rCtx ) );
354 Reference< XContentIdentifier > xId
355 = getContentIdentifierNoThrow(pBroker, rURL);
356 if ( !xId.is() )
357 return false;
359 Reference< XContent > xContent = getContentNoThrow(pBroker, xId);
360 if ( !xContent.is() )
361 return false;
363 rContent.m_xImpl
364 = new Content_Impl( rCtx, xContent, rEnv );
366 return true;
370 Content::~Content()
375 Content& Content::operator=( const Content& rOther )
377 m_xImpl = rOther.m_xImpl;
378 return *this;
381 Content& Content::operator=( Content&& rOther )
383 m_xImpl = std::move(rOther.m_xImpl);
384 return *this;
387 Reference< XContent > Content::get() const
389 return m_xImpl->getContent();
393 const OUString& Content::getURL() const
395 return m_xImpl->getURL();
399 const Reference< XCommandEnvironment >& Content::getCommandEnvironment() const
401 return m_xImpl->getEnvironment();
405 void Content::setCommandEnvironment(
406 const Reference< XCommandEnvironment >& xNewEnv )
408 m_xImpl->setEnvironment( xNewEnv );
412 Reference< XCommandInfo > Content::getCommands()
413 throw( CommandAbortedException, RuntimeException, Exception )
415 Command aCommand;
416 aCommand.Name = "getCommandInfo";
417 aCommand.Handle = -1; // n/a
418 aCommand.Argument = Any();
420 Any aResult = m_xImpl->executeCommand( aCommand );
422 Reference< XCommandInfo > xInfo;
423 aResult >>= xInfo;
424 return xInfo;
428 Reference< XPropertySetInfo > Content::getProperties()
429 throw( CommandAbortedException, RuntimeException, Exception )
431 Command aCommand;
432 aCommand.Name = "getPropertySetInfo";
433 aCommand.Handle = -1; // n/a
434 aCommand.Argument = Any();
436 Any aResult = m_xImpl->executeCommand( aCommand );
438 Reference< XPropertySetInfo > xInfo;
439 aResult >>= xInfo;
440 return xInfo;
444 Any Content::getPropertyValue( const OUString& rPropertyName )
445 throw( CommandAbortedException, RuntimeException, Exception )
447 Sequence<OUString> aNames { rPropertyName };
449 Sequence< Any > aRet = getPropertyValues( aNames );
450 return aRet.getConstArray()[ 0 ];
454 Any Content::setPropertyValue( const OUString& rName,
455 const Any& rValue )
456 throw( CommandAbortedException, RuntimeException, Exception )
458 Sequence<OUString> aNames { rName };
460 Sequence< Any > aValues( 1 );
461 aValues.getArray()[ 0 ] = rValue;
463 Sequence< Any > aErrors = setPropertyValues( aNames, aValues );
464 return aErrors.getConstArray()[ 0 ];
468 Sequence< Any > Content::getPropertyValues(
469 const Sequence< OUString >& rPropertyNames )
470 throw( CommandAbortedException, RuntimeException, Exception )
472 Reference< XRow > xRow = getPropertyValuesInterface( rPropertyNames );
474 sal_Int32 nCount = rPropertyNames.getLength();
475 Sequence< Any > aValues( nCount );
477 if ( xRow.is() )
479 Any* pValues = aValues.getArray();
481 for ( sal_Int32 n = 0; n < nCount; ++n )
482 pValues[ n ] = xRow->getObject( n + 1, Reference< XNameAccess >() );
485 return aValues;
489 Reference< XRow > Content::getPropertyValuesInterface(
490 const Sequence< OUString >& rPropertyNames )
491 throw( CommandAbortedException, RuntimeException, Exception )
493 sal_Int32 nCount = rPropertyNames.getLength();
494 Sequence< Property > aProps( nCount );
495 Property* pProps = aProps.getArray();
497 const OUString* pNames = rPropertyNames.getConstArray();
499 for ( sal_Int32 n = 0; n< nCount; ++n )
501 Property& rProp = pProps[ n ];
503 rProp.Name = pNames[ n ];
504 rProp.Handle = -1; // n/a
505 // rProp.Type =
506 // rProp.Attributes = ;
509 Command aCommand;
510 aCommand.Name = "getPropertyValues";
511 aCommand.Handle = -1; // n/a
512 aCommand.Argument <<= aProps;
514 Any aResult = m_xImpl->executeCommand( aCommand );
516 Reference< XRow > xRow;
517 aResult >>= xRow;
518 return xRow;
522 Sequence< Any > Content::setPropertyValues(
523 const Sequence< OUString >& rPropertyNames,
524 const Sequence< Any >& rValues )
525 throw( CommandAbortedException, RuntimeException, Exception )
527 if ( rPropertyNames.getLength() != rValues.getLength() )
529 ucbhelper::cancelCommandExecution(
530 makeAny( IllegalArgumentException(
531 OUString(
532 "Length of property names sequence and value "
533 "sequence are unequal!" ),
534 get(),
535 -1 ) ),
536 m_xImpl->getEnvironment() );
537 // Unreachable
540 sal_Int32 nCount = rValues.getLength();
541 Sequence< PropertyValue > aProps( nCount );
542 PropertyValue* pProps = aProps.getArray();
544 const OUString* pNames = rPropertyNames.getConstArray();
545 const Any* pValues = rValues.getConstArray();
547 for ( sal_Int32 n = 0; n< nCount; ++n )
549 PropertyValue& rProp = pProps[ n ];
551 rProp.Name = pNames[ n ];
552 rProp.Handle = -1; // n/a
553 rProp.Value = pValues[ n ];
554 // rProp.State = ;
557 Command aCommand;
558 aCommand.Name = "setPropertyValues";
559 aCommand.Handle = -1; // n/a
560 aCommand.Argument <<= aProps;
562 Any aResult = m_xImpl->executeCommand( aCommand );
564 Sequence< Any > aErrors;
565 aResult >>= aErrors;
566 return aErrors;
570 Any Content::executeCommand( const OUString& rCommandName,
571 const Any& rCommandArgument )
572 throw( CommandAbortedException, RuntimeException, Exception )
574 Command aCommand;
575 aCommand.Name = rCommandName;
576 aCommand.Handle = -1; // n/a
577 aCommand.Argument = rCommandArgument;
579 return m_xImpl->executeCommand( aCommand );
583 Any Content::createCursorAny( const Sequence< OUString >& rPropertyNames,
584 ResultSetInclude eMode )
585 throw( CommandAbortedException, RuntimeException, Exception )
587 sal_Int32 nCount = rPropertyNames.getLength();
588 Sequence< Property > aProps( nCount );
589 Property* pProps = aProps.getArray();
590 const OUString* pNames = rPropertyNames.getConstArray();
591 for ( sal_Int32 n = 0; n < nCount; ++n )
593 Property& rProp = pProps[ n ];
594 rProp.Name = pNames[ n ];
595 rProp.Handle = -1; // n/a
598 OpenCommandArgument2 aArg;
599 aArg.Mode = ( eMode == INCLUDE_FOLDERS_ONLY )
600 ? OpenMode::FOLDERS
601 : ( eMode == INCLUDE_DOCUMENTS_ONLY )
602 ? OpenMode::DOCUMENTS : OpenMode::ALL;
603 aArg.Priority = 0; // unused
604 aArg.Sink.clear(); // unused
605 aArg.Properties = aProps;
607 Command aCommand;
608 aCommand.Name = "open";
609 aCommand.Handle = -1; // n/a
610 aCommand.Argument <<= aArg;
612 return m_xImpl->executeCommand( aCommand );
616 Reference< XResultSet > Content::createCursor(
617 const Sequence< OUString >& rPropertyNames,
618 ResultSetInclude eMode )
619 throw( CommandAbortedException, RuntimeException, Exception )
621 Any aCursorAny = createCursorAny( rPropertyNames, eMode );
623 Reference< XDynamicResultSet > xDynSet;
624 Reference< XResultSet > aResult;
626 aCursorAny >>= xDynSet;
627 if ( xDynSet.is() )
628 aResult = xDynSet->getStaticResultSet();
630 OSL_ENSURE( aResult.is(), "Content::createCursor - no cursor!" );
632 if ( !aResult.is() )
634 // Former, the open command directly returned a XResultSet.
635 aCursorAny >>= aResult;
637 OSL_ENSURE( !aResult.is(),
638 "Content::createCursor - open-Command must "
639 "return a Reference< XDynnamicResultSet >!" );
642 return aResult;
646 Reference< XDynamicResultSet > Content::createDynamicCursor(
647 const Sequence< OUString >& rPropertyNames,
648 ResultSetInclude eMode )
649 throw( CommandAbortedException, RuntimeException, Exception )
651 Reference< XDynamicResultSet > aResult;
652 createCursorAny( rPropertyNames, eMode ) >>= aResult;
654 OSL_ENSURE( aResult.is(), "Content::createDynamicCursor - no cursor!" );
656 return aResult;
660 Reference< XResultSet > Content::createSortedCursor(
661 const Sequence< OUString >& rPropertyNames,
662 const Sequence< NumberedSortingInfo >& rSortInfo,
663 const Reference< XAnyCompareFactory >& rAnyCompareFactory,
664 ResultSetInclude eMode )
665 throw( CommandAbortedException, RuntimeException, Exception )
667 Reference< XResultSet > aResult;
668 Reference< XDynamicResultSet > aDynSet;
670 Any aCursorAny = createCursorAny( rPropertyNames, eMode );
672 aCursorAny >>= aDynSet;
674 if( aDynSet.is() )
676 Reference< XDynamicResultSet > aDynResult;
678 if( m_xImpl->getComponentContext().is() )
680 Reference< XSortedDynamicResultSetFactory > aSortFactory =
681 SortedDynamicResultSetFactory::create( m_xImpl->getComponentContext());
683 aDynResult = aSortFactory->createSortedDynamicResultSet( aDynSet,
684 rSortInfo,
685 rAnyCompareFactory );
688 OSL_ENSURE( aDynResult.is(), "Content::createSortedCursor - no sorted cursor!\n" );
690 if( aDynResult.is() )
691 aResult = aDynResult->getStaticResultSet();
692 else
693 aResult = aDynSet->getStaticResultSet();
696 OSL_ENSURE( aResult.is(), "Content::createSortedCursor - no cursor!" );
698 if ( !aResult.is() )
700 // Former, the open command directly returned a XResultSet.
701 aCursorAny >>= aResult;
703 OSL_ENSURE( !aResult.is(),
704 "Content::createCursor - open-Command must "
705 "return a Reference< XDynnamicResultSet >!" );
708 return aResult;
712 Reference< XInputStream > Content::openStream()
713 throw( CommandAbortedException, RuntimeException, Exception )
715 if ( !isDocument() )
716 return Reference< XInputStream >();
718 Reference< XActiveDataSink > xSink = new ActiveDataSink;
720 OpenCommandArgument2 aArg;
721 aArg.Mode = OpenMode::DOCUMENT;
722 aArg.Priority = 0; // unused
723 aArg.Sink = xSink;
724 aArg.Properties = Sequence< Property >( 0 ); // unused
726 Command aCommand;
727 aCommand.Name = "open";
728 aCommand.Handle = -1; // n/a
729 aCommand.Argument <<= aArg;
731 m_xImpl->executeCommand( aCommand );
733 return xSink->getInputStream();
737 Reference< XInputStream > Content::openStreamNoLock()
738 throw( CommandAbortedException, RuntimeException, Exception )
740 if ( !isDocument() )
741 return Reference< XInputStream >();
743 Reference< XActiveDataSink > xSink = new ActiveDataSink;
745 OpenCommandArgument2 aArg;
746 aArg.Mode = OpenMode::DOCUMENT_SHARE_DENY_NONE;
747 aArg.Priority = 0; // unused
748 aArg.Sink = xSink;
749 aArg.Properties = Sequence< Property >( 0 ); // unused
751 Command aCommand;
752 aCommand.Name = "open";
753 aCommand.Handle = -1; // n/a
754 aCommand.Argument <<= aArg;
756 m_xImpl->executeCommand( aCommand );
758 return xSink->getInputStream();
762 Reference< XStream > Content::openWriteableStream()
763 throw( CommandAbortedException, RuntimeException, Exception )
765 if ( !isDocument() )
766 return Reference< XStream >();
768 Reference< XActiveDataStreamer > xStreamer = new ActiveDataStreamer;
770 OpenCommandArgument2 aArg;
771 aArg.Mode = OpenMode::DOCUMENT;
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 Reference< XStream > Content::openWriteableStreamNoLock()
788 throw( CommandAbortedException, RuntimeException, Exception )
790 if ( !isDocument() )
791 return Reference< XStream >();
793 Reference< XActiveDataStreamer > xStreamer = new ActiveDataStreamer;
795 OpenCommandArgument2 aArg;
796 aArg.Mode = OpenMode::DOCUMENT_SHARE_DENY_NONE;
797 aArg.Priority = 0; // unused
798 aArg.Sink = xStreamer;
799 aArg.Properties = Sequence< Property >( 0 ); // unused
801 Command aCommand;
802 aCommand.Name = "open";
803 aCommand.Handle = -1; // n/a
804 aCommand.Argument <<= aArg;
806 m_xImpl->executeCommand( aCommand );
808 return xStreamer->getStream();
812 bool Content::openStream( const Reference< XActiveDataSink >& rSink )
813 throw( CommandAbortedException, RuntimeException, Exception )
815 if ( !isDocument() )
816 return false;
818 OpenCommandArgument2 aArg;
819 aArg.Mode = OpenMode::DOCUMENT;
820 aArg.Priority = 0; // unused
821 aArg.Sink = rSink;
822 aArg.Properties = Sequence< Property >( 0 ); // unused
824 Command aCommand;
825 aCommand.Name = "open";
826 aCommand.Handle = -1; // n/a
827 aCommand.Argument <<= aArg;
829 m_xImpl->executeCommand( aCommand );
831 return true;
835 bool Content::openStream( const Reference< XOutputStream >& rStream )
836 throw( CommandAbortedException, RuntimeException, Exception )
838 if ( !isDocument() )
839 return false;
841 OpenCommandArgument2 aArg;
842 aArg.Mode = OpenMode::DOCUMENT;
843 aArg.Priority = 0; // unused
844 aArg.Sink = rStream;
845 aArg.Properties = Sequence< Property >( 0 ); // unused
847 Command aCommand;
848 aCommand.Name = "open";
849 aCommand.Handle = -1; // n/a
850 aCommand.Argument <<= aArg;
852 m_xImpl->executeCommand( aCommand );
854 return true;
858 void Content::writeStream( const Reference< XInputStream >& rStream,
859 bool bReplaceExisting )
860 throw( CommandAbortedException, RuntimeException, Exception )
862 InsertCommandArgument aArg;
863 aArg.Data = rStream.is() ? rStream : new EmptyInputStream;
864 aArg.ReplaceExisting = bReplaceExisting;
866 Command aCommand;
867 aCommand.Name = "insert";
868 aCommand.Handle = -1; // n/a
869 aCommand.Argument <<= aArg;
871 m_xImpl->executeCommand( aCommand );
873 m_xImpl->inserted();
877 Sequence< ContentInfo > Content::queryCreatableContentsInfo()
878 throw( CommandAbortedException, RuntimeException, Exception )
880 // First, try it using "CreatableContentsInfo" property -> the "new" way.
881 Sequence< ContentInfo > aInfo;
882 if ( getPropertyValue(
883 "CreatableContentsInfo" )
884 >>= aInfo )
885 return aInfo;
887 // Second, try it using XContentCreator interface -> the "old" way (not
888 // providing the chance to supply an XCommandEnvironment.
889 Reference< XContentCreator > xCreator( m_xImpl->getContent(), UNO_QUERY );
890 if ( xCreator.is() )
891 aInfo = xCreator->queryCreatableContentsInfo();
893 return aInfo;
897 bool Content::insertNewContent( const OUString& rContentType,
898 const Sequence< OUString >&
899 rPropertyNames,
900 const Sequence< Any >& rPropertyValues,
901 Content& rNewContent )
902 throw( CommandAbortedException, RuntimeException, Exception )
904 return insertNewContent( rContentType,
905 rPropertyNames,
906 rPropertyValues,
907 new EmptyInputStream,
908 rNewContent );
912 bool Content::insertNewContent( const OUString& rContentType,
913 const Sequence< OUString >&
914 rPropertyNames,
915 const Sequence< Any >& rPropertyValues,
916 const Reference< XInputStream >& rData,
917 Content& rNewContent )
918 throw( CommandAbortedException, RuntimeException, Exception )
920 if ( rContentType.isEmpty() )
921 return false;
923 // First, try it using "createNewContent" command -> the "new" way.
924 ContentInfo aInfo;
925 aInfo.Type = rContentType;
926 aInfo.Attributes = 0;
928 Command aCommand;
929 aCommand.Name = "createNewContent";
930 aCommand.Handle = -1; // n/a
931 aCommand.Argument <<= aInfo;
933 Reference< XContent > xNew;
936 m_xImpl->executeCommand( aCommand ) >>= xNew;
938 catch ( RuntimeException const & )
940 throw;
942 catch ( Exception const & )
946 if ( !xNew.is() )
948 // Second, try it using XContentCreator interface -> the "old"
949 // way (not providing the chance to supply an XCommandEnvironment.
950 Reference< XContentCreator > xCreator( m_xImpl->getContent(), UNO_QUERY );
952 if ( !xCreator.is() )
953 return false;
955 xNew = xCreator->createNewContent( aInfo );
957 if ( !xNew.is() )
958 return false;
961 Content aNewContent(
962 xNew, m_xImpl->getEnvironment(), m_xImpl->getComponentContext() );
963 aNewContent.setPropertyValues( rPropertyNames, rPropertyValues );
964 aNewContent.executeCommand( "insert",
965 makeAny(
966 InsertCommandArgument(
967 rData.is() ? rData : new EmptyInputStream,
968 false /* ReplaceExisting */ ) ) );
969 aNewContent.m_xImpl->inserted();
971 rNewContent = aNewContent;
972 return true;
976 bool Content::transferContent( const Content& rSourceContent,
977 InsertOperation eOperation,
978 const OUString & rTitle,
979 const sal_Int32 nNameClashAction,
980 const OUString & rMimeType,
981 bool bMajorVersion,
982 const OUString & rVersionComment,
983 OUString* pResultURL,
984 const OUString & rDocumentId )
985 throw( CommandAbortedException, RuntimeException, Exception )
987 Reference< XUniversalContentBroker > pBroker(
988 UniversalContentBroker::create( m_xImpl->getComponentContext() ) );
990 // Execute command "globalTransfer" at UCB.
992 TransferCommandOperation eTransOp = TransferCommandOperation();
993 OUString sCommand( "globalTransfer" );
994 bool bCheckIn = false;
995 switch ( eOperation )
997 case InsertOperation_COPY:
998 eTransOp = TransferCommandOperation_COPY;
999 break;
1001 case InsertOperation_MOVE:
1002 eTransOp = TransferCommandOperation_MOVE;
1003 break;
1005 case InsertOperation_LINK:
1006 eTransOp = TransferCommandOperation_LINK;
1007 break;
1009 case InsertOperation_CHECKIN:
1010 eTransOp = TransferCommandOperation_COPY;
1011 sCommand = "checkin";
1012 bCheckIn = true;
1013 break;
1015 Command aCommand;
1016 aCommand.Name = sCommand;
1017 aCommand.Handle = -1; // n/a
1019 if ( !bCheckIn )
1021 GlobalTransferCommandArgument2 aTransferArg(
1022 eTransOp,
1023 rSourceContent.getURL(), // SourceURL
1024 getURL(), // TargetFolderURL,
1025 rTitle,
1026 nNameClashAction,
1027 rMimeType,
1028 rDocumentId );
1029 aCommand.Argument <<= aTransferArg;
1031 else
1033 CheckinArgument aCheckinArg( bMajorVersion, rVersionComment,
1034 rSourceContent.getURL(), getURL(), rTitle, rMimeType );
1035 aCommand.Argument <<= aCheckinArg;
1038 Any aRet = pBroker->execute( aCommand, 0, m_xImpl->getEnvironment() );
1039 if ( pResultURL != nullptr )
1040 aRet >>= *pResultURL;
1041 return true;
1045 bool Content::isFolder()
1046 throw( CommandAbortedException, RuntimeException, Exception )
1048 bool bFolder = false;
1049 if ( getPropertyValue("IsFolder")
1050 >>= bFolder )
1051 return bFolder;
1053 ucbhelper::cancelCommandExecution(
1054 makeAny( UnknownPropertyException(
1055 OUString(
1056 "Unable to retrieve value of property 'IsFolder'!" ),
1057 get() ) ),
1058 m_xImpl->getEnvironment() );
1060 #if !(defined(_MSC_VER) && defined(ENABLE_LTO))
1061 // Unreachable - cancelCommandExecution always throws an exception.
1062 // But some compilers complain...
1063 return false;
1064 #endif
1068 SAL_WNOUNREACHABLE_CODE_PUSH
1070 bool Content::isDocument()
1071 throw( CommandAbortedException, RuntimeException, Exception )
1073 bool bDoc = false;
1074 if ( getPropertyValue("IsDocument")
1075 >>= bDoc )
1076 return bDoc;
1078 ucbhelper::cancelCommandExecution(
1079 makeAny( UnknownPropertyException(
1080 OUString(
1081 "Unable to retrieve value of property 'IsDocument'!" ),
1082 get() ) ),
1083 m_xImpl->getEnvironment() );
1085 // Unreachable - cancelCommandExecution always throws an exception,
1086 // But some compilers complain...
1087 return false;
1090 SAL_WNOUNREACHABLE_CODE_POP
1092 void Content::lock()
1093 throw( CommandAbortedException, RuntimeException, Exception )
1095 Command aCommand;
1096 aCommand.Name = "lock";
1097 aCommand.Handle = -1; // n/a
1099 m_xImpl->executeCommand( aCommand );
1103 void Content::unlock()
1104 throw( CommandAbortedException, RuntimeException, Exception )
1107 Command aCommand;
1108 aCommand.Name = "unlock";
1109 aCommand.Handle = -1; // n/a
1111 m_xImpl->executeCommand( aCommand );
1116 // Content_Impl Implementation.
1119 Content_Impl::Content_Impl( const Reference< XComponentContext >& rCtx,
1120 const Reference< XContent >& rContent,
1121 const Reference< XCommandEnvironment >& rEnv )
1122 : m_xCtx( rCtx ),
1123 m_xContent( rContent ),
1124 m_xEnv( rEnv )
1126 assert(rCtx.is());
1127 if ( m_xContent.is() )
1129 m_xContentEventListener = new ContentEventListener_Impl( *this );
1130 m_xContent->addContentEventListener( m_xContentEventListener );
1132 #if OSL_DEBUG_LEVEL > 0
1133 // Only done on demand in product version for performance reasons,
1134 // but a nice debug helper.
1135 getURL();
1136 #endif
1141 void Content_Impl::reinit( const Reference< XContent >& xContent )
1143 osl::MutexGuard aGuard( m_aMutex );
1145 m_xCommandProcessor = nullptr;
1147 // #92581# - Don't reset m_aURL!!!
1149 if ( m_xContent.is() )
1153 m_xContent->removeContentEventListener( m_xContentEventListener );
1155 catch ( RuntimeException const & )
1160 if ( xContent.is() )
1162 m_xContent = xContent;
1163 m_xContent->addContentEventListener( m_xContentEventListener );
1165 #if OSL_DEBUG_LEVEL > 0
1166 // Only done on demand in product version for performance reasons,
1167 // but a nice debug helper.
1168 getURL();
1169 #endif
1171 else
1173 // We need m_xContent's URL in order to be able to create the
1174 // content object again if demanded ( --> Content_Impl::getContent() )
1175 getURL();
1177 m_xContent = nullptr;
1182 // virtual
1183 Content_Impl::~Content_Impl()
1185 if ( m_xContent.is() )
1189 m_xContent->removeContentEventListener( m_xContentEventListener );
1191 catch ( RuntimeException const & )
1198 void Content_Impl::disposing( const EventObject& Source )
1200 Reference<XContent> xContent;
1203 osl::MutexGuard aGuard( m_aMutex );
1204 if(Source.Source != m_xContent)
1205 return;
1207 xContent = m_xContent;
1209 m_aURL.clear();
1210 m_xCommandProcessor = nullptr;
1211 m_xContent = nullptr;
1214 if ( xContent.is() )
1218 xContent->removeContentEventListener( m_xContentEventListener );
1220 catch ( RuntimeException const & )
1227 const OUString& Content_Impl::getURL() const
1229 if ( m_aURL.isEmpty() && m_xContent.is() )
1231 osl::MutexGuard aGuard( m_aMutex );
1233 if ( m_aURL.isEmpty() && m_xContent.is() )
1235 Reference< XContentIdentifier > xId = m_xContent->getIdentifier();
1236 if ( xId.is() )
1237 m_aURL = xId->getContentIdentifier();
1241 return m_aURL;
1245 Reference< XContent > Content_Impl::getContent()
1247 if ( !m_xContent.is() && !m_aURL.isEmpty() )
1249 osl::MutexGuard aGuard( m_aMutex );
1251 if ( !m_xContent.is() && !m_aURL.isEmpty() )
1253 Reference< XUniversalContentBroker > pBroker(
1254 UniversalContentBroker::create( getComponentContext() ) );
1256 OSL_ENSURE( pBroker->queryContentProviders().getLength(),
1257 "Content Broker not configured (no providers)!" );
1259 Reference< XContentIdentifier > xId
1260 = pBroker->createContentIdentifier( m_aURL );
1262 OSL_ENSURE( xId.is(), "No Content Identifier!" );
1264 if ( xId.is() )
1268 m_xContent = pBroker->queryContent( xId );
1270 catch ( IllegalIdentifierException const & )
1274 if ( m_xContent.is() )
1275 m_xContent->addContentEventListener(
1276 m_xContentEventListener );
1281 return m_xContent;
1285 Reference< XCommandProcessor > Content_Impl::getCommandProcessor()
1287 if ( !m_xCommandProcessor.is() )
1289 osl::MutexGuard aGuard( m_aMutex );
1291 if ( !m_xCommandProcessor.is() )
1292 m_xCommandProcessor.set( getContent(), UNO_QUERY );
1295 return m_xCommandProcessor;
1299 Any Content_Impl::executeCommand( const Command& rCommand )
1301 Reference< XCommandProcessor > xProc = getCommandProcessor();
1302 if ( !xProc.is() )
1303 return Any();
1305 // Execute command
1306 return xProc->execute( rCommand, 0, m_xEnv );
1310 inline const Reference< XCommandEnvironment >&
1311 Content_Impl::getEnvironment() const
1313 return m_xEnv;
1317 inline void Content_Impl::setEnvironment(
1318 const Reference< XCommandEnvironment >& xNewEnv )
1320 osl::MutexGuard aGuard( m_aMutex );
1321 m_xEnv = xNewEnv;
1325 void Content_Impl::inserted()
1327 // URL might have changed during 'insert' => recalculate in next getURL()
1328 osl::MutexGuard aGuard( m_aMutex );
1329 m_aURL.clear();
1333 // ContentEventListener_Impl Implementation.
1336 // XInterface methods.
1338 void SAL_CALL ContentEventListener_Impl::acquire()
1339 throw()
1341 OWeakObject::acquire();
1344 void SAL_CALL ContentEventListener_Impl::release()
1345 throw()
1347 OWeakObject::release();
1350 css::uno::Any SAL_CALL ContentEventListener_Impl::queryInterface( const css::uno::Type & rType )
1351 throw( css::uno::RuntimeException, std::exception )
1353 css::uno::Any aRet = cppu::queryInterface( rType,
1354 (static_cast< XContentEventListener* >(this)),
1355 (static_cast< XEventListener* >(this))
1357 return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
1360 // XContentEventListener methods.
1363 // virtual
1364 void SAL_CALL ContentEventListener_Impl::contentEvent( const ContentEvent& evt )
1365 throw( RuntimeException, std::exception )
1367 if ( evt.Source == m_rContent.m_xContent )
1369 switch ( evt.Action )
1371 case ContentAction::DELETED:
1372 m_rContent.reinit( Reference< XContent >() );
1373 break;
1375 case ContentAction::EXCHANGED:
1376 m_rContent.reinit( evt.Content );
1377 break;
1379 default:
1380 break;
1386 // XEventListenr methods.
1389 // virtual
1390 void SAL_CALL ContentEventListener_Impl::disposing( const EventObject& Source )
1391 throw( RuntimeException, std::exception )
1393 m_rContent.disposing(Source);
1396 } /* namespace ucbhelper */
1398 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */