LibreOffice Module ucbhelper (master)  1
content.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <sal/config.h>
21 
22 #include <cassert>
23 
24 #include <o3tl/unreachable.hxx>
25 #include <osl/diagnose.h>
26 #include <osl/mutex.hxx>
27 #include <sal/log.hxx>
29 #include <cppuhelper/weak.hxx>
31 
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>
59 #include "activedatastreamer.hxx"
61 
62 namespace com::sun::star::ucb { class XCommandEnvironment; }
63 namespace com::sun::star::ucb { class XContentProvider; }
64 namespace com::sun::star::sdbc { class XResultSet; }
65 
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;
74 
75 namespace ucbhelper
76 {
77 
78 namespace {
79 
80 class EmptyInputStream : public ::cppu::WeakImplHelper< XInputStream >
81 {
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;
90 };
91 
92 }
93 
94 sal_Int32 EmptyInputStream::readBytes(
95  Sequence< sal_Int8 > & data, sal_Int32 )
96 {
97  data.realloc( 0 );
98  return 0;
99 }
100 
101 sal_Int32 EmptyInputStream::readSomeBytes(
102  Sequence< sal_Int8 > & data, sal_Int32 )
103 {
104  data.realloc( 0 );
105  return 0;
106 }
107 
108 void EmptyInputStream::skipBytes( sal_Int32 )
109 {
110 }
111 
112 sal_Int32 EmptyInputStream::available()
113 {
114  return 0;
115 }
116 
117 void EmptyInputStream::closeInput()
118 {
119 }
120 
121 
122 
123 namespace {
124 
125 class ContentEventListener_Impl : public cppu::OWeakObject,
126  public XContentEventListener
127 {
128  Content_Impl& m_rContent;
129 
130 public:
131  explicit ContentEventListener_Impl( Content_Impl& rContent )
132  : m_rContent( rContent ) {}
133 
134  // XInterface
135  virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type & rType ) override;
136  virtual void SAL_CALL acquire()
137  throw() override;
138  virtual void SAL_CALL release()
139  throw() override;
140 
141  // XContentEventListener
142  virtual void SAL_CALL contentEvent( const ContentEvent& evt ) override;
143 
144  // XEventListener ( base of XContentEventListener )
145  virtual void SAL_CALL disposing( const EventObject& Source ) override;
146 };
147 
148 }
149 
150 
151 
152 class Content_Impl : public salhelper::SimpleReferenceObject
153 {
155 
156  mutable OUString m_aURL;
162  mutable osl::Mutex m_aMutex;
163 
164 private:
165  void reinit( const Reference< XContent >& xContent );
166  void disposing(const EventObject& Source);
167 
168 public:
171  const Reference< XContent >& rContent,
172  const Reference< XCommandEnvironment >& rEnv );
173 
174  virtual ~Content_Impl() override;
175 
176  const OUString& getURL() const;
177  Reference< XContent > getContent();
178  Reference< XCommandProcessor > getCommandProcessor();
180  { assert(m_xCtx.is()); return m_xCtx; }
181 
182  Any executeCommand( const Command& rCommand );
183 
184  inline const Reference< XCommandEnvironment >& getEnvironment() const;
185  inline void setEnvironment(
186  const Reference< XCommandEnvironment >& xNewEnv );
187 
188  void inserted();
189 };
190 
191 
192 // Helpers.
193 
197  const OUString & rURL )
198 {
200  = rBroker->queryContentProvider( rURL );
201  if ( !xProv.is() )
202  {
203  throw ContentCreationException(
204  "No Content Provider available for URL: " + rURL,
206  ContentCreationError_NO_CONTENT_PROVIDER );
207  }
208 }
209 
213  const Reference< XUniversalContentBroker > & rBroker,
214  const OUString & rURL)
215 {
217  = rBroker->createContentIdentifier( rURL );
218 
219  if (!xId.is())
220  {
221  ensureContentProviderForURL( rBroker, rURL );
222 
223  throw ContentCreationException(
224  "Unable to create Content Identifier!",
226  ContentCreationError_IDENTIFIER_CREATION_FAILED );
227  }
228 
229  return xId;
230 }
231 
234  const Reference< XUniversalContentBroker > & rBroker,
235  const OUString & rURL)
236 {
237  return rBroker->createContentIdentifier(rURL);
238 }
239 
243  const Reference< XUniversalContentBroker > & rBroker,
245 {
247  OUString msg;
248  try
249  {
250  xContent = rBroker->queryContent( xId );
251  }
252  catch ( IllegalIdentifierException const & e )
253  {
254  msg = e.Message;
255  // handled below.
256  }
257 
258  if ( !xContent.is() )
259  {
260  ensureContentProviderForURL( rBroker, xId->getContentIdentifier() );
261 
262  throw ContentCreationException(
263  "Unable to create Content for <" + xId->getContentIdentifier() + ">: " + msg,
265  ContentCreationError_CONTENT_CREATION_FAILED );
266  }
267 
268  return xContent;
269 }
270 
273  const Reference< XUniversalContentBroker > & rBroker,
275 {
277  try
278  {
279  xContent = rBroker->queryContent( xId );
280  }
281  catch ( IllegalIdentifierException const & e )
282  {
283  SAL_WARN("ucbhelper", "getContentNoThrow: " << e);
284  }
285 
286  return xContent;
287 }
288 
289 
290 // Content Implementation.
291 
292 
293 Content::Content()
294 : m_xImpl( new Content_Impl )
295 {
296 }
297 
298 
299 Content::Content( const OUString& rURL,
301  const Reference< XComponentContext >& rCtx )
302 {
304  UniversalContentBroker::create( rCtx ) );
305 
307  = getContentIdentifierThrow(pBroker, rURL);
308 
310 
311  m_xImpl = new Content_Impl( rCtx, xContent, rEnv );
312 }
313 
314 
315 Content::Content( const Reference< XContent >& rContent,
317  const Reference< XComponentContext >& rCtx )
318 {
319  m_xImpl = new Content_Impl( rCtx, rContent, rEnv );
320 }
321 
322 
323 Content::Content( const Content& rOther )
324 {
325  m_xImpl = rOther.m_xImpl;
326 }
327 
328 Content::Content( Content&& rOther ) noexcept
329 {
330  m_xImpl = std::move(rOther.m_xImpl);
331 }
332 
333 // static
334 bool Content::create( const OUString& rURL,
336  const Reference< XComponentContext >& rCtx,
337  Content& rContent )
338 {
340  UniversalContentBroker::create( rCtx ) );
341 
343  = getContentIdentifierNoThrow(pBroker, rURL);
344  if ( !xId.is() )
345  return false;
346 
348  if ( !xContent.is() )
349  return false;
350 
351  rContent.m_xImpl
352  = new Content_Impl( rCtx, xContent, rEnv );
353 
354  return true;
355 }
356 
357 
359 {
360 }
361 
362 
364 {
365  m_xImpl = rOther.m_xImpl;
366  return *this;
367 }
368 
369 Content& Content::operator=( Content&& rOther ) noexcept
370 {
371  m_xImpl = std::move(rOther.m_xImpl);
372  return *this;
373 }
374 
376 {
377  return m_xImpl->getContent();
378 }
379 
380 
381 const OUString& Content::getURL() const
382 {
383  return m_xImpl->getURL();
384 }
385 
386 
388 {
389  return m_xImpl->getEnvironment();
390 }
391 
392 
394  const Reference< XCommandEnvironment >& xNewEnv )
395 {
396  m_xImpl->setEnvironment( xNewEnv );
397 }
398 
399 
401 {
403  aCommand.Name = "getCommandInfo";
404  aCommand.Handle = -1; // n/a
405  aCommand.Argument = Any();
406 
407  Any aResult = m_xImpl->executeCommand( aCommand );
408 
410  aResult >>= xInfo;
411  return xInfo;
412 }
413 
414 
416 {
418  aCommand.Name = "getPropertySetInfo";
419  aCommand.Handle = -1; // n/a
420  aCommand.Argument = Any();
421 
422  Any aResult = m_xImpl->executeCommand( aCommand );
423 
425  aResult >>= xInfo;
426  return xInfo;
427 }
428 
429 
430 Any Content::getPropertyValue( const OUString& rPropertyName )
431 {
432  Sequence<OUString> aNames { rPropertyName };
433 
434  Sequence< Any > aRet = getPropertyValues( aNames );
435  return aRet.getConstArray()[ 0 ];
436 }
437 
438 
439 Any Content::setPropertyValue( const OUString& rName,
440  const Any& rValue )
441 {
442  Sequence<OUString> aNames { rName };
443 
444  Sequence< Any > aValues( 1 );
445  aValues.getArray()[ 0 ] = rValue;
446 
447  Sequence< Any > aErrors = setPropertyValues( aNames, aValues );
448  return aErrors.getConstArray()[ 0 ];
449 }
450 
451 
453  const Sequence< OUString >& rPropertyNames )
454 {
456 
457  sal_Int32 nCount = rPropertyNames.getLength();
458  Sequence< Any > aValues( nCount );
459 
460  if ( xRow.is() )
461  {
462  Any* pValues = aValues.getArray();
463 
464  for ( sal_Int32 n = 0; n < nCount; ++n )
465  pValues[ n ] = xRow->getObject( n + 1, Reference< XNameAccess >() );
466  }
467 
468  return aValues;
469 }
470 
471 
473  const Sequence< OUString >& rPropertyNames )
474 {
475  sal_Int32 nCount = rPropertyNames.getLength();
476  Sequence< Property > aProps( nCount );
477  Property* pProps = aProps.getArray();
478 
479  const OUString* pNames = rPropertyNames.getConstArray();
480 
481  for ( sal_Int32 n = 0; n< nCount; ++n )
482  {
483  Property& rProp = pProps[ n ];
484 
485  rProp.Name = pNames[ n ];
486  rProp.Handle = -1; // n/a
487 // rProp.Type =
488 // rProp.Attributes = ;
489  }
490 
492  aCommand.Name = "getPropertyValues";
493  aCommand.Handle = -1; // n/a
494  aCommand.Argument <<= aProps;
495 
496  Any aResult = m_xImpl->executeCommand( aCommand );
497 
498  Reference< XRow > xRow;
499  aResult >>= xRow;
500  return xRow;
501 }
502 
503 
505  const Sequence< OUString >& rPropertyNames,
506  const Sequence< Any >& rValues )
507 {
508  if ( rPropertyNames.getLength() != rValues.getLength() )
509  {
511  makeAny( IllegalArgumentException(
512  "Length of property names sequence and value "
513  "sequence are unequal!",
514  get(),
515  -1 ) ),
516  m_xImpl->getEnvironment() );
517  // Unreachable
518  }
519 
520  sal_Int32 nCount = rValues.getLength();
521  Sequence< PropertyValue > aProps( nCount );
522  PropertyValue* pProps = aProps.getArray();
523 
524  const OUString* pNames = rPropertyNames.getConstArray();
525  const Any* pValues = rValues.getConstArray();
526 
527  for ( sal_Int32 n = 0; n< nCount; ++n )
528  {
529  PropertyValue& rProp = pProps[ n ];
530 
531  rProp.Name = pNames[ n ];
532  rProp.Handle = -1; // n/a
533  rProp.Value = pValues[ n ];
534 // rProp.State = ;
535  }
536 
538  aCommand.Name = "setPropertyValues";
539  aCommand.Handle = -1; // n/a
540  aCommand.Argument <<= aProps;
541 
542  Any aResult = m_xImpl->executeCommand( aCommand );
543 
544  Sequence< Any > aErrors;
545  aResult >>= aErrors;
546  return aErrors;
547 }
548 
549 
550 Any Content::executeCommand( const OUString& rCommandName,
551  const Any& rCommandArgument )
552 {
553  Command aCommand;
554  aCommand.Name = rCommandName;
555  aCommand.Handle = -1; // n/a
556  aCommand.Argument = rCommandArgument;
557 
558  return m_xImpl->executeCommand( aCommand );
559 }
560 
561 
563  ResultSetInclude eMode )
564 {
565  sal_Int32 nCount = rPropertyNames.getLength();
566  Sequence< Property > aProps( nCount );
567  Property* pProps = aProps.getArray();
568  const OUString* pNames = rPropertyNames.getConstArray();
569  for ( sal_Int32 n = 0; n < nCount; ++n )
570  {
571  Property& rProp = pProps[ n ];
572  rProp.Name = pNames[ n ];
573  rProp.Handle = -1; // n/a
574  }
575 
576  OpenCommandArgument2 aArg;
577  aArg.Mode = ( eMode == INCLUDE_FOLDERS_ONLY )
578  ? OpenMode::FOLDERS
579  : ( eMode == INCLUDE_DOCUMENTS_ONLY )
580  ? OpenMode::DOCUMENTS : OpenMode::ALL;
581  aArg.Priority = 0; // unused
582  aArg.Sink.clear(); // unused
583  aArg.Properties = aProps;
584 
585  Command aCommand;
586  aCommand.Name = "open";
587  aCommand.Handle = -1; // n/a
588  aCommand.Argument <<= aArg;
589 
590  return m_xImpl->executeCommand( aCommand );
591 }
592 
593 
595  const Sequence< OUString >& rPropertyNames,
596  ResultSetInclude eMode )
597 {
598  Any aCursorAny = createCursorAny( rPropertyNames, eMode );
599 
601  Reference< XResultSet > aResult;
602 
603  aCursorAny >>= xDynSet;
604  if ( xDynSet.is() )
605  aResult = xDynSet->getStaticResultSet();
606 
607  OSL_ENSURE( aResult.is(), "Content::createCursor - no cursor!" );
608 
609  if ( !aResult.is() )
610  {
611  // Former, the open command directly returned a XResultSet.
612  aCursorAny >>= aResult;
613 
614  OSL_ENSURE( !aResult.is(),
615  "Content::createCursor - open-Command must "
616  "return a Reference< XDynnamicResultSet >!" );
617  }
618 
619  return aResult;
620 }
621 
622 
624  const Sequence< OUString >& rPropertyNames,
625  ResultSetInclude eMode )
626 {
628  createCursorAny( rPropertyNames, eMode ) >>= aResult;
629 
630  OSL_ENSURE( aResult.is(), "Content::createDynamicCursor - no cursor!" );
631 
632  return aResult;
633 }
634 
635 
637  const Sequence< OUString >& rPropertyNames,
638  const Sequence< NumberedSortingInfo >& rSortInfo,
639  const Reference< XAnyCompareFactory >& rAnyCompareFactory,
640  ResultSetInclude eMode )
641 {
642  Reference< XResultSet > aResult;
644 
645  Any aCursorAny = createCursorAny( rPropertyNames, eMode );
646 
647  aCursorAny >>= aDynSet;
648 
649  if( aDynSet.is() )
650  {
652 
653  if( m_xImpl->getComponentContext().is() )
654  {
656  SortedDynamicResultSetFactory::create( m_xImpl->getComponentContext());
657 
658  aDynResult = aSortFactory->createSortedDynamicResultSet( aDynSet,
659  rSortInfo,
660  rAnyCompareFactory );
661  }
662 
663  OSL_ENSURE( aDynResult.is(), "Content::createSortedCursor - no sorted cursor!" );
664 
665  if( aDynResult.is() )
666  aResult = aDynResult->getStaticResultSet();
667  else
668  aResult = aDynSet->getStaticResultSet();
669  }
670 
671  OSL_ENSURE( aResult.is(), "Content::createSortedCursor - no cursor!" );
672 
673  if ( !aResult.is() )
674  {
675  // Former, the open command directly returned a XResultSet.
676  aCursorAny >>= aResult;
677 
678  OSL_ENSURE( !aResult.is(),
679  "Content::createCursor - open-Command must "
680  "return a Reference< XDynnamicResultSet >!" );
681  }
682 
683  return aResult;
684 }
685 
686 
688 {
689  if ( !isDocument() )
690  return Reference< XInputStream >();
691 
692  Reference< XActiveDataSink > xSink = new ActiveDataSink;
693 
694  OpenCommandArgument2 aArg;
695  aArg.Mode = OpenMode::DOCUMENT;
696  aArg.Priority = 0; // unused
697  aArg.Sink = xSink;
698  aArg.Properties = Sequence< Property >( 0 ); // unused
699 
700  Command aCommand;
701  aCommand.Name = "open";
702  aCommand.Handle = -1; // n/a
703  aCommand.Argument <<= aArg;
704 
705  m_xImpl->executeCommand( aCommand );
706 
707  return xSink->getInputStream();
708 }
709 
710 
712 {
713  if ( !isDocument() )
714  return Reference< XInputStream >();
715 
716  Reference< XActiveDataSink > xSink = new ActiveDataSink;
717 
718  OpenCommandArgument2 aArg;
719  aArg.Mode = OpenMode::DOCUMENT_SHARE_DENY_NONE;
720  aArg.Priority = 0; // unused
721  aArg.Sink = xSink;
722  aArg.Properties = Sequence< Property >( 0 ); // unused
723 
724  Command aCommand;
725  aCommand.Name = "open";
726  aCommand.Handle = -1; // n/a
727  aCommand.Argument <<= aArg;
728 
729  m_xImpl->executeCommand( aCommand );
730 
731  return xSink->getInputStream();
732 }
733 
734 
736 {
737  if ( !isDocument() )
738  return Reference< XStream >();
739 
741 
742  OpenCommandArgument2 aArg;
743  aArg.Mode = OpenMode::DOCUMENT;
744  aArg.Priority = 0; // unused
745  aArg.Sink = xStreamer;
746  aArg.Properties = Sequence< Property >( 0 ); // unused
747 
748  Command aCommand;
749  aCommand.Name = "open";
750  aCommand.Handle = -1; // n/a
751  aCommand.Argument <<= aArg;
752 
753  m_xImpl->executeCommand( aCommand );
754 
755  return xStreamer->getStream();
756 }
757 
758 
760 {
761  if ( !isDocument() )
762  return Reference< XStream >();
763 
765 
766  OpenCommandArgument2 aArg;
767  aArg.Mode = OpenMode::DOCUMENT_SHARE_DENY_NONE;
768  aArg.Priority = 0; // unused
769  aArg.Sink = xStreamer;
770  aArg.Properties = Sequence< Property >( 0 ); // unused
771 
772  Command aCommand;
773  aCommand.Name = "open";
774  aCommand.Handle = -1; // n/a
775  aCommand.Argument <<= aArg;
776 
777  m_xImpl->executeCommand( aCommand );
778 
779  return xStreamer->getStream();
780 }
781 
782 
784 {
785  if ( !isDocument() )
786  return false;
787 
788  OpenCommandArgument2 aArg;
789  aArg.Mode = OpenMode::DOCUMENT;
790  aArg.Priority = 0; // unused
791  aArg.Sink = rSink;
792  aArg.Properties = Sequence< Property >( 0 ); // unused
793 
794  Command aCommand;
795  aCommand.Name = "open";
796  aCommand.Handle = -1; // n/a
797  aCommand.Argument <<= aArg;
798 
799  m_xImpl->executeCommand( aCommand );
800 
801  return true;
802 }
803 
804 
805 bool Content::openStream( const Reference< XOutputStream >& rStream )
806 {
807  if ( !isDocument() )
808  return false;
809 
810  OpenCommandArgument2 aArg;
811  aArg.Mode = OpenMode::DOCUMENT;
812  aArg.Priority = 0; // unused
813  aArg.Sink = rStream;
814  aArg.Properties = Sequence< Property >( 0 ); // unused
815 
816  Command aCommand;
817  aCommand.Name = "open";
818  aCommand.Handle = -1; // n/a
819  aCommand.Argument <<= aArg;
820 
821  m_xImpl->executeCommand( aCommand );
822 
823  return true;
824 }
825 
826 
828  bool bReplaceExisting )
829 {
830  InsertCommandArgument aArg;
831  aArg.Data = rStream.is() ? rStream : new EmptyInputStream;
832  aArg.ReplaceExisting = bReplaceExisting;
833 
834  Command aCommand;
835  aCommand.Name = "insert";
836  aCommand.Handle = -1; // n/a
837  aCommand.Argument <<= aArg;
838 
839  m_xImpl->executeCommand( aCommand );
840 
841  m_xImpl->inserted();
842 }
843 
844 
846 {
847  // First, try it using "CreatableContentsInfo" property -> the "new" way.
849  if ( getPropertyValue(
850  "CreatableContentsInfo" )
851  >>= aInfo )
852  return aInfo;
853 
854  // Second, try it using XContentCreator interface -> the "old" way (not
855  // providing the chance to supply an XCommandEnvironment.
856  Reference< XContentCreator > xCreator( m_xImpl->getContent(), UNO_QUERY );
857  if ( xCreator.is() )
858  aInfo = xCreator->queryCreatableContentsInfo();
859 
860  return aInfo;
861 }
862 
863 
864 bool Content::insertNewContent( const OUString& rContentType,
865  const Sequence< OUString >&
866  rPropertyNames,
867  const Sequence< Any >& rPropertyValues,
868  Content& rNewContent )
869 {
870  return insertNewContent( rContentType,
871  rPropertyNames,
872  rPropertyValues,
873  new EmptyInputStream,
874  rNewContent );
875 }
876 
877 
878 bool Content::insertNewContent( const OUString& rContentType,
879  const Sequence< OUString >&
880  rPropertyNames,
881  const Sequence< Any >& rPropertyValues,
882  const Reference< XInputStream >& rData,
883  Content& rNewContent )
884 {
885  if ( rContentType.isEmpty() )
886  return false;
887 
888  // First, try it using "createNewContent" command -> the "new" way.
889  ContentInfo aInfo;
890  aInfo.Type = rContentType;
891  aInfo.Attributes = 0;
892 
893  Command aCommand;
894  aCommand.Name = "createNewContent";
895  aCommand.Handle = -1; // n/a
896  aCommand.Argument <<= aInfo;
897 
899  try
900  {
901  m_xImpl->executeCommand( aCommand ) >>= xNew;
902  }
903  catch ( RuntimeException const & )
904  {
905  throw;
906  }
907  catch ( Exception const & )
908  {
909  }
910 
911  if ( !xNew.is() )
912  {
913  // Second, try it using XContentCreator interface -> the "old"
914  // way (not providing the chance to supply an XCommandEnvironment.
915  Reference< XContentCreator > xCreator( m_xImpl->getContent(), UNO_QUERY );
916 
917  if ( !xCreator.is() )
918  return false;
919 
920  xNew = xCreator->createNewContent( aInfo );
921 
922  if ( !xNew.is() )
923  return false;
924  }
925 
926  Content aNewContent(
927  xNew, m_xImpl->getEnvironment(), m_xImpl->getComponentContext() );
928  aNewContent.setPropertyValues( rPropertyNames, rPropertyValues );
929  aNewContent.executeCommand( "insert",
930  makeAny(
931  InsertCommandArgument(
932  rData.is() ? rData : new EmptyInputStream,
933  false /* ReplaceExisting */ ) ) );
934  aNewContent.m_xImpl->inserted();
935 
936  rNewContent = aNewContent;
937  return true;
938 }
939 
940 
941 void Content::transferContent( const Content& rSourceContent,
942  InsertOperation eOperation,
943  const OUString & rTitle,
944  const sal_Int32 nNameClashAction,
945  const OUString & rMimeType,
946  bool bMajorVersion,
947  const OUString & rVersionComment,
948  OUString* pResultURL,
949  const OUString & rDocumentId ) const
950 {
952  UniversalContentBroker::create( m_xImpl->getComponentContext() ) );
953 
954  // Execute command "globalTransfer" at UCB.
955 
956  TransferCommandOperation eTransOp = TransferCommandOperation();
957  OUString sCommand( "globalTransfer" );
958  bool bCheckIn = false;
959  switch ( eOperation )
960  {
962  eTransOp = TransferCommandOperation_COPY;
963  break;
964 
966  eTransOp = TransferCommandOperation_MOVE;
967  break;
968 
970  eTransOp = TransferCommandOperation_COPY;
971  sCommand = "checkin";
972  bCheckIn = true;
973  break;
974  }
975  Command aCommand;
976  aCommand.Name = sCommand;
977  aCommand.Handle = -1; // n/a
978 
979  if ( !bCheckIn )
980  {
981  GlobalTransferCommandArgument2 aTransferArg(
982  eTransOp,
983  rSourceContent.getURL(), // SourceURL
984  getURL(), // TargetFolderURL,
985  rTitle,
986  nNameClashAction,
987  rMimeType,
988  rDocumentId );
989  aCommand.Argument <<= aTransferArg;
990  }
991  else
992  {
993  CheckinArgument aCheckinArg( bMajorVersion, rVersionComment,
994  rSourceContent.getURL(), getURL(), rTitle, rMimeType );
995  aCommand.Argument <<= aCheckinArg;
996  }
997 
998  Any aRet = pBroker->execute( aCommand, 0, m_xImpl->getEnvironment() );
999  if ( pResultURL != nullptr )
1000  aRet >>= *pResultURL;
1001 }
1002 
1003 
1005 {
1006  bool bFolder = false;
1007  if ( getPropertyValue("IsFolder")
1008  >>= bFolder )
1009  return bFolder;
1010 
1012  makeAny( UnknownPropertyException(
1013  "Unable to retrieve value of property 'IsFolder'!",
1014  get() ) ),
1015  m_xImpl->getEnvironment() );
1016 
1018 }
1019 
1020 
1022 
1024 {
1025  bool bDoc = false;
1026  if ( getPropertyValue("IsDocument")
1027  >>= bDoc )
1028  return bDoc;
1029 
1031  makeAny( UnknownPropertyException(
1032  "Unable to retrieve value of property 'IsDocument'!",
1033  get() ) ),
1034  m_xImpl->getEnvironment() );
1035 
1036  // Unreachable - cancelCommandExecution always throws an exception,
1037  // But some compilers complain...
1038  return false;
1039 }
1040 
1042 
1044 {
1045  Command aCommand;
1046  aCommand.Name = "lock";
1047  aCommand.Handle = -1; // n/a
1048 
1049  m_xImpl->executeCommand( aCommand );
1050 
1051 }
1052 
1054 {
1055 
1056  Command aCommand;
1057  aCommand.Name = "unlock";
1058  aCommand.Handle = -1; // n/a
1059 
1060  m_xImpl->executeCommand( aCommand );
1061 
1062 }
1063 
1064 
1065 // Content_Impl Implementation.
1066 
1067 
1069  const Reference< XContent >& rContent,
1070  const Reference< XCommandEnvironment >& rEnv )
1071 : m_xCtx( rCtx ),
1072  m_xContent( rContent ),
1073  m_xEnv( rEnv )
1074 {
1075  assert(rCtx.is());
1076  if ( m_xContent.is() )
1077  {
1079  m_xContent->addContentEventListener( m_xContentEventListener );
1080 
1081 #if OSL_DEBUG_LEVEL > 0
1082  // Only done on demand in product version for performance reasons,
1083  // but a nice debug helper.
1084  getURL();
1085 #endif
1086  }
1087 }
1088 
1089 
1091 {
1092  osl::MutexGuard aGuard( m_aMutex );
1093 
1094  m_xCommandProcessor = nullptr;
1095 
1096  // #92581# - Don't reset m_aURL!!!
1097 
1098  if ( m_xContent.is() )
1099  {
1100  try
1101  {
1102  m_xContent->removeContentEventListener( m_xContentEventListener );
1103  }
1104  catch ( RuntimeException const & )
1105  {
1106  }
1107  }
1108 
1109  if ( xContent.is() )
1110  {
1111  m_xContent = xContent;
1112  m_xContent->addContentEventListener( m_xContentEventListener );
1113 
1114 #if OSL_DEBUG_LEVEL > 0
1115  // Only done on demand in product version for performance reasons,
1116  // but a nice debug helper.
1117  getURL();
1118 #endif
1119  }
1120  else
1121  {
1122  // We need m_xContent's URL in order to be able to create the
1123  // content object again if demanded ( --> Content_Impl::getContent() )
1124  getURL();
1125 
1126  m_xContent = nullptr;
1127  }
1128 }
1129 
1130 
1131 // virtual
1133 {
1134  if ( m_xContent.is() )
1135  {
1136  try
1137  {
1138  m_xContent->removeContentEventListener( m_xContentEventListener );
1139  }
1140  catch ( RuntimeException const & )
1141  {
1142  }
1143  }
1144 }
1145 
1146 
1147 void Content_Impl::disposing( const EventObject& Source )
1148 {
1149  Reference<XContent> xContent;
1150 
1151  {
1152  osl::MutexGuard aGuard( m_aMutex );
1153  if(Source.Source != m_xContent)
1154  return;
1155 
1156  xContent = m_xContent;
1157 
1158  m_aURL.clear();
1159  m_xCommandProcessor = nullptr;
1160  m_xContent = nullptr;
1161  }
1162 
1163  if ( xContent.is() )
1164  {
1165  try
1166  {
1167  xContent->removeContentEventListener( m_xContentEventListener );
1168  }
1169  catch ( RuntimeException const & )
1170  {
1171  }
1172  }
1173 }
1174 
1175 
1176 const OUString& Content_Impl::getURL() const
1177 {
1178  if ( m_aURL.isEmpty() && m_xContent.is() )
1179  {
1180  osl::MutexGuard aGuard( m_aMutex );
1181 
1182  if ( m_aURL.isEmpty() && m_xContent.is() )
1183  {
1184  Reference< XContentIdentifier > xId = m_xContent->getIdentifier();
1185  if ( xId.is() )
1186  m_aURL = xId->getContentIdentifier();
1187  }
1188  }
1189 
1190  return m_aURL;
1191 }
1192 
1193 
1195 {
1196  if ( !m_xContent.is() && !m_aURL.isEmpty() )
1197  {
1198  osl::MutexGuard aGuard( m_aMutex );
1199 
1200  if ( !m_xContent.is() && !m_aURL.isEmpty() )
1201  {
1203  UniversalContentBroker::create( getComponentContext() ) );
1204 
1205  OSL_ENSURE( pBroker->queryContentProviders().hasElements(),
1206  "Content Broker not configured (no providers)!" );
1207 
1209  = pBroker->createContentIdentifier( m_aURL );
1210 
1211  OSL_ENSURE( xId.is(), "No Content Identifier!" );
1212 
1213  if ( xId.is() )
1214  {
1215  try
1216  {
1217  m_xContent = pBroker->queryContent( xId );
1218  }
1219  catch ( IllegalIdentifierException const & )
1220  {
1221  }
1222 
1223  if ( m_xContent.is() )
1224  m_xContent->addContentEventListener(
1226  }
1227  }
1228  }
1229 
1230  return m_xContent;
1231 }
1232 
1233 
1235 {
1236  if ( !m_xCommandProcessor.is() )
1237  {
1238  osl::MutexGuard aGuard( m_aMutex );
1239 
1240  if ( !m_xCommandProcessor.is() )
1241  m_xCommandProcessor.set( getContent(), UNO_QUERY );
1242  }
1243 
1244  return m_xCommandProcessor;
1245 }
1246 
1247 
1248 Any Content_Impl::executeCommand( const Command& rCommand )
1249 {
1251  if ( !xProc.is() )
1252  return Any();
1253 
1254  // Execute command
1255  return xProc->execute( rCommand, 0, m_xEnv );
1256 }
1257 
1258 
1261 {
1262  return m_xEnv;
1263 }
1264 
1265 
1267  const Reference< XCommandEnvironment >& xNewEnv )
1268 {
1269  osl::MutexGuard aGuard( m_aMutex );
1270  m_xEnv = xNewEnv;
1271 }
1272 
1273 
1275 {
1276  // URL might have changed during 'insert' => recalculate in next getURL()
1277  osl::MutexGuard aGuard( m_aMutex );
1278  m_aURL.clear();
1279 }
1280 
1281 
1282 // ContentEventListener_Impl Implementation.
1283 
1284 
1285 // XInterface methods.
1286 
1287 void SAL_CALL ContentEventListener_Impl::acquire()
1288  throw()
1289 {
1290  OWeakObject::acquire();
1291 }
1292 
1293 void SAL_CALL ContentEventListener_Impl::release()
1294  throw()
1295 {
1296  OWeakObject::release();
1297 }
1298 
1299 css::uno::Any SAL_CALL ContentEventListener_Impl::queryInterface( const css::uno::Type & rType )
1300 {
1301  css::uno::Any aRet = cppu::queryInterface( rType,
1302  static_cast< XContentEventListener* >(this),
1303  static_cast< XEventListener* >(this)
1304  );
1305  return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
1306 }
1307 
1308 // XContentEventListener methods.
1309 
1310 
1311 // virtual
1312 void SAL_CALL ContentEventListener_Impl::contentEvent( const ContentEvent& evt )
1313 {
1314  if ( evt.Source != m_rContent.m_xContent )
1315  return;
1316 
1317  switch ( evt.Action )
1318  {
1319  case ContentAction::DELETED:
1320  m_rContent.reinit( Reference< XContent >() );
1321  break;
1322 
1323  case ContentAction::EXCHANGED:
1324  m_rContent.reinit( evt.Content );
1325  break;
1326 
1327  default:
1328  break;
1329  }
1330 }
1331 
1332 
1333 // XEventListenr methods.
1334 
1335 
1336 // virtual
1337 void SAL_CALL ContentEventListener_Impl::disposing( const EventObject& Source )
1338 {
1339  m_rContent.disposing(Source);
1340 }
1341 
1342 } /* namespace ucbhelper */
1343 
1344 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
tools::SvRef< SvBaseLink > xSink
css::uno::Environment getEnvironment(OUString const &name, OUString const &implementation)
css::uno::Reference< css::sdbc::XRow > getPropertyValuesInterface(const css::uno::Sequence< OUString > &rPropertyNames)
This method can be used to read multiple property values.
Definition: content.cxx:472
rtl::Reference< Content_Impl > m_xImpl
Definition: content.hxx:100
bool insertNewContent(const OUString &rContentType, const css::uno::Sequence< OUString > &rPropertyNames, const css::uno::Sequence< css::uno::Any > &rPropertyValues, Content &rNewContent)
This method creates, initializes and inserts ( commits ) a new content (i.e.
bool isDocument()
This method returns the value of the content's property "IsDocument".
Definition: content.cxx:1023
#define SAL_WNOUNREACHABLE_CODE_POP
css::uno::Any getPropertyValue(const OUString &rPropertyName)
This method can be used to read a single property value.
Definition: content.cxx:430
Content_Impl & m_rContent
Definition: content.cxx:128
sal_Int64 n
Reference< XComponentContext > m_xCtx
Definition: content.cxx:157
static Reference< XContentIdentifier > getContentIdentifierNoThrow(const Reference< XUniversalContentBroker > &rBroker, const OUString &rURL)
Definition: content.cxx:233
css::uno::Sequence< css::ucb::ContentInfo > queryCreatableContentsInfo()
This method returns the different types of contents this content can create.
Definition: content.cxx:845
Reference< XCommandProcessor > getCommandProcessor()
Definition: content.cxx:1234
static void ensureContentProviderForURL(const Reference< XUniversalContentBroker > &rBroker, const OUString &rURL)
Definition: content.cxx:196
void lock()
This method lock the resource.
Definition: content.cxx:1043
ResultSetInclude
These are the possible values for the parameter eMode of method ucbhelper::Content::createCursor.
Definition: content.hxx:73
static Reference< XContent > getContentThrow(const Reference< XUniversalContentBroker > &rBroker, const Reference< XContentIdentifier > &xId)
Definition: content.cxx:242
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
Reference< XComponentContext > const & getComponentContext() const
Definition: content.cxx:179
Reference< XComponentContext > m_xCtx
int nCount
css::uno::Any createCursorAny(const css::uno::Sequence< OUString > &rPropertyNames, ResultSetInclude eMode)
Definition: content.cxx:562
InsertOperation
These are the possible values for the parameter eOperation of method ucbhelper::Content::insertNewCon...
Definition: content.hxx:84
uno::Reference< sdbc::XRow > xRow
static Reference< XContentIdentifier > getContentIdentifierThrow(const Reference< XUniversalContentBroker > &rBroker, const OUString &rURL)
Definition: content.cxx:212
const css::uno::Reference< css::ucb::XCommandEnvironment > & getCommandEnvironment() const
This method returns the environment to use when executing commands.
Definition: content.cxx:387
Content()
Constructor.
Definition: content.cxx:293
void setCommandEnvironment(const css::uno::Reference< css::ucb::XCommandEnvironment > &xNewEnv)
This method sets a new command environment.
Definition: content.cxx:393
void cancelCommandExecution(const uno::Any &rException, const uno::Reference< ucb::XCommandEnvironment > &xEnv)
uno::Reference< ucb::XContent > m_xContent
void unlock()
This method unlock the resource.
Definition: content.cxx:1053
#define O3TL_UNREACHABLE
DECL_LISTENERMULTIPLEXER_END void SAL_CALL inserted(::sal_Int32 ID) override
Content & operator=(const Content &rOther)
Assignment operator.
Definition: content.cxx:363
Reference< XCommandProcessor > m_xCommandProcessor
Definition: content.cxx:159
const OUString & getURL() const
This method returns the URL of the content.
Definition: content.cxx:381
friend ContentEventListener_Impl
Definition: content.cxx:154
Reference< XCommandEnvironment > m_xEnv
Definition: content.cxx:160
css::uno::Reference< css::sdbc::XResultSet > createCursor(const css::uno::Sequence< OUString > &rPropertyNames, ResultSetInclude eMode=INCLUDE_FOLDERS_AND_DOCUMENTS)
This methods gives access to the children of a folder content.
Definition: content.cxx:594
~Content()
Destructor.
Definition: content.cxx:358
css::uno::Reference< css::io::XStream > openWriteableStream()
This methods gives read/write access to the content stream of a content (i.e the content of a file lo...
Definition: content.cxx:735
This class simplifies access to UCB contents by providing a more convenient API for frequently used f...
Definition: content.hxx:98
Reference< XContent > m_xContent
Definition: content.cxx:158
css::uno::Reference< css::ucb::XDynamicResultSet > createDynamicCursor(const css::uno::Sequence< OUString > &rPropertyNames, ResultSetInclude eMode=INCLUDE_FOLDERS_AND_DOCUMENTS)
This methods gives access to the children of a folder content.
Definition: content.cxx:623
virtual ~Content_Impl() override
Definition: content.cxx:1132
const Reference< XCommandEnvironment > & getEnvironment() const
Definition: content.cxx:1260
css::uno::Reference< css::ucb::XContent > get() const
This method provides access to the "native" UCB content interface(s).
Definition: content.cxx:375
css::uno::Reference< css::beans::XPropertySetInfo > getProperties()
This methods provides access to meta data of the properties supported by this content.
Definition: content.cxx:415
const PropertyValue * pValues
css::uno::Reference< css::io::XInputStream > openStream()
This methods gives read access to the content stream of a content (i.e the content of a file located ...
Definition: content.cxx:687
#define SAL_WNOUNREACHABLE_CODE_PUSH
static Reference< XContent > getContentNoThrow(const Reference< XUniversalContentBroker > &rBroker, const Reference< XContentIdentifier > &xId)
Definition: content.cxx:272
static bool create(const OUString &rURL, const css::uno::Reference< css::ucb::XCommandEnvironment > &rEnv, const css::uno::Reference< css::uno::XComponentContext > &rCtx, Content &rContent)
Constructor.
css::uno::Reference< css::io::XInputStream > openStreamNoLock()
This methods gives read access to the content stream of a content (i.e the content of a file located ...
Definition: content.cxx:711
This class implements the interface css::io::XActiveDataStreamer.
void setEnvironment(const Reference< XCommandEnvironment > &xNewEnv)
Definition: content.cxx:1266
void disposing(const EventObject &Source)
Definition: content.cxx:1147
css::uno::Reference< css::sdbc::XResultSet > createSortedCursor(const css::uno::Sequence< OUString > &rPropertyNames, const css::uno::Sequence< css::ucb::NumberedSortingInfo > &rSortInfo, const css::uno::Reference< css::ucb::XAnyCompareFactory > &rAnyCompareFactory, ResultSetInclude eMode=INCLUDE_FOLDERS_AND_DOCUMENTS)
Definition: content.cxx:636
void transferContent(const Content &rSourceContent, InsertOperation eOperation, const OUString &rTitle, const sal_Int32 nNameClashAction, const OUString &rMimeType=OUString(), bool bMajorVersion=false, const OUString &rCommentVersion=OUString(), OUString *pResultURL=nullptr, const OUString &rDocumentId=OUString()) const
This method transfers (copies/moves) a content.
Definition: content.cxx:941
const OUString & getURL() const
Definition: content.cxx:1176
css::uno::Reference< css::ucb::XCommandInfo > getCommands()
This methods provides access to meta data of the commands supported by this content.
Definition: content.cxx:400
uno::Reference< ucb::XContent > xContent
css::uno::Any setPropertyValue(const OUString &rPropertyName, const css::uno::Any &rValue)
This method can be used to set a single property value.
Definition: content.cxx:439
#define SAL_WARN(area, stream)
css::uno::Any executeCommand(const OUString &rCommandName, const css::uno::Any &rCommandArgument)
This method can be used to execute any command supported by the content.
Definition: content.cxx:550
OUString aCommand
void writeStream(const css::uno::Reference< css::io::XInputStream > &rStream, bool bReplaceExisting)
This methods gives write access to the content stream of a content (i.e the content of a file located...
Definition: content.cxx:827
css::uno::Sequence< css::uno::Any > getPropertyValues(const css::uno::Sequence< OUString > &rPropertyNames)
This method can be used to read multiple property values.
Reference< XContent > getContent()
Definition: content.cxx:1194
bool isFolder()
This method returns the value of the content's property "IsFolder".
Definition: content.cxx:1004
Any executeCommand(const Command &rCommand)
Definition: content.cxx:1248
css::uno::Reference< css::io::XStream > openWriteableStreamNoLock()
This methods gives read/write access to the content stream of a content (i.e the content of a file lo...
Definition: content.cxx:759
Reference< XContentEventListener > m_xContentEventListener
Definition: content.cxx:161
css::uno::Sequence< css::uno::Any > setPropertyValues(const css::uno::Sequence< OUString > &rPropertyNames, const css::uno::Sequence< css::uno::Any > &rValues)
This method can be used to set multiple property values.
uno::Reference< ucb::XContentIdentifier > xId
css::uno::Any SAL_CALL queryInterface(const css::uno::Type &rType, Interface1 *p1)
void reinit(const Reference< XContent > &xContent)
Definition: content.cxx:1090
css::uno::Any SAL_CALL makeAny(const SharedUNOComponent< INTERFACE, COMPONENT > &value)