1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: odma_content.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_ucb.hxx"
34 /**************************************************************************
36 **************************************************************************
38 *************************************************************************/
39 #include <osl/diagnose.h>
40 #include "odma_contentprops.hxx"
41 #include <com/sun/star/ucb/XDynamicResultSet.hpp>
42 #include <com/sun/star/beans/PropertyAttribute.hpp>
43 #include <com/sun/star/beans/XPropertyAccess.hpp>
44 #include <com/sun/star/lang/IllegalAccessException.hpp>
45 #include <com/sun/star/ucb/UnsupportedDataSinkException.hpp>
46 #include <com/sun/star/sdbc/XRow.hpp>
47 #include <com/sun/star/io/XOutputStream.hpp>
48 #include <com/sun/star/io/XActiveDataSink.hpp>
49 #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
50 #include <com/sun/star/ucb/OpenMode.hpp>
51 #include <com/sun/star/ucb/XCommandInfo.hpp>
52 #include <com/sun/star/ucb/XPersistentPropertySet.hpp>
53 #include <ucbhelper/contentidentifier.hxx>
54 #include <ucbhelper/propertyvalueset.hxx>
55 #include <ucbhelper/cancelcommandexecution.hxx>
56 #include <com/sun/star/ucb/UnsupportedOpenModeException.hpp>
57 #include <com/sun/star/ucb/MissingInputStreamException.hpp>
58 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
59 #include <com/sun/star/ucb/MissingPropertiesException.hpp>
60 #include <com/sun/star/io/XActiveDataStreamer.hpp>
61 #include <com/sun/star/ucb/TransferInfo.hpp>
62 #include <com/sun/star/ucb/NameClash.hpp>
63 #include "odma_content.hxx"
64 #include "odma_provider.hxx"
65 #include "odma_resultset.hxx"
66 #include "odma_inputstream.hxx"
67 #include <ucbhelper/content.hxx>
68 #include <com/sun/star/uno/Exception.hpp>
69 #include <rtl/ref.hxx>
70 #include <osl/file.hxx>
72 using namespace com::sun::star
;
75 //=========================================================================
76 //=========================================================================
78 // Content Implementation.
80 //=========================================================================
81 //=========================================================================
83 Content::Content( const uno::Reference
< lang::XMultiServiceFactory
>& rxSMgr
,
84 ContentProvider
* pProvider
,
85 const uno::Reference
< ucb::XContentIdentifier
>& Identifier
,
86 const ::rtl::Reference
<ContentProperties
>& _rProps
)
87 : ContentImplHelper( rxSMgr
, pProvider
, Identifier
)
89 ,m_pProvider(pProvider
)
92 OSL_ENSURE(m_aProps
.is(),"No valid ContentPropeties!");
95 //=========================================================================
102 //=========================================================================
104 // XInterface methods.
106 //=========================================================================
109 void SAL_CALL
Content::acquire() throw()
111 ContentImplHelper::acquire();
114 //=========================================================================
116 void SAL_CALL
Content::release() throw()
118 ContentImplHelper::release();
121 //=========================================================================
123 uno::Any SAL_CALL
Content::queryInterface( const uno::Type
& rType
)
124 throw ( uno::RuntimeException
)
128 // @@@ Add support for additional interfaces.
130 aRet
= cppu::queryInterface( rType
,
131 static_cast< yyy::Xxxxxxxxx
* >( this ) );
134 return aRet
.hasValue() ? aRet
: ContentImplHelper::queryInterface( rType
);
137 //=========================================================================
139 // XTypeProvider methods.
141 //=========================================================================
143 XTYPEPROVIDER_COMMON_IMPL( Content
);
145 //=========================================================================
147 uno::Sequence
< uno::Type
> SAL_CALL
Content::getTypes()
148 throw( uno::RuntimeException
)
150 // @@@ Add own interfaces.
152 static cppu::OTypeCollection
* pCollection
= 0;
156 osl::Guard
< osl::Mutex
> aGuard( osl::Mutex::getGlobalMutex() );
159 static cppu::OTypeCollection
aCollection(
160 CPPU_TYPE_REF( lang::XTypeProvider
),
161 CPPU_TYPE_REF( lang::XServiceInfo
),
162 CPPU_TYPE_REF( lang::XComponent
),
163 CPPU_TYPE_REF( ucb::XContent
),
164 CPPU_TYPE_REF( ucb::XCommandProcessor
),
165 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier
),
166 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier
),
167 CPPU_TYPE_REF( beans::XPropertyContainer
),
168 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier
),
169 CPPU_TYPE_REF( container::XChild
) );
170 pCollection
= &aCollection
;
174 return (*pCollection
).getTypes();
177 //=========================================================================
179 // XServiceInfo methods.
181 //=========================================================================
184 rtl::OUString SAL_CALL
Content::getImplementationName()
185 throw( uno::RuntimeException
)
187 // @@@ Adjust implementation name. Keep the prefix "com.sun.star.comp."!
188 return rtl::OUString::createFromAscii( "com.sun.star.comp.odma.Content" );
191 //=========================================================================
193 uno::Sequence
< rtl::OUString
> SAL_CALL
Content::getSupportedServiceNames()
194 throw( uno::RuntimeException
)
196 // @@@ Adjust macro name.
197 uno::Sequence
< rtl::OUString
> aSNS( 1 );
199 = rtl::OUString::createFromAscii( ODMA_CONTENT_SERVICE_NAME
);
203 //=========================================================================
207 //=========================================================================
210 rtl::OUString SAL_CALL
Content::getContentType()
211 throw( uno::RuntimeException
)
213 // @@@ Adjust macro name ( def in odma_provider.hxx ).
214 return rtl::OUString::createFromAscii( ODMA_CONTENT_TYPE
);
217 //=========================================================================
219 // XCommandProcessor methods.
221 //=========================================================================
224 uno::Any SAL_CALL
Content::execute(
225 const ucb::Command
& aCommand
,
226 sal_Int32
/*CommandId*/,
227 const uno::Reference
< ucb::XCommandEnvironment
>& Environment
)
228 throw( uno::Exception
,
229 ucb::CommandAbortedException
,
230 uno::RuntimeException
)
234 if ( aCommand
.Name
.equalsAsciiL(
235 RTL_CONSTASCII_STRINGPARAM( "getPropertyValues" ) ) )
237 //////////////////////////////////////////////////////////////////
239 //////////////////////////////////////////////////////////////////
241 uno::Sequence
< beans::Property
> Properties
;
242 if ( !( aCommand
.Argument
>>= Properties
) )
244 OSL_ENSURE( sal_False
, "Wrong argument type!" );
245 ucbhelper::cancelCommandExecution(
246 uno::makeAny( lang::IllegalArgumentException(
248 static_cast< cppu::OWeakObject
* >( this ),
254 aRet
<<= getPropertyValues( Properties
, Environment
);
256 else if ( aCommand
.Name
.equalsAsciiL(
257 RTL_CONSTASCII_STRINGPARAM( "setPropertyValues" ) ) )
259 //////////////////////////////////////////////////////////////////
261 //////////////////////////////////////////////////////////////////
263 uno::Sequence
< beans::PropertyValue
> aProperties
;
264 if ( !( aCommand
.Argument
>>= aProperties
) )
266 OSL_ENSURE( sal_False
, "Wrong argument type!" );
267 ucbhelper::cancelCommandExecution(
268 uno::makeAny( lang::IllegalArgumentException(
270 static_cast< cppu::OWeakObject
* >( this ),
276 if ( !aProperties
.getLength() )
278 OSL_ENSURE( sal_False
, "No properties!" );
279 ucbhelper::cancelCommandExecution(
280 uno::makeAny( lang::IllegalArgumentException(
282 static_cast< cppu::OWeakObject
* >( this ),
288 aRet
<<= setPropertyValues( aProperties
, Environment
);
290 else if ( aCommand
.Name
.equalsAsciiL(
291 RTL_CONSTASCII_STRINGPARAM( "getPropertySetInfo" ) ) )
293 //////////////////////////////////////////////////////////////////
294 // getPropertySetInfo
295 //////////////////////////////////////////////////////////////////
297 // Note: Implemented by base class.
298 aRet
<<= getPropertySetInfo( Environment
);
300 else if ( aCommand
.Name
.equalsAsciiL(
301 RTL_CONSTASCII_STRINGPARAM( "getCommandInfo" ) ) )
303 //////////////////////////////////////////////////////////////////
305 //////////////////////////////////////////////////////////////////
307 // Note: Implemented by base class.
308 aRet
<<= getCommandInfo( Environment
);
310 else if ( aCommand
.Name
.equalsAsciiL(
311 RTL_CONSTASCII_STRINGPARAM( "open" ) ) )
313 ucb::OpenCommandArgument2 aOpenCommand
;
314 if ( !( aCommand
.Argument
>>= aOpenCommand
) )
316 OSL_ENSURE( sal_False
, "Wrong argument type!" );
317 ucbhelper::cancelCommandExecution(
318 uno::makeAny( lang::IllegalArgumentException(
320 static_cast< cppu::OWeakObject
* >( this ),
326 sal_Bool bOpenFolder
=
327 ( ( aOpenCommand
.Mode
== ucb::OpenMode::ALL
) ||
328 ( aOpenCommand
.Mode
== ucb::OpenMode::FOLDERS
) ||
329 ( aOpenCommand
.Mode
== ucb::OpenMode::DOCUMENTS
) );
333 // open as folder - return result set
335 uno::Reference
< ucb::XDynamicResultSet
> xSet
336 = new DynamicResultSet( m_xSMgr
,
343 if ( aOpenCommand
.Sink
.is() )
345 // Open document - supply document data stream.
348 if ( ( aOpenCommand
.Mode
349 == ucb::OpenMode::DOCUMENT_SHARE_DENY_NONE
) ||
351 == ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE
) )
354 ucbhelper::cancelCommandExecution(
355 uno::makeAny( ucb::UnsupportedOpenModeException(
357 static_cast< cppu::OWeakObject
* >( this ),
358 sal_Int16( aOpenCommand
.Mode
) ) ),
364 rtl::OUString aURL
= m_xIdentifier
->getContentIdentifier();
365 rtl::OUString sFileURL
= openDoc();
367 m_pContent
= new ::ucbhelper::Content(sFileURL
,NULL
);
368 if(!m_pContent
->isDocument())
370 rtl::OUString
sErrorMsg(RTL_CONSTASCII_USTRINGPARAM("File: "));
371 sErrorMsg
+= sFileURL
;
372 sErrorMsg
+= rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" could not be found."));
373 ucbhelper::cancelCommandExecution(
374 uno::makeAny( io::IOException(
376 static_cast< cppu::OWeakObject
* >( this )) ),
380 uno::Reference
< io::XOutputStream
> xOut
381 = uno::Reference
< io::XOutputStream
>(
382 aOpenCommand
.Sink
, uno::UNO_QUERY
);
385 // @@@ PUSH: write data into xOut
386 m_pContent
->openStream(xOut
);
390 uno::Reference
< io::XActiveDataSink
> xDataSink
391 = uno::Reference
< io::XActiveDataSink
>(
392 aOpenCommand
.Sink
, uno::UNO_QUERY
);
393 if ( xDataSink
.is() )
395 // @@@ PULL: wait for client read
396 uno::Reference
< io::XInputStream
> xIn
;
399 xIn
= m_pContent
->openStream();
401 catch(uno::Exception
&)
403 OSL_ENSURE(0,"Exception occured while creating the file content!");
405 xDataSink
->setInputStream( xIn
);
409 uno::Reference
< io::XActiveDataStreamer
> activeDataStreamer( aOpenCommand
.Sink
,uno::UNO_QUERY
);
410 if(activeDataStreamer
.is())
412 activeDataStreamer
->setStream(new OOdmaStream(m_pContent
,getContentProvider(),m_aProps
));
413 m_pContent
= NULL
; // don't delete here because the stream is now the owner
417 // Note: aOpenCommand.Sink may contain an XStream
418 // implementation. Support for this type of
419 // sink is optional...
420 ucbhelper::cancelCommandExecution(
421 uno::makeAny( ucb::UnsupportedDataSinkException(
423 static_cast< cppu::OWeakObject
* >( this ),
424 aOpenCommand
.Sink
) ),
432 else if ( aCommand
.Name
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "close" ) ) )
434 getContentProvider()->closeDocument(m_aProps
->m_sDocumentId
);
436 else if ( aCommand
.Name
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "delete" ) ) )
438 //////////////////////////////////////////////////////////////////
440 //////////////////////////////////////////////////////////////////
442 // Remove own and all children's Additional Core Properties.
443 removeAdditionalPropertySet( sal_True
);
444 // Remove own and all childrens(!) persistent data.
445 if(!getContentProvider()->deleteDocument(m_aProps
))
446 ucbhelper::cancelCommandExecution(
447 uno::makeAny( lang::IllegalArgumentException(
449 static_cast< cppu::OWeakObject
* >( this ),
453 else if ( aCommand
.Name
.equalsAsciiL(
454 RTL_CONSTASCII_STRINGPARAM( "insert" ) ) )
456 //////////////////////////////////////////////////////////////////
458 //////////////////////////////////////////////////////////////////
460 ucb::InsertCommandArgument arg
;
461 if ( !( aCommand
.Argument
>>= arg
) )
463 OSL_ENSURE( sal_False
, "Wrong argument type!" );
464 ucbhelper::cancelCommandExecution(
465 uno::makeAny( lang::IllegalArgumentException(
467 static_cast< cppu::OWeakObject
* >( this ),
473 insert( arg
.Data
, arg
.ReplaceExisting
, Environment
);
475 else if( ! aCommand
.Name
.compareToAscii( "transfer" ) )
477 // So far I have determined that this command is called when
478 // doing "Save As" to copy an already written backup copy of
479 // the document in the file system into the DMS.
481 // Maybe also in other situations.
483 ucb::TransferInfo aTransferInfo
;
484 if( ! ( aCommand
.Argument
>>= aTransferInfo
) )
486 OSL_ENSURE( sal_False
, "Wrong argument type!" );
487 ucbhelper::cancelCommandExecution(
488 uno::makeAny( lang::IllegalArgumentException(
490 static_cast< cppu::OWeakObject
* >( this ),
495 ::rtl::Reference
<ContentProperties
> aProp
= m_aProps
;
496 if(aProp
->m_bIsFolder
)
498 aProp
= getContentProvider()->getContentPropertyWithDocumentId(aTransferInfo
.NewTitle
);
500 aProp
= getContentProvider()->getContentPropertyWithSavedAsName(aTransferInfo
.NewTitle
);
501 sal_Bool bError
= !aProp
.is();
503 // There used to be code below that called ODMSaveAsEx,
504 // but that was very broken. We have already called
505 // ODMSaveAsEx in the ODMA file picker when selecting the
506 // name for a new document, or the document already exists
507 // in the DMS and we don't need any ODMSaveAsEx. The ODMA
508 // file picker tells odma::ContentProvider about the new
509 // document's DOCID, so the
510 // getContentPropertyWithDocumentId() call above should
514 ucbhelper::cancelCommandExecution(
515 uno::makeAny( lang::IllegalArgumentException(
517 static_cast< cppu::OWeakObject
* >( this ),
521 rtl::OUString sFileURL
= ContentProvider::openDoc(aProp
);
523 sal_Int32 nLastIndex
= sFileURL
.lastIndexOf( sal_Unicode('/') );
524 // Create a new Content object for the "shadow" file
525 // corresponding to the opened document from the DMS.
526 ::ucbhelper::Content
aContent(sFileURL
.copy(0,nLastIndex
),NULL
);
527 // aTransferInfo.NameClash = ucb::NameClash::OVERWRITE;
528 aTransferInfo
.NewTitle
= sFileURL
.copy( 1 + nLastIndex
);
529 // Copy our saved backup copy to the "shadow" file.
530 aContent
.executeCommand(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("transfer")),uno::makeAny(aTransferInfo
));
531 // Tell the DMS that the "shadow" file is done and can be
533 getContentProvider()->saveDocument(aProp
->m_sDocumentId
);
535 else if ( aCommand
.Name
.equalsAsciiL(
536 RTL_CONSTASCII_STRINGPARAM( "getCasePreservingURL" ) ) )
538 rtl::OUString CasePreservingURL
= openDoc();
539 aRet
<<= CasePreservingURL
;
543 //////////////////////////////////////////////////////////////////
544 // Unsupported command
545 //////////////////////////////////////////////////////////////////
547 OSL_ENSURE( sal_False
, "Content::execute - unsupported command!" );
549 ucbhelper::cancelCommandExecution(
550 uno::makeAny( ucb::UnsupportedCommandException(
552 static_cast< cppu::OWeakObject
* >( this ) ) ),
560 //=========================================================================
562 void SAL_CALL
Content::abort( sal_Int32
/*CommandId*/ )
563 throw( uno::RuntimeException
)
565 // @@@ Implement logic to abort running commands, if this makes
566 // sense for your content.
569 //=========================================================================
571 // Non-interface methods.
573 //=========================================================================
576 ::rtl::OUString
Content::getParentURL()
578 ::rtl::OUString sURL
= m_xIdentifier
->getContentIdentifier();
580 // @@@ Extract URL of parent from aURL and return it...
581 static ::rtl::OUString
sScheme1(RTL_CONSTASCII_USTRINGPARAM(ODMA_URL_SCHEME ODMA_URL_SHORT
"/"));
582 static ::rtl::OUString
sScheme2(RTL_CONSTASCII_USTRINGPARAM(ODMA_URL_SCHEME ODMA_URL_SHORT
));
583 if(sURL
== sScheme1
|| sURL
== sScheme2
)
584 sURL
= ::rtl::OUString();
591 //=========================================================================
593 uno::Reference
< sdbc::XRow
> Content::getPropertyValues(
594 const uno::Reference
< lang::XMultiServiceFactory
>& rSMgr
,
595 const uno::Sequence
< beans::Property
>& rProperties
,
596 const rtl::Reference
<ContentProperties
>& rData
,
597 const rtl::Reference
< ::ucbhelper::ContentProviderImplHelper
>& rProvider
,
598 const rtl::OUString
& rContentId
)
600 // Note: Empty sequence means "get values of all supported properties".
602 rtl::Reference
< ::ucbhelper::PropertyValueSet
> xRow
603 = new ::ucbhelper::PropertyValueSet( rSMgr
);
605 sal_Int32 nCount
= rProperties
.getLength();
608 uno::Reference
< beans::XPropertySet
> xAdditionalPropSet
;
609 sal_Bool bTriedToGetAdditonalPropSet
= sal_False
;
611 const beans::Property
* pProps
= rProperties
.getConstArray();
612 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
614 const beans::Property
& rProp
= pProps
[ n
];
616 // Process Core properties.
618 if ( rProp
.Name
.equalsAsciiL(
619 RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) )
621 xRow
->appendString ( rProp
, rData
->m_sContentType
);
623 else if ( rProp
.Name
.equalsAsciiL(
624 RTL_CONSTASCII_STRINGPARAM( "Title" ) ) )
626 xRow
->appendString ( rProp
, rData
->m_sTitle
);
628 else if ( rProp
.Name
.equalsAsciiL(
629 RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) )
631 xRow
->appendBoolean( rProp
, rData
->m_bIsDocument
);
633 else if ( rProp
.Name
.equalsAsciiL(
634 RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) )
636 xRow
->appendBoolean( rProp
, rData
->m_bIsFolder
);
638 else if ( rProp
.Name
.equalsAsciiL(
639 RTL_CONSTASCII_STRINGPARAM( "DateCreated" ) ) )
641 xRow
->appendTimestamp( rProp
, rData
->m_aDateCreated
);
643 else if ( rProp
.Name
.equalsAsciiL(
644 RTL_CONSTASCII_STRINGPARAM( "DateModified" ) ) )
646 xRow
->appendTimestamp( rProp
, rData
->m_aDateModified
);
648 else if ( rProp
.Name
.equalsAsciiL(
649 RTL_CONSTASCII_STRINGPARAM( "IsReadOnly" ) ) )
651 xRow
->appendBoolean( rProp
, rData
->m_bIsReadOnly
);
653 else if ( rProp
.Name
.equalsAsciiL(
654 RTL_CONSTASCII_STRINGPARAM( "Author" ) ) )
656 xRow
->appendString ( rProp
, rData
->m_sAuthor
);
658 else if ( rProp
.Name
.equalsAsciiL(
659 RTL_CONSTASCII_STRINGPARAM( "Subject" ) ) )
661 xRow
->appendString ( rProp
, rData
->m_sSubject
);
663 else if ( rProp
.Name
.equalsAsciiL(
664 RTL_CONSTASCII_STRINGPARAM( "Keywords" ) ) )
666 xRow
->appendString ( rProp
, rData
->m_sKeywords
);
670 // @@@ Note: If your data source supports adding/removing
671 // properties, you should implement the interface
672 // XPropertyContainer by yourself and supply your own
673 // logic here. The base class uses the service
674 // "com.sun.star.ucb.Store" to maintain Additional Core
675 // properties. But using server functionality is preferred!
677 // Not a Core Property! Maybe it's an Additional Core Property?!
679 if ( !bTriedToGetAdditonalPropSet
&& !xAdditionalPropSet
.is() )
682 = uno::Reference
< beans::XPropertySet
>(
683 rProvider
->getAdditionalPropertySet( rContentId
,
686 bTriedToGetAdditonalPropSet
= sal_True
;
689 if ( xAdditionalPropSet
.is() )
691 if ( !xRow
->appendPropertySetValue(
695 // Append empty entry.
696 xRow
->appendVoid( rProp
);
701 // Append empty entry.
702 xRow
->appendVoid( rProp
);
709 // Append all Core Properties.
711 beans::Property( rtl::OUString::createFromAscii( "ContentType" ),
713 getCppuType( static_cast< const rtl::OUString
* >( 0 ) ),
714 beans::PropertyAttribute::BOUND
715 | beans::PropertyAttribute::READONLY
),
716 rData
->m_sContentType
);
718 beans::Property( rtl::OUString::createFromAscii( "Title" ),
720 getCppuType( static_cast< const rtl::OUString
* >( 0 ) ),
721 beans::PropertyAttribute::BOUND
),
724 beans::Property( rtl::OUString::createFromAscii( "IsDocument" ),
726 getCppuBooleanType(),
727 beans::PropertyAttribute::BOUND
728 | beans::PropertyAttribute::READONLY
),
729 rData
->m_bIsDocument
);
731 beans::Property( rtl::OUString::createFromAscii( "IsFolder" ),
733 getCppuBooleanType(),
734 beans::PropertyAttribute::BOUND
735 | beans::PropertyAttribute::READONLY
),
736 rData
->m_bIsFolder
);
738 // @@@ Append other properties supported directly.
739 xRow
->appendTimestamp(
740 beans::Property( rtl::OUString::createFromAscii( "DateCreated" ),
742 getCppuType(static_cast< const util::DateTime
* >( 0 ) ),
743 beans::PropertyAttribute::BOUND
744 | beans::PropertyAttribute::READONLY
),
745 rData
->m_aDateCreated
);
746 xRow
->appendTimestamp(
747 beans::Property( rtl::OUString::createFromAscii( "DateModified" ),
749 getCppuType(static_cast< const util::DateTime
* >( 0 ) ),
750 beans::PropertyAttribute::BOUND
751 | beans::PropertyAttribute::READONLY
),
752 rData
->m_aDateModified
);
754 beans::Property( rtl::OUString::createFromAscii( "IsReadOnly" ),
756 getCppuBooleanType(),
757 beans::PropertyAttribute::BOUND
758 | beans::PropertyAttribute::READONLY
),
759 rData
->m_bIsReadOnly
);
761 beans::Property( rtl::OUString::createFromAscii( "Author" ),
763 getCppuType( static_cast< const rtl::OUString
* >( 0 ) ),
764 beans::PropertyAttribute::BOUND
),
767 beans::Property( rtl::OUString::createFromAscii( "Subject" ),
769 getCppuType( static_cast< const rtl::OUString
* >( 0 ) ),
770 beans::PropertyAttribute::BOUND
),
773 beans::Property( rtl::OUString::createFromAscii( "Keywords" ),
775 getCppuType( static_cast< const rtl::OUString
* >( 0 ) ),
776 beans::PropertyAttribute::BOUND
),
777 rData
->m_sKeywords
);
779 // @@@ Note: If your data source supports adding/removing
780 // properties, you should implement the interface
781 // XPropertyContainer by yourself and supply your own
782 // logic here. The base class uses the service
783 // "com.sun.star.ucb.Store" to maintain Additional Core
784 // properties. But using server functionality is preferred!
786 // Append all Additional Core Properties.
788 uno::Reference
< beans::XPropertySet
> xSet(
789 rProvider
->getAdditionalPropertySet( rContentId
, sal_False
),
791 xRow
->appendPropertySet( xSet
);
794 return uno::Reference
< sdbc::XRow
>( xRow
.get() );
797 //=========================================================================
798 uno::Reference
< sdbc::XRow
> Content::getPropertyValues(
799 const uno::Sequence
< beans::Property
>& rProperties
,
800 const uno::Reference
< ucb::XCommandEnvironment
>& /*xEnv*/ )
802 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
803 return getPropertyValues( m_xSMgr
,
807 ::ucbhelper::ContentProviderImplHelper
>(
809 m_xIdentifier
->getContentIdentifier() );
812 //=========================================================================
813 uno::Sequence
< uno::Any
> Content::setPropertyValues(
814 const uno::Sequence
< beans::PropertyValue
>& rValues
,
815 const uno::Reference
< ucb::XCommandEnvironment
>& /*xEnv*/ )
817 osl::ClearableGuard
< osl::Mutex
> aGuard( m_aMutex
);
819 uno::Sequence
< uno::Any
> aRet( rValues
.getLength() );
820 uno::Sequence
< beans::PropertyChangeEvent
> aChanges( rValues
.getLength() );
821 sal_Int32 nChanged
= 0;
823 beans::PropertyChangeEvent aEvent
;
824 aEvent
.Source
= static_cast< cppu::OWeakObject
* >( this );
825 aEvent
.Further
= sal_False
;
826 // aEvent.PropertyName =
827 aEvent
.PropertyHandle
= -1;
831 const beans::PropertyValue
* pValues
= rValues
.getConstArray();
832 sal_Int32 nCount
= rValues
.getLength();
834 uno::Reference
< ucb::XPersistentPropertySet
> xAdditionalPropSet
;
835 sal_Bool bTriedToGetAdditonalPropSet
= sal_False
;
837 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
839 const beans::PropertyValue
& rValue
= pValues
[ n
];
841 if ( rValue
.Name
.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "Title" ) ) )
843 changePropertyValue(rValue
,n
,m_aProps
->m_sTitle
,nChanged
,aRet
,aChanges
);
845 else if ( rValue
.Name
.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "Author") ) )
847 changePropertyValue(rValue
,n
,m_aProps
->m_sAuthor
,nChanged
,aRet
,aChanges
);
849 else if ( rValue
.Name
.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "Keywords") ) )
851 changePropertyValue(rValue
,n
,m_aProps
->m_sKeywords
,nChanged
,aRet
,aChanges
);
853 else if ( rValue
.Name
.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "Subject") ) )
855 changePropertyValue(rValue
,n
,m_aProps
->m_sSubject
,nChanged
,aRet
,aChanges
);
857 else if ( rValue
.Name
.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) ||
858 rValue
.Name
.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) ||
859 rValue
.Name
.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) ||
860 rValue
.Name
.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "DateCreated" ) ) ||
861 rValue
.Name
.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "DateModified" ) ) ||
862 rValue
.Name
.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "IsReadOnly" ) ) )
864 // Read-only property!
865 aRet
[ n
] <<= lang::IllegalAccessException(
866 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
867 "Property is read-only!") ),
868 static_cast< cppu::OWeakObject
* >( this ) );
872 // @@@ Note: If your data source supports adding/removing
873 // properties, you should implement the interface
874 // XPropertyContainer by yourself and supply your own
875 // logic here. The base class uses the service
876 // "com.sun.star.ucb.Store" to maintain Additional Core
877 // properties. But using server functionality is preferred!
879 // Not a Core Property! Maybe it's an Additional Core Property?!
881 if ( !bTriedToGetAdditonalPropSet
&& !xAdditionalPropSet
.is() )
883 xAdditionalPropSet
= getAdditionalPropertySet( sal_False
);
884 bTriedToGetAdditonalPropSet
= sal_True
;
887 if ( xAdditionalPropSet
.is() )
892 = xAdditionalPropSet
->getPropertyValue( rValue
.Name
);
893 if ( aOldValue
!= rValue
.Value
)
895 xAdditionalPropSet
->setPropertyValue(
896 rValue
.Name
, rValue
.Value
);
898 aEvent
.PropertyName
= rValue
.Name
;
899 aEvent
.OldValue
= aOldValue
;
900 aEvent
.NewValue
= rValue
.Value
;
902 aChanges
.getArray()[ nChanged
] = aEvent
;
907 // Old value equals new value. No error!
910 catch ( beans::UnknownPropertyException
const & e
)
914 catch ( lang::WrappedTargetException
const & e
)
918 catch ( beans::PropertyVetoException
const & e
)
922 catch ( lang::IllegalArgumentException
const & e
)
929 aRet
[ n
] <<= uno::Exception(
930 rtl::OUString::createFromAscii(
931 "No property set for storing the value!" ),
932 static_cast< cppu::OWeakObject
* >( this ) );
943 aChanges
.realloc( nChanged
);
944 notifyPropertiesChange( aChanges
);
951 //=========================================================================
952 void Content::queryChildren( ContentRefList
& rChildren
)
954 // @@@ Adapt method to your URL scheme...
956 // Obtain a list with a snapshot of all currently instanciated contents
957 // from provider and extract the contents which are direct children
960 ::ucbhelper::ContentRefList aAllContents
;
961 m_xProvider
->queryExistingContents( aAllContents
);
963 OUString aURL
= m_xIdentifier
->getContentIdentifier();
964 sal_Int32 nPos
= aURL
.lastIndexOf( '/' );
966 if ( nPos
!= ( aURL
.getLength() - 1 ) )
968 // No trailing slash found. Append.
969 aURL
+= OUString::createFromAscii( "/" );
972 sal_Int32 nLen
= aURL
.getLength();
974 ::ucbhelper::ContentRefList::const_iterator it
= aAllContents
.begin();
975 ::ucbhelper::ContentRefList::const_iterator end
= aAllContents
.end();
979 ::ucbhelper::ContentImplHelperRef xChild
= (*it
);
980 OUString aChildURL
= xChild
->getIdentifier()->getContentIdentifier();
982 // Is aURL a prefix of aChildURL?
983 if ( ( aChildURL
.getLength() > nLen
) &&
984 ( aChildURL
.compareTo( aURL
, nLen
) == 0 ) )
986 sal_Int32 nPos
= nLen
;
987 nPos
= aChildURL
.indexOf( '/', nPos
);
989 if ( ( nPos
== -1 ) ||
990 ( nPos
== ( aChildURL
.getLength() - 1 ) ) )
992 // No further slashes / only a final slash. It's a child!
995 static_cast< Content
* >( xChild
.get() ) ) );
1002 //=========================================================================
1003 void Content::insert(
1004 const uno::Reference
< io::XInputStream
> & xInputStream
,
1005 sal_Bool bReplaceExisting
,
1006 const uno::Reference
< ucb::XCommandEnvironment
>& Environment
)
1007 throw( uno::Exception
)
1009 osl::ClearableGuard
< osl::Mutex
> aGuard( m_aMutex
);
1011 // Check, if all required properties were set.
1012 if ( !m_aProps
->m_sTitle
.getLength())
1014 OSL_ENSURE( sal_False
, "Content::insert - property value missing!" );
1016 uno::Sequence
< rtl::OUString
> aProps( 1 );
1017 aProps
[ 0 ] = rtl::OUString::createFromAscii( "zzzz" );
1018 ucbhelper::cancelCommandExecution(
1019 uno::makeAny( ucb::MissingPropertiesException(
1021 static_cast< cppu::OWeakObject
* >( this ),
1027 if ( !xInputStream
.is() )
1029 OSL_ENSURE( sal_False
, "Content::insert - No data stream!" );
1031 ucbhelper::cancelCommandExecution(
1032 uno::makeAny( ucb::MissingInputStreamException(
1034 static_cast< cppu::OWeakObject
* >( this ) ) ),
1039 // Assemble new content identifier...
1041 // uno::Reference< ucb::XContentIdentifier > xId = ...;
1043 // Fail, if a resource with given id already exists.
1044 if ( !bReplaceExisting
) // && hasData( m_xIdentifier ) )
1046 ucbhelper::cancelCommandExecution(
1047 uno::makeAny( ucb::UnsupportedCommandException(
1049 static_cast< cppu::OWeakObject
* >( this ) ) ),
1051 // ucbhelper::cancelCommandExecution(
1052 // ucb::IOErrorCode_ALREADY_EXISTING,
1054 // uno::makeAny(static_cast< cppu::OWeakObject * >( this ))
1059 // m_xIdentifier = xId;
1068 //=========================================================================
1069 void Content::destroy( sal_Bool bDeletePhysical
)
1070 throw( uno::Exception
)
1072 // @@@ take care about bDeletePhysical -> trashcan support
1074 uno::Reference
< ucb::XContent
> xThis
= this;
1078 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
1080 // Process instanciated children...
1082 ContentRefList aChildren
;
1083 queryChildren( aChildren
);
1085 ContentRefList::const_iterator it
= aChildren
.begin();
1086 ContentRefList::const_iterator end
= aChildren
.end();
1090 (*it
)->destroy( bDeletePhysical
);
1096 // -----------------------------------------------------------------------------
1097 ::rtl::OUString
Content::openDoc()
1099 OSL_ENSURE(m_aProps
.is(),"No valid content properties!");
1100 return ContentProvider::openDoc(m_aProps
);
1102 // -----------------------------------------------------------------------------
1103 void Content::changePropertyValue(const beans::PropertyValue
& _rValue
,
1104 sal_Int32 _rnCurrentPos
,
1105 ::rtl::OUString
& _rsMemberValue
,
1106 sal_Int32
& _rnChanged
,
1107 uno::Sequence
< uno::Any
>& _rRet
,
1108 uno::Sequence
< beans::PropertyChangeEvent
>& _rChanges
) throw (beans::IllegalTypeException
)
1110 rtl::OUString sNewValue
;
1111 sal_Bool bError
= sal_False
;
1112 if ( _rValue
.Value
>>= sNewValue
)
1114 if ( sNewValue
!= _rsMemberValue
)
1116 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
1117 // first we have to check if we could change the property inside the DMS
1118 ::rtl::OString sDocInfoValue
= ::rtl::OUStringToOString(sNewValue
,RTL_TEXTENCODING_ASCII_US
);
1120 if(&_rsMemberValue
== &m_aProps
->m_sTitle
)
1121 nDocInfo
= ODM_TITLETEXT
;
1122 else if(&_rsMemberValue
== &m_aProps
->m_sAuthor
)
1123 nDocInfo
= ODM_AUTHOR
;
1124 else if(&_rsMemberValue
== &m_aProps
->m_sSubject
)
1125 nDocInfo
= ODM_SUBJECT
;
1126 else if(&_rsMemberValue
== &m_aProps
->m_sKeywords
)
1127 nDocInfo
= ODM_KEYWORDS
;
1133 ODMSTATUS odm
= NODMSetDocInfo( ContentProvider::getHandle(),
1134 const_cast<sal_Char
*>(m_aProps
->m_sDocumentId
.getStr()),
1136 const_cast<sal_Char
*>(sDocInfoValue
.getStr())
1138 if(odm
== ODM_SUCCESS
)
1140 beans::PropertyChangeEvent aEvent
;
1141 aEvent
.Source
= static_cast< cppu::OWeakObject
* >( this );
1142 aEvent
.Further
= sal_False
;
1143 aEvent
.PropertyHandle
= -1;
1144 aEvent
.PropertyName
= _rValue
.Name
;
1145 aEvent
.OldValue
= uno::makeAny( _rsMemberValue
);
1146 aEvent
.NewValue
= uno::makeAny( sNewValue
);
1148 _rChanges
.getArray()[ _rnChanged
] = aEvent
;
1150 _rsMemberValue
= sNewValue
;
1157 // Old value equals new value. No error!
1165 _rRet
[ _rnCurrentPos
] <<= beans::IllegalTypeException(
1166 rtl::OUString::createFromAscii(
1167 "Property value has wrong type!" ),
1168 static_cast< cppu::OWeakObject
* >( this ) );
1171 // -----------------------------------------------------------------------------