Update ooo320-m1
[ooovba.git] / ucb / source / ucp / odma / odma_content.cxx
blob63cd5d0444ebc93e0b5469a770914262b3b5b0cf
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: odma_content.cxx,v $
10 * $Revision: 1.7 $
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 /**************************************************************************
35 TODO
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;
73 using namespace odma;
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 )
88 ,m_aProps(_rProps)
89 ,m_pProvider(pProvider)
90 ,m_pContent(NULL)
92 OSL_ENSURE(m_aProps.is(),"No valid ContentPropeties!");
95 //=========================================================================
96 // virtual
97 Content::~Content()
99 delete m_pContent;
102 //=========================================================================
104 // XInterface methods.
106 //=========================================================================
108 // virtual
109 void SAL_CALL Content::acquire() throw()
111 ContentImplHelper::acquire();
114 //=========================================================================
115 // virtual
116 void SAL_CALL Content::release() throw()
118 ContentImplHelper::release();
121 //=========================================================================
122 // virtual
123 uno::Any SAL_CALL Content::queryInterface( const uno::Type & rType )
124 throw ( uno::RuntimeException )
126 uno::Any aRet;
128 // @@@ Add support for additional interfaces.
129 #if 0
130 aRet = cppu::queryInterface( rType,
131 static_cast< yyy::Xxxxxxxxx * >( this ) );
132 #endif
134 return aRet.hasValue() ? aRet : ContentImplHelper::queryInterface( rType );
137 //=========================================================================
139 // XTypeProvider methods.
141 //=========================================================================
143 XTYPEPROVIDER_COMMON_IMPL( Content );
145 //=========================================================================
146 // virtual
147 uno::Sequence< uno::Type > SAL_CALL Content::getTypes()
148 throw( uno::RuntimeException )
150 // @@@ Add own interfaces.
152 static cppu::OTypeCollection* pCollection = 0;
154 if ( !pCollection )
156 osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
157 if ( !pCollection )
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 //=========================================================================
183 // virtual
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 //=========================================================================
192 // virtual
193 uno::Sequence< rtl::OUString > SAL_CALL Content::getSupportedServiceNames()
194 throw( uno::RuntimeException )
196 // @@@ Adjust macro name.
197 uno::Sequence< rtl::OUString > aSNS( 1 );
198 aSNS.getArray()[ 0 ]
199 = rtl::OUString::createFromAscii( ODMA_CONTENT_SERVICE_NAME );
200 return aSNS;
203 //=========================================================================
205 // XContent methods.
207 //=========================================================================
209 // virtual
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 //=========================================================================
223 // virtual
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 )
232 uno::Any aRet;
234 if ( aCommand.Name.equalsAsciiL(
235 RTL_CONSTASCII_STRINGPARAM( "getPropertyValues" ) ) )
237 //////////////////////////////////////////////////////////////////
238 // getPropertyValues
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(
247 rtl::OUString(),
248 static_cast< cppu::OWeakObject * >( this ),
249 -1 ) ),
250 Environment );
251 // Unreachable
254 aRet <<= getPropertyValues( Properties, Environment );
256 else if ( aCommand.Name.equalsAsciiL(
257 RTL_CONSTASCII_STRINGPARAM( "setPropertyValues" ) ) )
259 //////////////////////////////////////////////////////////////////
260 // setPropertyValues
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(
269 rtl::OUString(),
270 static_cast< cppu::OWeakObject * >( this ),
271 -1 ) ),
272 Environment );
273 // Unreachable
276 if ( !aProperties.getLength() )
278 OSL_ENSURE( sal_False, "No properties!" );
279 ucbhelper::cancelCommandExecution(
280 uno::makeAny( lang::IllegalArgumentException(
281 rtl::OUString(),
282 static_cast< cppu::OWeakObject * >( this ),
283 -1 ) ),
284 Environment );
285 // Unreachable
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 //////////////////////////////////////////////////////////////////
304 // getCommandInfo
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(
319 rtl::OUString(),
320 static_cast< cppu::OWeakObject * >( this ),
321 -1 ) ),
322 Environment );
323 // Unreachable
326 sal_Bool bOpenFolder =
327 ( ( aOpenCommand.Mode == ucb::OpenMode::ALL ) ||
328 ( aOpenCommand.Mode == ucb::OpenMode::FOLDERS ) ||
329 ( aOpenCommand.Mode == ucb::OpenMode::DOCUMENTS ) );
331 if ( bOpenFolder)
333 // open as folder - return result set
335 uno::Reference< ucb::XDynamicResultSet > xSet
336 = new DynamicResultSet( m_xSMgr,
337 this,
338 aOpenCommand,
339 Environment );
340 aRet <<= xSet;
343 if ( aOpenCommand.Sink.is() )
345 // Open document - supply document data stream.
347 // Check open mode
348 if ( ( aOpenCommand.Mode
349 == ucb::OpenMode::DOCUMENT_SHARE_DENY_NONE ) ||
350 ( aOpenCommand.Mode
351 == ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE ) )
353 // Unsupported.
354 ucbhelper::cancelCommandExecution(
355 uno::makeAny( ucb::UnsupportedOpenModeException(
356 rtl::OUString(),
357 static_cast< cppu::OWeakObject * >( this ),
358 sal_Int16( aOpenCommand.Mode ) ) ),
359 Environment );
360 // Unreachable
364 rtl::OUString aURL = m_xIdentifier->getContentIdentifier();
365 rtl::OUString sFileURL = openDoc();
366 delete m_pContent;
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(
375 sErrorMsg,
376 static_cast< cppu::OWeakObject * >( this )) ),
377 Environment );
380 uno::Reference< io::XOutputStream > xOut
381 = uno::Reference< io::XOutputStream >(
382 aOpenCommand.Sink, uno::UNO_QUERY );
383 if ( xOut.is() )
385 // @@@ PUSH: write data into xOut
386 m_pContent->openStream(xOut);
388 else
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 );
407 else
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
415 else
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(
422 rtl::OUString(),
423 static_cast< cppu::OWeakObject * >( this ),
424 aOpenCommand.Sink ) ),
425 Environment );
426 // Unreachable
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 //////////////////////////////////////////////////////////////////
439 // delete
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(
448 rtl::OUString(),
449 static_cast< cppu::OWeakObject * >( this ),
450 -1 ) ),
451 Environment );
453 else if ( aCommand.Name.equalsAsciiL(
454 RTL_CONSTASCII_STRINGPARAM( "insert" ) ) )
456 //////////////////////////////////////////////////////////////////
457 // insert
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(
466 rtl::OUString(),
467 static_cast< cppu::OWeakObject * >( this ),
468 -1 ) ),
469 Environment );
470 // Unreachable
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(
489 rtl::OUString(),
490 static_cast< cppu::OWeakObject * >( this ),
491 -1 ) ),
492 Environment );
493 // Unreachable
495 ::rtl::Reference<ContentProperties> aProp = m_aProps;
496 if(aProp->m_bIsFolder)
498 aProp = getContentProvider()->getContentPropertyWithDocumentId(aTransferInfo.NewTitle);
499 if(!aProp.is())
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
511 // succeed.
513 if(bError)
514 ucbhelper::cancelCommandExecution(
515 uno::makeAny( lang::IllegalArgumentException(
516 rtl::OUString(),
517 static_cast< cppu::OWeakObject * >( this ),
518 -1 ) ),
519 Environment );
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
532 // imported.
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;
541 else
543 //////////////////////////////////////////////////////////////////
544 // Unsupported command
545 //////////////////////////////////////////////////////////////////
547 OSL_ENSURE( sal_False, "Content::execute - unsupported command!" );
549 ucbhelper::cancelCommandExecution(
550 uno::makeAny( ucb::UnsupportedCommandException(
551 rtl::OUString(),
552 static_cast< cppu::OWeakObject * >( this ) ) ),
553 Environment );
554 // Unreachable
557 return aRet;
560 //=========================================================================
561 // virtual
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 //=========================================================================
575 // virtual
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();
585 else
586 sURL = sScheme1;
588 return sURL;
591 //=========================================================================
592 // static
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();
606 if ( nCount )
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 );
668 else
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() )
681 xAdditionalPropSet
682 = uno::Reference< beans::XPropertySet >(
683 rProvider->getAdditionalPropertySet( rContentId,
684 sal_False ),
685 uno::UNO_QUERY );
686 bTriedToGetAdditonalPropSet = sal_True;
689 if ( xAdditionalPropSet.is() )
691 if ( !xRow->appendPropertySetValue(
692 xAdditionalPropSet,
693 rProp ) )
695 // Append empty entry.
696 xRow->appendVoid( rProp );
699 else
701 // Append empty entry.
702 xRow->appendVoid( rProp );
707 else
709 // Append all Core Properties.
710 xRow->appendString (
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 );
717 xRow->appendString (
718 beans::Property( rtl::OUString::createFromAscii( "Title" ),
720 getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
721 beans::PropertyAttribute::BOUND ),
722 rData->m_sTitle );
723 xRow->appendBoolean(
724 beans::Property( rtl::OUString::createFromAscii( "IsDocument" ),
726 getCppuBooleanType(),
727 beans::PropertyAttribute::BOUND
728 | beans::PropertyAttribute::READONLY ),
729 rData->m_bIsDocument );
730 xRow->appendBoolean(
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 );
753 xRow->appendBoolean(
754 beans::Property( rtl::OUString::createFromAscii( "IsReadOnly" ),
756 getCppuBooleanType(),
757 beans::PropertyAttribute::BOUND
758 | beans::PropertyAttribute::READONLY ),
759 rData->m_bIsReadOnly );
760 xRow->appendString (
761 beans::Property( rtl::OUString::createFromAscii( "Author" ),
763 getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
764 beans::PropertyAttribute::BOUND ),
765 rData->m_sAuthor );
766 xRow->appendString (
767 beans::Property( rtl::OUString::createFromAscii( "Subject" ),
769 getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
770 beans::PropertyAttribute::BOUND ),
771 rData->m_sSubject );
772 xRow->appendString (
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 ),
790 uno::UNO_QUERY );
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,
804 rProperties,
805 m_aProps,
806 rtl::Reference<
807 ::ucbhelper::ContentProviderImplHelper >(
808 m_xProvider.get() ),
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;
828 // aEvent.OldValue =
829 // aEvent.NewValue =
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 ) );
870 else
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() )
891 uno::Any aOldValue
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;
903 nChanged++;
905 else
907 // Old value equals new value. No error!
910 catch ( beans::UnknownPropertyException const & e )
912 aRet[ n ] <<= e;
914 catch ( lang::WrappedTargetException const & e )
916 aRet[ n ] <<= e;
918 catch ( beans::PropertyVetoException const & e )
920 aRet[ n ] <<= e;
922 catch ( lang::IllegalArgumentException const & e )
924 aRet[ n ] <<= e;
927 else
929 aRet[ n ] <<= uno::Exception(
930 rtl::OUString::createFromAscii(
931 "No property set for storing the value!" ),
932 static_cast< cppu::OWeakObject * >( this ) );
937 if ( nChanged > 0 )
939 // @@@ Save changes.
940 // storeData();
942 aGuard.clear();
943 aChanges.realloc( nChanged );
944 notifyPropertiesChange( aChanges );
947 return aRet;
950 #if 0
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
958 // of this content.
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();
977 while ( it != 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!
993 rChildren.push_back(
994 ContentRef(
995 static_cast< Content * >( xChild.get() ) ) );
998 ++it;
1001 #endif
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(
1020 rtl::OUString(),
1021 static_cast< cppu::OWeakObject * >( this ),
1022 aProps ) ),
1023 Environment );
1024 // Unreachable
1027 if ( !xInputStream.is() )
1029 OSL_ENSURE( sal_False, "Content::insert - No data stream!" );
1031 ucbhelper::cancelCommandExecution(
1032 uno::makeAny( ucb::MissingInputStreamException(
1033 rtl::OUString(),
1034 static_cast< cppu::OWeakObject * >( this ) ) ),
1035 Environment );
1036 // Unreachable
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(
1048 rtl::OUString(),
1049 static_cast< cppu::OWeakObject * >( this ) ) ),
1050 Environment );
1051 // ucbhelper::cancelCommandExecution(
1052 // ucb::IOErrorCode_ALREADY_EXISTING,
1053 // Environment,
1054 // uno::makeAny(static_cast< cppu::OWeakObject * >( this ))
1055 // );
1056 // Unreachable
1059 // m_xIdentifier = xId;
1061 // @@@
1062 // storeData();
1064 aGuard.clear();
1065 inserted();
1067 #if 0
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;
1076 deleted();
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();
1088 while ( it != end )
1090 (*it)->destroy( bDeletePhysical );
1091 ++it;
1094 #endif
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);
1119 WORD nDocInfo = 0;
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;
1128 else
1129 bError = sal_True;
1131 if(!bError)
1133 ODMSTATUS odm = NODMSetDocInfo( ContentProvider::getHandle(),
1134 const_cast<sal_Char*>(m_aProps->m_sDocumentId.getStr()),
1135 nDocInfo,
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;
1151 ++_rnChanged;
1155 else
1157 // Old value equals new value. No error!
1160 else
1161 bError = sal_True;
1163 if(bError)
1165 _rRet[ _rnCurrentPos ] <<= beans::IllegalTypeException(
1166 rtl::OUString::createFromAscii(
1167 "Property value has wrong type!" ),
1168 static_cast< cppu::OWeakObject * >( this ) );
1171 // -----------------------------------------------------------------------------